Version 1.24.0-dev.1.0

Merge commit '7f7c681893ece113e6f5fb3186092a45ca659baf' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef965e1..8562f03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
     that don't store it in an environment variable.
   * Added `ProcessInfo.currentRss` and `ProcessInfo.maxRss` for inspecting
     the Dart VM process current and peak resident set size.
+  * Added 'RawSynchronousSocket', a basic synchronous socket implementation.
 
 ### Dart VM
 
@@ -21,6 +22,11 @@
       transformer.
     * Allow publishing packages that depend on the Flutter SDK.
 
+* dartfmt
+    * Preserve type parameters in new generic function typedef syntax.
+    * Add self-test validation to ensure formatter bugs do not cause user code
+      to be lost.
+
 ## 1.23.0
 
 #### Strong Mode
@@ -96,12 +102,13 @@
       int x = 42;
     }
     class D extends C {
-      int x = 123;
-      get y => super.x;
+      get x {
+        print("x got called");
+        return super.x;
+      }
     }
     main() {
       print(new D().x);
-      print(new D().y);
     }
     ```
 
diff --git a/DEPS b/DEPS
index 18be85e..2ebbfbb 100644
--- a/DEPS
+++ b/DEPS
@@ -37,14 +37,13 @@
   "gperftools_revision": "@02eeed29df112728564a5dde6417fa4622b57a06",
 
   # Revisions of /third_party/* dependencies.
-  "angular_analyzer_plugin_tag": "@v0.0.8",
   "args_tag": "@0.13.7",
   "async_tag": "@1.13.0",
   "barback-0.13.0_rev": "@34853",
   "barback-0.14.0_rev": "@36398",
   "barback-0.14.1_rev": "@38525",
   "barback_tag" : "@0.15.2+9",
-  "bazel_worker_tag": "@0.1.2",
+  "bazel_worker_tag": "@v0.1.4",
   "boolean_selector_tag" : "@1.0.2",
   "boringssl_gen_rev": "@753224969dbe43dad29343146529727b5066c0f3",
   "boringssl_rev" : "@d519bf6be0b447fb80fbc539d4bff4479b5482a2",
@@ -58,7 +57,7 @@
   "csslib_tag" : "@0.13.3+1",
   "dart2js_info_tag" : "@0.5.4+2",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
-  "dart_style_tag": "@1.0.3",
+  "dart_style_tag": "@1.0.4",
   "dartdoc_tag" : "@v0.9.14-dev",
   "fixnum_tag": "@0.10.5",
   "func_tag": "@1.0.0",
@@ -91,7 +90,7 @@
   "plugin_tag": "@0.2.0",
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "@1.3.0",
-  "protobuf_tag": "@0.5.3",
+  "protobuf_tag": "@0.5.4",
   "pub_rev": "@69be47ed84c3ced304047aaa885c8f8f48dad4e6",
   "pub_semver_tag": "@1.3.2",
   "quiver_tag": "@0.22.0",
@@ -105,7 +104,7 @@
   "smoke_tag" : "@v0.3.6+2",
   "source_map_stack_trace_tag": "@1.1.4",
   "source_maps-0.9.4_rev": "@38524",
-  "source_maps_tag": "@0.10.3",
+  "source_maps_tag": "@0.10.4",
   "source_span_tag": "@1.3.1",
   "stack_trace_tag": "@1.7.2",
   "stream_channel_tag": "@1.6.1",
@@ -175,9 +174,6 @@
       Var('chromium_git') + '/external/github.com/gperftools/gperftools.git' +
       Var("gperftools_revision"),
 
-  Var("dart_root") + "/third_party/pkg/angular_analyzer_plugin":
-      (Var("github_mirror") % "angular_analyzer_plugin") +
-      Var("angular_analyzer_plugin_tag"),
   Var("dart_root") + "/third_party/pkg/args":
       (Var("github_mirror") % "args") + Var("args_tag"),
   Var("dart_root") + "/third_party/pkg/async":
@@ -276,7 +272,10 @@
   Var("dart_root") + "/third_party/pkg/pool":
       (Var("github_mirror") % "pool") + Var("pool_tag"),
   Var("dart_root") + "/third_party/pkg/protobuf":
-      (Var("github_mirror") % "dart-protobuf") + Var("protobuf_tag"),
+      # Restore the github mirror once it's corrected to point to protobuf
+      # instead of dart-protobuf
+      # (Var("github_mirror") % "dart-protobuf") + Var("protobuf_tag"),
+      (Var("github_dartlang") % "protobuf") + Var("protobuf_tag"),
   Var("dart_root") + "/third_party/pkg/pub_semver":
       (Var("github_mirror") % "pub_semver") + Var("pub_semver_tag"),
   Var("dart_root") + "/third_party/pkg/pub":
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index ed6583e..daf26ed 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -158,7 +158,7 @@
 
 # Some third party code might not compile with WIN32_LEAN_AND_MEAN so we have
 # to have a separate config for it. Remove this config from your target to
-# get the "bloaty and accomodating" version of windows.h.
+# get the "bloaty and accommodating" version of windows.h.
 config("lean_and_mean") {
   defines = [ "WIN32_LEAN_AND_MEAN" ]
 }
diff --git a/build/gn_run_binary.py b/build/gn_run_binary.py
index 76d1992..224936a 100755
--- a/build/gn_run_binary.py
+++ b/build/gn_run_binary.py
@@ -48,7 +48,7 @@
     print "Binary not found: " + path
     return error_exit
 
-  # The rest of the arguements are passed directly to the executable.
+  # The rest of the arguments are passed directly to the executable.
   args = [path] + argv[3:]
 
   result = run_command(args)
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 3d43547..7efe146 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -155,7 +155,7 @@
 % ~. ~ does not actually parse stuff - it just looks ahead and checks. To get the effect of
 % parsing anything but X, one needs ~X ANYTHING, not just ~X. There are bugs in the
 % grammar related to this.
-% The alternative is to define ~X as anything but X, or to introduce an anthingBut(X)
+% The alternative is to define ~X as anything but X, or to introduce an anythingBut(X)
 % combinator, such as !X
 
 \LMHash{}
@@ -3501,8 +3501,11 @@
 Then, if $q$ is a non-factory constructor of an abstract class then an \code{AbstractClassInstantiationError} is thrown.
 
 \LMHash{}
-If $T$  is malformed or if $T$ is a type variable a dynamic error occurs. In checked mode, if $T$ or any of its superclasses is malbounded a dynamic error occurs.
-Otherwise, if $q$ is not defined or not accessible, a \code{NoSuchMethodError} is thrown.  If $q$ has fewer than $n$ positional parameters or more than $n$ required parameters, or if $q$ lacks any of the keyword parameters $\{ x_{n+1}, \ldots, x_{n+k}\}$ a \code{NoSuchMethodError} is thrown.
+If $T$ is malformed or if $T$ is a type variable a dynamic error occurs.
+In checked mode, if $T$ or any of its superclasses is malbounded a dynamic error occurs.
+Otherwise, if $q$ is not defined or not accessible, a \code{NoSuchMethodError} is thrown.
+If $q$ has fewer than $n$ positional parameters or more than $n$ required parameters,
+or if $q$ lacks any of the named parameters $\{ x_{n+1}, \ldots, x_{n+k}\}$ a \code{NoSuchMethodError} is thrown.
 
 \LMHash{}
 Otherwise, if $q$ is a generative constructor (\ref{generativeConstructors}), then:
diff --git a/docs/language/informal/covariant-from-class.md b/docs/language/informal/covariant-from-class.md
index b9f3afe..83120e2 100644
--- a/docs/language/informal/covariant-from-class.md
+++ b/docs/language/informal/covariant-from-class.md
@@ -276,7 +276,7 @@
 ## Alternatives
 
 The "erasure" of the reified parameter type for each covariant parameter to
-`Object` may seem agressive.
+`Object` may seem aggressive.
 
 In particular, it ignores upper bounds on the formal type parameter which gives
 rise to the covariance due to class covariance, and it ignores the structure of
diff --git a/pkg/analysis_server/analysis_server.iml b/pkg/analysis_server/analysis_server.iml
index ea34ce5..eeb9c7a 100644
--- a/pkg/analysis_server/analysis_server.iml
+++ b/pkg/analysis_server/analysis_server.iml
@@ -57,5 +57,6 @@
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="Dart SDK" level="application" />
     <orderEntry type="library" name="Dart SDK" level="project" />
+    <orderEntry type="library" name="Dart Packages" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 2c51967..8af322c 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -69,6 +69,7 @@
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:plugin/plugin.dart';
+import 'package:watcher/watcher.dart';
 
 typedef void OptionUpdater(AnalysisOptionsImpl options);
 
@@ -374,6 +375,12 @@
   Function onNoAnalysisResult;
 
   /**
+   * This exists as a temporary stopgap for plugins, until the official plugin
+   * API is complete.
+   */
+  Function onNoAnalysisCompletion;
+
+  /**
    * The set of the files that are currently priority.
    */
   final Set<String> priorityFiles = new Set<String>();
@@ -422,8 +429,6 @@
         options.enableIncrementalResolutionApi;
     defaultContextOptions.incrementalValidation =
         options.enableIncrementalResolutionValidation;
-    defaultContextOptions.finerGrainedInvalidation =
-        options.finerGrainedInvalidation;
     defaultContextOptions.generateImplicitErrors = false;
     operationQueue = new ServerOperationQueue();
 
@@ -1894,7 +1899,6 @@
   bool enableIncrementalResolutionApi = false;
   bool enableIncrementalResolutionValidation = false;
   bool enableNewAnalysisDriver = false;
-  bool finerGrainedInvalidation = false;
   bool noIndex = false;
   bool useAnalysisHighlight2 = false;
   String fileReadMode = 'as-is';
@@ -2109,6 +2113,11 @@
   }
 
   @override
+  void broadcastWatchEvent(WatchEvent event) {
+    analysisServer.pluginManager.broadcastWatchEvent(event);
+  }
+
+  @override
   void computingPackageMap(bool computing) =>
       analysisServer._computingPackageMap(computing);
 
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 686c088..096e4a6 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -386,6 +386,11 @@
   void applyFileRemoved(AnalysisDriver driver, String file);
 
   /**
+   * Sent the given watch [event] to any interested plugins.
+   */
+  void broadcastWatchEvent(WatchEvent event);
+
+  /**
    * Signals that the context manager has started to compute a package map (if
    * [computing] is `true`) or has finished (if [computing] is `false`).
    */
@@ -1395,7 +1400,10 @@
     // but implicitly referenced in another context, we will only send a
     // changeSet to the context that explicitly includes the file (because
     // that's the only context that's watching the file).
-    ContextInfo info = _getInnermostContextInfoFor(event.path);
+    callbacks.broadcastWatchEvent(event);
+    String path = event.path;
+    ChangeType type = event.type;
+    ContextInfo info = _getInnermostContextInfoFor(path);
     if (info == null) {
       // This event doesn't apply to any context.  This could happen due to a
       // race condition (e.g. a context was removed while one of its events was
@@ -1403,8 +1411,7 @@
       return;
     }
     _instrumentationService.logWatchEvent(
-        info.folder.path, event.path, event.type.toString());
-    String path = event.path;
+        info.folder.path, path, type.toString());
     // First handle changes that affect folderDisposition (since these need to
     // be processed regardless of whether they are part of an excluded/ignored
     // path).
@@ -1426,7 +1433,7 @@
       return;
     }
     // handle the change
-    switch (event.type) {
+    switch (type) {
       case ChangeType.ADD:
         Resource resource = resourceProvider.getResource(path);
 
@@ -1543,7 +1550,7 @@
         break;
     }
     _checkForPackagespecUpdate(path, info, info.folder);
-    _checkForAnalysisOptionsUpdate(path, info, event.type);
+    _checkForAnalysisOptionsUpdate(path, info, type);
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index d903e86..b036879 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -16,6 +16,7 @@
 import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
 import 'package:analysis_server/src/operation/operation_analysis.dart'
     show NavigationOperation, OccurrencesOperation;
+import 'package:analysis_server/src/plugin/request_converter.dart';
 import 'package:analysis_server/src/protocol/protocol_internal.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
@@ -290,6 +291,15 @@
       }
       server.reanalyze(rootResources);
     }
+    //
+    // Forward the request to the plugins.
+    //
+    RequestConverter converter = new RequestConverter();
+    server.pluginManager
+        .broadcastRequest(converter.convertAnalysisReanalyzeParams(params));
+    //
+    // Send the response.
+    //
     return new AnalysisReanalyzeResult().toResponse(request.id);
   }
 
@@ -333,6 +343,15 @@
   Response setPriorityFiles(Request request) {
     var params = new AnalysisSetPriorityFilesParams.fromRequest(request);
     server.setPriorityFiles(request.id, params.files);
+    //
+    // Forward the request to the plugins.
+    //
+    RequestConverter converter = new RequestConverter();
+    server.pluginManager.setAnalysisSetPriorityFilesParams(
+        converter.convertAnalysisSetPriorityFilesParams(params));
+    //
+    // Send the response.
+    //
     return new AnalysisSetPriorityFilesResult().toResponse(request.id);
   }
 
@@ -345,6 +364,15 @@
     Map<AnalysisService, Set<String>> subMap = mapMap(params.subscriptions,
         valueCallback: (List<String> subscriptions) => subscriptions.toSet());
     server.setAnalysisSubscriptions(subMap);
+    //
+    // Forward the request to the plugins.
+    //
+    RequestConverter converter = new RequestConverter();
+    server.pluginManager.setAnalysisSetSubscriptionsParams(
+        converter.convertAnalysisSetSubscriptionsParams(params));
+    //
+    // Send the response.
+    //
     return new AnalysisSetSubscriptionsResult().toResponse(request.id);
   }
 
@@ -354,6 +382,15 @@
   Response updateContent(Request request) {
     var params = new AnalysisUpdateContentParams.fromRequest(request);
     server.updateContent(request.id, params.files);
+    //
+    // Forward the request to the plugins.
+    //
+    RequestConverter converter = new RequestConverter();
+    server.pluginManager.setAnalysisUpdateContentParams(
+        converter.convertAnalysisUpdateContentParams(params));
+    //
+    // Send the response.
+    //
     return new AnalysisUpdateContentResult().toResponse(request.id);
   }
 
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 916b20e..682615b 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -9,30 +9,31 @@
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/domain_abstract.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
+import 'package:analysis_server/src/plugin/result_converter.dart';
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/services/completion/completion_core.dart';
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
-import 'package:analyzer/src/source/source_resource.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/source_resource.dart';
+import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 
 /**
  * Instances of the class [CompletionDomainHandler] implement a [RequestHandler]
  * that handles requests in the completion domain.
  */
-class CompletionDomainHandler implements RequestHandler {
+class CompletionDomainHandler extends AbstractRequestHandler {
   /**
    * The maximum number of performance measurements to keep.
    */
   static const int performanceListMaxLength = 50;
 
   /**
-   * The analysis server that is using this handler to process requests.
-   */
-  final AnalysisServer server;
-
-  /**
    * The next completion response id.
    */
   int _nextCompletionId = 0;
@@ -62,7 +63,7 @@
   /**
    * Initialize a new request handler for the given [server].
    */
-  CompletionDomainHandler(this.server);
+  CompletionDomainHandler(AnalysisServer server) : super(server);
 
   /**
    * Compute completion results for the given request and append them to the stream.
@@ -71,8 +72,26 @@
    * Subclasses should override this method, append at least one result
    * to the [controller], and close the controller stream once complete.
    */
-  Future<CompletionResult> computeSuggestions(
-      CompletionRequestImpl request) async {
+  Future<CompletionResult> computeSuggestions(CompletionRequestImpl request,
+      CompletionGetSuggestionsParams params) async {
+    //
+    // Allow plugins to start computing fixes.
+    //
+    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+    plugin.CompletionGetSuggestionsParams requestParams;
+    if (server.options.enableNewAnalysisDriver) {
+      String file = params.file;
+      int offset = params.offset;
+      AnalysisDriver driver = server.getAnalysisDriver(file);
+      if (driver != null) {
+        requestParams = new plugin.CompletionGetSuggestionsParams(file, offset);
+        pluginFutures = server.pluginManager
+            .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
+      }
+    }
+    //
+    // Compute completions generated by server.
+    //
     Iterable<CompletionContributor> newContributors =
         server.serverPlugin.completionContributors;
     List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
@@ -91,13 +110,28 @@
       }
       performance.logElapseTime(contributorTag);
     }
-
     performance.logElapseTime(COMPUTE_SUGGESTIONS_TAG);
 
-    // TODO (danrubel) if request is obsolete
-    // (processAnalysisRequest returns false)
-    // then send empty results
+    // TODO (danrubel) if request is obsolete (processAnalysisRequest returns
+    // false) then send empty results
 
+    //
+    // Add the fixes produced by plugins to the server-generated fixes.
+    //
+    if (pluginFutures != null) {
+      List<plugin.Response> responses = await waitForResponses(pluginFutures,
+          requestParameters: requestParams);
+      ResultConverter converter = new ResultConverter();
+      for (plugin.Response response in responses) {
+        plugin.CompletionGetSuggestionsResult result =
+            new plugin.CompletionGetSuggestionsResult.fromResponse(response);
+        suggestions
+            .addAll(result.results.map(converter.convertCompletionSuggestion));
+      }
+    }
+    //
+    // Return the result.
+    //
     return new CompletionResult(
         request.replacementOffset, request.replacementLength, suggestions);
   }
@@ -122,6 +156,12 @@
     });
   }
 
+  void ifMatchesRequestClear(CompletionRequest completionRequest) {
+    if (_currentRequest == completionRequest) {
+      _currentRequest = null;
+    }
+  }
+
   /**
    * Process a `completion.getSuggestions` request.
    */
@@ -139,8 +179,15 @@
       result = await server.getAnalysisResult(params.file);
 
       if (result == null || !result.exists) {
-        server.sendResponse(new Response.unknownSource(request));
-        return;
+        if (server.onNoAnalysisCompletion != null) {
+          String completionId = (_nextCompletionId++).toString();
+          await server.onNoAnalysisCompletion(
+              request, this, params, performance, completionId);
+          return;
+        } else {
+          server.sendResponse(new Response.unknownSource(request));
+          return;
+        }
       }
 
       if (params.offset < 0 || params.offset > result.content.length) {
@@ -187,32 +234,30 @@
         params.offset,
         performance,
         server.ideOptions);
+
     String completionId = (_nextCompletionId++).toString();
 
-    _abortCurrentRequest();
-    _currentRequest = completionRequest;
+    setNewRequest(completionRequest);
 
     // initial response without results
     server.sendResponse(new CompletionGetSuggestionsResult(completionId)
         .toResponse(request.id));
 
     // Compute suggestions in the background
-    computeSuggestions(completionRequest).then((CompletionResult result) {
+    computeSuggestions(completionRequest, params)
+        .then((CompletionResult result) {
       const SEND_NOTIFICATION_TAG = 'send notification';
       performance.logStartTime(SEND_NOTIFICATION_TAG);
       sendCompletionNotification(completionId, result.replacementOffset,
           result.replacementLength, result.suggestions);
       performance.logElapseTime(SEND_NOTIFICATION_TAG);
-
       performance.notificationCount = 1;
       performance.logFirstNotificationComplete('notification 1 complete');
       performance.suggestionCountFirst = result.suggestions.length;
       performance.suggestionCountLast = result.suggestions.length;
       performance.complete();
     }).whenComplete(() {
-      if (_currentRequest == completionRequest) {
-        _currentRequest = null;
-      }
+      ifMatchesRequestClear(completionRequest);
     });
   }
 
@@ -247,6 +292,11 @@
         .toNotification());
   }
 
+  void setNewRequest(CompletionRequest completionRequest) {
+    _abortCurrentRequest();
+    _currentRequest = completionRequest;
+  }
+
   /**
    * Abort the current completion request, if any.
    */
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index c3a286d..55f94fb 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -152,11 +152,16 @@
       //
       // Allow plugins to start computing assists.
       //
-      AnalysisDriver driver = server.getAnalysisDriver(file);
+      Map<PluginInfo, Future<plugin.Response>> pluginFutures;
       plugin.EditGetAssistsParams requestParams =
           new plugin.EditGetAssistsParams(file, offset, length);
-      Map<PluginInfo, Future<plugin.Response>> pluginFutures =
-          server.pluginManager.broadcast(driver.contextRoot, requestParams);
+      AnalysisDriver driver = server.getAnalysisDriver(file);
+      if (driver == null) {
+        pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+      } else {
+        pluginFutures = server.pluginManager
+            .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
+      }
       //
       // Compute fixes associated with server-generated errors.
       //
@@ -225,11 +230,16 @@
       //
       // Allow plugins to start computing fixes.
       //
-      AnalysisDriver driver = server.getAnalysisDriver(file);
+      Map<PluginInfo, Future<plugin.Response>> pluginFutures;
       plugin.EditGetFixesParams requestParams =
           new plugin.EditGetFixesParams(file, offset);
-      Map<PluginInfo, Future<plugin.Response>> pluginFutures =
-          server.pluginManager.broadcast(driver.contextRoot, requestParams);
+      AnalysisDriver driver = server.getAnalysisDriver(file);
+      if (driver == null) {
+        pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+      } else {
+        pluginFutures = server.pluginManager
+            .broadcastRequest(requestParams, contextRoot: driver.contextRoot);
+      }
       //
       // Compute fixes associated with server-generated errors.
       //
@@ -445,7 +455,7 @@
     List<engine.AnalysisError> errors;
     if (server.options.enableNewAnalysisDriver) {
       AnalysisDriver driver = server.getAnalysisDriver(file);
-      ParseResult result = await driver.parseFile(file);
+      ParseResult result = await driver?.parseFile(file);
       if (result == null) {
         server.sendResponse(new Response.fileNotAnalyzed(request, file));
         return;
diff --git a/pkg/analysis_server/lib/src/plugin/notification_manager.dart b/pkg/analysis_server/lib/src/plugin/notification_manager.dart
index 53d0513..9927131 100644
--- a/pkg/analysis_server/lib/src/plugin/notification_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/notification_manager.dart
@@ -173,6 +173,17 @@
                     converter.convertOutline(outline))
                 .toList());
         break;
+      case plugin.PLUGIN_NOTIFICATION_ERROR:
+        plugin.PluginErrorParams params =
+            new plugin.PluginErrorParams.fromNotification(notification);
+        // TODO(brianwilkerson) There is no indication for the client as to the
+        // fact that the error came from a plugin, let alone which plugin it
+        // came from. We should consider whether we really want to send them to
+        // the client.
+        channel.sendNotification(new server.ServerErrorParams(
+                params.isFatal, params.message, params.stackTrace)
+            .toNotification());
+        break;
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
index 85e3527..0566680 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
@@ -51,8 +51,14 @@
    * associated with the package.
    *
    * This will look first in the `pubspec.yaml` file in the package root for a
-   * key indicating where the plugin is located. If such a key is not defined,
-   * then it will fall back to a well known location within the package.
+   * top-level key (`analysis_plugin`) indicating where the plugin is located.
+   * The value associated with the key is expected to be the path of the plugin
+   * relative to the package root. If the directory exists, the it is returned.
+   *
+   * If the key is not defined in the `pubspec.yaml` file, or if the directory
+   * given does not exist, then this method will look for the directory
+   * `tools/analysis_plugin` relative to the package root. If the directory
+   * exists, then it is returned.
    *
    * This method does not validate the content of the plugin directory before
    * returning it.
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index 645cb4c..50fb85c 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -12,8 +12,10 @@
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/bazel.dart';
 import 'package:analyzer/src/generated/gn.dart';
+import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer_plugin/channel/channel.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart';
+import 'package:analyzer_plugin/protocol/protocol_constants.dart';
 import 'package:analyzer_plugin/protocol/protocol_generated.dart';
 import 'package:analyzer_plugin/src/channel/isolate_channel.dart';
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';
@@ -21,6 +23,7 @@
 import 'package:crypto/crypto.dart';
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
+import 'package:watcher/watcher.dart' as watcher;
 
 /**
  * Information about a single plugin.
@@ -98,6 +101,15 @@
   }
 
   /**
+   * If the plugin is currently running, send a request based on the given
+   * [params] to the plugin. If the plugin is not running, the request will
+   * silently be dropped.
+   */
+  void sendRequest(RequestParams params) {
+    currentSession?.sendRequest(params);
+  }
+
+  /**
    * Start a new isolate that is running the plugin. Return the state object
    * used to interact with the plugin.
    */
@@ -168,6 +180,27 @@
   Map<String, PluginInfo> _pluginMap = <String, PluginInfo>{};
 
   /**
+   * The parameters for the last 'analysis.setPriorityFiles' request that was
+   * received from the client. Because plugins are lazily discovered, this needs
+   * to be retained so that it can be sent after a plugin has been started.
+   */
+  AnalysisSetPriorityFilesParams _analysisSetPriorityFilesParams;
+
+  /**
+   * The parameters for the last 'analysis.setSubscriptions' request that was
+   * received from the client. Because plugins are lazily discovered, this needs
+   * to be retained so that it can be sent after a plugin has been started.
+   */
+  AnalysisSetSubscriptionsParams _analysisSetSubscriptionsParams;
+
+  /**
+   * The current state of content overlays. Because plugins are lazily
+   * discovered, the state needs to be retained so that it can be sent after a
+   * plugin has been started.
+   */
+  Map<String, dynamic> _overlayState = <String, dynamic>{};
+
+  /**
    * Initialize a newly created plugin manager. The notifications from the
    * running plugins will be handled by the given [notificationManager].
    */
@@ -182,8 +215,12 @@
   Future<Null> addPluginToContextRoot(
       analyzer.ContextRoot contextRoot, String path) async {
     PluginInfo plugin = _pluginMap[path];
-    if (plugin == null) {
+    bool isNew = plugin == null;
+    if (isNew) {
       List<String> pluginPaths = _pathsFor(path);
+      if (pluginPaths == null) {
+        return;
+      }
       plugin = new PluginInfo(path, pluginPaths[0], pluginPaths[1],
           notificationManager, instrumentationService);
       _pluginMap[path] = plugin;
@@ -195,6 +232,17 @@
       }
     }
     plugin.addContextRoot(contextRoot);
+    if (isNew) {
+      if (_analysisSetSubscriptionsParams != null) {
+        plugin.sendRequest(_analysisSetSubscriptionsParams);
+      }
+      if (_overlayState.isNotEmpty) {
+        plugin.sendRequest(new AnalysisUpdateContentParams(_overlayState));
+      }
+      if (_analysisSetPriorityFilesParams != null) {
+        plugin.sendRequest(_analysisSetPriorityFilesParams);
+      }
+    }
   }
 
   /**
@@ -203,8 +251,8 @@
    * containing futures that will complete when each of the plugins have sent a
    * response.
    */
-  Map<PluginInfo, Future<Response>> broadcast(
-      analyzer.ContextRoot contextRoot, RequestParams params) {
+  Map<PluginInfo, Future<Response>> broadcastRequest(RequestParams params,
+      {analyzer.ContextRoot contextRoot}) {
     List<PluginInfo> plugins = pluginsForContextRoot(contextRoot);
     Map<PluginInfo, Future<Response>> responseMap =
         <PluginInfo, Future<Response>>{};
@@ -215,11 +263,46 @@
   }
 
   /**
+   * Broadcast the given [watchEvent] to all of the plugins that are analyzing
+   * in contexts containing the file associated with the event. Return a list
+   * containing futures that will complete when each of the plugins have sent a
+   * response.
+   */
+  Future<List<Future<Response>>> broadcastWatchEvent(
+      watcher.WatchEvent watchEvent) async {
+    String filePath = watchEvent.path;
+
+    /**
+     * Return `true` if the given glob [pattern] matches the file being watched.
+     */
+    bool matches(String pattern) =>
+        new Glob(path.separator, pattern).matches(filePath);
+
+    WatchEvent event = null;
+    List<Future<Response>> responses = <Future<Response>>[];
+    for (PluginInfo plugin in _pluginMap.values) {
+      PluginSession session = plugin.currentSession;
+      if (session != null &&
+          path.isWithin(plugin.path, filePath) &&
+          session.interestingFiles.any(matches)) {
+        event ??= _convertWatchEvent(watchEvent);
+        AnalysisHandleWatchEventsParams params =
+            new AnalysisHandleWatchEventsParams([event]);
+        responses.add(session.sendRequest(params));
+      }
+    }
+    return responses;
+  }
+
+  /**
    * Return a list of all of the plugins that are currently associated with the
    * given [contextRoot].
    */
   @visibleForTesting
   List<PluginInfo> pluginsForContextRoot(analyzer.ContextRoot contextRoot) {
+    if (contextRoot == null) {
+      return _pluginMap.values.toList();
+    }
     List<PluginInfo> plugins = <PluginInfo>[];
     for (PluginInfo plugin in _pluginMap.values) {
       if (plugin.contextRoots.contains(contextRoot)) {
@@ -244,12 +327,84 @@
   }
 
   /**
+   * Send a request based on the given [params] to existing plugins to set the
+   * priority files to those specified by the [params]. As a side-effect, record
+   * the parameters so that they can be sent to any newly started plugins.
+   */
+  void setAnalysisSetPriorityFilesParams(
+      AnalysisSetPriorityFilesParams params) {
+    for (PluginInfo plugin in _pluginMap.values) {
+      plugin.sendRequest(params);
+    }
+    _analysisSetPriorityFilesParams = params;
+  }
+
+  /**
+   * Send a request based on the given [params] to existing plugins to set the
+   * subscriptions to those specified by the [params]. As a side-effect, record
+   * the parameters so that they can be sent to any newly started plugins.
+   */
+  void setAnalysisSetSubscriptionsParams(
+      AnalysisSetSubscriptionsParams params) {
+    for (PluginInfo plugin in _pluginMap.values) {
+      plugin.sendRequest(params);
+    }
+    _analysisSetSubscriptionsParams = params;
+  }
+
+  /**
+   * Send a request based on the given [params] to existing plugins to set the
+   * content overlays to those specified by the [params]. As a side-effect,
+   * update the overlay state so that it can be sent to any newly started
+   * plugins.
+   */
+  void setAnalysisUpdateContentParams(AnalysisUpdateContentParams params) {
+    for (PluginInfo plugin in _pluginMap.values) {
+      plugin.sendRequest(params);
+    }
+    Map<String, dynamic> files = params.files;
+    for (String file in files.keys) {
+      Object overlay = files[file];
+      if (overlay is RemoveContentOverlay) {
+        _overlayState.remove(file);
+      } else if (overlay is AddContentOverlay) {
+        _overlayState[file] = overlay;
+      } else if (overlay is ChangeContentOverlay) {
+        AddContentOverlay previousOverlay = _overlayState[file];
+        String newContent =
+            SourceEdit.applySequence(previousOverlay.content, overlay.edits);
+        _overlayState[file] = new AddContentOverlay(newContent);
+      } else {
+        throw new ArgumentError(
+            'Invalid class of overlay: ${overlay.runtimeType}');
+      }
+    }
+  }
+
+  /**
    * Stop all of the plugins that are currently running.
    */
   Future<List<Null>> stopAll() {
     return Future.wait(_pluginMap.values.map((PluginInfo info) => info.stop()));
   }
 
+  WatchEventType _convertChangeType(watcher.ChangeType type) {
+    switch (type) {
+      case watcher.ChangeType.ADD:
+        return WatchEventType.ADD;
+      case watcher.ChangeType.MODIFY:
+        return WatchEventType.MODIFY;
+      case watcher.ChangeType.REMOVE:
+        return WatchEventType.REMOVE;
+      default:
+        throw new StateError('Unknown change type: $type');
+    }
+  }
+
+  WatchEvent _convertWatchEvent(watcher.WatchEvent watchEvent) {
+    return new WatchEvent(_convertChangeType(watchEvent.type), watchEvent.path);
+  }
+
   /**
    * Return the execution path and .packages path associated with the plugin at
    * the given [path], or `null` if there is a problem that prevents us from
@@ -289,8 +444,9 @@
           if (!packagesFile.exists) {
             packagesFile = null;
           }
+        } else {
+          packagesFile = null;
         }
-        packagesFile = null;
       }
       return <String>[pluginFile.path, packagesFile?.path];
     }
@@ -406,6 +562,14 @@
    * Handle the given [notification].
    */
   void handleNotification(Notification notification) {
+    if (notification.event == PLUGIN_NOTIFICATION_ERROR) {
+      PluginErrorParams params =
+          new PluginErrorParams.fromNotification(notification);
+      if (params.isFatal) {
+        info.stop();
+        stop();
+      }
+    }
     info.notificationManager.handlePluginNotification(info.path, notification);
   }
 
diff --git a/pkg/analysis_server/lib/src/plugin/request_converter.dart b/pkg/analysis_server/lib/src/plugin/request_converter.dart
new file mode 100644
index 0000000..8613ef9
--- /dev/null
+++ b/pkg/analysis_server/lib/src/plugin/request_converter.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/plugin/protocol/protocol.dart' as server;
+import 'package:analysis_server/src/protocol/protocol_internal.dart' as server;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
+
+/**
+ * An object used to convert between similar objects defined by both the plugin
+ * protocol and the server protocol.
+ */
+class RequestConverter {
+  plugin.AnalysisReanalyzeParams convertAnalysisReanalyzeParams(
+      server.AnalysisReanalyzeParams params) {
+    return new plugin.AnalysisReanalyzeParams(roots: params.roots);
+  }
+
+  plugin.AnalysisService convertAnalysisService(
+      server.AnalysisService service) {
+    return new plugin.AnalysisService(service.name);
+  }
+
+  plugin.AnalysisSetPriorityFilesParams convertAnalysisSetPriorityFilesParams(
+      server.AnalysisSetPriorityFilesParams params) {
+    return new plugin.AnalysisSetPriorityFilesParams(params.files);
+  }
+
+  plugin.AnalysisSetSubscriptionsParams convertAnalysisSetSubscriptionsParams(
+      server.AnalysisSetSubscriptionsParams params) {
+    Map<server.AnalysisService, List<String>> serverSubscriptions =
+        params.subscriptions;
+    Map<plugin.AnalysisService, List<String>> pluginSubscriptions =
+        <plugin.AnalysisService, List<String>>{};
+    for (server.AnalysisService service in serverSubscriptions.keys) {
+      try {
+        pluginSubscriptions[convertAnalysisService(service)] =
+            serverSubscriptions[service];
+      } catch (exception) {
+        // Ignore the exception. It indicates that the service isn't one that
+        // should be passed along to plugins.
+      }
+    }
+    return new plugin.AnalysisSetSubscriptionsParams(pluginSubscriptions);
+  }
+
+  plugin.AnalysisUpdateContentParams convertAnalysisUpdateContentParams(
+      server.AnalysisUpdateContentParams params) {
+    Map<String, dynamic> serverOverlays = params.files;
+    Map<String, dynamic> pluginOverlays = <String, dynamic>{};
+    for (String file in serverOverlays.keys) {
+      pluginOverlays[file] = convertFileOverlay(serverOverlays[file]);
+    }
+    return new plugin.AnalysisUpdateContentParams(pluginOverlays);
+  }
+
+  Object convertFileOverlay(Object overlay) {
+    if (overlay is server.AddContentOverlay) {
+      return new plugin.AddContentOverlay(overlay.content);
+    } else if (overlay is server.ChangeContentOverlay) {
+      return new plugin.ChangeContentOverlay(
+          overlay.edits.map(convertSourceEdit).toList());
+    } else if (overlay is server.RemoveContentOverlay) {
+      return new plugin.RemoveContentOverlay();
+    }
+    return null;
+  }
+
+  plugin.SourceEdit convertSourceEdit(server.SourceEdit edit) {
+    return new plugin.SourceEdit(edit.offset, edit.length, edit.replacement);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
index 6274b4a..8159c1c 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart
@@ -389,8 +389,7 @@
     // If the node's first token is a keyword or identifier, then the node is a
     // candidate entity if its first token is.
     Token beginToken = node.beginToken;
-    if (beginToken.type == TokenType.KEYWORD ||
-        beginToken.type == TokenType.IDENTIFIER) {
+    if (beginToken.type.isKeyword || beginToken.type == TokenType.IDENTIFIER) {
       return _isCandidateToken(beginToken, offset);
     }
 
@@ -413,7 +412,7 @@
     if (offset < token.end) {
       return true;
     } else if (offset == token.end) {
-      return token.type == TokenType.KEYWORD ||
+      return token.type.isKeyword ||
           token.type == TokenType.IDENTIFIER ||
           token.length == 0;
     } else if (!token.isSynthetic) {
@@ -425,8 +424,7 @@
     if (offset < previous.end) {
       return true;
     } else if (offset == previous.end) {
-      return token.type == TokenType.KEYWORD ||
-          previous.type == TokenType.IDENTIFIER;
+      return token.type.isKeyword || previous.type == TokenType.IDENTIFIER;
     } else {
       return false;
     }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index f2ed4a3..497727e 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -249,11 +249,6 @@
       'disable-new-analysis-driver';
 
   /**
-   * The name of the option used to enable fined grained invalidation.
-   */
-  static const String FINER_GRAINED_INVALIDATION = 'finer-grained-invalidation';
-
-  /**
    * The name of the option used to cause instrumentation to also be written to
    * a local file.
    */
@@ -396,8 +391,6 @@
         results[INCREMENTAL_RESOLUTION_VALIDATION];
     analysisServerOptions.enableNewAnalysisDriver =
         !results[DISABLE_NEW_ANALYSIS_DRIVER];
-    analysisServerOptions.finerGrainedInvalidation =
-        results[FINER_GRAINED_INVALIDATION];
     analysisServerOptions.noIndex = results[NO_INDEX];
     analysisServerOptions.useAnalysisHighlight2 =
         results[USE_ANALYSIS_HIGHLIGHT2];
@@ -559,10 +552,6 @@
         help: "disable using new analysis driver",
         defaultsTo: false,
         negatable: false);
-    parser.addFlag(FINER_GRAINED_INVALIDATION,
-        help: "enable finer grained invalidation",
-        defaultsTo: false,
-        negatable: false);
     parser.addOption(INSTRUMENTATION_LOG_FILE,
         help:
             "the path of the file to which instrumentation data will be written");
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 579b7b8..59fc1c0 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -14,6 +14,7 @@
 import 'package:analysis_server/src/services/correction/flutter_util.dart';
 import 'package:analysis_server/src/utilities/documentation.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
@@ -251,6 +252,7 @@
       if (appendColon) {
         completion += ': ';
       }
+      int selectionOffset = completion.length;
       if (appendComma) {
         completion += ',';
       }
@@ -258,7 +260,7 @@
           CompletionSuggestionKind.NAMED_ARGUMENT,
           DART_RELEVANCE_NAMED_PARAMETER,
           completion,
-          completion.length,
+          selectionOffset,
           0,
           false,
           false,
@@ -275,6 +277,9 @@
         sb.write('${parameter.name}: ');
         int offset = sb.length;
         sb.write(defaultValue);
+        if (appendComma) {
+          sb.write(',');
+        }
         suggestion.defaultArgumentListString = sb.toString();
         suggestion.defaultArgumentListTextRanges = [
           offset,
@@ -300,12 +305,14 @@
     // method which returns some enum with 5+ cases.
     if (_isEditingNamedArgLabel(request) || _isAppendingToArgList(request)) {
       if (requiredCount == 0 || requiredCount < _argCount(request)) {
-        _addDefaultParamSuggestions(parameters);
+        bool addTrailingComma =
+            !_isFollowedByAComma(request) && _isInFlutterCreation(request);
+        _addDefaultParamSuggestions(parameters, addTrailingComma);
       }
     } else if (_isInsertingToArgListWithNoSynthetic(request)) {
       _addDefaultParamSuggestions(parameters, true);
     } else if (_isInsertingToArgListWithSynthetic(request)) {
-      _addDefaultParamSuggestions(parameters);
+      _addDefaultParamSuggestions(parameters, !_isFollowedByAComma(request));
     }
   }
 
@@ -322,6 +329,28 @@
     return null;
   }
 
+  bool _isFollowedByAComma(DartCompletionRequest request) {
+    // new A(^); NO
+    // new A(one: 1, ^); NO
+    // new A(^ , one: 1); YES
+    // new A(^), ... NO
+
+    var containingNode = request.target.containingNode;
+    var entity = request.target.entity;
+    Token token =
+        entity is AstNode ? entity.endToken : entity is Token ? entity : null;
+    return (token != containingNode?.endToken) &&
+        token?.next?.type == TokenType.COMMA;
+  }
+
+  bool _isInFlutterCreation(DartCompletionRequest request) {
+    AstNode containingNode = request?.target?.containingNode;
+    InstanceCreationExpression newExpr = containingNode != null
+        ? identifyNewExpression(containingNode.parent)
+        : null;
+    return newExpr != null && isFlutterInstanceCreationExpression(newExpr);
+  }
+
   /**
    * If the given [comment] is not `null`, fill the [suggestion] documentation
    * fields.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 9e504c6..e8c6645 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -508,7 +508,7 @@
 
   factory ReplacementRange.compute(int requestOffset, CompletionTarget target) {
     bool isKeywordOrIdentifier(Token token) =>
-        token.type == TokenType.KEYWORD || token.type == TokenType.IDENTIFIER;
+        token.type.isKeyword || token.type == TokenType.IDENTIFIER;
 
     //TODO(danrubel) Ideally this needs to be pushed down into the contributors
     // but that implies that each suggestion can have a different
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index ee485ff..96cf40b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -182,11 +182,11 @@
           !node.directives.any((d) => d is LibraryDirective)) {
         _addSuggestions([Keyword.LIBRARY], DART_RELEVANCE_HIGH);
       }
-      _addSuggestion2('${Keyword.IMPORT.syntax} \'\';',
+      _addSuggestion2('${Keyword.IMPORT.lexeme} \'\';',
           offset: 8, relevance: DART_RELEVANCE_HIGH);
-      _addSuggestion2('${Keyword.EXPORT.syntax} \'\';',
+      _addSuggestion2('${Keyword.EXPORT.lexeme} \'\';',
           offset: 8, relevance: DART_RELEVANCE_HIGH);
-      _addSuggestion2('${Keyword.PART.syntax} \'\';',
+      _addSuggestion2('${Keyword.PART.lexeme} \'\';',
           offset: 6, relevance: DART_RELEVANCE_HIGH);
     }
     if (entity == null || entity is Declaration) {
@@ -561,7 +561,7 @@
 
   void _addSuggestion(Keyword keyword,
       [int relevance = DART_RELEVANCE_KEYWORD]) {
-    _addSuggestion2(keyword.syntax, relevance: relevance);
+    _addSuggestion2(keyword.lexeme, relevance: relevance);
   }
 
   void _addSuggestion2(String completion,
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 7a8d005..fe9b12c 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -13,7 +13,6 @@
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/error.dart' as engine;
@@ -34,6 +33,8 @@
       'SIMPLE_ENTER', "Insert a newline at the end of the current line");
   static const SIMPLE_SEMICOLON = const StatementCompletionKind(
       'SIMPLE_SEMICOLON', "Add a semicolon and newline");
+  static const COMPLETE_CONTROL_FLOW_BLOCK = const StatementCompletionKind(
+      'COMPLETE_CONTROL_FLOW_BLOCK', "Complete control flow block");
   static const COMPLETE_DO_STMT = const StatementCompletionKind(
       'COMPLETE_DO_STMT', "Complete do-statement");
   static const COMPLETE_IF_STMT = const StatementCompletionKind(
@@ -172,7 +173,17 @@
       return NO_COMPLETION;
     }
     // TODO(messick): This needs to work for declarations.
-    node = node.getAncestor((n) => n is Statement);
+    AstNode newNode = node.getAncestor((n) => n is Statement);
+    if (newNode is Block) {
+      Block blockNode = newNode;
+      if (blockNode.statements.isNotEmpty) {
+        node = blockNode.statements.last;
+      } else {
+        node = newNode;
+      }
+    } else {
+      node = newNode;
+    }
     if (_isEmptyStatement(node)) {
       node = node.parent;
     }
@@ -186,7 +197,7 @@
     }
 
     if (errors.isEmpty) {
-      if (_complete_simpleEnter()) {
+      if (_complete_controlFlowBlock() || _complete_simpleEnter()) {
         return completion;
       }
     } else {
@@ -197,8 +208,8 @@
           _complete_switchStatement() ||
           _complete_tryStatement() ||
           _complete_whileStatement() ||
-          _complete_simpleSemicolon() ||
           _complete_controlFlowBlock() ||
+          _complete_simpleSemicolon() ||
           _complete_simpleEnter()) {
         return completion;
       }
@@ -231,10 +242,14 @@
   }
 
   int _appendNewlinePlusIndent() {
+    return _appendNewlinePlusIndentAt(selectionOffset);
+  }
+
+  int _appendNewlinePlusIndentAt(int offset) {
     // Append a newline plus proper indent and another newline.
     // Return the position before the second newline.
-    String indent = utils.getLinePrefix(selectionOffset);
-    int loc = utils.getLineNext(selectionOffset);
+    String indent = utils.getLinePrefix(offset);
+    int loc = utils.getLineNext(offset);
     _addInsertEdit(loc, indent + eol);
     return loc + indent.length;
   }
@@ -248,11 +263,55 @@
   }
 
   bool _complete_controlFlowBlock() {
-    //TODO(messick) Implement _complete_controlFlowBlock
-    // Use statement completion to move the cursor to a new line outside the
-    // current block. The statement has no errors in this case. Used to jump
-    // out of do/for/if/while blocks.
-    return false;
+    Expression expr = (node is ExpressionStatement)
+        ? (node as ExpressionStatement).expression
+        : (node is ReturnStatement
+            ? (node as ReturnStatement).expression
+            : null);
+    if (!(node is ReturnStatement || expr is ThrowExpression)) {
+      return false;
+    }
+    if (node.parent is! Block) {
+      return false;
+    }
+    AstNode outer = node.parent.parent;
+    if (!(outer is DoStatement ||
+        outer is ForStatement ||
+        outer is ForEachStatement ||
+        outer is IfStatement ||
+        outer is WhileStatement)) {
+      return false;
+    }
+    int delta = 0;
+    if (errors.isNotEmpty) {
+      var error =
+          _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
+      if (error != null) {
+        int insertOffset;
+        if (expr == null || expr.isSynthetic) {
+          if (node is ReturnStatement) {
+            insertOffset = (node as ReturnStatement).returnKeyword.end;
+          } else if (node is ExpressionStatement) {
+            insertOffset =
+                ((node as ExpressionStatement).expression as ThrowExpression)
+                    .throwKeyword
+                    .end;
+          } else {
+            insertOffset = node.end; // Not reached.
+          }
+        } else {
+          insertOffset = expr.end;
+        }
+        //TODO(messick) Uncomment the following line when error location is fixed.
+        //insertOffset = error.offset + error.length;
+        _addInsertEdit(insertOffset, ';');
+        delta = 1;
+      }
+    }
+    int offset = _appendNewlinePlusIndentAt(node.parent.end);
+    exitPosition = new Position(file, offset + delta);
+    _setCompletion(DartStatementCompletion.COMPLETE_CONTROL_FLOW_BLOCK);
+    return true;
   }
 
   bool _complete_doStatement() {
@@ -540,6 +599,7 @@
     }
     var error = _findError(ParserErrorCode.EXPECTED_TOKEN, partialMatch: "';'");
     if (error != null) {
+      // TODO(messick) Fix this to find the correct place in all cases.
       int insertOffset = error.offset + error.length;
       _addInsertEdit(insertOffset, ';');
       int offset = _appendNewlinePlusIndent() + 1 /* ';' */;
@@ -583,6 +643,17 @@
       // See https://github.com/dart-lang/sdk/issues/29391
       sb.append(' ');
       _appendEmptyBraces(sb, exitPosition == null);
+    } else {
+      SwitchMember member = _findInvalidElement(switchNode.members);
+      if (member != null) {
+        if (member.colon.isSynthetic) {
+          int loc =
+              member is SwitchCase ? member.expression.end : member.keyword.end;
+          sb = new SourceBuilder(file, loc);
+          sb.append(': ');
+          exitPosition = new Position(file, loc + 2);
+        }
+      }
     }
     _insertBuilder(sb);
     _setCompletion(DartStatementCompletion.COMPLETE_SWITCH_STMT);
@@ -612,7 +683,8 @@
       _appendEmptyBraces(sb, true);
       _insertBuilder(sb);
       sb = null;
-    } else if ((catchNode = _firstInvalidCatch(tryNode.catchClauses)) != null) {
+    } else if ((catchNode = _findInvalidElement(tryNode.catchClauses)) !=
+        null) {
       if (catchNode.onKeyword != null) {
         if (catchNode.exceptionType.length == 0) {
           String src = utils.getNodeText(catchNode);
@@ -706,19 +778,12 @@
     return null;
   }
 
-  CatchClause _firstInvalidCatch(NodeList<CatchClause> list) {
-    return list.firstWhere((e) {
-      bool found = false;
-      for (var error in errors) {
-        if (error.offset >= e.offset && error.offset <= e.end) {
-          if (error.errorCode is! HintCode) {
-            found = true;
-            break;
-          }
-        }
-      }
-      return found;
-    }, orElse: () => null);
+  T _findInvalidElement<T extends AstNode>(NodeList<T> list) {
+    return list.firstWhere(
+        (catchClause) =>
+            selectionOffset >= catchClause.offset &&
+            selectionOffset <= catchClause.end,
+        orElse: () => null);
   }
 
   LinkedEditGroup _getLinkedPosition(String groupId) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 4c7c487..26054d4 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -109,8 +109,12 @@
     errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER ||
     (errorCode is LintCode &&
         (errorCode.name == LintNames.annotate_overrides ||
+            errorCode.name == LintNames.avoid_init_to_null ||
+            errorCode.name == LintNames.prefer_collection_literals ||
+            errorCode.name == LintNames.prefer_conditional_assignment ||
             errorCode.name == LintNames.unnecessary_brace_in_string_interp ||
-            errorCode.name == LintNames.avoid_init_to_null));
+            errorCode.name == LintNames.unnecessary_lambdas ||
+            errorCode.name == LintNames.unnecessary_this));
 
 /**
  * An enumeration of possible quick fix kinds.
@@ -196,8 +200,12 @@
       const FixKind('REMOVE_DEAD_CODE', 50, "Remove dead code");
   static const MAKE_FIELD_NOT_FINAL =
       const FixKind('MAKE_FIELD_NOT_FINAL', 50, "Make field '{0}' not final");
+  static const REMOVE_EMPTY_STATEMENT =
+      const FixKind('REMOVE_EMPTY_STATEMENT', 50, "Remove empty statement");
   static const REMOVE_INITIALIZER =
       const FixKind('REMOVE_INITIALIZER', 50, "Remove initializer");
+  static const REMOVE_METHOD_DECLARATION = const FixKind(
+      'REMOVE_METHOD_DECLARATION', 50, 'Remove method declaration');
   static const REMOVE_PARAMETERS_IN_GETTER_DECLARATION = const FixKind(
       'REMOVE_PARAMETERS_IN_GETTER_DECLARATION',
       50,
@@ -206,6 +214,8 @@
       'REMOVE_PARENTHESIS_IN_GETTER_INVOCATION',
       50,
       "Remove parentheses in getter invocation");
+  static const REMOVE_THIS_EXPRESSION =
+      const FixKind('REMOVE_THIS_EXPRESSION', 50, "Remove this expression");
   static const REMOVE_UNNECESSARY_CAST =
       const FixKind('REMOVE_UNNECESSARY_CAST', 50, "Remove unnecessary cast");
   static const REMOVE_UNUSED_CATCH_CLAUSE =
@@ -222,10 +232,18 @@
       'REPLACE_RETURN_TYPE_FUTURE',
       50,
       "Return 'Future' from 'async' function");
+  static const REPLACE_WITH_BRACKETS =
+      const FixKind('REPLACE_WITH_BRACKETS', 50, "Replace with { }");
+  static const REPLACE_WITH_CONDITIONAL_ASSIGNMENT = const FixKind(
+      'REPLACE_WITH_CONDITIONAL_ASSIGNMENT', 50, 'Replace with ??=');
+  static const REPLACE_WITH_LITERAL =
+      const FixKind('REPLACE_WITH_LITERAL', 50, 'Replace with literal');
   static const REPLACE_WITH_NULL_AWARE = const FixKind(
       'REPLACE_WITH_NULL_AWARE',
       50,
       "Replace the '.' with a '?.' in the invocation");
+  static const REPLACE_WITH_TEAR_OFF = const FixKind(
+      'REPLACE_WITH_TEAR_OFF', 50, "Replace function literal with tear-off");
   static const USE_CONST = const FixKind('USE_CONST', 50, "Change to constant");
   static const USE_EFFECTIVE_INTEGER_DIVISION = const FixKind(
       'USE_EFFECTIVE_INTEGER_DIVISION',
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 151201b..d2ad4b9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -22,7 +22,6 @@
 import 'package:analysis_server/src/services/correction/source_buffer.dart';
 import 'package:analysis_server/src/services/correction/source_range.dart'
     as rf;
-import 'package:analysis_server/src/services/correction/source_range.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
@@ -382,11 +381,29 @@
       if (errorCode.name == LintNames.annotate_overrides) {
         _addLintFixAddOverrideAnnotation();
       }
+      if (errorCode.name == LintNames.avoid_init_to_null) {
+        _addFix_removeInitializer();
+      }
+      if (errorCode.name == LintNames.empty_statements) {
+        _addFix_removeEmptyStatement();
+      }
+      if (errorCode.name == LintNames.prefer_collection_literals) {
+        _addFix_replaceWithLiteral();
+      }
+      if (errorCode.name == LintNames.prefer_conditional_assignment) {
+        _addFix_replaceWithConditionalAssignment();
+      }
       if (errorCode.name == LintNames.unnecessary_brace_in_string_interp) {
         _addLintRemoveInterpolationBraces();
       }
-      if (errorCode.name == LintNames.avoid_init_to_null) {
-        _addFix_removeInitializer();
+      if (errorCode.name == LintNames.unnecessary_lambdas) {
+        _addFix_replaceWithTearOff();
+      }
+      if (errorCode.name == LintNames.unnecessary_override) {
+        _addFix_removeMethodDeclaration();
+      }
+      if (errorCode.name == LintNames.unnecessary_this) {
+        _addFix_removeThisExpression();
       }
     }
     // done
@@ -680,8 +697,8 @@
           _addInsertEdit,
           _addRemoveEdit,
           _addReplaceEdit,
-          rangeStartLength,
-          rangeNode);
+          rf.rangeStartLength,
+          rf.rangeNode);
       _addFix(DartFixKind.CONVERT_FLUTTER_CHILD, []);
       return;
     }
@@ -1802,6 +1819,20 @@
     }
   }
 
+  void _addFix_removeEmptyStatement() {
+    EmptyStatement emptyStatement = node;
+    if (emptyStatement.parent is Block) {
+      _addRemoveEdit(utils.getLinesRange(rf.rangeNode(emptyStatement)));
+      _addFix(DartFixKind.REMOVE_EMPTY_STATEMENT, []);
+    } else {
+      _addReplaceEdit(
+          rf.rangeStartEnd(
+              emptyStatement.beginToken.previous.end, emptyStatement.end),
+          ' {}');
+      _addFix(DartFixKind.REPLACE_WITH_BRACKETS, []);
+    }
+  }
+
   void _addFix_removeInitializer() {
     // Retrieve the linted node.
     VariableDeclaration ancestor =
@@ -1816,6 +1847,15 @@
     _addFix(DartFixKind.REMOVE_INITIALIZER, []);
   }
 
+  void _addFix_removeMethodDeclaration() {
+    MethodDeclaration declaration =
+        node.getAncestor((node) => node is MethodDeclaration);
+    if (declaration != null) {
+      _addRemoveEdit(utils.getLinesRange(rf.rangeNode(declaration)));
+      _addFix(DartFixKind.REMOVE_METHOD_DECLARATION, []);
+    }
+  }
+
   void _addFix_removeParameters_inGetterDeclaration() {
     if (node is MethodDeclaration) {
       MethodDeclaration method = node as MethodDeclaration;
@@ -1838,6 +1878,20 @@
     }
   }
 
+  void _addFix_removeThisExpression() {
+    final thisExpression = node is ThisExpression
+        ? node
+        : node.getAncestor((node) => node is ThisExpression);
+    final parent = thisExpression.parent;
+    if (parent is PropertyAccess) {
+      _addRemoveEdit(rf.rangeStartEnd(parent.offset, parent.operator.end));
+      _addFix(DartFixKind.REMOVE_THIS_EXPRESSION, []);
+    } else if (parent is MethodInvocation) {
+      _addRemoveEdit(rf.rangeStartEnd(parent.offset, parent.operator.end));
+      _addFix(DartFixKind.REMOVE_THIS_EXPRESSION, []);
+    }
+  }
+
   void _addFix_removeUnnecessaryCast() {
     if (coveredNode is! AsExpression) {
       return;
@@ -1895,6 +1949,33 @@
     _addFix(DartFixKind.REPLACE_VAR_WITH_DYNAMIC, []);
   }
 
+  void _addFix_replaceWithConditionalAssignment() {
+    IfStatement ifStatement = node is IfStatement
+        ? node
+        : node.getAncestor((node) => node is IfStatement);
+    var thenStatement = ifStatement.thenStatement;
+    Statement uniqueStatement(Statement statement) {
+      if (statement is Block) {
+        return uniqueStatement(statement.statements.first);
+      }
+      return statement;
+    }
+
+    thenStatement = uniqueStatement(thenStatement);
+    if (thenStatement is ExpressionStatement) {
+      final expression = thenStatement.expression.unParenthesized;
+      if (expression is AssignmentExpression) {
+        final buffer = new StringBuffer();
+        buffer.write(utils.getNodeText(expression.leftHandSide));
+        buffer.write(' ??= ');
+        buffer.write(utils.getNodeText(expression.rightHandSide));
+        buffer.write(';');
+        _addReplaceEdit(rf.rangeNode(ifStatement), buffer.toString());
+        _addFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT, []);
+      }
+    }
+  }
+
   void _addFix_replaceWithConstInstanceCreation() {
     if (coveredNode is InstanceCreationExpression) {
       var instanceCreation = coveredNode as InstanceCreationExpression;
@@ -1903,6 +1984,57 @@
     }
   }
 
+  void _addFix_replaceWithLiteral() {
+    final InstanceCreationExpression instanceCreation =
+        node.getAncestor((node) => node is InstanceCreationExpression);
+    final InterfaceType type = instanceCreation.staticType;
+    final buffer = new StringBuffer();
+    final generics = instanceCreation.constructorName.type.typeArguments;
+    if (generics != null) {
+      buffer.write(utils.getNodeText(generics));
+    }
+    if (type.name == 'List') {
+      buffer.write('[]');
+    } else {
+      buffer.write('{}');
+    }
+    _addReplaceEdit(rf.rangeNode(instanceCreation), buffer.toString());
+    _addFix(DartFixKind.REPLACE_WITH_LITERAL, []);
+  }
+
+  void _addFix_replaceWithTearOff() {
+    FunctionExpression ancestor =
+        node.getAncestor((a) => a is FunctionExpression);
+    if (ancestor == null) {
+      return;
+    }
+    void addFixOfExpression(InvocationExpression expression) {
+      final buffer = new StringBuffer();
+      if (expression is MethodInvocation && expression.target != null) {
+        buffer.write(utils.getNodeText(expression.target));
+        buffer.write('.');
+      }
+      buffer.write(utils.getNodeText(expression.function));
+      _addReplaceEdit(rf.rangeNode(ancestor), buffer.toString());
+      _addFix(DartFixKind.REPLACE_WITH_TEAR_OFF, []);
+    }
+
+    final body = ancestor.body;
+    if (body is ExpressionFunctionBody) {
+      final expression = body.expression;
+      addFixOfExpression(expression.unParenthesized);
+    } else if (body is BlockFunctionBody) {
+      final statement = body.block.statements.first;
+      if (statement is ExpressionStatement) {
+        final expression = statement.expression;
+        addFixOfExpression(expression.unParenthesized);
+      } else if (statement is ReturnStatement) {
+        final expression = statement.expression;
+        addFixOfExpression(expression.unParenthesized);
+      }
+    }
+  }
+
   void _addFix_undefinedClass_useSimilar() {
     AstNode node = this.node;
     // Prepare the optional import prefix name.
@@ -3050,8 +3182,15 @@
 class LintNames {
   static const String annotate_overrides = 'annotate_overrides';
   static const String avoid_init_to_null = 'avoid_init_to_null';
+  static const String empty_statements = 'empty_statements';
+  static const String prefer_collection_literals = 'prefer_collection_literals';
+  static const String prefer_conditional_assignment =
+      'prefer_conditional_assignment';
   static const String unnecessary_brace_in_string_interp =
       'unnecessary_brace_in_string_interp';
+  static const String unnecessary_lambdas = 'unnecessary_lambdas';
+  static const String unnecessary_override = 'unnecessary_override';
+  static const String unnecessary_this = 'unnecessary_this';
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 1957ba1..477c7f3 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -531,7 +531,6 @@
         results.add(LIBRARY_ERRORS_READY);
         results.add(PARSE_ERRORS);
         results.add(PARSED_UNIT);
-        results.add(REFERENCED_NAMES);
         results.add(SCAN_ERRORS);
         results.add(SOURCE_KIND);
         results.add(TOKEN_STREAM);
diff --git a/pkg/analysis_server/lib/src/status/validator.dart b/pkg/analysis_server/lib/src/status/validator.dart
index f25f8bf..b3f1be5 100644
--- a/pkg/analysis_server/lib/src/status/validator.dart
+++ b/pkg/analysis_server/lib/src/status/validator.dart
@@ -1509,8 +1509,6 @@
       return _compareLibrarySpecificUnits(expected, actual, buffer);
     } else if (actual is LineInfo) {
       return _compareLineInfos(expected, actual, buffer);
-    } else if (actual is ReferencedNames) {
-      return _compareReferencedNames(expected, actual, buffer);
     } else if (actual is Source) {
       return _compareSources(expected, actual, buffer);
     } else if (actual is SourceKind) {
@@ -1546,116 +1544,6 @@
     return false;
   }
 
-  bool _compareReferencedNames(
-      ReferencedNames expected, ReferencedNames actual, StringBuffer buffer) {
-    Set<String> expectedNames = expected.names;
-    Map<String, Set<String>> expectedUserToDependsOn = expected.userToDependsOn;
-    Set<String> expectedKeys = expectedUserToDependsOn.keys.toSet();
-
-    Set<String> actualNames = actual.names;
-    Map<String, Set<String>> actualUserToDependsOn = actual.userToDependsOn;
-    Set<String> actualKeys = actualUserToDependsOn.keys.toSet();
-
-    Set<String> missingNames = expectedNames.difference(actualNames);
-    Set<String> extraNames = actualNames.difference(expectedNames);
-    Set<String> missingKeys = expectedKeys.difference(actualKeys);
-    Set<String> extraKeys = actualKeys.difference(expectedKeys);
-    Map<String, List<Set<String>>> mismatchedDependencies =
-        new HashMap<String, List<Set<String>>>();
-    Set<String> commonKeys = expectedKeys.intersection(actualKeys);
-    for (String key in commonKeys) {
-      Set<String> expectedDependencies = expectedUserToDependsOn[key];
-      Set<String> actualDependencies = actualUserToDependsOn[key];
-      Set<String> missingDependencies =
-          expectedDependencies.difference(actualDependencies);
-      Set<String> extraDependencies =
-          actualDependencies.difference(expectedDependencies);
-      if (missingDependencies.isNotEmpty || extraDependencies.isNotEmpty) {
-        mismatchedDependencies[key] = [missingDependencies, extraDependencies];
-      }
-    }
-
-    if (missingNames.isEmpty &&
-        extraNames.isEmpty &&
-        missingKeys.isEmpty &&
-        extraKeys.isEmpty &&
-        mismatchedDependencies.isEmpty) {
-      return true;
-    }
-    if (buffer != null) {
-      void write(String title, Set<String> names) {
-        buffer.write(names.length);
-        buffer.write(' ');
-        buffer.write(title);
-        buffer.write(': {');
-        bool first = true;
-        for (String name in names) {
-          if (first) {
-            first = false;
-          } else {
-            buffer.write(', ');
-          }
-          buffer.write(name);
-        }
-        buffer.write('}');
-      }
-
-      bool needsNewline = false;
-      if (missingNames.isNotEmpty) {
-        buffer.write('Has ');
-        write('missing names', missingNames);
-        needsNewline = true;
-      }
-      if (extraNames.isNotEmpty) {
-        if (needsNewline) {
-          buffer.write('</p><p>');
-        }
-        buffer.write('Has ');
-        write('extra names', extraNames);
-        needsNewline = true;
-      }
-      if (missingKeys.isNotEmpty) {
-        if (needsNewline) {
-          buffer.write('</p><p>');
-        }
-        buffer.write('Has ');
-        write('missing keys', missingKeys);
-        needsNewline = true;
-      }
-      if (extraKeys.isNotEmpty) {
-        if (needsNewline) {
-          buffer.write('</p><p>');
-        }
-        buffer.write('Has ');
-        write('extra keys', extraKeys);
-        needsNewline = true;
-      }
-      mismatchedDependencies.forEach((String key, List<Set<String>> value) {
-        Set<String> missingDependencies = value[0];
-        Set<String> extraDependencies = value[1];
-        if (needsNewline) {
-          buffer.write('</p><p>');
-        }
-        buffer.write('The key ');
-        buffer.write(key);
-        buffer.write(' has ');
-        bool needsConjunction = false;
-        if (missingNames.isNotEmpty) {
-          write('missing dependencies', missingDependencies);
-          needsConjunction = true;
-        }
-        if (extraNames.isNotEmpty) {
-          if (needsConjunction) {
-            buffer.write(' and ');
-          }
-          write('extra dependencies', extraDependencies);
-        }
-        needsNewline = true;
-      });
-    }
-    return true;
-  }
-
   bool _compareSources(Source expected, Source actual, StringBuffer buffer) {
     if (actual.fullName == expected.fullName) {
       return true;
diff --git a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
index 49378d1..176cec5 100644
--- a/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
+++ b/pkg/analysis_server/lib/src/utilities/change_builder_dart.dart
@@ -103,7 +103,7 @@
     // TODO(brianwilkerson) Add support for type parameters, probably as a
     // parameterWriter parameter.
     if (isAbstract) {
-      write(Keyword.ABSTRACT.syntax);
+      write(Keyword.ABSTRACT.lexeme);
       write(' ');
     }
     write('class ');
@@ -139,7 +139,7 @@
       List<String> fieldNames,
       bool isConst: false}) {
     if (isConst) {
-      write(Keyword.CONST.syntax);
+      write(Keyword.CONST.lexeme);
       write(' ');
     }
     write(className);
@@ -178,21 +178,21 @@
       DartType type,
       String typeGroupName}) {
     if (isStatic) {
-      write(Keyword.STATIC.syntax);
+      write(Keyword.STATIC.lexeme);
       write(' ');
     }
     bool typeRequired = true;
     if (isConst) {
-      write(Keyword.CONST.syntax);
+      write(Keyword.CONST.lexeme);
       typeRequired = false;
     } else if (isFinal) {
-      write(Keyword.FINAL.syntax);
+      write(Keyword.FINAL.lexeme);
       typeRequired = false;
     }
     if (type != null) {
       writeType(type, groupName: typeGroupName, required: true);
     } else if (typeRequired) {
-      write(Keyword.VAR.syntax);
+      write(Keyword.VAR.lexeme);
     }
     write(' ');
     if (nameGroupName != null) {
@@ -218,7 +218,7 @@
       DartType returnType,
       String returnTypeGroupName}) {
     if (isStatic) {
-      write(Keyword.STATIC.syntax);
+      write(Keyword.STATIC.lexeme);
       write(' ');
     }
     if (returnType != null) {
@@ -257,14 +257,14 @@
       DartType returnType,
       String returnTypeGroupName}) {
     if (isStatic) {
-      write(Keyword.STATIC.syntax);
+      write(Keyword.STATIC.lexeme);
       write(' ');
     }
     if (returnType != null && !returnType.isDynamic) {
       writeType(returnType, groupName: returnTypeGroupName);
       write(' ');
     }
-    write(Keyword.GET.syntax);
+    write(Keyword.GET.lexeme);
     write(' ');
     if (nameGroupName != null) {
       addLinkedEdit(nameGroupName, (LinkedEditBuilder builder) {
@@ -291,10 +291,10 @@
       String typeGroupName}) {
     bool typeRequired = true;
     if (isConst) {
-      write(Keyword.CONST.syntax);
+      write(Keyword.CONST.lexeme);
       typeRequired = false;
     } else if (isFinal) {
-      write(Keyword.FINAL.syntax);
+      write(Keyword.FINAL.lexeme);
       typeRequired = false;
     }
     if (type != null) {
@@ -304,7 +304,7 @@
       }
       writeType(type, groupName: typeGroupName);
     } else if (typeRequired) {
-      write(Keyword.VAR.syntax);
+      write(Keyword.VAR.lexeme);
     }
     write(' ');
     if (nameGroupName != null) {
@@ -346,13 +346,13 @@
         writeType(member.type.returnType, groupName: returnTypeGroupName);
     write(' ');
     if (isGetter) {
-      write(Keyword.GET.syntax);
+      write(Keyword.GET.lexeme);
       write(' ');
     } else if (isSetter) {
-      write(Keyword.SET.syntax);
+      write(Keyword.SET.lexeme);
       write(' ');
     } else if (isOperator) {
-      write(Keyword.OPERATOR.syntax);
+      write(Keyword.OPERATOR.lexeme);
       write(' ');
     }
     // name
@@ -501,7 +501,7 @@
       }
     }
     if (required) {
-      write(Keyword.VAR.syntax);
+      write(Keyword.VAR.lexeme);
       return true;
     }
     return false;
diff --git a/pkg/analysis_server/test/analysis/reanalyze_test.dart b/pkg/analysis_server/test/analysis/reanalyze_test.dart
index a6cbb89..d644abc 100644
--- a/pkg/analysis_server/test/analysis/reanalyze_test.dart
+++ b/pkg/analysis_server/test/analysis/reanalyze_test.dart
@@ -72,4 +72,13 @@
       expect(errors, hasLength(1));
     }
   }
+
+  test_sentToPlugins() async {
+    createProject();
+    await waitForTasksFinished();
+    Request request = new Request("0", ANALYSIS_REANALYZE);
+    handleSuccessfulRequest(request);
+    // verify
+    expect(pluginManager.broadcastedRequest, isNotNull);
+  }
 }
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index 5a870cc..28a0629 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/src/generated/engine.dart'
     show InternalAnalysisContext;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -126,6 +127,20 @@
     expect(response.error.code, RequestErrorCode.UNANALYZED_PRIORITY_FILES);
   }
 
+  test_sentToPlugins() async {
+    addTestFile('');
+    // wait for analysis to ensure that the file is known to the context
+    await server.onAnalysisComplete;
+    // set priority files
+    Response response = await _setPriorityFile(testFile);
+    expect(response, isResponseSuccess('0'));
+    // verify
+    plugin.AnalysisSetPriorityFilesParams params =
+        pluginManager.analysisSetPriorityFilesParams;
+    expect(params, isNotNull);
+    expect(params.files, <String>[testFile]);
+  }
+
   _setPriorityFile(String file) async {
     Request request =
         new AnalysisSetPriorityFilesParams(<String>[file]).toRequest('0');
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index 005528e..8c73c90 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:typed_mock/typed_mock.dart';
@@ -269,6 +270,55 @@
     expect(filesErrors, isNotEmpty);
   }
 
+  test_sentToPlugins() {
+    String filePath = '/project/target.dart';
+    String fileContent = 'import "none.dart";';
+    //
+    // Add
+    //
+    handleSuccessfulRequest(new AnalysisUpdateContentParams(
+            <String, dynamic>{filePath: new AddContentOverlay(fileContent)})
+        .toRequest('0'));
+    plugin.AnalysisUpdateContentParams params =
+        pluginManager.analysisUpdateContentParams;
+    expect(params, isNotNull);
+    Map<String, dynamic> files = params.files;
+    expect(files, hasLength(1));
+    Object overlay = files[filePath];
+    expect(overlay, new isInstanceOf<plugin.AddContentOverlay>());
+    plugin.AddContentOverlay addOverlay = overlay;
+    expect(addOverlay.content, fileContent);
+    //
+    // Change
+    //
+    pluginManager.analysisUpdateContentParams = null;
+    handleSuccessfulRequest(new AnalysisUpdateContentParams(<String, dynamic>{
+      filePath: new ChangeContentOverlay(
+          <SourceEdit>[new SourceEdit(8, 1, "'"), new SourceEdit(18, 1, "'")])
+    }).toRequest('1'));
+    params = pluginManager.analysisUpdateContentParams;
+    expect(params, isNotNull);
+    files = params.files;
+    expect(files, hasLength(1));
+    overlay = files[filePath];
+    expect(overlay, new isInstanceOf<plugin.ChangeContentOverlay>());
+    plugin.ChangeContentOverlay changeOverlay = overlay;
+    expect(changeOverlay.edits, hasLength(2));
+    //
+    // Remove
+    //
+    pluginManager.analysisUpdateContentParams = null;
+    handleSuccessfulRequest(new AnalysisUpdateContentParams(
+            <String, dynamic>{filePath: new RemoveContentOverlay()})
+        .toRequest('2'));
+    params = pluginManager.analysisUpdateContentParams;
+    expect(params, isNotNull);
+    files = params.files;
+    expect(files, hasLength(1));
+    overlay = files[filePath];
+    expect(overlay, new isInstanceOf<plugin.RemoveContentOverlay>());
+  }
+
   CompilationUnit _getTestUnit() {
     ContextSourcePair pair = server.getContextSourcePair(testFile);
     AnalysisContext context = pair.context;
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index d0c918d..66850f0 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -22,10 +22,12 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
 import 'package:plugin/manager.dart';
 import 'package:plugin/plugin.dart';
 import 'package:test/test.dart';
+import 'package:watcher/watcher.dart';
 
 import 'mock_sdk.dart';
 import 'mocks.dart';
@@ -270,6 +272,10 @@
  * hard-coding the responses.
  */
 class TestPluginManager implements PluginManager {
+  plugin.AnalysisSetPriorityFilesParams analysisSetPriorityFilesParams;
+  plugin.AnalysisSetSubscriptionsParams analysisSetSubscriptionsParams;
+  plugin.AnalysisUpdateContentParams analysisUpdateContentParams;
+  plugin.RequestParams broadcastedRequest;
   Map<PluginInfo, Future<plugin.Response>> broadcastResults;
 
   @override
@@ -304,12 +310,20 @@
   }
 
   @override
-  Map<PluginInfo, Future<plugin.Response>> broadcast(
-      analyzer.ContextRoot contextRoot, plugin.RequestParams params) {
+  Map<PluginInfo, Future<plugin.Response>> broadcastRequest(
+      plugin.RequestParams params,
+      {analyzer.ContextRoot contextRoot}) {
+    broadcastedRequest = params;
     return broadcastResults ?? <PluginInfo, Future<plugin.Response>>{};
   }
 
   @override
+  Future<List<Future<plugin.Response>>> broadcastWatchEvent(
+      WatchEvent watchEvent) async {
+    return <Future<plugin.Response>>[];
+  }
+
+  @override
   List<PluginInfo> pluginsForContextRoot(analyzer.ContextRoot contextRoot) {
     fail('Unexpected invocation of pluginsForContextRoot');
     return null;
@@ -321,6 +335,24 @@
   }
 
   @override
+  void setAnalysisSetPriorityFilesParams(
+      plugin.AnalysisSetPriorityFilesParams params) {
+    analysisSetPriorityFilesParams = params;
+  }
+
+  @override
+  void setAnalysisSetSubscriptionsParams(
+      plugin.AnalysisSetSubscriptionsParams params) {
+    analysisSetSubscriptionsParams = params;
+  }
+
+  @override
+  void setAnalysisUpdateContentParams(
+      plugin.AnalysisUpdateContentParams params) {
+    analysisUpdateContentParams = params;
+  }
+
+  @override
   Future<List<Null>> stopAll() async {
     fail('Unexpected invocation of stopAll');
     return null;
diff --git a/pkg/analysis_server/test/context_manager_driver_test.dart b/pkg/analysis_server/test/context_manager_driver_test.dart
index 4930908..44f37a0 100644
--- a/pkg/analysis_server/test/context_manager_driver_test.dart
+++ b/pkg/analysis_server/test/context_manager_driver_test.dart
@@ -64,7 +64,7 @@
 
   @failingTest
   test_path_filter_analysis_option() async {
-    // This fails because we're not analyzing the analyis options file.
+    // This fails because we're not analyzing the analysis options file.
     return super.test_path_filter_analysis_option();
   }
 }
@@ -100,7 +100,7 @@
 
   @failingTest
   test_path_filter_analysis_option() async {
-    // This fails because we're not analyzing the analyis options file.
+    // This fails because we're not analyzing the analysis options file.
     return super.test_path_filter_analysis_option();
   }
 }
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index c928026..96db4e2 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -4,6 +4,7 @@
 
 library test.context.directory.manager;
 
+import 'dart:async';
 import 'dart:collection';
 
 import 'package:analysis_server/src/context_manager.dart';
@@ -33,6 +34,7 @@
 import 'package:plugin/plugin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:watcher/watcher.dart';
 
 import 'mock_sdk.dart';
 import 'mocks.dart';
@@ -2598,6 +2600,14 @@
     // Verify that analysis options was parsed and strong-mode set.
     expect(analysisOptions.strongMode, true);
   }
+
+  test_watchEvents() async {
+    String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    newFile([libPath, 'main.dart']);
+    await new Future.delayed(new Duration(milliseconds: 1));
+    expect(callbacks.watchEvents, hasLength(1));
+  }
 }
 
 class TestContextManagerCallbacks extends ContextManagerCallbacks {
@@ -2664,6 +2674,11 @@
    */
   List<String> lastFlushedFiles;
 
+  /**
+   * The watch events that have been broadcast.
+   */
+  List<WatchEvent> watchEvents = <WatchEvent>[];
+
   TestContextManagerCallbacks(
       this.resourceProvider, this.sdkManager, this.logger, this.scheduler);
 
@@ -2802,6 +2817,11 @@
   }
 
   @override
+  void broadcastWatchEvent(WatchEvent event) {
+    watchEvents.add(event);
+  }
+
+  @override
   void computingPackageMap(bool computing) {
     // Do nothing.
   }
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 24c5788..f0e7c9c 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:plugin/manager.dart';
 import 'package:plugin/plugin.dart';
 import 'package:test/test.dart';
@@ -798,4 +799,21 @@
     await waitForTasksFinished();
     expect(filesHighlights[testFile], isNotEmpty);
   }
+
+  test_sentToPlugins() async {
+    addTestFile('int V = 42;');
+    createProject();
+    // subscribe
+    addAnalysisSubscription(AnalysisService.HIGHLIGHTS, testFile);
+    // wait for analysis
+    await waitForTasksFinished();
+    plugin.AnalysisSetSubscriptionsParams params =
+        pluginManager.analysisSetSubscriptionsParams;
+    expect(params, isNotNull);
+    Map<plugin.AnalysisService, List<String>> subscriptions =
+        params.subscriptions;
+    expect(subscriptions, hasLength(1));
+    List<String> files = subscriptions[plugin.AnalysisService.HIGHLIGHTS];
+    expect(files, [testFile]);
+  }
 }
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 31d853b..73b6aec 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -8,10 +8,14 @@
 
 import 'package:analysis_server/plugin/protocol/protocol.dart';
 import 'package:analysis_server/src/domain_completion.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
+import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -28,6 +32,12 @@
 
 @reflectiveTest
 class CompletionDomainHandlerTest extends AbstractCompletionDomainTest {
+  @override
+  void setUp() {
+    enableNewAnalysisDriver = true;
+    super.setUp();
+  }
+
   test_ArgumentList_constructor_named_param_label() async {
     addTestFile('main() { new A(^);}'
         'class A { A({one, two}) {} }');
@@ -169,7 +179,11 @@
     expect(suggestions, hasLength(2));
   }
 
+  @failingTest
   test_html() {
+    //
+    // We no longer support the analysis of non-dart files.
+    //
     testFile = '/project/web/test.html';
     addTestFile('''
       <html>^</html>
@@ -209,7 +223,12 @@
     });
   }
 
+  @failingTest
   test_imports_aborted_new_request() async {
+    // TODO(brianwilkerson) Figure out whether this test makes sense when
+    // running the new driver. It waits for an initial empty notification then
+    // waits for a new notification. But I think that under the driver we only
+    // ever send one notification.
     addTestFile('''
         class foo { }
         c^''');
@@ -247,7 +266,12 @@
         relevance: DART_RELEVANCE_HIGH);
   }
 
+  @failingTest
   test_imports_aborted_source_changed() async {
+    // TODO(brianwilkerson) Figure out whether this test makes sense when
+    // running the new driver. It waits for an initial empty notification then
+    // waits for a new notification. But I think that under the driver we only
+    // ever send one notification.
     addTestFile('''
         class foo { }
         c^''');
@@ -626,6 +650,33 @@
     });
   }
 
+  test_sentToPlugins() async {
+    addTestFile('''
+      void main() {
+        ^
+      }
+    ''');
+    PluginInfo info = new PluginInfo('a', 'b', 'c', null, null);
+    plugin.CompletionGetSuggestionsResult result =
+        new plugin.CompletionGetSuggestionsResult(
+            1, 2, <plugin.CompletionSuggestion>[
+      new plugin.CompletionSuggestion(
+          plugin.CompletionSuggestionKind.IDENTIFIER,
+          DART_RELEVANCE_DEFAULT,
+          'plugin completion',
+          3,
+          0,
+          false,
+          false)
+    ]);
+    pluginManager.broadcastResults = <PluginInfo, Future<plugin.Response>>{
+      info: new Future.value(result.toResponse('-'))
+    };
+    await getSuggestions();
+    assertHasResult(CompletionSuggestionKind.IDENTIFIER, 'plugin completion',
+        selectionOffset: 3);
+  }
+
   test_simple() {
     addTestFile('''
       void main() {
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index ab40d91..82b6b79 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -200,6 +200,7 @@
 library dart.collection;
 
 abstract class HashMap<K, V> implements Map<K, V> {}
+abstract class LinkedHashMap<K, V> implements Map<K, V> {}
 ''');
 
   static const MockSdkLibrary LIB_CONVERT = const MockSdkLibrary(
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index b06ac9e..31f5725 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -32,6 +32,20 @@
     }
   }
 
+  /**
+   * Assert that there is a suggestion with the given parameter [name] that has
+   * the given [completion], [selectionOffset] and [selectionLength].
+   */
+  void assertSuggestArgumentAndCompletion(String name,
+      {String completion, int selectionOffset, int selectionLength: 0}) {
+    CompletionSuggestion suggestion =
+        suggestions.firstWhere((s) => s.parameterName == name);
+    expect(suggestion, isNotNull);
+    expect(suggestion.completion, completion);
+    expect(suggestion.selectionOffset, selectionOffset);
+    expect(suggestion.selectionLength, selectionLength);
+  }
+
   void assertSuggestArgumentList(
       List<String> paramNames, List<String> paramTypes) {
     // DEPRECATED... argument lists are no longer suggested.
@@ -84,15 +98,23 @@
    * the only suggestions.
    */
   void assertSuggestArgumentsAndTypes(
-      {Map<String, String> namedArgumentsWithTypes, bool includeColon: true}) {
+      {Map<String, String> namedArgumentsWithTypes,
+      bool includeColon: true,
+      bool includeComma: false}) {
     List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
     namedArgumentsWithTypes.forEach((String name, String type) {
       String completion = includeColon ? '$name: ' : name;
+      // Selection should be before any trailing commas.
+      int selectionOffset = completion.length;
+      if (includeComma) {
+        completion = '$completion,';
+      }
       expected.add(assertSuggest(completion,
           csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
           relevance: DART_RELEVANCE_NAMED_PARAMETER,
           paramName: name,
-          paramType: type));
+          paramType: type,
+          selectionOffset: selectionOffset));
     });
     assertNoOtherSuggestions(expected);
   }
@@ -103,9 +125,13 @@
   void assertSuggestions(List<String> suggestions) {
     List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
     for (String suggestion in suggestions) {
+      // Selection offset should be before any trailing commas.
+      int selectionOffset =
+          suggestion.endsWith(',') ? suggestion.length - 1 : suggestion.length;
       expected.add(assertSuggest('$suggestion',
           csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
-          relevance: DART_RELEVANCE_NAMED_PARAMETER));
+          relevance: DART_RELEVANCE_NAMED_PARAMETER,
+          selectionOffset: selectionOffset));
     }
     assertNoOtherSuggestions(expected);
   }
@@ -543,11 +569,76 @@
 class A { A({int one, String two: 'defaultValue'}) { } }
 main() { new A(^);}''');
     await computeSuggestions();
+
     assertSuggestArgumentsAndTypes(
         namedArgumentsWithTypes: {'one': 'int', 'two': 'String'});
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
   }
 
-  test_ArgumentList_local_constructor_named_param2() async {
+  test_ArgumentList_local_constructor_named_param_1() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(o^);}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(
+        namedArgumentsWithTypes: {'one': 'int', 'two': 'String'});
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_2() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(^o,);}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(
+        namedArgumentsWithTypes: {'one': 'int', 'two': 'String'});
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_3() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(two: 'foo', ^);}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {'one': 'int'});
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_4() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(two: 'foo', o^);}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {'one': 'int'});
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_5() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(two: 'foo', o^,);}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {'one': 'int'});
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_6() async {
     //
     addTestSource('''
 class A { A.foo({int one, String two: 'defaultValue'}) { } }
@@ -557,6 +648,58 @@
         namedArgumentsWithTypes: {'one': 'int', 'two': 'String'});
   }
 
+  test_ArgumentList_local_constructor_named_param_prefixed_prepend() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(o^ two: 'foo');}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(
+        namedArgumentsWithTypes: {'one': 'int'}, includeComma: true);
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ,', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_prepend() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(^ two: 'foo');}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(
+        namedArgumentsWithTypes: {'one': 'int'}, includeComma: true);
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ,', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_prepend_1() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(o^, two: 'foo');}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(
+        namedArgumentsWithTypes: {'one': 'int'}, includeComma: false);
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
+  test_ArgumentList_local_constructor_named_param_prepend_2() async {
+    //
+    addTestSource('''
+class A { A({int one, String two: 'defaultValue'}) { } }
+main() { new A(^, two: 'foo');}''');
+    await computeSuggestions();
+
+    assertSuggestArgumentsAndTypes(
+        namedArgumentsWithTypes: {'one': 'int'}, includeComma: false);
+    assertSuggestArgumentAndCompletion('one',
+        completion: 'one: ', selectionOffset: 5);
+  }
+
   test_ArgumentList_local_function_1() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('''
@@ -725,6 +868,103 @@
   @override
   bool get enableNewAnalysisDriver => true;
 
+  test_ArgumentList_Flutter_InstanceCreationExpression_0() async {
+    configureFlutterPkg({
+      'src/widgets/framework.dart': flutter_framework_code,
+    });
+
+    addTestSource('''
+import 'package:flutter/src/widgets/framework.dart';
+
+build() => new Row(
+    key: null,
+    ^
+  );
+''');
+
+    // Don't generate children boilerplate.
+    await computeSuggestions();
+
+    assertSuggest('children: ,',
+        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+        relevance: DART_RELEVANCE_NAMED_PARAMETER,
+        defaultArgListString: null, // No default values.
+        selectionOffset: 10);
+  }
+
+  test_ArgumentList_Flutter_InstanceCreationExpression_01() async {
+    configureFlutterPkg({
+      'src/widgets/framework.dart': flutter_framework_code,
+    });
+
+    addTestSource('''
+import 'package:flutter/src/widgets/framework.dart';
+
+  build() => new Scaffold(
+        appBar: new AppBar(
+          ^
+        ),
+  );
+''');
+
+    // Don't generate children boilerplate.
+    await computeSuggestions();
+
+    assertSuggest('color: ,',
+        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+        relevance: DART_RELEVANCE_NAMED_PARAMETER,
+        defaultArgListString: null, // No default values.
+        selectionOffset: 7);
+  }
+
+  test_ArgumentList_Flutter_InstanceCreationExpression_1() async {
+    configureFlutterPkg({
+      'src/widgets/framework.dart': flutter_framework_code,
+    });
+
+    addTestSource('''
+import 'package:flutter/src/widgets/framework.dart';
+
+build() => new Row(
+    key: null,
+    ^
+  );
+''');
+
+    await computeSuggestions(options: generateChildrenBoilerPlate);
+
+    assertSuggest('children: ,',
+        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+        relevance: DART_RELEVANCE_NAMED_PARAMETER,
+        defaultArgListString: 'children: <Widget>[],',
+        selectionOffset: 10,
+        defaultArgumentListTextRanges: [10, 10]);
+  }
+
+  test_ArgumentList_Flutter_InstanceCreationExpression_2() async {
+    configureFlutterPkg({
+      'src/widgets/framework.dart': flutter_framework_code,
+    });
+
+    addTestSource('''
+import 'package:flutter/src/widgets/framework.dart';
+
+build() => new Row(
+    ^
+    key: null,
+  );
+''');
+
+    await computeSuggestions(options: generateChildrenBoilerPlate);
+
+    assertSuggest('children: ,',
+        csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+        relevance: DART_RELEVANCE_NAMED_PARAMETER,
+        defaultArgListString: 'children: <Widget>[],',
+        selectionOffset: 10,
+        defaultArgumentListTextRanges: [10, 10]);
+  }
+
   test_ArgumentList_Flutter_InstanceCreationExpression_children() async {
     configureFlutterPkg({
       'src/widgets/framework.dart': flutter_framework_code,
@@ -740,10 +980,11 @@
 
     await computeSuggestions(options: generateChildrenBoilerPlate);
 
-    assertSuggest('children: ',
+    assertSuggest('children: ,',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
-        defaultArgListString: 'children: <Widget>[]',
+        defaultArgListString: 'children: <Widget>[],',
+        selectionOffset: 10,
         defaultArgumentListTextRanges: [10, 10]);
   }
 
@@ -765,10 +1006,11 @@
 
     await computeSuggestions(options: generateChildrenBoilerPlate);
 
-    assertSuggest('children: ',
+    assertSuggest('children: ,',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
-        defaultArgListString: 'children: []');
+        selectionOffset: 10,
+        defaultArgListString: 'children: [],');
   }
 
   test_ArgumentList_Flutter_InstanceCreationExpression_children_Map() async {
@@ -788,9 +1030,10 @@
 
     await computeSuggestions(options: generateChildrenBoilerPlate);
 
-    assertSuggest('children: ',
+    assertSuggest('children: ,',
         csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
         relevance: DART_RELEVANCE_NAMED_PARAMETER,
+        selectionOffset: 10,
         defaultArgListString: null);
   }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 67baee0..9f75662 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -118,6 +118,7 @@
       bool isPotential: false,
       String elemFile,
       int elemOffset,
+      int selectionOffset,
       String paramName,
       String paramType,
       String defaultArgListString: _UNCHECKED,
@@ -134,7 +135,7 @@
       expect(cs.relevance, equals(relevance), reason: completion);
     }
     expect(cs.importUri, importUri);
-    expect(cs.selectionOffset, equals(completion.length));
+    expect(cs.selectionOffset, equals(selectionOffset ?? completion.length));
     expect(cs.selectionLength, equals(0));
     expect(cs.isDeprecated, equals(isDeprecated));
     expect(cs.isPotential, equals(isPotential));
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index c9462d3..9490d0e 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -220,7 +220,7 @@
     Set<String> expectedCompletions = new Set<String>();
     Map<String, int> expectedOffsets = <String, int>{};
     Set<String> actualCompletions = new Set<String>();
-    expectedCompletions.addAll(expectedKeywords.map((k) => k.syntax));
+    expectedCompletions.addAll(expectedKeywords.map((k) => k.lexeme));
     ['import', 'export', 'part'].forEach((s) {
       if (expectedCompletions.contains(s)) {
         expectedCompletions.remove(s);
@@ -251,11 +251,11 @@
     }
     for (CompletionSuggestion s in suggestions) {
       if (s.kind == CompletionSuggestionKind.KEYWORD) {
-        if (s.completion.startsWith(Keyword.IMPORT.syntax)) {
+        if (s.completion.startsWith(Keyword.IMPORT.lexeme)) {
           int importRelevance = relevance;
           expect(s.relevance, equals(importRelevance), reason: s.completion);
         } else {
-          if (s.completion == Keyword.RETHROW.syntax) {
+          if (s.completion == Keyword.RETHROW.lexeme) {
             expect(s.relevance, equals(relevance - 1), reason: s.completion);
           } else {
             expect(s.relevance, equals(relevance), reason: s.completion);
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index 3d4750e..d953db9 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -14,6 +14,7 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(_ControlFlowCompletionTest);
     defineReflectiveTests(_DoCompletionTest);
     defineReflectiveTests(_ForCompletionTest);
     defineReflectiveTests(_ForEachCompletionTest);
@@ -93,6 +94,177 @@
 }
 
 @reflectiveTest
+class _ControlFlowCompletionTest extends StatementCompletionTest {
+  test_doReturnExprLineComment() async {
+    await _prepareCompletion(
+        'return 3',
+        '''
+ex(e) {
+  do {
+    return 3//
+  } while (true);
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  do {
+    return 3;//
+  } while (true);
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+
+  test_doReturnUnterminated() async {
+    await _prepareCompletion(
+        'return',
+        '''
+ex(e) {
+  do {
+    return
+  } while (true);
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  do {
+    return;
+  } while (true);
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+
+  test_forEachReturn() async {
+    await _prepareCompletion(
+        'return;',
+        '''
+ex(e) {
+  for (var x in e) {
+    return;
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  for (var x in e) {
+    return;
+  }
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+
+  test_forThrowUnterminated() async {
+    await _prepareCompletion(
+        'throw e',
+        '''
+ex(e) {
+  for (int i = 0; i < 3; i++) {
+    throw e
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  for (int i = 0; i < 3; i++) {
+    throw e;
+  }
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+
+  test_ifThrow() async {
+    await _prepareCompletion(
+        'throw e;',
+        '''
+ex(e) {
+  if (true) {
+    throw e;
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  if (true) {
+    throw e;
+  }
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+
+  test_ifThrowUnterminated() async {
+    await _prepareCompletion(
+        'throw e',
+        '''
+ex(e) {
+  if (true) {
+    throw e
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  if (true) {
+    throw e;
+  }
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+
+  test_whileReturnExpr() async {
+    await _prepareCompletion(
+        '+ 4',
+        '''
+ex(e) {
+  while (true) {
+    return 3 + 4
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete control flow block',
+        '''
+ex(e) {
+  while (true) {
+    return 3 + 4;
+  }
+  ////
+}
+''',
+        (s) => _afterLast(s, '  '));
+  }
+}
+
+@reflectiveTest
 class _DoCompletionTest extends StatementCompletionTest {
   test_emptyCondition() async {
     await _prepareCompletion(
@@ -420,11 +592,7 @@
 @reflectiveTest
 class _IfCompletionTest extends StatementCompletionTest {
   test_afterCondition_BAD() async {
-    // TODO(messick): Fix the code to make this like test_completeIfWithCondition.
-    // Recap: Finding the node at the selectionOffset returns the block, not the
-    // if-statement. Need to understand if that only happens when the if-statement
-    // is the only statement in the block, or perhaps first or last? And what
-    // happens when it is in the middle of other statements?
+    // TODO(messick) Stop inserting the space after the closing brace.
     await _prepareCompletion(
         'if (true) ', // Trigger completion after space.
         '''
@@ -434,15 +602,15 @@
 ''',
         atEnd: true);
     _assertHasChange(
-        // Note: This is not what we want.
-        'Insert a newline at the end of the current line',
+        'Complete if-statement',
         '''
 main() {
-  if (true) ////
-  }
+  if (true) {
+    ////
+  } ////
 }
 ''',
-        (s) => _after(s, 'if (true) '));
+        (s) => _after(s, '    '));
   }
 
   test_emptyCondition() async {
@@ -597,6 +765,52 @@
 
 @reflectiveTest
 class _SwitchCompletionTest extends StatementCompletionTest {
+  test_caseNoColon() async {
+    await _prepareCompletion(
+        'label',
+        '''
+main(x) {
+  switch (x) {
+    case label
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete switch-statement',
+        '''
+main(x) {
+  switch (x) {
+    case label: ////
+  }
+}
+''',
+        (s) => _after(s, 'label: '));
+  }
+
+  test_defaultNoColon() async {
+    await _prepareCompletion(
+        'default',
+        '''
+main(x) {
+  switch (x) {
+    default
+  }
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete switch-statement',
+        '''
+main(x) {
+  switch (x) {
+    default: ////
+  }
+}
+''',
+        (s) => _after(s, 'default: '));
+  }
+
   test_emptyCondition() async {
     await _prepareCompletion(
         'switch',
@@ -665,7 +879,7 @@
 class _TryCompletionTest extends StatementCompletionTest {
   test_catchOnly() async {
     await _prepareCompletion(
-        'catch',
+        '{} catch',
         '''
 main() {
   try {
@@ -686,6 +900,31 @@
         (s) => _after(s, 'catch ('));
   }
 
+  test_catchSecond() async {
+    await _prepareCompletion(
+        '} catch ',
+        '''
+main() {
+  try {
+  } catch() {
+  } catch(e){} catch ////
+}
+''',
+        atEnd: true);
+    _assertHasChange(
+        'Complete try-statement',
+        '''
+main() {
+  try {
+  } catch() {
+  } catch(e){} catch () {
+    ////
+  }
+}
+''',
+        (s) => _afterLast(s, 'catch ('));
+  }
+
   test_finallyOnly() async {
     await _prepareCompletion(
         'finally',
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index cf0cfcc..86d2ee4 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -5943,6 +5943,65 @@
 ''');
   }
 
+  test_removeEmptyStatement_insideBlock() async {
+    String src = '''
+void foo() {
+  while(true) {
+    /*LINT*/;
+  }
+}
+''';
+    await findLint(src, LintNames.empty_statements);
+
+    await applyFix(DartFixKind.REMOVE_EMPTY_STATEMENT);
+
+    verifyResult('''
+void foo() {
+  while(true) {
+  }
+}
+''');
+  }
+
+  test_removeEmptyStatement_outOfBlock_otherLine() async {
+    String src = '''
+void foo() {
+  while(true)
+  /*LINT*/;
+  print('hi');
+}
+''';
+    await findLint(src, LintNames.empty_statements);
+
+    await applyFix(DartFixKind.REPLACE_WITH_BRACKETS);
+
+    verifyResult('''
+void foo() {
+  while(true) {}
+  print('hi');
+}
+''');
+  }
+
+  test_removeEmptyStatement_outOfBlock_sameLine() async {
+    String src = '''
+void foo() {
+  while(true)/*LINT*/;
+  print('hi');
+}
+''';
+    await findLint(src, LintNames.empty_statements);
+
+    await applyFix(DartFixKind.REPLACE_WITH_BRACKETS);
+
+    verifyResult('''
+void foo() {
+  while(true) {}
+  print('hi');
+}
+''');
+  }
+
   test_removeInitializer_field() async {
     String src = '''
 class Test {
@@ -5986,6 +6045,474 @@
 ''');
   }
 
+  test_removeMethodDeclaration_getter() async {
+    String src = '''
+class A {
+  int x;
+}
+class B extends A {
+  @override
+  int get /*LINT*/x => super.x;
+}
+''';
+    await findLint(src, LintNames.unnecessary_override);
+
+    await applyFix(DartFixKind.REMOVE_METHOD_DECLARATION);
+
+    verifyResult('''
+class A {
+  int x;
+}
+class B extends A {
+}
+''');
+  }
+
+  test_removeMethodDeclaration_method() async {
+    String src = '''
+class A {
+  @override
+  String /*LINT*/toString() => super.toString();
+}
+''';
+    await findLint(src, LintNames.unnecessary_override);
+
+    await applyFix(DartFixKind.REMOVE_METHOD_DECLARATION);
+
+    verifyResult('''
+class A {
+}
+''');
+  }
+
+  test_removeMethodDeclaration_setter() async {
+    String src = '''
+class A {
+  int x;
+}
+class B extends A {
+  @override
+  set /*LINT*/x(int other) {
+    this.x = other;
+  }
+}
+''';
+    await findLint(src, LintNames.unnecessary_override);
+
+    await applyFix(DartFixKind.REMOVE_METHOD_DECLARATION);
+
+    verifyResult('''
+class A {
+  int x;
+}
+class B extends A {
+}
+''');
+  }
+
+  test_removeThisExpression_methodInvocation_oneCharacterOperator() async {
+    String src = '''
+class A {
+  void foo() {
+    /*LINT*/this.foo();
+  }
+}
+''';
+    await findLint(src, LintNames.unnecessary_this);
+
+    await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION);
+
+    verifyResult('''
+class A {
+  void foo() {
+    foo();
+  }
+}
+''');
+  }
+
+  test_removeThisExpression_methodInvocation_twoCharactersOperator() async {
+    String src = '''
+class A {
+  void foo() {
+    /*LINT*/this?.foo();
+  }
+}
+''';
+    await findLint(src, LintNames.unnecessary_this);
+
+    await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION);
+
+    verifyResult('''
+class A {
+  void foo() {
+    foo();
+  }
+}
+''');
+  }
+
+  test_removeThisExpression_propertyAccess_oneCharacterOperator() async {
+    String src = '''
+class A {
+  int x;
+  void foo() {
+    /*LINT*/this.x = 2;
+  }
+}
+''';
+    await findLint(src, LintNames.unnecessary_this);
+
+    await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION);
+
+    verifyResult('''
+class A {
+  int x;
+  void foo() {
+    x = 2;
+  }
+}
+''');
+  }
+
+  test_removeThisExpression_propertyAccess_twoCharactersOperator() async {
+    String src = '''
+class A {
+  int x;
+  void foo() {
+    /*LINT*/this?.x = 2;
+  }
+}
+''';
+    await findLint(src, LintNames.unnecessary_this);
+
+    await applyFix(DartFixKind.REMOVE_THIS_EXPRESSION);
+
+    verifyResult('''
+class A {
+  int x;
+  void foo() {
+    x = 2;
+  }
+}
+''');
+  }
+
+  test_replaceWithConditionalAssignment_withCodeBeforeAndAfter() async {
+    String src = '''
+class Person {
+  String _fullName;
+  void foo() {
+    print('hi');
+    /*LINT*/if (_fullName == null) {
+      _fullName = getFullUserName(this);
+    }
+    print('hi');
+  }
+}
+''';
+    await findLint(src, LintNames.prefer_conditional_assignment);
+
+    await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT);
+
+    verifyResult('''
+class Person {
+  String _fullName;
+  void foo() {
+    print('hi');
+    _fullName ??= getFullUserName(this);
+    print('hi');
+  }
+}
+''');
+  }
+
+  test_replaceWithConditionalAssignment_withOneBlock() async {
+    String src = '''
+class Person {
+  String _fullName;
+  void foo() {
+    /*LINT*/if (_fullName == null) {
+      _fullName = getFullUserName(this);
+    }
+  }
+}
+''';
+    await findLint(src, LintNames.prefer_conditional_assignment);
+
+    await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT);
+
+    verifyResult('''
+class Person {
+  String _fullName;
+  void foo() {
+    _fullName ??= getFullUserName(this);
+  }
+}
+''');
+  }
+
+  test_replaceWithConditionalAssignment_withoutBlock() async {
+    String src = '''
+class Person {
+  String _fullName;
+  void foo() {
+    /*LINT*/if (_fullName == null)
+      _fullName = getFullUserName(this);
+  }
+}
+''';
+    await findLint(src, LintNames.prefer_conditional_assignment);
+
+    await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT);
+
+    verifyResult('''
+class Person {
+  String _fullName;
+  void foo() {
+    _fullName ??= getFullUserName(this);
+  }
+}
+''');
+  }
+
+  test_replaceWithConditionalAssignment_withTwoBlock() async {
+    String src = '''
+class Person {
+  String _fullName;
+  void foo() {
+    /*LINT*/if (_fullName == null) {{
+      _fullName = getFullUserName(this);
+    }}
+  }
+}
+''';
+    await findLint(src, LintNames.prefer_conditional_assignment);
+
+    await applyFix(DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT);
+
+    verifyResult('''
+class Person {
+  String _fullName;
+  void foo() {
+    _fullName ??= getFullUserName(this);
+  }
+}
+''');
+  }
+
+  test_replaceWithLiteral_linkedHashMap_withCommentsInGeneric() async {
+    String src = '''
+import 'dart:collection';
+
+final a = /*LINT*/new LinkedHashMap<int,/*comment*/int>();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+import 'dart:collection';
+
+final a = <int,/*comment*/int>{};
+''');
+  }
+
+  test_replaceWithLiteral_linkedHashMap_withDynamicGenerics() async {
+    String src = '''
+import 'dart:collection';
+
+final a = /*LINT*/new LinkedHashMap<dynamic,dynamic>();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+import 'dart:collection';
+
+final a = <dynamic,dynamic>{};
+''');
+  }
+
+  test_replaceWithLiteral_linkedHashMap_withGeneric() async {
+    String src = '''
+import 'dart:collection';
+
+final a = /*LINT*/new LinkedHashMap<int,int>();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+import 'dart:collection';
+
+final a = <int,int>{};
+''');
+  }
+
+  test_replaceWithLiteral_linkedHashMap_withoutGeneric() async {
+    String src = '''
+import 'dart:collection';
+
+final a = /*LINT*/new LinkedHashMap();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+import 'dart:collection';
+
+final a = {};
+''');
+  }
+
+  test_replaceWithLiteral_list_withGeneric() async {
+    String src = '''
+final a = /*LINT*/new List<int>();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+final a = <int>[];
+''');
+  }
+
+  test_replaceWithLiteral_list_withoutGeneric() async {
+    String src = '''
+final a = /*LINT*/new List();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+final a = [];
+''');
+  }
+
+  test_replaceWithLiteral_map_withGeneric() async {
+    String src = '''
+final a = /*LINT*/new Map<int,int>();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+final a = <int,int>{};
+''');
+  }
+
+  test_replaceWithLiteral_map_withoutGeneric() async {
+    String src = '''
+final a = /*LINT*/new Map();
+''';
+    await findLint(src, LintNames.prefer_collection_literals);
+
+    await applyFix(DartFixKind.REPLACE_WITH_LITERAL);
+
+    verifyResult('''
+final a = {};
+''');
+  }
+
+  test_replaceWithTearOff_function_oneParameter() async {
+    String src = '''
+final x = /*LINT*/(name) {
+  print(name);
+};
+''';
+    await findLint(src, LintNames.unnecessary_lambdas);
+
+    await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF);
+
+    verifyResult('''
+final x = print;
+''');
+  }
+
+  test_replaceWithTearOff_function_zeroParameters() async {
+    String src = '''
+void foo(){}
+Function finalVar() {
+  return /*LINT*/() {
+    foo();
+  };
+}
+''';
+    await findLint(src, LintNames.unnecessary_lambdas);
+
+    await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF);
+
+    verifyResult('''
+void foo(){}
+Function finalVar() {
+  return foo;
+}
+''');
+  }
+
+  test_replaceWithTearOff_lambda_asArgument() async {
+    String src = '''
+void foo() {
+  bool isPair(int a) => a % 2 == 0;
+  final finalList = <int>[];
+  finalList.where(/*LINT*/(number) =>
+    isPair(number));
+}
+''';
+    await findLint(src, LintNames.unnecessary_lambdas);
+
+    await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF);
+
+    verifyResult('''
+void foo() {
+  bool isPair(int a) => a % 2 == 0;
+  final finalList = <int>[];
+  finalList.where(isPair);
+}
+''');
+  }
+
+  test_replaceWithTearOff_method_oneParameter() async {
+    String src = '''
+var a = /*LINT*/(x) => finalList.remove(x);
+''';
+    await findLint(src, LintNames.unnecessary_lambdas);
+
+    await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF);
+
+    verifyResult('''
+var a = finalList.remove;
+''');
+  }
+
+  test_replaceWithTearOff_method_zeroParameter() async {
+    String src = '''
+final Object a;
+Function finalVar() {
+  return /*LINT*/() {
+    return a.toString();
+  };
+}
+''';
+    await findLint(src, LintNames.unnecessary_lambdas);
+
+    await applyFix(DartFixKind.REPLACE_WITH_TEAR_OFF);
+
+    verifyResult('''
+final Object a;
+Function finalVar() {
+  return a.toString;
+}
+''');
+  }
+
   void verifyResult(String expectedResult) {
     expect(resultCode, expectedResult);
   }
diff --git a/pkg/analysis_server/test/services/correction/flutter_util.dart b/pkg/analysis_server/test/services/correction/flutter_util.dart
index 5979e69..100f1b0 100644
--- a/pkg/analysis_server/test/services/correction/flutter_util.dart
+++ b/pkg/analysis_server/test/services/correction/flutter_util.dart
@@ -10,6 +10,7 @@
 class Widget {}
 class RenderObjectWidget extends Widget {}
 class StatelessWidget extends Widget {}
+abstract class StatefulWidget extends Widget { }
 class SingleChildRenderObjectWidget extends RenderObjectWidget {}
 class Transform extends SingleChildRenderObjectWidget {}
 class ClipRect extends SingleChildRenderObjectWidget { ClipRect.rect(){} }
@@ -17,7 +18,9 @@
 class Container extends StatelessWidget { Container({child: null, width: null, height: null}){}}
 class Center extends StatelessWidget { Center({child: null, key: null}){}}
 class DefaultTextStyle extends StatelessWidget { DefaultTextStyle({child: null}){}}
-class Row extends Widget { Row({List<Widget> children: null}){}}
+class Row extends Widget { Row({List<Widget> children: null, key: null}){}}
 class GestureDetector extends SingleChildRenderObjectWidget { GestureDetector({child: null, onTap: null}){}}
-class Scaffold extends Widget { Scaffold({body: null}){}}
+class AppBar extends StatefulWidget implements PreferredSizeWidget { AppBar(title: null, color: null, key: null) }
+class Scaffold extends Widget { Scaffold({body: null, PreferredSizeWidget appBar: null}){}}
+class PreferredSizeWidget implements Widget {}
 ''';
diff --git a/pkg/analysis_server/test/src/plugin/notification_manager_test.dart b/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
index b37be53..c240c69 100644
--- a/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
@@ -125,6 +125,16 @@
     _verifyOutlines(fileA, serverOutline1);
   }
 
+  void test_handlePluginNotification_pluginError() {
+    bool isFatal = false;
+    String message = 'message';
+    String stackTrace = 'stackTrace';
+    plugin.PluginErrorParams params =
+        new plugin.PluginErrorParams(isFatal, message, stackTrace);
+    manager.handlePluginNotification('a', params.toNotification());
+    _verifyPluginError(isFatal, message, stackTrace);
+  }
+
   void test_recordAnalysisErrors_noSubscription() {
     server.AnalysisError error = serverAnalysisError(0, 0, file: fileA);
     manager.recordAnalysisErrors('a', fileA, [error]);
@@ -472,6 +482,19 @@
     expect(params.outline, equals(expectedOutline));
     channel.sentNotification = null;
   }
+
+  void _verifyPluginError(bool isFatal, String message, String stackTrace) {
+    server.Notification notification = channel.sentNotification;
+    expect(notification, isNotNull);
+    expect(notification.event, 'server.error');
+    server.ServerErrorParams params =
+        new server.ServerErrorParams.fromNotification(notification);
+    expect(params, isNotNull);
+    expect(params.isFatal, isFatal);
+    expect(params.message, message);
+    expect(params.stackTrace, stackTrace);
+    channel.sentNotification = null;
+  }
 }
 
 class TestChannel implements ServerCommunicationChannel {
diff --git a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
index f572cfd..51c2901 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
@@ -18,6 +18,7 @@
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:watcher/watcher.dart' as watcher;
 
 main() {
   defineReflectiveSuite(() {
@@ -127,7 +128,7 @@
     pkg1Dir.deleteSync(recursive: true);
   }
 
-  test_broadcast_many() async {
+  test_broadcastRequest_many() async {
     io.Directory pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
     String pkgPath = pkg1Dir.resolveSymbolicLinksSync();
     await withPlugin(
@@ -140,9 +141,34 @@
                 await manager.addPluginToContextRoot(contextRoot, plugin1Path);
                 await manager.addPluginToContextRoot(contextRoot, plugin2Path);
 
-                Map<PluginInfo, Future<Response>> responses = manager.broadcast(
-                    contextRoot,
-                    new CompletionGetSuggestionsParams(
+                Map<PluginInfo, Future<Response>> responses =
+                    manager.broadcastRequest(
+                        new CompletionGetSuggestionsParams(
+                            '/pkg1/lib/pkg1.dart', 100),
+                        contextRoot: contextRoot);
+                expect(responses, hasLength(2));
+
+                await manager.stopAll();
+              });
+        });
+    pkg1Dir.deleteSync(recursive: true);
+  }
+
+  test_broadcastRequest_many_noContextRoot() async {
+    io.Directory pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
+    String pkgPath = pkg1Dir.resolveSymbolicLinksSync();
+    await withPlugin(
+        pluginName: 'plugin1',
+        test: (String plugin1Path) async {
+          await withPlugin(
+              pluginName: 'plugin2',
+              test: (String plugin2Path) async {
+                ContextRoot contextRoot = new ContextRoot(pkgPath, []);
+                await manager.addPluginToContextRoot(contextRoot, plugin1Path);
+                await manager.addPluginToContextRoot(contextRoot, plugin2Path);
+
+                Map<PluginInfo, Future<Response>> responses =
+                    manager.broadcastRequest(new CompletionGetSuggestionsParams(
                         '/pkg1/lib/pkg1.dart', 100));
                 expect(responses, hasLength(2));
 
@@ -152,6 +178,30 @@
     pkg1Dir.deleteSync(recursive: true);
   }
 
+  test_broadcastWatchEvent() async {
+    io.Directory pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
+    String pkgPath = pkg1Dir.resolveSymbolicLinksSync();
+    await withPlugin(
+        pluginName: 'plugin1',
+        test: (String plugin1Path) async {
+          ContextRoot contextRoot = new ContextRoot(pkgPath, []);
+          await manager.addPluginToContextRoot(contextRoot, plugin1Path);
+          List<PluginInfo> plugins = manager.pluginsForContextRoot(contextRoot);
+          expect(plugins, hasLength(1));
+          watcher.WatchEvent watchEvent = new watcher.WatchEvent(
+              watcher.ChangeType.MODIFY,
+              path.join(plugin1Path, 'lib', 'lib.dart'));
+          List<Future<Response>> responses =
+              await manager.broadcastWatchEvent(watchEvent);
+          expect(responses, hasLength(1));
+          Response response = await responses[0];
+          expect(response, isNotNull);
+          expect(response.error, isNull);
+          await manager.stopAll();
+        });
+    pkg1Dir.deleteSync(recursive: true);
+  }
+
   test_pluginsForContextRoot_multiple() async {
     io.Directory pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
     String pkgPath = pkg1Dir.resolveSymbolicLinksSync();
@@ -224,10 +274,11 @@
         notificationManager, InstrumentationService.NULL_SERVICE);
   }
 
-  void test_broadcast_none() {
+  void test_broadcastRequest_none() {
     ContextRoot contextRoot = new ContextRoot('/pkg1', []);
-    Map<PluginInfo, Future<Response>> responses = manager.broadcast(contextRoot,
-        new CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100));
+    Map<PluginInfo, Future<Response>> responses = manager.broadcastRequest(
+        new CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100),
+        contextRoot: contextRoot);
     expect(responses, hasLength(0));
   }
 
@@ -460,6 +511,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer_plugin/plugin/plugin.dart';
+import 'package:analyzer_plugin/protocol/protocol_generated.dart';
 import 'package:analyzer_plugin/starter.dart';
 import 'package:pub_semver/pub_semver.dart';
 
@@ -472,7 +524,7 @@
   MinimalPlugin(ResourceProvider provider) : super(provider);
 
   @override
-  List<String> get fileGlobsToAnalyze => <String>[];
+  List<String> get fileGlobsToAnalyze => <String>['**/*.dart'];
 
   @override
   String get name => 'minimal';
@@ -481,6 +533,11 @@
   String get version => '0.0.1';
 
   @override
+  AnalysisHandleWatchEventsResult handleAnalysisHandleWatchEvents(
+          Map<String, Object> parameters) =>
+    new AnalysisHandleWatchEventsResult();
+
+  @override
   bool isCompatibleWith(Version serverVersion) => true;
 }
 ''';
@@ -503,8 +560,7 @@
    * Return the path to the '.packages' file in the root of the SDK checkout.
    */
   String _sdkPackagesPath() {
-    String packagesPath =
-        io.Platform.script.toFilePath(windows: io.Platform.isWindows);
+    String packagesPath = io.Platform.script.toFilePath();
     while (packagesPath.isNotEmpty &&
         path.basename(packagesPath) != 'analysis_server') {
       packagesPath = path.dirname(packagesPath);
diff --git a/pkg/analysis_server/test/src/plugin/request_converter_test.dart b/pkg/analysis_server/test/src/plugin/request_converter_test.dart
new file mode 100644
index 0000000..c8e47e8
--- /dev/null
+++ b/pkg/analysis_server/test/src/plugin/request_converter_test.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/plugin/protocol/protocol.dart' as server;
+import 'package:analysis_server/src/plugin/request_converter.dart';
+import 'package:analysis_server/src/protocol/protocol_internal.dart' as server;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'protocol_test_utilities.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RequestConverterTest);
+  });
+}
+
+@reflectiveTest
+class RequestConverterTest extends ProtocolTestUtilities {
+  RequestConverter converter = new RequestConverter();
+
+  void test_convertAnalysisService() {
+    Map<plugin.AnalysisService, server.AnalysisService> kindMap =
+        <plugin.AnalysisService, server.AnalysisService>{
+      plugin.AnalysisService.FOLDING: server.AnalysisService.FOLDING,
+      plugin.AnalysisService.HIGHLIGHTS: server.AnalysisService.HIGHLIGHTS,
+      plugin.AnalysisService.NAVIGATION: server.AnalysisService.NAVIGATION,
+      plugin.AnalysisService.OCCURRENCES: server.AnalysisService.OCCURRENCES,
+      plugin.AnalysisService.OUTLINE: server.AnalysisService.OUTLINE,
+    };
+    kindMap.forEach(
+        (plugin.AnalysisService pluginKind, server.AnalysisService serverKind) {
+      expect(converter.convertAnalysisService(serverKind), pluginKind);
+    });
+  }
+
+  void test_convertAnalysisSetPriorityFilesParams() {
+    List<String> files = <String>['a', 'b', 'c'];
+    plugin.AnalysisSetPriorityFilesParams result =
+        converter.convertAnalysisSetPriorityFilesParams(
+            new server.AnalysisSetPriorityFilesParams(files));
+    expect(result, isNotNull);
+    expect(result.files, files);
+  }
+
+  void test_convertAnalysisSetSubscriptionsParams() {
+    Map<server.AnalysisService, List<String>> serverSubscriptions =
+        <server.AnalysisService, List<String>>{
+      server.AnalysisService.HIGHLIGHTS: <String>['a', 'b'],
+      server.AnalysisService.OUTLINE: <String>['c'],
+      server.AnalysisService.OVERRIDES: <String>['d', 'e']
+    };
+    plugin.AnalysisSetSubscriptionsParams result =
+        converter.convertAnalysisSetSubscriptionsParams(
+            new server.AnalysisSetSubscriptionsParams(serverSubscriptions));
+    expect(result, isNotNull);
+    Map<plugin.AnalysisService, List<String>> pluginSubscriptions =
+        result.subscriptions;
+    expect(pluginSubscriptions, hasLength(2));
+    expect(
+        pluginSubscriptions[plugin.AnalysisService.HIGHLIGHTS], hasLength(2));
+    expect(pluginSubscriptions[plugin.AnalysisService.OUTLINE], hasLength(1));
+  }
+
+  void test_convertAnalysisUpdateContentParams() {
+    Map<String, dynamic> serverFiles = <String, dynamic>{
+      'file1': new server.AddContentOverlay('content1'),
+      'file2': new server.AddContentOverlay('content2'),
+    };
+    plugin.AnalysisUpdateContentParams result =
+        converter.convertAnalysisUpdateContentParams(
+            new server.AnalysisUpdateContentParams(serverFiles));
+    expect(result, isNotNull);
+    Map<String, dynamic> pluginFiles = result.files;
+    expect(pluginFiles, hasLength(2));
+    expect(pluginFiles['file1'], new isInstanceOf<plugin.AddContentOverlay>());
+    expect(pluginFiles['file2'], new isInstanceOf<plugin.AddContentOverlay>());
+  }
+
+  void test_convertFileOverlay_add() {
+    String content = 'content';
+    plugin.AddContentOverlay result =
+        converter.convertFileOverlay(new server.AddContentOverlay(content));
+    expect(result, isNotNull);
+    expect(result.content, content);
+  }
+
+  void test_convertFileOverlay_change() {
+    List<server.SourceEdit> serverEdits = <server.SourceEdit>[
+      new server.SourceEdit(10, 5, 'a'),
+      new server.SourceEdit(20, 6, 'b'),
+      new server.SourceEdit(30, 7, 'c'),
+    ];
+    plugin.ChangeContentOverlay result = converter
+        .convertFileOverlay(new server.ChangeContentOverlay(serverEdits));
+    expect(result, isNotNull);
+    List<plugin.SourceEdit> pluginEdits = result.edits;
+    int editCount = serverEdits.length;
+    expect(pluginEdits, hasLength(editCount));
+    for (int i = 0; i < editCount; i++) {
+      server.SourceEdit serverEdit = serverEdits[i];
+      plugin.SourceEdit pluginEdit = pluginEdits[i];
+      expect(pluginEdit.offset, serverEdit.offset);
+      expect(pluginEdit.length, serverEdit.length);
+      expect(pluginEdit.replacement, serverEdit.replacement);
+    }
+  }
+
+  void test_convertFileOverlay_remove() {
+    plugin.RemoveContentOverlay result =
+        converter.convertFileOverlay(new server.RemoveContentOverlay());
+    expect(result, isNotNull);
+  }
+
+  void test_convertSourceEdit() {
+    int offset = 5;
+    int length = 3;
+    String replacement = 'x';
+    plugin.SourceEdit result = converter
+        .convertSourceEdit(new server.SourceEdit(offset, length, replacement));
+    expect(result, isNotNull);
+    expect(result.offset, offset);
+    expect(result.length, length);
+    expect(result.replacement, replacement);
+  }
+}
diff --git a/pkg/analysis_server/test/src/plugin/test_all.dart b/pkg/analysis_server/test/src/plugin/test_all.dart
index 9da4fdc..a1f7564 100644
--- a/pkg/analysis_server/test/src/plugin/test_all.dart
+++ b/pkg/analysis_server/test/src/plugin/test_all.dart
@@ -8,6 +8,7 @@
 import 'plugin_locator_test.dart' as plugin_locator_test;
 import 'plugin_manager_test.dart' as plugin_manager_test;
 import 'plugin_watcher_test.dart' as plugin_watcher_test;
+import 'request_converter_test.dart' as request_converter_test;
 import 'result_collector_test.dart' as result_collector_test;
 import 'result_converter_test.dart' as result_converter_test;
 import 'result_merger_test.dart' as result_merger_test;
@@ -18,6 +19,7 @@
     plugin_locator_test.main();
     plugin_manager_test.main();
     plugin_watcher_test.main();
+    request_converter_test.main();
     result_collector_test.main();
     result_converter_test.main();
     result_merger_test.main();
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 8449bf0..21af976 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,7 +1,7 @@
 ## 0.30.0-alpha.0
 * Changed the API for creating BazelWorkspace.  It should now be constructed using BazelWorkspace.find().  Note that this might return `null` in the event that the given path is not part of a BazelWorkspace.
 * Added an AST structure to support asserts in constructor initializers (AssertInitializer).  AstVisitor classes must now implement visitAssertInitializer().
-* Changed the API for creating PartOfDirective.  It now accepts a StringLiteral URI, to accomodate "part of" declarations with a URI string rather than a library name.
+* Changed the API for creating PartOfDirective.  It now accepts a StringLiteral URI, to accommodate "part of" declarations with a URI string rather than a library name.
 * Removed AST constructors.  AST nodes should now be created using `astFactory`, located in `package:analyzer/dart/ast/standard_ast_factory.dart`.
 
 ## 0.29.0-alpha.0
diff --git a/pkg/analyzer/analyzer.iml b/pkg/analyzer/analyzer.iml
index 5b8978b..a065d15a 100644
--- a/pkg/analyzer/analyzer.iml
+++ b/pkg/analyzer/analyzer.iml
@@ -24,6 +24,7 @@
       <excludeFolder url="file://$MODULE_DIR$/test/src/dart/constant/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/dart/element/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/dart/packages" />
+      <excludeFolder url="file://$MODULE_DIR$/test/src/dart/parser/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/dart/sdk/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/lint/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/packages" />
@@ -32,7 +33,7 @@
       <excludeFolder url="file://$MODULE_DIR$/test/src/task/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/task/strong/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/util/packages" />
-      <excludeFolder url="file://$MODULE_DIR$/test/stress/packages" />
+      <excludeFolder url="file://$MODULE_DIR$/tool/analysis_driver/packages" />
       <excludeFolder url="file://$MODULE_DIR$/tool/packages" />
       <excludeFolder url="file://$MODULE_DIR$/tool/summary/packages" />
       <excludeFolder url="file://$MODULE_DIR$/tool/task_dependency_graph/packages" />
@@ -41,5 +42,6 @@
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="Dart SDK" level="application" />
     <orderEntry type="library" name="Dart SDK" level="project" />
+    <orderEntry type="library" name="Dart Packages" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/pkg/analyzer/doc/tasks.html b/pkg/analyzer/doc/tasks.html
index 6f5a691..960dc69 100644
--- a/pkg/analyzer/doc/tasks.html
+++ b/pkg/analyzer/doc/tasks.html
@@ -214,7 +214,6 @@
   ParseDartTask -> LIBRARY_SPECIFIC_UNITS
   ParseDartTask -> PARSED_UNIT
   ParseDartTask -> PARSE_ERRORS
-  ParseDartTask -> REFERENCED_NAMES
   ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
@@ -233,7 +232,6 @@
   READY_RESOLVED_UNIT -> ResolveLibraryTask
   READY_RESOLVED_UNIT -> VerifyUnitTask
   READY_RESOLVED_UNIT [shape=box]
-  REFERENCED_NAMES [shape=box]
   REFERENCED_SOURCES -> BuildDirectiveElementsTask
   REFERENCED_SOURCES -> ResolveDirectiveElementsTask
   REFERENCED_SOURCES -> VerifyUnitTask
diff --git a/pkg/analyzer/lib/context/context_root.dart b/pkg/analyzer/lib/context/context_root.dart
index f871ab1..cfc47ff 100644
--- a/pkg/analyzer/lib/context/context_root.dart
+++ b/pkg/analyzer/lib/context/context_root.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:path/path.dart' as path;
 
 /**
  * Information about the root directory associated with an analysis context.
@@ -45,6 +46,24 @@
   }
 
   /**
+   * Return `true` if the file with the given [filePath] is contained within
+   * this context root. A file contained in a context root if it is within the
+   * context [root] neither explicitly excluded or within one of the excluded
+   * directories.
+   */
+  bool containsFile(String filePath) {
+    if (!path.isWithin(root, filePath)) {
+      return false;
+    }
+    for (String excluded in exclude) {
+      if (filePath == excluded || path.isWithin(excluded, filePath)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
    * Compare the lists [listA] and [listB], using [itemEqual] to compare
    * list elements.
    */
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index f38236b..5c70a2b 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -54,7 +54,7 @@
  * 3. Look in each package for an SDK extension file (_sdkext). For each such
  *    file, add the specified files to the SDK.
  *
- * 4. Look for an analysis options file (`analyis_options.yaml` or
+ * 4. Look for an analysis options file (`analysis_options.yaml` or
  *    `.analysis_options`) and process the options in the file.
  *
  * 5. Create a new context. Initialize its source factory based on steps 1, 2
@@ -817,7 +817,10 @@
       throw new ArgumentError('not absolute: $path');
     }
     path = context.normalize(path);
-
+    Resource resource = provider.getResource(path);
+    if (resource is File) {
+      path = resource.parent.path;
+    }
     return new _BasicWorkspace._(provider, path, builder);
   }
 }
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 5c20e0b..4f04145 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -29,7 +29,6 @@
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/dart_work_manager.dart';
 import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/incremental_element_builder.dart';
 import 'package:analyzer/src/task/manager.dart';
 import 'package:analyzer/task/dart.dart';
 import 'package:analyzer/task/general.dart';
@@ -337,7 +336,6 @@
     this._options.strongMode = options.strongMode;
     this._options.trackCacheDependencies = options.trackCacheDependencies;
     this._options.disableCacheFlushing = options.disableCacheFlushing;
-    this._options.finerGrainedInvalidation = options.finerGrainedInvalidation;
     this._options.patchPaths = options.patchPaths;
     if (options is AnalysisOptionsImpl) {
       this._options.strongModeHints = options.strongModeHints;
@@ -1841,53 +1839,6 @@
 
     // We need to invalidate the cache.
     {
-      if (analysisOptions.finerGrainedInvalidation &&
-          AnalysisEngine.isDartFileName(source.fullName)) {
-        // TODO(scheglov) Incorrect implementation in general.
-        entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
-        entry.setState(PARSED_UNIT, CacheState.FLUSHED);
-        SourceKind sourceKind = getKindOf(source);
-        List<Source> partSources = getResult(source, INCLUDED_PARTS);
-        if (sourceKind == SourceKind.LIBRARY && partSources.isEmpty) {
-          Source librarySource = source;
-          // Try to find an old unit which has element model.
-          CacheEntry unitEntry =
-              getCacheEntry(new LibrarySpecificUnit(librarySource, source));
-          CompilationUnit oldUnit = RESOLVED_UNIT_RESULTS
-              .skipWhile((result) => result != RESOLVED_UNIT2)
-              .map(unitEntry.getValue)
-              .firstWhere((unit) => unit != null, orElse: () => null);
-          // If we have the old unit, we can try to update it.
-          if (oldUnit != null) {
-            // Safely parse the source.
-            CompilationUnit newUnit;
-            try {
-              newUnit = parseCompilationUnit(source);
-            } catch (_) {
-              // The source might have been removed by this time.
-              // We cannot perform incremental invalidation.
-            }
-            // If the new unit was parsed successfully, continue.
-            if (newUnit != null) {
-              IncrementalCompilationUnitElementBuilder builder =
-                  new IncrementalCompilationUnitElementBuilder(
-                      oldUnit, newUnit);
-              builder.build();
-              CompilationUnitElementDelta unitDelta = builder.unitDelta;
-              if (!unitDelta.hasDirectiveChange) {
-                unitEntry.setValueIncremental(
-                    COMPILATION_UNIT_CONSTANTS, builder.unitConstants, false);
-                DartDelta dartDelta = new DartDelta(source);
-                unitDelta.addedDeclarations.forEach(dartDelta.elementChanged);
-                unitDelta.removedDeclarations.forEach(dartDelta.elementChanged);
-                unitDelta.classDeltas.values.forEach(dartDelta.classChanged);
-                entry.setState(CONTENT, CacheState.INVALID, delta: dartDelta);
-                return;
-              }
-            }
-          }
-        }
-      }
       entry.setState(CONTENT, CacheState.INVALID);
       entry.setState(MODIFICATION_TIME, CacheState.INVALID);
       entry.setState(SOURCE_KIND, CacheState.INVALID);
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 2e63f8d..f25bd27 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -9,7 +9,8 @@
 import 'package:analyzer/context/context_root.dart';
 import 'package:analyzer/context/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement;
+import 'package:analyzer/dart/element/element.dart'
+    show CompilationUnitElement, LibraryElement;
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
@@ -30,6 +31,7 @@
 import 'package:analyzer/src/summary/api_signature.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:meta/meta.dart';
 
 /**
@@ -73,7 +75,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 33;
+  static const int DATA_VERSION = 34;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
@@ -105,6 +107,13 @@
   final ByteStore _byteStore;
 
   /**
+   * The optional store with externally provided unlinked and corresponding
+   * linked summaries. These summaries are always added to the store for any
+   * file analysis.
+   */
+  final SummaryDataStore _externalSummaries;
+
+  /**
    * This [ContentCache] is consulted for a file content before reading
    * the content from the file.
    */
@@ -232,6 +241,8 @@
 
   AnalysisDriverTestView _testView;
 
+  FileSystemState _fsState;
+
   /**
    * The [FileTracker] used by this driver.
    */
@@ -276,13 +287,15 @@
       SourceFactory sourceFactory,
       this._analysisOptions,
       {PackageBundle sdkBundle,
-      this.disableChangesAndCacheAllResults: false})
+      this.disableChangesAndCacheAllResults: false,
+      SummaryDataStore externalSummaries})
       : _logger = logger,
         _sourceFactory = sourceFactory.clone(),
-        _sdkBundle = sdkBundle {
+        _sdkBundle = sdkBundle,
+        _externalSummaries = externalSummaries {
     _onResults = _resultController.stream.asBroadcastStream();
     _testView = new AnalysisDriverTestView(this);
-    _createFileTracker(logger);
+    _createFileTracker();
     _scheduler.add(this);
     _search = new Search(this);
   }
@@ -305,7 +318,7 @@
   /**
    * The current file system state.
    */
-  FileSystemState get fsState => _fileTracker.fsState;
+  FileSystemState get fsState => _fsState;
 
   /**
    * Return `true` if the driver has a file to analyze.
@@ -323,7 +336,7 @@
    * always include all added files or all implicitly used file. If a file has
    * not been processed yet, it might be missing.
    */
-  Set<String> get knownFiles => _fileTracker.fsState.knownFilePaths;
+  Set<String> get knownFiles => _fsState.knownFilePaths;
 
   /**
    * Return the path of the folder at the root of the context.
@@ -456,7 +469,7 @@
    * The results of analysis are eventually produced by the [results] stream.
    */
   void addFile(String path) {
-    if (!_fileTracker.fsState.hasUri(path)) {
+    if (!_fsState.hasUri(path)) {
       return;
     }
     if (AnalysisEngine.isDartFileName(path)) {
@@ -504,7 +517,7 @@
       _sourceFactory = sourceFactory;
     }
     Iterable<String> addedFiles = _fileTracker.addedFiles;
-    _createFileTracker(_logger);
+    _createFileTracker();
     _fileTracker.addFiles(addedFiles);
   }
 
@@ -573,7 +586,7 @@
    * analyzed.
    */
   Future<AnalysisDriverUnitIndex> getIndex(String path) {
-    if (!_fileTracker.fsState.hasUri(path)) {
+    if (!_fsState.hasUri(path)) {
       return new Future.value();
     }
     var completer = new Completer<AnalysisDriverUnitIndex>();
@@ -584,6 +597,21 @@
     return completer.future;
   }
 
+  /**
+   * Return a [Future] that completes with the [LibraryElement] for the given
+   * [uri], which is either resynthesized from the provided external summary
+   * store, or built for a file to which the given [uri] is resolved.
+   */
+  Future<LibraryElement> getLibraryByUri(String uri) async {
+    if (_externalSummaries != null && _externalSummaries.hasUnlinkedUnit(uri)) {
+      return LibraryContext.resynthesizeLibraryElement(analysisOptions,
+          declaredVariables, sourceFactory, _externalSummaries, uri);
+    }
+    Source source = sourceFactory.resolveUri(null, uri);
+    UnitElementResult unitResult = await getUnitElement(source.fullName);
+    return unitResult.element.library;
+  }
+
   ApiSignature getResolvedUnitKeyByPath(String path) {
     ApiSignature signature = getUnitKeyByPath(path);
     var file = fsState.getFileForPath(path);
@@ -609,7 +637,7 @@
    * time the analysis state transitions to "idle".
    */
   Future<AnalysisResult> getResult(String path) {
-    if (!_fileTracker.fsState.hasUri(path)) {
+    if (!_fsState.hasUri(path)) {
       return new Future.value();
     }
 
@@ -642,7 +670,7 @@
    */
   Future<SourceKind> getSourceKind(String path) async {
     if (AnalysisEngine.isDartFileName(path)) {
-      FileState file = _fileTracker.fsState.getFileForPath(path);
+      FileState file = _fsState.getFileForPath(path);
       return file.isPart ? SourceKind.PART : SourceKind.LIBRARY;
     }
     return null;
@@ -665,7 +693,7 @@
    * file with the given [path], or with `null` if the file cannot be analyzed.
    */
   Future<UnitElementResult> getUnitElement(String path) {
-    if (!_fileTracker.fsState.hasUri(path)) {
+    if (!_fsState.hasUri(path)) {
       return new Future.value();
     }
     var completer = new Completer<UnitElementResult>();
@@ -683,10 +711,10 @@
    *
    * The signature is based the APIs of the files of the library (including
    * the file itself) of the requested file and the transitive closure of files
-   * imported and exported by the the library.
+   * imported and exported by the library.
    */
   Future<String> getUnitElementSignature(String path) {
-    if (!_fileTracker.fsState.hasUri(path)) {
+    if (!_fsState.hasUri(path)) {
       return new Future.value();
     }
     var completer = new Completer<String>();
@@ -948,7 +976,7 @@
       {bool withUnit: false,
       bool asIsIfPartWithoutLibrary: false,
       bool skipIfSameSignature: false}) {
-    FileState file = _fileTracker.fsState.getFileForPath(path);
+    FileState file = _fsState.getFileForPath(path);
 
     // Prepare the library - the file itself, or the known library.
     FileState library = file.isPart ? file.library : file;
@@ -990,7 +1018,7 @@
               analysisOptions,
               declaredVariables,
               sourceFactory,
-              _fileTracker.fsState,
+              _fsState,
               libraryContext.store,
               library);
           Map<FileState, UnitAnalysisResult> results = analyzer.analyze();
@@ -1044,7 +1072,7 @@
   }
 
   UnitElementResult _computeUnitElement(String path) {
-    FileState file = _fileTracker.fsState.getFileForPath(path);
+    FileState file = _fsState.getFileForPath(path);
     FileState library = file.library ?? file;
 
     // Create the AnalysisContext to resynthesize elements in.
@@ -1062,36 +1090,41 @@
   }
 
   String _computeUnitElementSignature(String path) {
-    FileState file = _fileTracker.fsState.getFileForPath(path);
+    FileState file = _fsState.getFileForPath(path);
     FileState library = file.library ?? file;
     return library.transitiveSignature;
   }
 
   /**
-   * Creates a new [FileTracker] object and stores it in [_fileTracker].
+   * Creates new [FileSystemState] and [FileTracker] objects.
    *
    * This is used both on initial construction and whenever the configuration
    * changes.
    */
-  void _createFileTracker(PerformanceLog logger) {
+  void _createFileTracker() {
     _fillSalt();
-    _fileTracker = new FileTracker(logger, _byteStore, _contentOverlay,
-        _resourceProvider, sourceFactory, _analysisOptions, _salt, _changeHook);
+    _fsState = new FileSystemState(_logger, _byteStore, _contentOverlay,
+        _resourceProvider, sourceFactory, analysisOptions, _salt,
+        externalSummaries: _externalSummaries);
+    _fileTracker = new FileTracker(_logger, _fsState, _changeHook);
   }
 
   /**
    * Return the context in which the [library] should be analyzed.
    */
-  LibraryContext _createLibraryContext(FileState library) =>
-      new LibraryContext.forSingleLibrary(
-          library,
-          _logger,
-          _sdkBundle,
-          _byteStore,
-          _analysisOptions,
-          declaredVariables,
-          _sourceFactory,
-          _fileTracker);
+  LibraryContext _createLibraryContext(FileState library) {
+    _testView.numOfCreatedLibraryContexts++;
+    return new LibraryContext.forSingleLibrary(
+        library,
+        _logger,
+        _sdkBundle,
+        _byteStore,
+        _analysisOptions,
+        declaredVariables,
+        _sourceFactory,
+        _externalSummaries,
+        fsState);
+  }
 
   /**
    * Fill [_salt] with data.
@@ -1526,6 +1559,8 @@
 class AnalysisDriverTestView {
   final AnalysisDriver driver;
 
+  int numOfCreatedLibraryContexts = 0;
+
   int numOfAnalyzedLibraries = 0;
 
   AnalysisDriverTestView(this.driver);
@@ -1533,6 +1568,16 @@
   FileTracker get fileTracker => driver._fileTracker;
 
   Map<String, AnalysisResult> get priorityResults => driver._priorityResults;
+
+  SummaryDataStore getSummaryStore(String libraryPath) {
+    FileState library = driver.fsState.getFileForPath(libraryPath);
+    LibraryContext libraryContext = driver._createLibraryContext(library);
+    try {
+      return libraryContext.store;
+    } finally {
+      libraryContext.dispose();
+    }
+  }
 }
 
 /**
@@ -1594,7 +1639,7 @@
 
   /**
    * The signature of the result based on the content of the file, and the
-   * transitive closure of files imported and exported by the the library of
+   * transitive closure of files imported and exported by the library of
    * the requested file.
    */
   final String _signature;
@@ -1859,7 +1904,7 @@
   /**
    * The signature of the [element] is based the APIs of the files of the
    * library (including the file itself) of the requested file and the
-   * transitive closure of files imported and exported by the the library.
+   * transitive closure of files imported and exported by the library.
    */
   final String signature;
 
@@ -1934,7 +1979,7 @@
 
       // Check the next file.
       String path = filesToCheck.removeLast();
-      FileState file = driver._fileTracker.fsState.getFileForPath(path);
+      FileState file = driver._fsState.getFileForPath(path);
       if (file.definedClassMemberNames.contains(name)) {
         definingFiles.add(path);
       }
@@ -1991,7 +2036,7 @@
 
       // Check the next file.
       String path = filesToCheck.removeLast();
-      FileState file = driver._fileTracker.fsState.getFileForPath(path);
+      FileState file = driver._fsState.getFileForPath(path);
       if (file.referencedNames.contains(name)) {
         referencingFiles.add(path);
       }
@@ -2041,7 +2086,7 @@
     // Check the next file.
     String path = filesToCheck.removeLast();
     if (checkedFiles.add(path)) {
-      FileState file = driver._fileTracker.fsState.getFileForPath(path);
+      FileState file = driver._fsState.getFileForPath(path);
       if (!file.isPart) {
         bool isExported = false;
         TopLevelDeclaration declaration = file.topLevelDeclarations[name];
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 2519e41..44100e2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -29,6 +29,7 @@
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/name_filter.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary/summarize_ast.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
@@ -92,7 +93,15 @@
   /**
    * The [Source] of the file with the [uri].
    */
-  Source source;
+  final Source source;
+
+  /**
+   * Return `true` if this file is a stub created for a file in the provided
+   * external summary store. The values of most properties are not the same
+   * as they would be if the file were actually read from the file system.
+   * The value of the property [uri] is correct.
+   */
+  final bool isInExternalSummaries;
 
   bool _exists;
   List<int> _contentBytes;
@@ -123,7 +132,15 @@
    */
   bool hasErrorOrWarning = false;
 
-  FileState._(this._fsState, this.path, this.uri, this.source);
+  FileState._(this._fsState, this.path, this.uri, this.source)
+      : isInExternalSummaries = false;
+
+  FileState._external(this._fsState, this.uri)
+      : isInExternalSummaries = true,
+        path = null,
+        source = null {
+    _apiSignature = new Uint8List(16);
+  }
 
   /**
    * The unlinked API signature of the file.
@@ -607,6 +624,17 @@
   final Uint32List _salt;
 
   /**
+   * The optional store with externally provided unlinked and corresponding
+   * linked summaries. These summaries are always added to the store for any
+   * file analysis.
+   *
+   * While walking the file graph, when we reach a file that exists in the
+   * external store, we add a stub [FileState], but don't attempt to read its
+   * content, or its unlinked unit, or imported libraries, etc.
+   */
+  final SummaryDataStore externalSummaries;
+
+  /**
    * Mapping from a URI to the corresponding [FileState].
    */
   final Map<Uri, FileState> _uriToFile = {};
@@ -674,7 +702,8 @@
       this._resourceProvider,
       this._sourceFactory,
       this._analysisOptions,
-      this._salt) {
+      this._salt,
+      {this.externalSummaries}) {
     _testView = new FileSystemStateTestView(this);
   }
 
@@ -744,6 +773,17 @@
   FileState getFileForUri(Uri uri) {
     FileState file = _uriToFile[uri];
     if (file == null) {
+      // If the external store has this URI, create a stub file for it.
+      // We are given all required unlinked and linked summaries for it.
+      if (externalSummaries != null) {
+        String uriStr = uri.toString();
+        if (externalSummaries.hasUnlinkedUnit(uriStr)) {
+          file = new FileState._external(this, uri);
+          _uriToFile[uri] = file;
+          return file;
+        }
+      }
+
       Source uriSource = _sourceFactory.resolveUri(null, uri.toString());
 
       // If the URI cannot be resolved, for example because the factory
@@ -825,17 +865,14 @@
 
   void _scheduleKnownFilesSetChange() {
     Duration delay = _knownFilesSetChangesDelay ?? new Duration(seconds: 1);
-    // Note: we don't use ??= here due to issue #29393
-    if (_knownFilesSetChangesTimer == null) {
-      _knownFilesSetChangesTimer = new Timer(delay, () {
-        Set<String> addedFiles = _addedKnownFiles.toSet();
-        Set<String> removedFiles = new Set<String>();
-        _knownFilesSetChangesController
-            .add(new KnownFilesSetChange(addedFiles, removedFiles));
-        _addedKnownFiles.clear();
-        _knownFilesSetChangesTimer = null;
-      });
-    }
+    _knownFilesSetChangesTimer ??= new Timer(delay, () {
+      Set<String> addedFiles = _addedKnownFiles.toSet();
+      Set<String> removedFiles = new Set<String>();
+      _knownFilesSetChangesController
+          .add(new KnownFilesSetChange(addedFiles, removedFiles));
+      _addedKnownFiles.clear();
+      _knownFilesSetChangesTimer = null;
+    });
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart b/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
index aaee810..9323960 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
@@ -3,14 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
-import 'dart:typed_data';
 
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
 
 /**
  * Callback used by [FileTracker] to report to its client that files have been
@@ -40,12 +35,12 @@
   /**
    * The logger to write performed operations and performance to.
    */
-  final PerformanceLog logger;
+  final PerformanceLog _logger;
 
   /**
    * The current file system state.
    */
-  final FileSystemState fsState;
+  final FileSystemState _fsState;
 
   /**
    * The set of added files.
@@ -82,17 +77,7 @@
    */
   var _pendingFiles = new LinkedHashSet<String>();
 
-  FileTracker(
-      this.logger,
-      ByteStore byteStore,
-      FileContentOverlay contentOverlay,
-      ResourceProvider resourceProvider,
-      SourceFactory sourceFactory,
-      AnalysisOptions analysisOptions,
-      Uint32List salt,
-      this._changeHook)
-      : fsState = new FileSystemState(logger, byteStore, contentOverlay,
-            resourceProvider, sourceFactory, analysisOptions, salt);
+  FileTracker(this._logger, this._fsState, this._changeHook);
 
   /**
    * Returns the path to exactly one that needs analysis.  Throws a [StateError]
@@ -218,7 +203,7 @@
     _pendingFiles.remove(path);
     // TODO(paulberry): removing the path from [fsState] and re-analyzing all
     // files seems extreme.
-    fsState.removeFile(path);
+    _fsState.removeFile(path);
     _pendingFiles.addAll(addedFiles);
     _changeHook();
   }
@@ -228,9 +213,9 @@
    * which linked libraries should be invalidated, and files reanalyzed.
    */
   FileState verifyApiSignature(String path) {
-    return logger.run('Verify API signature of $path', () {
+    return _logger.run('Verify API signature of $path', () {
       bool anyApiChanged = false;
-      List<FileState> files = fsState.getFilesForPath(path);
+      List<FileState> files = _fsState.getFilesForPath(path);
       for (FileState file in files) {
         bool apiChanged = file.refresh();
         if (apiChanged) {
@@ -238,7 +223,7 @@
         }
       }
       if (anyApiChanged) {
-        logger.writeln('API signatures mismatch found for $path');
+        _logger.writeln('API signatures mismatch found for $path');
         // TODO(scheglov) schedule analysis of only affected files
         var pendingChangedFiles = new LinkedHashSet<String>();
         var pendingImportFiles = new LinkedHashSet<String>();
@@ -252,7 +237,7 @@
 
         // Add files that directly import the changed file.
         for (String addedPath in addedFiles) {
-          FileState addedFile = fsState.getFileForPath(addedPath);
+          FileState addedFile = _fsState.getFileForPath(addedPath);
           for (FileState changedFile in files) {
             if (addedFile.importedFiles.contains(changedFile)) {
               pendingImportFiles.add(addedPath);
@@ -262,7 +247,7 @@
 
         // Add files with errors or warnings that might be fixed.
         for (String addedPath in addedFiles) {
-          FileState addedFile = fsState.getFileForPath(addedPath);
+          FileState addedFile = _fsState.getFileForPath(addedPath);
           if (addedFile.hasErrorOrWarning) {
             pendingErrorFiles.add(addedPath);
           }
@@ -300,7 +285,7 @@
       _changedFiles.remove(path);
       // If the file has not been accessed yet, we either will eventually read
       // it later while analyzing one of the added files, or don't need it.
-      if (fsState.knownFilePaths.contains(path)) {
+      if (_fsState.knownFilePaths.contains(path)) {
         verifyApiSignature(path);
       }
       return true;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index acbf423..4987624 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -758,6 +758,12 @@
 
   @override
   bool getExists(Source source) {
+    if (fsState.externalSummaries != null) {
+      String uriStr = source.uri.toString();
+      if (fsState.externalSummaries.hasUnlinkedUnit(uriStr)) {
+        return true;
+      }
+    }
     return _getFileForSource(source).exists;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index f14cde2..9ec2aea 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -4,13 +4,13 @@
 
 import 'package:analyzer/context/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart' show CompilationUnitElement;
+import 'package:analyzer/dart/element/element.dart'
+    show CompilationUnitElement, LibraryElement;
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/dart/analysis/file_tracker.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisEngine, AnalysisOptions;
 import 'package:analyzer/src/generated/source.dart';
@@ -47,11 +47,16 @@
       AnalysisOptions options,
       DeclaredVariables declaredVariables,
       SourceFactory sourceFactory,
-      FileTracker fileTracker) {
+      SummaryDataStore externalSummaries,
+      FileSystemState fsState) {
     return logger.run('Create library context', () {
       Map<String, FileState> libraries = <String, FileState>{};
       SummaryDataStore store = new SummaryDataStore(const <String>[]);
 
+      if (externalSummaries != null) {
+        store.addStore(externalSummaries);
+      }
+
       if (sdkBundle != null) {
         store.addBundle(null, sdkBundle);
       }
@@ -63,6 +68,10 @@
             return;
           }
 
+          if (library.isInExternalSummaries) {
+            return;
+          }
+
           libraries[library.uriStr] = library;
 
           // Append the defining unit.
@@ -122,8 +131,9 @@
         byteStore.put(key, bytes);
       });
 
-      var analysisContext = _createAnalysisContext(
-          options, declaredVariables, sourceFactory, fileTracker, store);
+      AnalysisContextImpl analysisContext = _createAnalysisContext(
+          options, declaredVariables, sourceFactory, store);
+      analysisContext.contentCache = new _ContentCacheWrapper(fsState);
 
       return new LibraryContext._(store, analysisContext);
     });
@@ -161,19 +171,37 @@
     return new ResolutionResult(resolvedUnit, errors);
   }
 
-  static AnalysisContext _createAnalysisContext(
-      AnalysisOptions _analysisOptions,
+  /**
+   * Resynthesize the [LibraryElement] from the given [store].
+   */
+  static LibraryElement resynthesizeLibraryElement(
+      AnalysisOptions analysisOptions,
       DeclaredVariables declaredVariables,
-      SourceFactory _sourceFactory,
-      FileTracker fileTracker,
+      SourceFactory sourceFactory,
+      SummaryDataStore store,
+      String uri) {
+    AnalysisContextImpl analysisContext = _createAnalysisContext(
+        analysisOptions, declaredVariables, sourceFactory, store);
+    try {
+      return new StoreBasedSummaryResynthesizer(
+              analysisContext, sourceFactory, analysisOptions.strongMode, store)
+          .getLibraryElement(uri);
+    } finally {
+      analysisContext.dispose();
+    }
+  }
+
+  static AnalysisContextImpl _createAnalysisContext(
+      AnalysisOptions analysisOptions,
+      DeclaredVariables declaredVariables,
+      SourceFactory sourceFactory,
       SummaryDataStore store) {
     AnalysisContextImpl analysisContext =
         AnalysisEngine.instance.createAnalysisContext();
     analysisContext.useSdkCachePartition = false;
-    analysisContext.analysisOptions = _analysisOptions;
+    analysisContext.analysisOptions = analysisOptions;
     analysisContext.declaredVariables.addAll(declaredVariables);
-    analysisContext.sourceFactory = _sourceFactory.clone();
-    analysisContext.contentCache = new _ContentCacheWrapper(fileTracker);
+    analysisContext.sourceFactory = sourceFactory.clone();
     analysisContext.resultProvider =
         new InputPackagesResultProvider(analysisContext, store);
     return analysisContext;
@@ -195,9 +223,9 @@
  * [ContentCache] wrapper around [FileContentOverlay].
  */
 class _ContentCacheWrapper implements ContentCache {
-  final FileTracker fileTracker;
+  final FileSystemState fsState;
 
-  _ContentCacheWrapper(this.fileTracker);
+  _ContentCacheWrapper(this.fsState);
 
   @override
   void accept(ContentCacheVisitor visitor) {
@@ -214,6 +242,10 @@
     if (source.isInSystemLibrary) {
       return true;
     }
+    String uriStr = source.uri.toString();
+    if (fsState.externalSummaries.hasUnlinkedUnit(uriStr)) {
+      return true;
+    }
     return _getFileForSource(source).exists;
   }
 
@@ -232,6 +264,6 @@
 
   FileState _getFileForSource(Source source) {
     String path = source.fullName;
-    return fileTracker.fsState.getFileForPath(path);
+    return fsState.getFileForPath(path);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 656b1c2..5573798 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -9456,6 +9456,16 @@
         return false;
       }
     }
+    if (parent is FieldFormalParameter) {
+      if (identical(parent.identifier, target)) {
+        return false;
+      }
+    }
+    if (parent is VariableDeclaration) {
+      if (identical(parent.name, target)) {
+        return false;
+      }
+    }
     return true;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 9572778..58b3e7b 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -740,6 +740,9 @@
         // it redirects to.
         ConstructorElement constructor = initializer.staticElement;
         if (constructor != null && constructor.isConst) {
+          // Instantiate the constructor with the in-scope type arguments.
+          constructor = ConstructorMember.from(constructor, definingClass);
+
           DartObjectImpl result = evaluateConstructorCall(
               node,
               initializer.argumentList.arguments,
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 17a7e99..a22e9bb 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2426,7 +2426,7 @@
    * with this element. The single instance of this class should be accessed
    * through the method [instance].
    */
-  DynamicElementImpl() : super(Keyword.DYNAMIC.syntax, -1) {
+  DynamicElementImpl() : super(Keyword.DYNAMIC.lexeme, -1) {
     setModifier(Modifier.SYNTHETIC, true);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 2189a20..5462ac6 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -283,14 +283,14 @@
    * Prevent the creation of instances of this class.
    */
   DynamicTypeImpl._()
-      : super(new DynamicElementImpl(), Keyword.DYNAMIC.syntax) {
+      : super(new DynamicElementImpl(), Keyword.DYNAMIC.lexeme) {
     (element as DynamicElementImpl).type = this;
   }
 
   /**
    * Constructor used by [CircularTypeImpl].
    */
-  DynamicTypeImpl._circular() : super(instance.element, Keyword.DYNAMIC.syntax);
+  DynamicTypeImpl._circular() : super(instance.element, Keyword.DYNAMIC.lexeme);
 
   @override
   int get hashCode => 1;
@@ -2842,7 +2842,7 @@
    * Prevent the creation of instances of this class.
    */
   UndefinedTypeImpl._()
-      : super(DynamicElementImpl.instance, Keyword.DYNAMIC.syntax);
+      : super(DynamicElementImpl.instance, Keyword.DYNAMIC.lexeme);
 
   @override
   int get hashCode => 1;
@@ -2911,7 +2911,7 @@
   /**
    * Prevent the creation of instances of this class.
    */
-  VoidTypeImpl._() : super(null, Keyword.VOID.syntax);
+  VoidTypeImpl._() : super(null, Keyword.VOID.lexeme);
 
   @override
   int get hashCode => 2;
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index bb10100..0bb2e72 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -10,10 +10,9 @@
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:front_end/src/fasta/scanner.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/precedence.dart' as fasta;
 import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
 import 'package:front_end/src/scanner/scanner.dart' as fe;
-import 'package:front_end/src/scanner/token.dart' show Token;
+import 'package:front_end/src/scanner/token.dart' show Token, TokenType;
 
 export 'package:analyzer/src/dart/error/syntactic_errors.dart';
 export 'package:front_end/src/scanner/scanner.dart' show KeywordState;
@@ -156,7 +155,7 @@
     fasta.Token token = result.tokens;
     // The default recovery strategy used by scanString
     // places all error tokens at the head of the stream.
-    while (token.info == fasta.BAD_INPUT_INFO) {
+    while (token.info == TokenType.BAD_INPUT) {
       translateErrorToken(token, reportError);
       token = token.next;
     }
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index f86f0d9..155b8d8 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1135,7 +1135,7 @@
           "This class can't implement the deferred class '{0}'.",
           "Try specifying a different interface, "
           "removing the class from the list, or "
-          "changing the import to not be deferred..");
+          "changing the import to not be deferred.");
 
   /**
    * 12.2 Null: It is a compile-time error for a class to attempt to extend or
diff --git a/pkg/front_end/lib/src/fasta/analyzer/analyzer_diet_listener.dart b/pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart
similarity index 65%
rename from pkg/front_end/lib/src/fasta/analyzer/analyzer_diet_listener.dart
rename to pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart
index 497aea7..7bc3433 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/analyzer_diet_listener.dart
+++ b/pkg/analyzer/lib/src/fasta/analyzer_diet_listener.dart
@@ -6,17 +6,20 @@
 
 import 'package:kernel/ast.dart' show AsyncMarker;
 
-import '../source/stack_listener.dart' show StackListener;
+import 'package:front_end/src/fasta/source/stack_listener.dart'
+    show StackListener;
 
-import '../builder/builder.dart';
+import 'package:front_end/src/fasta/builder/builder.dart';
 
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import 'package:front_end/src/fasta/source/source_library_builder.dart'
+    show SourceLibraryBuilder;
 
-import '../source/diet_listener.dart' show DietListener;
+import 'package:front_end/src/fasta/source/diet_listener.dart'
+    show DietListener;
 
-import 'package:analyzer/src/fasta/element_store.dart' show ElementStore;
+import 'element_store.dart' show ElementStore;
 
-import 'package:analyzer/src/fasta/ast_builder.dart' show AstBuilder;
+import 'ast_builder.dart' show AstBuilder;
 
 class AnalyzerDietListener extends DietListener {
   final ElementStore elementStore;
diff --git a/pkg/front_end/lib/src/fasta/analyzer/analyzer_loader.dart b/pkg/analyzer/lib/src/fasta/analyzer_loader.dart
similarity index 73%
rename from pkg/front_end/lib/src/fasta/analyzer/analyzer_loader.dart
rename to pkg/analyzer/lib/src/fasta/analyzer_loader.dart
index 0afa0ac..ea95f82 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/analyzer_loader.dart
+++ b/pkg/analyzer/lib/src/fasta/analyzer_loader.dart
@@ -6,13 +6,16 @@
 
 import 'package:kernel/ast.dart' show Program;
 
-import '../builder/builder.dart' show LibraryBuilder;
+import 'package:front_end/src/fasta/builder/builder.dart' show LibraryBuilder;
 
-import '../target_implementation.dart' show TargetImplementation;
+import 'package:front_end/src/fasta/target_implementation.dart'
+    show TargetImplementation;
 
-import '../source/source_class_builder.dart' show SourceClassBuilder;
+import 'package:front_end/src/fasta/source/source_class_builder.dart'
+    show SourceClassBuilder;
 
-import '../source/source_loader.dart' show SourceLoader;
+import 'package:front_end/src/fasta/source/source_loader.dart'
+    show SourceLoader;
 
 import 'package:analyzer/src/fasta/element_store.dart' show ElementStore;
 
diff --git a/pkg/front_end/lib/src/fasta/analyzer/analyzer_target.dart b/pkg/analyzer/lib/src/fasta/analyzer_target.dart
similarity index 74%
rename from pkg/front_end/lib/src/fasta/analyzer/analyzer_target.dart
rename to pkg/analyzer/lib/src/fasta/analyzer_target.dart
index 8e6434c..29eb092 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/analyzer_target.dart
+++ b/pkg/analyzer/lib/src/fasta/analyzer_target.dart
@@ -6,11 +6,12 @@
 
 import 'package:kernel/ast.dart' show Library, Source;
 
-import '../kernel/kernel_target.dart' show KernelTarget;
+import 'package:front_end/src/fasta/kernel/kernel_target.dart'
+    show KernelTarget;
 
-import '../translate_uri.dart' show TranslateUri;
+import 'package:front_end/src/fasta/translate_uri.dart' show TranslateUri;
 
-import '../dill/dill_target.dart' show DillTarget;
+import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
 
 import 'analyzer_loader.dart' show AnalyzerLoader;
 
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 3344672..a49b372 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -8,10 +8,10 @@
 import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory;
 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
 import 'package:analyzer/dart/ast/token.dart' as analyzer show Token;
+import 'package:analyzer/dart/ast/token.dart' show TokenType;
 import 'package:analyzer/dart/element/element.dart' show Element;
 import 'package:front_end/src/fasta/parser/parser.dart'
     show FormalParameterType, Parser;
-import 'package:front_end/src/fasta/scanner/precedence.dart';
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
 import 'package:front_end/src/fasta/scanner/token.dart'
     show BeginGroupToken, CommentToken, Token;
@@ -1916,12 +1916,13 @@
   Token injectGenericCommentTypeAssign(Token token) {
     // TODO(paulberry,scheglov,ahe): figure out how to share these generic
     // comment methods with BodyBuilder.
-    return _injectGenericComment(token, GENERIC_METHOD_TYPE_ASSIGN, 3);
+    return _injectGenericComment(
+        token, TokenType.GENERIC_METHOD_TYPE_ASSIGN, 3);
   }
 
   @override
   Token injectGenericCommentTypeList(Token token) {
-    return _injectGenericComment(token, GENERIC_METHOD_TYPE_LIST, 2);
+    return _injectGenericComment(token, TokenType.GENERIC_METHOD_TYPE_LIST, 2);
   }
 
   @override
@@ -1938,10 +1939,10 @@
   }
 
   /// Check if the given [token] has a comment token with the given [info],
-  /// which should be either [GENERIC_METHOD_TYPE_ASSIGN] or
-  /// [GENERIC_METHOD_TYPE_LIST].  If found, parse the comment into tokens and
-  /// inject into the token stream before the [token].
-  Token _injectGenericComment(Token token, PrecedenceInfo info, int prefixLen) {
+  /// which should be either [TokenType.GENERIC_METHOD_TYPE_ASSIGN] or
+  /// [TokenType.GENERIC_METHOD_TYPE_LIST].  If found, parse the comment
+  /// into tokens and inject into the token stream before the [token].
+  Token _injectGenericComment(Token token, TokenType info, int prefixLen) {
     if (parseGenericMethodComments) {
       CommentToken t = token.precedingCommentTokens;
       for (; t != null; t = t.next) {
@@ -1964,7 +1965,7 @@
   void _injectTokenList(Token beforeToken, Token firstToken) {
     // Scanner creates a cyclic EOF token.
     Token lastToken = firstToken;
-    while (lastToken.next.info != EOF_INFO) {
+    while (lastToken.next.info != TokenType.EOF) {
       lastToken = lastToken.next;
     }
     // Inject these new tokens into the stream.
diff --git a/pkg/analyzer/lib/src/fasta/token_utils.dart b/pkg/analyzer/lib/src/fasta/token_utils.dart
index 11d0a66..ed035bc 100644
--- a/pkg/analyzer/lib/src/fasta/token_utils.dart
+++ b/pkg/analyzer/lib/src/fasta/token_utils.dart
@@ -8,8 +8,6 @@
 
 import 'package:front_end/src/scanner/token.dart' show Keyword;
 
-import 'package:front_end/src/fasta/scanner/precedence.dart';
-
 import 'package:front_end/src/fasta/scanner/token.dart'
     show
         BeginGroupToken,
@@ -168,9 +166,9 @@
 /// Converts a single Fasta comment token to an analyzer comment token.
 analyzer.CommentToken toAnalyzerCommentToken(Token token) {
   TokenType type;
-  if (token.type == GENERIC_METHOD_TYPE_ASSIGN) {
+  if (token.type == TokenType.GENERIC_METHOD_TYPE_ASSIGN) {
     type = TokenType.GENERIC_METHOD_TYPE_ASSIGN;
-  } else if (token.type == GENERIC_METHOD_TYPE_LIST) {
+  } else if (token.type == TokenType.GENERIC_METHOD_TYPE_LIST) {
     type = TokenType.GENERIC_METHOD_TYPE_LIST;
   } else {
     // TODO(paulberry,ahe): It would be nice if the scanner gave us an
@@ -277,16 +275,23 @@
 
 /// Converts a single analyzer token into a Fasta token.
 Token fromAnalyzerToken(analyzer.Token token) {
-  Token beginGroup(PrecedenceInfo info) =>
-      new BeginGroupToken(info, token.offset);
-  Token string(PrecedenceInfo info) =>
+  Token beginGroup(TokenType info) => new BeginGroupToken(info, token.offset);
+  Token string(TokenType info) =>
       new StringToken.fromString(info, token.lexeme, token.offset);
-  Token symbol(PrecedenceInfo info) => new SymbolToken(info, token.offset);
+  Token symbol(TokenType info) => new SymbolToken(info, token.offset);
+  if (token.type.isKeyword) {
+    var keyword = Keyword.keywords[token.lexeme];
+    if (keyword != null) {
+      return new KeywordToken(keyword, token.offset);
+    } else {
+      return internalError("Unrecognized keyword: '${token.lexeme}'.");
+    }
+  }
   switch (token.type) {
     case TokenType.DOUBLE:
-      return string(DOUBLE_INFO);
+      return string(TokenType.DOUBLE);
     case TokenType.HEXADECIMAL:
-      return string(HEXADECIMAL_INFO);
+      return string(TokenType.HEXADECIMAL);
     case TokenType.IDENTIFIER:
       // Certain identifiers have special grammatical meanings even though they
       // are neither keywords nor built-in identifiers (e.g. "async").  Analyzer
@@ -297,159 +302,151 @@
         assert(keyword.isPseudo);
         return new KeywordToken(keyword, token.offset);
       } else {
-        return string(IDENTIFIER_INFO);
+        return string(TokenType.IDENTIFIER);
       }
       break;
     case TokenType.INT:
-      return string(INT_INFO);
-    case TokenType.KEYWORD:
-      var keyword = Keyword.keywords[token.lexeme];
-      if (keyword != null) {
-        return new KeywordToken(keyword, token.offset);
-      } else {
-        return internalError("Unrecognized keyword: '${token.lexeme}'.");
-      }
-      break;
+      return string(TokenType.INT);
     case TokenType.MULTI_LINE_COMMENT:
       if (token.lexeme.startsWith('/**')) {
-        return new DartDocToken.fromSubstring(
-            MULTI_LINE_COMMENT_INFO, token.lexeme, 0, token.lexeme.length, 0);
+        return new DartDocToken.fromSubstring(TokenType.MULTI_LINE_COMMENT,
+            token.lexeme, 0, token.lexeme.length, 0);
       }
-      return new CommentToken.fromSubstring(
-          MULTI_LINE_COMMENT_INFO, token.lexeme, 0, token.lexeme.length, 0);
+      return new CommentToken.fromSubstring(TokenType.MULTI_LINE_COMMENT,
+          token.lexeme, 0, token.lexeme.length, 0);
     case TokenType.SCRIPT_TAG:
-      return string(SCRIPT_INFO);
+      return string(TokenType.SCRIPT_TAG);
     case TokenType.SINGLE_LINE_COMMENT:
       if (token.lexeme.startsWith('///')) {
-        return new DartDocToken.fromSubstring(
-            SINGLE_LINE_COMMENT_INFO, token.lexeme, 0, token.lexeme.length, 0);
+        return new DartDocToken.fromSubstring(TokenType.SINGLE_LINE_COMMENT,
+            token.lexeme, 0, token.lexeme.length, 0);
       }
-      return new CommentToken.fromSubstring(
-          SINGLE_LINE_COMMENT_INFO, token.lexeme, 0, token.lexeme.length, 0);
+      return new CommentToken.fromSubstring(TokenType.SINGLE_LINE_COMMENT,
+          token.lexeme, 0, token.lexeme.length, 0);
     case TokenType.STRING:
-      return string(STRING_INFO);
+      return string(TokenType.STRING);
     case TokenType.AMPERSAND:
-      return symbol(AMPERSAND_INFO);
+      return symbol(TokenType.AMPERSAND);
     case TokenType.AMPERSAND_AMPERSAND:
-      return symbol(AMPERSAND_AMPERSAND_INFO);
+      return symbol(TokenType.AMPERSAND_AMPERSAND);
     // case TokenType.AMPERSAND_AMPERSAND_EQ
     case TokenType.AMPERSAND_EQ:
-      return symbol(AMPERSAND_EQ_INFO);
+      return symbol(TokenType.AMPERSAND_EQ);
     case TokenType.AT:
-      return symbol(AT_INFO);
+      return symbol(TokenType.AT);
     case TokenType.BANG:
-      return symbol(BANG_INFO);
+      return symbol(TokenType.BANG);
     case TokenType.BANG_EQ:
-      return symbol(BANG_EQ_INFO);
+      return symbol(TokenType.BANG_EQ);
     case TokenType.BAR:
-      return symbol(BAR_INFO);
+      return symbol(TokenType.BAR);
     case TokenType.BAR_BAR:
-      return symbol(BAR_BAR_INFO);
+      return symbol(TokenType.BAR_BAR);
     // case TokenType.BAR_BAR_EQ
     case TokenType.BAR_EQ:
-      return symbol(BAR_EQ_INFO);
+      return symbol(TokenType.BAR_EQ);
     case TokenType.COLON:
-      return symbol(COLON_INFO);
+      return symbol(TokenType.COLON);
     case TokenType.COMMA:
-      return symbol(COMMA_INFO);
+      return symbol(TokenType.COMMA);
     case TokenType.CARET:
-      return symbol(CARET_INFO);
+      return symbol(TokenType.CARET);
     case TokenType.CARET_EQ:
-      return symbol(CARET_EQ_INFO);
+      return symbol(TokenType.CARET_EQ);
     case TokenType.CLOSE_CURLY_BRACKET:
-      return symbol(CLOSE_CURLY_BRACKET_INFO);
+      return symbol(TokenType.CLOSE_CURLY_BRACKET);
     case TokenType.CLOSE_PAREN:
-      return symbol(CLOSE_PAREN_INFO);
+      return symbol(TokenType.CLOSE_PAREN);
     case TokenType.CLOSE_SQUARE_BRACKET:
-      return symbol(CLOSE_SQUARE_BRACKET_INFO);
+      return symbol(TokenType.CLOSE_SQUARE_BRACKET);
     case TokenType.EQ:
-      return symbol(EQ_INFO);
+      return symbol(TokenType.EQ);
     case TokenType.EQ_EQ:
-      return symbol(EQ_EQ_INFO);
+      return symbol(TokenType.EQ_EQ);
     case TokenType.FUNCTION:
-      return symbol(FUNCTION_INFO);
+      return symbol(TokenType.FUNCTION);
     case TokenType.GT:
-      return symbol(GT_INFO);
+      return symbol(TokenType.GT);
     case TokenType.GT_EQ:
-      return symbol(GT_EQ_INFO);
+      return symbol(TokenType.GT_EQ);
     case TokenType.GT_GT:
-      return symbol(GT_GT_INFO);
+      return symbol(TokenType.GT_GT);
     case TokenType.GT_GT_EQ:
-      return symbol(GT_GT_EQ_INFO);
+      return symbol(TokenType.GT_GT_EQ);
     case TokenType.HASH:
-      return symbol(HASH_INFO);
+      return symbol(TokenType.HASH);
     case TokenType.INDEX:
-      return symbol(INDEX_INFO);
+      return symbol(TokenType.INDEX);
     case TokenType.INDEX_EQ:
-      return symbol(INDEX_EQ_INFO);
+      return symbol(TokenType.INDEX_EQ);
     case TokenType.LT:
-      return beginGroup(LT_INFO);
+      return beginGroup(TokenType.LT);
     case TokenType.LT_EQ:
-      return symbol(LT_EQ_INFO);
+      return symbol(TokenType.LT_EQ);
     case TokenType.LT_LT:
-      return symbol(LT_LT_INFO);
+      return symbol(TokenType.LT_LT);
     case TokenType.LT_LT_EQ:
-      return symbol(LT_LT_EQ_INFO);
+      return symbol(TokenType.LT_LT_EQ);
     case TokenType.MINUS:
-      return symbol(MINUS_INFO);
+      return symbol(TokenType.MINUS);
     case TokenType.MINUS_EQ:
-      return symbol(MINUS_EQ_INFO);
+      return symbol(TokenType.MINUS_EQ);
     case TokenType.MINUS_MINUS:
-      return symbol(MINUS_MINUS_INFO);
+      return symbol(TokenType.MINUS_MINUS);
     case TokenType.OPEN_CURLY_BRACKET:
-      return beginGroup(OPEN_CURLY_BRACKET_INFO);
+      return beginGroup(TokenType.OPEN_CURLY_BRACKET);
     case TokenType.OPEN_PAREN:
-      return beginGroup(OPEN_PAREN_INFO);
+      return beginGroup(TokenType.OPEN_PAREN);
     case TokenType.OPEN_SQUARE_BRACKET:
-      return beginGroup(OPEN_SQUARE_BRACKET_INFO);
+      return beginGroup(TokenType.OPEN_SQUARE_BRACKET);
     case TokenType.PERCENT:
-      return symbol(PERCENT_INFO);
+      return symbol(TokenType.PERCENT);
     case TokenType.PERCENT_EQ:
-      return symbol(PERCENT_EQ_INFO);
+      return symbol(TokenType.PERCENT_EQ);
     case TokenType.PERIOD:
-      return symbol(PERIOD_INFO);
+      return symbol(TokenType.PERIOD);
     case TokenType.PERIOD_PERIOD:
-      return symbol(PERIOD_PERIOD_INFO);
+      return symbol(TokenType.PERIOD_PERIOD);
     case TokenType.PLUS:
-      return symbol(PLUS_INFO);
+      return symbol(TokenType.PLUS);
     case TokenType.PLUS_EQ:
-      return symbol(PLUS_EQ_INFO);
+      return symbol(TokenType.PLUS_EQ);
     case TokenType.PLUS_PLUS:
-      return symbol(PLUS_PLUS_INFO);
+      return symbol(TokenType.PLUS_PLUS);
     case TokenType.QUESTION:
-      return symbol(QUESTION_INFO);
+      return symbol(TokenType.QUESTION);
     case TokenType.QUESTION_PERIOD:
-      return symbol(QUESTION_PERIOD_INFO);
+      return symbol(TokenType.QUESTION_PERIOD);
     case TokenType.QUESTION_QUESTION:
-      return symbol(QUESTION_QUESTION_INFO);
+      return symbol(TokenType.QUESTION_QUESTION);
     case TokenType.QUESTION_QUESTION_EQ:
-      return symbol(QUESTION_QUESTION_EQ_INFO);
+      return symbol(TokenType.QUESTION_QUESTION_EQ);
     case TokenType.SEMICOLON:
-      return symbol(SEMICOLON_INFO);
+      return symbol(TokenType.SEMICOLON);
     case TokenType.SLASH:
-      return symbol(SLASH_INFO);
+      return symbol(TokenType.SLASH);
     case TokenType.SLASH_EQ:
-      return symbol(SLASH_EQ_INFO);
+      return symbol(TokenType.SLASH_EQ);
     case TokenType.STAR:
-      return symbol(STAR_INFO);
+      return symbol(TokenType.STAR);
     case TokenType.STAR_EQ:
-      return symbol(STAR_EQ_INFO);
+      return symbol(TokenType.STAR_EQ);
     case TokenType.STRING_INTERPOLATION_EXPRESSION:
-      return beginGroup(STRING_INTERPOLATION_INFO);
+      return beginGroup(TokenType.STRING_INTERPOLATION_EXPRESSION);
     case TokenType.STRING_INTERPOLATION_IDENTIFIER:
-      return symbol(STRING_INTERPOLATION_IDENTIFIER_INFO);
+      return symbol(TokenType.STRING_INTERPOLATION_IDENTIFIER);
     case TokenType.TILDE:
-      return symbol(TILDE_INFO);
+      return symbol(TokenType.TILDE);
     case TokenType.TILDE_SLASH:
-      return symbol(TILDE_SLASH_INFO);
+      return symbol(TokenType.TILDE_SLASH);
     case TokenType.TILDE_SLASH_EQ:
-      return symbol(TILDE_SLASH_EQ_INFO);
+      return symbol(TokenType.TILDE_SLASH_EQ);
     case TokenType.BACKPING:
-      return symbol(BACKPING_INFO);
+      return symbol(TokenType.BACKPING);
     case TokenType.BACKSLASH:
-      return symbol(BACKSLASH_INFO);
+      return symbol(TokenType.BACKSLASH);
     case TokenType.PERIOD_PERIOD_PERIOD:
-      return symbol(PERIOD_PERIOD_PERIOD_INFO);
+      return symbol(TokenType.PERIOD_PERIOD_PERIOD);
     // case TokenType.GENERIC_METHOD_TYPE_ASSIGN
     // case TokenType.GENERIC_METHOD_TYPE_LIST
     default:
@@ -494,7 +491,7 @@
 
     case KEYWORD_TOKEN:
       KeywordToken keywordToken = token;
-      var syntax = keywordToken.keyword.syntax;
+      var syntax = keywordToken.keyword.lexeme;
       // TODO(paulberry): if the map lookup proves to be too slow, consider
       // using a switch statement, or perhaps a string of
       // "if (identical(syntax, "foo"))" checks.  (Note that identical checks
@@ -520,14 +517,14 @@
     case OPEN_SQUARE_BRACKET_TOKEN:
     case OPEN_PAREN_TOKEN:
     case STRING_INTERPOLATION_TOKEN:
-      return makeBeginToken(getTokenType(token));
+      return makeBeginToken(token.type);
 
     default:
       if (commentToken == null) {
-        return new analyzer.Token(getTokenType(token), token.charOffset);
+        return new analyzer.Token(token.type, token.charOffset);
       } else {
         return new analyzer.TokenWithComment(
-            getTokenType(token), token.charOffset, commentToken);
+            token.type, token.charOffset, commentToken);
       }
       break;
   }
@@ -600,155 +597,3 @@
   "sync": analyzer.Keyword.SYNC,
   "yield": analyzer.Keyword.YIELD,
 };
-
-TokenType getTokenType(Token token) {
-  switch (token.kind) {
-    case EOF_TOKEN:
-      return TokenType.EOF;
-    case DOUBLE_TOKEN:
-      return TokenType.DOUBLE;
-    case HEXADECIMAL_TOKEN:
-      return TokenType.HEXADECIMAL;
-    case IDENTIFIER_TOKEN:
-      return TokenType.IDENTIFIER;
-    case INT_TOKEN:
-      return TokenType.INT;
-    case KEYWORD_TOKEN:
-      return TokenType.KEYWORD;
-    // case MULTI_LINE_COMMENT_TOKEN: return TokenType.MULTI_LINE_COMMENT;
-    // case SCRIPT_TAG_TOKEN: return TokenType.SCRIPT_TAG;
-    // case SINGLE_LINE_COMMENT_TOKEN: return TokenType.SINGLE_LINE_COMMENT;
-    case STRING_TOKEN:
-      return TokenType.STRING;
-    case AMPERSAND_TOKEN:
-      return TokenType.AMPERSAND;
-    case AMPERSAND_AMPERSAND_TOKEN:
-      return TokenType.AMPERSAND_AMPERSAND;
-    // case AMPERSAND_AMPERSAND_EQ_TOKEN:
-    //   return TokenType.AMPERSAND_AMPERSAND_EQ;
-    case AMPERSAND_EQ_TOKEN:
-      return TokenType.AMPERSAND_EQ;
-    case AT_TOKEN:
-      return TokenType.AT;
-    case BANG_TOKEN:
-      return TokenType.BANG;
-    case BANG_EQ_TOKEN:
-      return TokenType.BANG_EQ;
-    case BAR_TOKEN:
-      return TokenType.BAR;
-    case BAR_BAR_TOKEN:
-      return TokenType.BAR_BAR;
-    // case BAR_BAR_EQ_TOKEN: return TokenType.BAR_BAR_EQ;
-    case BAR_EQ_TOKEN:
-      return TokenType.BAR_EQ;
-    case COLON_TOKEN:
-      return TokenType.COLON;
-    case COMMA_TOKEN:
-      return TokenType.COMMA;
-    case CARET_TOKEN:
-      return TokenType.CARET;
-    case CARET_EQ_TOKEN:
-      return TokenType.CARET_EQ;
-    case CLOSE_CURLY_BRACKET_TOKEN:
-      return TokenType.CLOSE_CURLY_BRACKET;
-    case CLOSE_PAREN_TOKEN:
-      return TokenType.CLOSE_PAREN;
-    case CLOSE_SQUARE_BRACKET_TOKEN:
-      return TokenType.CLOSE_SQUARE_BRACKET;
-    case EQ_TOKEN:
-      return TokenType.EQ;
-    case EQ_EQ_TOKEN:
-      return TokenType.EQ_EQ;
-    case FUNCTION_TOKEN:
-      return TokenType.FUNCTION;
-    case GT_TOKEN:
-      return TokenType.GT;
-    case GT_EQ_TOKEN:
-      return TokenType.GT_EQ;
-    case GT_GT_TOKEN:
-      return TokenType.GT_GT;
-    case GT_GT_EQ_TOKEN:
-      return TokenType.GT_GT_EQ;
-    case HASH_TOKEN:
-      return TokenType.HASH;
-    case INDEX_TOKEN:
-      return TokenType.INDEX;
-    case INDEX_EQ_TOKEN:
-      return TokenType.INDEX_EQ;
-    // case IS_TOKEN: return TokenType.IS;
-    case LT_TOKEN:
-      return TokenType.LT;
-    case LT_EQ_TOKEN:
-      return TokenType.LT_EQ;
-    case LT_LT_TOKEN:
-      return TokenType.LT_LT;
-    case LT_LT_EQ_TOKEN:
-      return TokenType.LT_LT_EQ;
-    case MINUS_TOKEN:
-      return TokenType.MINUS;
-    case MINUS_EQ_TOKEN:
-      return TokenType.MINUS_EQ;
-    case MINUS_MINUS_TOKEN:
-      return TokenType.MINUS_MINUS;
-    case OPEN_CURLY_BRACKET_TOKEN:
-      return TokenType.OPEN_CURLY_BRACKET;
-    case OPEN_PAREN_TOKEN:
-      return TokenType.OPEN_PAREN;
-    case OPEN_SQUARE_BRACKET_TOKEN:
-      return TokenType.OPEN_SQUARE_BRACKET;
-    case PERCENT_TOKEN:
-      return TokenType.PERCENT;
-    case PERCENT_EQ_TOKEN:
-      return TokenType.PERCENT_EQ;
-    case PERIOD_TOKEN:
-      return TokenType.PERIOD;
-    case PERIOD_PERIOD_TOKEN:
-      return TokenType.PERIOD_PERIOD;
-    case PLUS_TOKEN:
-      return TokenType.PLUS;
-    case PLUS_EQ_TOKEN:
-      return TokenType.PLUS_EQ;
-    case PLUS_PLUS_TOKEN:
-      return TokenType.PLUS_PLUS;
-    case QUESTION_TOKEN:
-      return TokenType.QUESTION;
-    case QUESTION_PERIOD_TOKEN:
-      return TokenType.QUESTION_PERIOD;
-    case QUESTION_QUESTION_TOKEN:
-      return TokenType.QUESTION_QUESTION;
-    case QUESTION_QUESTION_EQ_TOKEN:
-      return TokenType.QUESTION_QUESTION_EQ;
-    case SEMICOLON_TOKEN:
-      return TokenType.SEMICOLON;
-    case SLASH_TOKEN:
-      return TokenType.SLASH;
-    case SLASH_EQ_TOKEN:
-      return TokenType.SLASH_EQ;
-    case STAR_TOKEN:
-      return TokenType.STAR;
-    case STAR_EQ_TOKEN:
-      return TokenType.STAR_EQ;
-    case STRING_INTERPOLATION_TOKEN:
-      return TokenType.STRING_INTERPOLATION_EXPRESSION;
-    case STRING_INTERPOLATION_IDENTIFIER_TOKEN:
-      return TokenType.STRING_INTERPOLATION_IDENTIFIER;
-    case TILDE_TOKEN:
-      return TokenType.TILDE;
-    case TILDE_SLASH_TOKEN:
-      return TokenType.TILDE_SLASH;
-    case TILDE_SLASH_EQ_TOKEN:
-      return TokenType.TILDE_SLASH_EQ;
-    case BACKPING_TOKEN:
-      return TokenType.BACKPING;
-    case BACKSLASH_TOKEN:
-      return TokenType.BACKSLASH;
-    case PERIOD_PERIOD_PERIOD_TOKEN:
-      return TokenType.PERIOD_PERIOD_PERIOD;
-    case GENERIC_METHOD_TYPE_LIST_TOKEN:
-      return TokenType.GENERIC_METHOD_TYPE_LIST;
-    case GENERIC_METHOD_TYPE_ASSIGN_TOKEN:
-      return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
-    default:
-      return internalError("Unhandled token ${token.info}");
-  }
-}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index adb72c4..c692cbc 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1244,14 +1244,6 @@
   List<String> get excludePatterns;
 
   /**
-   * A flag indicating whether finer grained dependencies should be used
-   * instead of just source level dependencies.
-   *
-   * This option is experimental and subject to change.
-   */
-  bool get finerGrainedInvalidation;
-
-  /**
    * Return `true` if errors, warnings and hints should be generated for sources
    * that are implicitly being analyzed. The default value is `true`.
    */
@@ -1487,9 +1479,6 @@
    */
   List<String> nonnullableTypes = NONNULLABLE_TYPES;
 
-  @override
-  bool finerGrainedInvalidation = false;
-
   /**
    * A flag indicating whether implicit dynamic type is allowed, on by default.
    *
@@ -1540,7 +1529,6 @@
     }
     trackCacheDependencies = options.trackCacheDependencies;
     disableCacheFlushing = options.disableCacheFlushing;
-    finerGrainedInvalidation = options.finerGrainedInvalidation;
     patchPaths = options.patchPaths;
   }
 
@@ -1691,7 +1679,6 @@
     enableUriInPartOf = true;
     _errorProcessors = null;
     _excludePatterns = null;
-    finerGrainedInvalidation = false;
     generateImplicitErrors = true;
     generateSdkErrors = false;
     hint = true;
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 1d1cb03..a48ecd5 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -463,33 +463,15 @@
       _checkForMemberWithClassName();
       _checkForNoDefaultSuperConstructorImplicit(node);
       _checkForConflictingTypeVariableErrorCodes(node);
-      ExtendsClause extendsClause = node.extendsClause;
+      TypeName superclass = node.extendsClause?.superclass;
       ImplementsClause implementsClause = node.implementsClause;
       WithClause withClause = node.withClause;
+
       // Only do error checks on the clause nodes if there is a non-null clause
       if (implementsClause != null ||
-          extendsClause != null ||
+          superclass != null ||
           withClause != null) {
-        // Only check for all of the inheritance logic around clauses if there
-        // isn't an error code such as "Cannot extend double" already on the
-        // class.
-        if (!_checkForImplementsDisallowedClass(implementsClause) &&
-            !_checkForExtendsDisallowedClass(extendsClause) &&
-            !_checkForAllMixinErrorCodes(withClause)) {
-          _checkForExtendsDeferredClass(extendsClause);
-          _checkForImplementsDeferredClass(implementsClause);
-          _checkForNonAbstractClassInheritsAbstractMember(node.name);
-          _checkForInconsistentMethodInheritance();
-          _checkForRecursiveInterfaceInheritance(_enclosingClass);
-          _checkForConflictingGetterAndMethod();
-          _checkForConflictingInstanceGetterAndSuperclassMember();
-          _checkImplementsSuperClass(node);
-          _checkImplementsFunctionWithoutCall(node);
-          _checkForMixinHasNoConstructors(node);
-          if (_options.strongMode) {
-            _checkForMixinWithConflictingPrivateMember(node);
-          }
-        }
+        _checkClassInheritance(node, superclass, withClause, implementsClause);
       }
       visitClassDeclarationIncrementally(node);
       _checkForFinalNotInitializedInClass(node);
@@ -533,19 +515,8 @@
     ClassElementImpl outerClassElement = _enclosingClass;
     try {
       _enclosingClass = AbstractClassElementImpl.getImpl(node.element);
-      ImplementsClause implementsClause = node.implementsClause;
-      // Only check for all of the inheritance logic around clauses if there
-      // isn't an error code such as "Cannot extend double" already on the
-      // class.
-      if (!_checkForExtendsDisallowedClassInTypeAlias(node) &&
-          !_checkForImplementsDisallowedClass(implementsClause) &&
-          !_checkForAllMixinErrorCodes(node.withClause)) {
-        _checkForExtendsDeferredClassInTypeAlias(node);
-        _checkForImplementsDeferredClass(implementsClause);
-        _checkForRecursiveInterfaceInheritance(_enclosingClass);
-        _checkForNonAbstractClassInheritsAbstractMember(node.name);
-        _checkForMixinHasNoConstructors(node);
-      }
+      _checkClassInheritance(
+          node, node.superclass, node.withClause, node.implementsClause);
     } finally {
       _enclosingClass = outerClassElement;
     }
@@ -699,12 +670,6 @@
   }
 
   @override
-  Object visitExtendsClause(ExtendsClause node) {
-    _checkForImplicitDynamicType(node.superclass);
-    return super.visitExtendsClause(node);
-  }
-
-  @override
   Object visitFieldDeclaration(FieldDeclaration node) {
     _isInStaticVariableDeclaration = node.isStatic;
     _isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration;
@@ -1310,6 +1275,39 @@
   }
 
   /**
+   * Checks the class for problems with the superclass, mixins, or implemented
+   * interfaces.
+   */
+  void _checkClassInheritance(
+      NamedCompilationUnitMember node,
+      TypeName superclass,
+      WithClause withClause,
+      ImplementsClause implementsClause) {
+    // Only check for all of the inheritance logic around clauses if there
+    // isn't an error code such as "Cannot extend double" already on the
+    // class.
+    if (!_checkForExtendsDisallowedClass(superclass) &&
+        !_checkForImplementsDisallowedClass(implementsClause) &&
+        !_checkForAllMixinErrorCodes(withClause)) {
+      _checkForImplicitDynamicType(superclass);
+      _checkForExtendsDeferredClass(superclass);
+      _checkForImplementsDeferredClass(implementsClause);
+      _checkForNonAbstractClassInheritsAbstractMember(node.name);
+      _checkForInconsistentMethodInheritance();
+      _checkForRecursiveInterfaceInheritance(_enclosingClass);
+      _checkForConflictingGetterAndMethod();
+      _checkForConflictingInstanceGetterAndSuperclassMember();
+      _checkImplementsSuperClass(implementsClause);
+      _checkImplementsFunctionWithoutCall(node.name);
+      _checkForMixinHasNoConstructors(node);
+
+      if (_options.strongMode) {
+        _checkForMixinWithConflictingPrivateMember(withClause, superclass);
+      }
+    }
+  }
+
+  /**
    * Given a list of [directives] that have the same prefix, generate an error
    * if there is more than one import and any of those imports is deferred.
    *
@@ -2627,7 +2625,7 @@
   void _checkForBuiltInIdentifierAsName(
       SimpleIdentifier identifier, ErrorCode errorCode) {
     Token token = identifier.token;
-    if (token.type == TokenType.KEYWORD && token.keyword?.isPseudo != true) {
+    if (token.type.isKeyword && token.keyword?.isPseudo != true) {
       _errorReporter
           .reportErrorForNode(errorCode, identifier, [identifier.name]);
     }
@@ -2854,7 +2852,7 @@
       // prepare accessor properties
       String name = accessor.displayName;
       bool getter = accessor.isGetter;
-      // if non-final variable, ignore setter - we alreay reported problem for
+      // if non-final variable, ignore setter - we already reported problem for
       // getter
       if (accessor.isSetter && accessor.isSynthetic) {
         continue;
@@ -3589,25 +3587,12 @@
    *
    * See [CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS].
    */
-  void _checkForExtendsDeferredClass(ExtendsClause clause) {
-    if (clause == null) {
+  void _checkForExtendsDeferredClass(TypeName superclass) {
+    if (superclass == null) {
       return;
     }
     _checkForExtendsOrImplementsDeferredClass(
-        clause.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS);
-  }
-
-  /**
-   * Verify that the given type [alias] does not extend a deferred class.
-   *
-   * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS].
-   */
-  void _checkForExtendsDeferredClassInTypeAlias(ClassTypeAlias alias) {
-    if (alias == null) {
-      return;
-    }
-    _checkForExtendsOrImplementsDeferredClass(
-        alias.superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS);
+        superclass, CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS);
   }
 
   /**
@@ -3616,26 +3601,12 @@
    *
    * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS].
    */
-  bool _checkForExtendsDisallowedClass(ExtendsClause clause) {
-    if (clause == null) {
+  bool _checkForExtendsDisallowedClass(TypeName superclass) {
+    if (superclass == null) {
       return false;
     }
     return _checkForExtendsOrImplementsDisallowedClass(
-        clause.superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
-  }
-
-  /**
-   * Verify that the given type [alias] does not extend classes such as 'num' or
-   * 'String'.
-   *
-   * See [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS].
-   */
-  bool _checkForExtendsDisallowedClassInTypeAlias(ClassTypeAlias alias) {
-    if (alias == null) {
-      return false;
-    }
-    return _checkForExtendsOrImplementsDisallowedClass(
-        alias.superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
+        superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
   }
 
   /**
@@ -4896,12 +4867,12 @@
    * library that defines a private member that conflicts with a private name
    * from the same library but from a superclass or a different mixin.
    */
-  void _checkForMixinWithConflictingPrivateMember(ClassDeclaration node) {
-    WithClause withClause = node.withClause;
+  void _checkForMixinWithConflictingPrivateMember(
+      WithClause withClause, TypeName superclassName) {
     if (withClause == null) {
       return;
     }
-    DartType declaredSupertype = node.extendsClause?.superclass?.type;
+    DartType declaredSupertype = superclassName?.type;
     if (declaredSupertype is! InterfaceType) {
       return;
     }
@@ -6194,12 +6165,12 @@
    *
    * See [StaticWarningCode.FUNCTION_WITHOUT_CALL].
    */
-  void _checkImplementsFunctionWithoutCall(ClassDeclaration declaration) {
-    if (declaration.isAbstract) {
+  void _checkImplementsFunctionWithoutCall(AstNode className) {
+    ClassElement classElement = _enclosingClass;
+    if (classElement == null) {
       return;
     }
-    ClassElement classElement = declaration.element;
-    if (classElement == null) {
+    if (classElement.isAbstract) {
       return;
     }
     if (!_typeSystem.isSubtypeOf(
@@ -6217,7 +6188,7 @@
         callMethod is! MethodElement ||
         (callMethod as MethodElement).isAbstract) {
       _errorReporter.reportErrorForNode(
-          StaticWarningCode.FUNCTION_WITHOUT_CALL, declaration.name);
+          StaticWarningCode.FUNCTION_WITHOUT_CALL, className);
     }
   }
 
@@ -6227,14 +6198,13 @@
    *
    * See [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS].
    */
-  void _checkImplementsSuperClass(ClassDeclaration declaration) {
+  void _checkImplementsSuperClass(ImplementsClause implementsClause) {
     // prepare super type
     InterfaceType superType = _enclosingClass.supertype;
     if (superType == null) {
       return;
     }
     // prepare interfaces
-    ImplementsClause implementsClause = declaration.implementsClause;
     if (implementsClause == null) {
       return;
     }
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index b26d939..a9da4e9 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -886,10 +886,6 @@
     // parse results
     _sourceEntry.setValueIncremental(PARSE_ERRORS, _newParseErrors, true);
     _sourceEntry.setValueIncremental(PARSED_UNIT, _oldUnit, false);
-    // referenced names
-    ReferencedNames referencedNames = new ReferencedNames(_unitSource);
-    new ReferencedNamesBuilder(referencedNames).build(_oldUnit);
-    _sourceEntry.setValueIncremental(REFERENCED_NAMES, referencedNames, false);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index ea41c98..94baa56 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -158,17 +158,17 @@
  * A parser used to parse tokens into an AST structure.
  */
 class Parser {
-  static String ASYNC = Keyword.ASYNC.syntax;
+  static String ASYNC = Keyword.ASYNC.lexeme;
 
-  static String _AWAIT = Keyword.AWAIT.syntax;
+  static String _AWAIT = Keyword.AWAIT.lexeme;
 
-  static String _HIDE = Keyword.HIDE.syntax;
+  static String _HIDE = Keyword.HIDE.lexeme;
 
-  static String _SHOW = Keyword.SHOW.syntax;
+  static String _SHOW = Keyword.SHOW.lexeme;
 
-  static String SYNC = Keyword.SYNC.syntax;
+  static String SYNC = Keyword.SYNC.lexeme;
 
-  static String _YIELD = Keyword.YIELD.syntax;
+  static String _YIELD = Keyword.YIELD.lexeme;
 
   static const int _MAX_TREE_DEPTH = 300;
 
@@ -391,7 +391,7 @@
    */
   SimpleIdentifier createSyntheticIdentifier({bool isDeclaration: false}) {
     Token syntheticToken;
-    if (_currentToken.type == TokenType.KEYWORD) {
+    if (_currentToken.type.isKeyword) {
       // Consider current keyword token as an identifier.
       // It is not always true, e.g. "^is T" where "^" is place the place for
       // synthetic identifier. By creating SyntheticStringToken we can
@@ -585,7 +585,7 @@
     //     String get getterName
     if (allowAdditionalTokens) {
       if (type == TokenType.CLOSE_CURLY_BRACKET ||
-          type == TokenType.KEYWORD ||
+          type.isKeyword ||
           type == TokenType.IDENTIFIER ||
           type == TokenType.OPEN_CURLY_BRACKET) {
         return true;
@@ -3167,7 +3167,7 @@
       Token star = null;
       bool foundAsync = false;
       bool foundSync = false;
-      if (type == TokenType.KEYWORD) {
+      if (type.isKeyword) {
         String lexeme = _currentToken.lexeme;
         if (lexeme == ASYNC) {
           foundAsync = true;
@@ -4033,8 +4033,7 @@
         }
       }
       return parseBlock();
-    } else if (type == TokenType.KEYWORD &&
-        !_currentToken.keyword.isBuiltInOrPseudo) {
+    } else if (type.isKeyword && !_currentToken.keyword.isBuiltInOrPseudo) {
       Keyword keyword = _currentToken.keyword;
       // TODO(jwren) compute some metrics to figure out a better order for this
       // if-then sequence to optimize performance
@@ -5535,6 +5534,9 @@
     Token next = startToken.next; // Skip 'Function'
     if (_tokenMatches(next, TokenType.LT)) {
       next = skipTypeParameterList(next);
+      if (next == null) {
+        return null;
+      }
     }
     return skipFormalParameterList(next);
   }
@@ -5653,9 +5655,9 @@
     Token next = null;
     if (_atGenericFunctionTypeAfterReturnType(startToken)) {
       next = skipGenericFunctionTypeAfterReturnType(startToken);
-    } else if (_currentToken.keyword == Keyword.VOID &&
-        _atGenericFunctionTypeAfterReturnType(_currentToken.next)) {
-      next = next.next;
+    } else if (startToken.keyword == Keyword.VOID &&
+        _atGenericFunctionTypeAfterReturnType(startToken.next)) {
+      next = startToken.next;
     } else {
       next = skipTypeName(startToken);
     }
@@ -6011,7 +6013,7 @@
     // Remove uses of this method in favor of matches?
     // Pass in the error code to use to report the error?
     _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [keyword.syntax]);
+        ParserErrorCode.EXPECTED_TOKEN, [keyword.lexeme]);
     return _currentToken;
   }
 
@@ -6569,7 +6571,7 @@
       withClause = parseWithClause();
     } else {
       _reportErrorForCurrentToken(
-          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.syntax]);
+          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.lexeme]);
     }
     ImplementsClause implementsClause = null;
     if (_matchesKeyword(Keyword.IMPLEMENTS)) {
@@ -7567,7 +7569,7 @@
     // TODO(brianwilkerson) Should this function also return true for valid
     // top-level keywords?
     bool isKeywordAfterUri(Token token) =>
-        token.lexeme == Keyword.AS.syntax ||
+        token.lexeme == Keyword.AS.lexeme ||
         token.lexeme == _HIDE ||
         token.lexeme == _SHOW;
     TokenType type = _currentToken.type;
@@ -8082,8 +8084,7 @@
    * Return `true` if the given [token] is either an identifier or a keyword.
    */
   bool _tokenMatchesIdentifierOrKeyword(Token token) =>
-      _tokenMatches(token, TokenType.IDENTIFIER) ||
-      _tokenMatches(token, TokenType.KEYWORD);
+      _tokenMatches(token, TokenType.IDENTIFIER) || token.type.isKeyword;
 
   /**
    * Return `true` if the given [token] matches the given [keyword].
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 809feb2..d4da3a0 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -391,7 +391,7 @@
     }
     String rhsNameStr = typeName is TypeName ? typeName.name.name : null;
     // if x is dynamic
-    if (rhsType.isDynamic && rhsNameStr == Keyword.DYNAMIC.syntax) {
+    if (rhsType.isDynamic && rhsNameStr == Keyword.DYNAMIC.lexeme) {
       if (node.notOperator == null) {
         // the is case
         _errorReporter.reportErrorForNode(
@@ -4239,8 +4239,8 @@
    */
   final List<DartType> _returnStack = <DartType>[];
 
-  InferenceContext._(this._errorReporter, TypeProvider typeProvider,
-      this._typeSystem, this._inferenceHints)
+  InferenceContext._(TypeProvider typeProvider, this._typeSystem,
+      this._inferenceHints, this._errorReporter)
       : _typeProvider = typeProvider;
 
   /**
@@ -4323,7 +4323,7 @@
   }
 
   /**
-   * Clear the type information assocated with [node].
+   * Clear the type information associated with [node].
    */
   static void clearType(AstNode node) {
     node?.setProperty(_typeProperty, null);
@@ -5072,7 +5072,7 @@
       strongModeHints = options.strongModeHints;
     }
     this.inferenceContext = new InferenceContext._(
-        errorReporter, typeProvider, typeSystem, strongModeHints);
+        typeProvider, typeSystem, strongModeHints, errorReporter);
     this.typeAnalyzer = new StaticTypeAnalyzer(this);
   }
 
@@ -8618,7 +8618,7 @@
    */
   static bool _isBuiltInIdentifier(TypeName typeName) {
     Token token = typeName.name.beginToken;
-    return token.type == TokenType.KEYWORD;
+    return token.type.isKeyword;
   }
 
   /**
@@ -10347,7 +10347,7 @@
     // If the type is not an InterfaceType, then visitTypeName() sets the type
     // to be a DynamicTypeImpl
     Identifier name = typeName.name;
-    if (name.name == Keyword.DYNAMIC.syntax) {
+    if (name.name == Keyword.DYNAMIC.lexeme) {
       errorReporter.reportErrorForNode(dynamicTypeError, name, [name.name]);
     } else if (!nameScope.shouldIgnoreUndefined(name)) {
       errorReporter.reportErrorForNode(nonTypeError, name, [name.name]);
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 75a56d3..ff4eaf4 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -38,13 +38,15 @@
       identical(t, UnknownInferredType.instance);
 }
 
-typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
+typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<TypeImpl> visitedTypes);
 
 /**
  * Implementation of [TypeSystem] using the strong mode rules.
  * https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md
  */
 class StrongTypeSystemImpl extends TypeSystem {
+  static bool _comparingTypeParameterBounds = false;
+
   /**
    * True if implicit casts should be allowed, otherwise false.
    *
@@ -515,6 +517,15 @@
     return _isSubtypeOf(leftType, rightType, null);
   }
 
+  /// Given a [type] T that may have an unknown type `?`, returns a type
+  /// R such that R <: T for any type substituted for `?`.
+  ///
+  /// In practice this will always replace `?` with either bottom or top
+  /// (dynamic), depending on the position of `?`.
+  DartType lowerBoundForType(DartType type) {
+    return _substituteForUnknownType(type, lowerBound: true);
+  }
+
   @override
   DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
       DartType rightType, DartType currentType) {
@@ -578,85 +589,15 @@
     return t;
   }
 
-  // Given a [type] T that may have an unknown type `?`, returns a type
-  // R such that T <: R for any type substituted for `?`.
-  //
-  // In practice this will always replace `?` with either bottom or top
-  // (dynamic), depending on the position of `?`.
+  /// Given a [type] T that may have an unknown type `?`, returns a type
+  /// R such that T <: R for any type substituted for `?`.
+  ///
+  /// In practice this will always replace `?` with either bottom or top
+  /// (dynamic), depending on the position of `?`.
   DartType upperBoundForType(DartType type) {
     return _substituteForUnknownType(type);
   }
 
-  // Given a [type] T that may have an unknown type `?`, returns a type
-  // R such that R <: T for any type substituted for `?`.
-  //
-  // In practice this will always replace `?` with either bottom or top
-  // (dynamic), depending on the position of `?`.
-  DartType lowerBoundForType(DartType type) {
-    return _substituteForUnknownType(type, lowerBound: true);
-  }
-
-  DartType _substituteForUnknownType(DartType type,
-      {bool lowerBound: false, dynamicIsBottom: false}) {
-    if (identical(type, UnknownInferredType.instance)) {
-      if (lowerBound && !dynamicIsBottom) {
-        // TODO(jmesserly): this should be the bottom type, once i can be
-        // reified.
-        return typeProvider.nullType;
-      }
-      return typeProvider.dynamicType;
-    }
-    if (type is InterfaceTypeImpl) {
-      // Generic types are covariant, so keep the constraint direction.
-      var newTypeArgs = _transformList(type.typeArguments,
-          (t) => _substituteForUnknownType(t, lowerBound: lowerBound));
-      if (identical(type.typeArguments, newTypeArgs)) return type;
-      return new InterfaceTypeImpl(type.element, type.prunedTypedefs)
-        ..typeArguments = newTypeArgs;
-    }
-    if (type is FunctionType) {
-      var parameters = type.parameters;
-      var returnType = type.returnType;
-      var newParameters = _transformList(parameters, (ParameterElement p) {
-        // Parameters are contravariant, so flip the constraint direction.
-        // Also pass dynamicIsBottom, because this is a fuzzy arrow.
-        var newType = _substituteForUnknownType(p.type,
-            lowerBound: !lowerBound, dynamicIsBottom: true);
-        return new ParameterElementImpl.synthetic(
-            p.name, newType, p.parameterKind);
-      });
-      // Return type is covariant.
-      var newReturnType =
-          _substituteForUnknownType(returnType, lowerBound: lowerBound);
-      if (identical(parameters, newParameters) &&
-          identical(returnType, newReturnType)) {
-        return type;
-      }
-
-      var function = new FunctionElementImpl(type.name, -1)
-        ..isSynthetic = true
-        ..returnType = newReturnType
-        ..shareTypeParameters(type.typeFormals)
-        ..parameters = newParameters;
-      return function.type = new FunctionTypeImpl(function);
-    }
-    return type;
-  }
-
-  static List/*<T>*/ _transformList/*<T>*/(
-      List/*<T>*/ list, /*=T*/ f(/*=T*/ t)) {
-    List/*<T>*/ newList = null;
-    for (var i = 0; i < list.length; i++) {
-      var item = list[i];
-      var newItem = f(item);
-      if (!identical(item, newItem)) {
-        newList ??= new List.from(list);
-        newList[i] = newItem;
-      }
-    }
-    return newList ?? list;
-  }
-
   /**
    * Compute the greatest lower bound of function types [f] and [g].
    *
@@ -780,18 +721,17 @@
    */
   _GuardedSubtypeChecker<DartType> _guard(
       _GuardedSubtypeChecker<DartType> check) {
-    return (DartType t1, DartType t2, Set<Element> visited) {
-      Element element = t1.element;
-      if (visited == null) {
-        visited = new HashSet<Element>();
+    return (DartType t1, DartType t2, Set<TypeImpl> visitedTypes) {
+      if (visitedTypes == null) {
+        visitedTypes = new HashSet<TypeImpl>();
       }
-      if (element == null || !visited.add(element)) {
+      if (t1 == null || !visitedTypes.add(t1)) {
         return false;
       }
       try {
-        return check(t1, t2, visited);
+        return check(t1, t2, visitedTypes);
       } finally {
-        visited.remove(element);
+        visitedTypes.remove(t1);
       }
     };
   }
@@ -805,7 +745,7 @@
    * 2. If the two types have the same class element, then take the
    *    pointwise least upper bound of the type arguments.  This is again
    *    the best result, except that the recursive calls may not return
-   *    the true least uppper bounds.  The result is guaranteed to be a
+   *    the true least upper bounds.  The result is guaranteed to be a
    *    well-formed type under the assumption that the input types were
    *    well-formed (and assuming that the recursive calls return
    *    well-formed types).
@@ -847,25 +787,27 @@
   ///
   /// This will always assume function types use fuzzy arrows, in other words
   /// that dynamic parameters of f1 and f2 are treated as bottom.
-  bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2) {
+  bool _isFunctionSubtypeOf(
+      FunctionType f1, FunctionType f2, Set<TypeImpl> visitedTypes) {
     return FunctionTypeImpl.relate(
         f1,
         f2,
-        (t1, t2, _, __) => _isSubtypeOf(t2, t1, null, dynamicIsBottom: true),
+        (t1, t2, _, __) =>
+            _isSubtypeOf(t2, t1, visitedTypes, dynamicIsBottom: true),
         instantiateToBounds,
         returnRelation: isSubtypeOf);
   }
 
   bool _isInterfaceSubtypeOf(
-      InterfaceType i1, InterfaceType i2, Set<Element> visited) {
+      InterfaceType i1, InterfaceType i2, Set<TypeImpl> visitedTypes) {
     if (identical(i1, i2)) {
       return true;
     }
 
     // Guard recursive calls
     _GuardedSubtypeChecker<InterfaceType> guardedInterfaceSubtype = _guard(
-        (DartType i1, DartType i2, Set<Element> visited) =>
-            _isInterfaceSubtypeOf(i1, i2, visited));
+        (DartType i1, DartType i2, Set<TypeImpl> visitedTypes) =>
+            _isInterfaceSubtypeOf(i1, i2, visitedTypes));
 
     if (i1.element == i2.element) {
       List<DartType> tArgs1 = i1.typeArguments;
@@ -891,18 +833,18 @@
       return false;
     }
 
-    if (guardedInterfaceSubtype(i1.superclass, i2, visited)) {
+    if (guardedInterfaceSubtype(i1.superclass, i2, visitedTypes)) {
       return true;
     }
 
     for (final parent in i1.interfaces) {
-      if (guardedInterfaceSubtype(parent, i2, visited)) {
+      if (guardedInterfaceSubtype(parent, i2, visitedTypes)) {
         return true;
       }
     }
 
     for (final parent in i1.mixins) {
-      if (guardedInterfaceSubtype(parent, i2, visited)) {
+      if (guardedInterfaceSubtype(parent, i2, visitedTypes)) {
         return true;
       }
     }
@@ -910,7 +852,7 @@
     return false;
   }
 
-  bool _isSubtypeOf(DartType t1, DartType t2, Set<Element> visited,
+  bool _isSubtypeOf(DartType t1, DartType t2, Set<TypeImpl> visitedTypes,
       {bool dynamicIsBottom: false}) {
     if (identical(t1, t2)) {
       return true;
@@ -997,20 +939,87 @@
       return t2.isDartCoreFunction;
     }
 
+    // Guard recursive calls
+    _GuardedSubtypeChecker<FunctionType> guardedIsFunctionSubtype = _guard(
+        (DartType t1, DartType t2, Set<TypeImpl> visitedTypes) =>
+            _isFunctionSubtypeOf(
+                t1 as FunctionType, t2 as FunctionType, visitedTypes));
+
     // An interface type can only subtype a function type if
     // the interface type declares a call method with a type
     // which is a super type of the function type.
     if (t1 is InterfaceType && t2 is FunctionType) {
       var callType = getCallMethodDefiniteType(t1);
-      return (callType != null) && _isFunctionSubtypeOf(callType, t2);
+      return callType != null &&
+          guardedIsFunctionSubtype(callType, t2, visitedTypes);
     }
 
     // Two interface types
     if (t1 is InterfaceType && t2 is InterfaceType) {
-      return _isInterfaceSubtypeOf(t1, t2, visited);
+      return _isInterfaceSubtypeOf(t1, t2, visitedTypes);
     }
 
-    return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
+    return guardedIsFunctionSubtype(t1, t2, visitedTypes);
+  }
+
+  DartType _substituteForUnknownType(DartType type,
+      {bool lowerBound: false, dynamicIsBottom: false}) {
+    if (identical(type, UnknownInferredType.instance)) {
+      if (lowerBound && !dynamicIsBottom) {
+        // TODO(jmesserly): this should be the bottom type, once i can be
+        // reified.
+        return typeProvider.nullType;
+      }
+      return typeProvider.dynamicType;
+    }
+    if (type is InterfaceTypeImpl) {
+      // Generic types are covariant, so keep the constraint direction.
+      var newTypeArgs = _transformList(type.typeArguments,
+          (t) => _substituteForUnknownType(t, lowerBound: lowerBound));
+      if (identical(type.typeArguments, newTypeArgs)) return type;
+      return new InterfaceTypeImpl(type.element, type.prunedTypedefs)
+        ..typeArguments = newTypeArgs;
+    }
+    if (type is FunctionType) {
+      var parameters = type.parameters;
+      var returnType = type.returnType;
+      var newParameters = _transformList(parameters, (ParameterElement p) {
+        // Parameters are contravariant, so flip the constraint direction.
+        // Also pass dynamicIsBottom, because this is a fuzzy arrow.
+        var newType = _substituteForUnknownType(p.type,
+            lowerBound: !lowerBound, dynamicIsBottom: true);
+        return new ParameterElementImpl.synthetic(
+            p.name, newType, p.parameterKind);
+      });
+      // Return type is covariant.
+      var newReturnType =
+          _substituteForUnknownType(returnType, lowerBound: lowerBound);
+      if (identical(parameters, newParameters) &&
+          identical(returnType, newReturnType)) {
+        return type;
+      }
+
+      var function = new FunctionElementImpl(type.name, -1)
+        ..isSynthetic = true
+        ..returnType = newReturnType
+        ..shareTypeParameters(type.typeFormals)
+        ..parameters = newParameters;
+      return function.type = new FunctionTypeImpl(function);
+    }
+    return type;
+  }
+
+  bool _typeParameterBoundsSubtype(
+      DartType t1, DartType t2, bool recursionValue) {
+    if (_comparingTypeParameterBounds) {
+      return recursionValue;
+    }
+    _comparingTypeParameterBounds = true;
+    try {
+      return isSubtypeOf(t1, t2);
+    } finally {
+      _comparingTypeParameterBounds = false;
+    }
   }
 
   /**
@@ -1069,20 +1078,19 @@
     return getLeastUpperBound(type1, type2);
   }
 
-  bool _typeParameterBoundsSubtype(
-      DartType t1, DartType t2, bool recursionValue) {
-    if (_comparingTypeParameterBounds) {
-      return recursionValue;
+  static List/*<T>*/ _transformList/*<T>*/(
+      List/*<T>*/ list, /*=T*/ f(/*=T*/ t)) {
+    List/*<T>*/ newList = null;
+    for (var i = 0; i < list.length; i++) {
+      var item = list[i];
+      var newItem = f(item);
+      if (!identical(item, newItem)) {
+        newList ??= new List.from(list);
+        newList[i] = newItem;
+      }
     }
-    _comparingTypeParameterBounds = true;
-    try {
-      return isSubtypeOf(t1, t2);
-    } finally {
-      _comparingTypeParameterBounds = false;
-    }
+    return newList ?? list;
   }
-
-  static bool _comparingTypeParameterBounds = false;
 }
 
 /**
@@ -1544,6 +1552,104 @@
   }
 }
 
+/// A type that is being inferred but is not currently known.
+///
+/// This type will only appear in a downward inference context for type
+/// parameters that we do not know yet. Notationally it is written `?`, for
+/// example `List<?>`. This is distinct from `List<dynamic>`. These types will
+/// never appear in the final resolved AST.
+class UnknownInferredType extends TypeImpl {
+  static final UnknownInferredType instance = new UnknownInferredType._();
+
+  UnknownInferredType._()
+      : super(UnknownInferredTypeElement.instance, Keyword.DYNAMIC.lexeme);
+
+  @override
+  int get hashCode => 1;
+
+  @override
+  bool get isDynamic => true;
+
+  @override
+  bool operator ==(Object object) => identical(object, this);
+
+  @override
+  void appendTo(StringBuffer buffer, Set<TypeImpl> types) {
+    buffer.write('?');
+  }
+
+  @override
+  bool isMoreSpecificThan(DartType type,
+      [bool withDynamic = false, Set<Element> visitedElements]) {
+    // T is S
+    if (identical(this, type)) {
+      return true;
+    }
+    // else
+    return withDynamic;
+  }
+
+  @override
+  bool isSubtypeOf(DartType type) => true;
+
+  @override
+  bool isSupertypeOf(DartType type) => true;
+
+  @override
+  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
+
+  @override
+  DartType substitute2(
+      List<DartType> argumentTypes, List<DartType> parameterTypes,
+      [List<FunctionTypeAliasElement> prune]) {
+    int length = parameterTypes.length;
+    for (int i = 0; i < length; i++) {
+      if (parameterTypes[i] == this) {
+        return argumentTypes[i];
+      }
+    }
+    return this;
+  }
+
+  /// Given a [type] T, return true if it does not have an unknown type `?`.
+  static bool isKnown(DartType type) => !isUnknown(type);
+
+  /// Given a [type] T, return true if it has an unknown type `?`.
+  static bool isUnknown(DartType type) {
+    if (identical(type, UnknownInferredType.instance)) {
+      return true;
+    }
+    if (type is InterfaceTypeImpl) {
+      return type.typeArguments.any(isUnknown);
+    }
+    if (type is FunctionType) {
+      return isUnknown(type.returnType) ||
+          type.parameters.any((p) => isUnknown(p.type));
+    }
+    return false;
+  }
+}
+
+/// The synthetic element for [UnknownInferredType].
+class UnknownInferredTypeElement extends ElementImpl
+    implements TypeDefiningElement {
+  static final UnknownInferredTypeElement instance =
+      new UnknownInferredTypeElement._();
+
+  UnknownInferredTypeElement._() : super(Keyword.DYNAMIC.lexeme, -1) {
+    setModifier(Modifier.SYNTHETIC, true);
+  }
+
+  @override
+  ElementKind get kind => ElementKind.DYNAMIC;
+
+  @override
+  UnknownInferredType get type => UnknownInferredType.instance;
+
+  @override
+  /*=T*/ accept/*<T>*/(ElementVisitor visitor) => null;
+}
+
 /// Tracks upper and lower type bounds for a set of type parameters.
 ///
 /// This class is used by calling [isSubtypeOf]. When it encounters one of
@@ -1589,11 +1695,16 @@
     }
   }
 
-  /// Apply a return type constraint, which asserts that the [declaredType]
-  /// is a subtype of the [contextType].
-  void constrainReturnType(DartType declaredType, DartType contextType) {
-    var origin = new _TypeConstraintFromReturnType(declaredType, contextType);
-    _matchSubtypeOf(declaredType, contextType, null, origin, covariant: true);
+  /// Apply an argument constraint, which asserts that the [argument] staticType
+  /// is a subtype of the [parameterType].
+  void constrainArgument(
+      DartType argumentType, DartType parameterType, String parameterName,
+      {DartType genericType}) {
+    var origin = new _TypeConstraintFromArgument(
+        argumentType, parameterType, parameterName,
+        genericType: genericType);
+    _matchSubtypeOf(argumentType, parameterType, null, origin,
+        covariant: false);
   }
 
   /// Constrain a universal function type [fnType] used in a context
@@ -1609,16 +1720,336 @@
     _matchSubtypeOf(inferFnType, contextType, null, origin, covariant: true);
   }
 
-  /// Apply an argument constraint, which asserts that the [argument] staticType
-  /// is a subtype of the [parameterType].
-  void constrainArgument(
-      DartType argumentType, DartType parameterType, String parameterName,
-      {DartType genericType}) {
-    var origin = new _TypeConstraintFromArgument(
-        argumentType, parameterType, parameterName,
-        genericType: genericType);
-    _matchSubtypeOf(argumentType, parameterType, null, origin,
-        covariant: false);
+  /// Apply a return type constraint, which asserts that the [declaredType]
+  /// is a subtype of the [contextType].
+  void constrainReturnType(DartType declaredType, DartType contextType) {
+    var origin = new _TypeConstraintFromReturnType(declaredType, contextType);
+    _matchSubtypeOf(declaredType, contextType, null, origin, covariant: true);
+  }
+
+  /// Given the constraints that were given by calling [isSubtypeOf], find the
+  /// instantiation of the generic function that satisfies these constraints.
+  ///
+  /// If [downwardsInferPhase] is set, we are in the first pass of inference,
+  /// pushing context types down. At that point we are allowed to push down
+  /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is
+  /// false, we are on our final inference pass, have all available information
+  /// including argument types, and must not conclude `?` for any type formal.
+  /*=T*/ infer/*<T extends ParameterizedType>*/(
+      /*=T*/ genericType,
+      List<TypeParameterElement> typeFormals,
+      {ErrorReporter errorReporter,
+      AstNode errorNode,
+      bool downwardsInferPhase: false}) {
+    var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals);
+
+    // Initialize the inferred type array.
+    //
+    // In the downwards phase, they all start as `?` to offer reasonable
+    // degradation for f-bounded type parameters.
+    var inferredTypes = new List<DartType>.filled(
+        fnTypeParams.length, UnknownInferredType.instance);
+    var _inferTypeParameter = downwardsInferPhase
+        ? _inferTypeParameterFromContext
+        : _inferTypeParameterFromAll;
+
+    for (int i = 0; i < fnTypeParams.length; i++) {
+      TypeParameterType typeParam = fnTypeParams[i];
+
+      var typeParamBound = typeParam.bound;
+      _TypeConstraint extendsClause;
+      if (!typeParamBound.isDynamic) {
+        extendsClause = new _TypeConstraint.fromExtends(typeParam,
+            typeParam.bound.substitute2(inferredTypes, fnTypeParams));
+      }
+
+      var constraints = _constraints[typeParam.element];
+      inferredTypes[i] = _inferTypeParameter(constraints, extendsClause);
+    }
+
+    // If the downwards infer phase has failed, we'll catch this in the upwards
+    // phase later on.
+    if (downwardsInferPhase) {
+      return genericType.instantiate(inferredTypes) as dynamic/*=T*/;
+    }
+
+    // Check the inferred types against all of the constraints.
+    var knownTypes = new HashMap<TypeParameterType, DartType>(
+        equals: (x, y) => x.element == y.element,
+        hashCode: (x) => x.element.hashCode);
+    for (int i = 0; i < fnTypeParams.length; i++) {
+      TypeParameterType typeParam = fnTypeParams[i];
+      var constraints = _constraints[typeParam.element];
+      var typeParamBound =
+          typeParam.bound.substitute2(inferredTypes, fnTypeParams);
+
+      var inferred = inferredTypes[i];
+      bool success =
+          constraints.every((c) => c.isSatisifedBy(_typeSystem, inferred));
+      if (success && !typeParamBound.isDynamic) {
+        // If everything else succeeded, check the `extends` constraint.
+        var extendsConstraint =
+            new _TypeConstraint.fromExtends(typeParam, typeParamBound);
+        constraints.add(extendsConstraint);
+        success = extendsConstraint.isSatisifedBy(_typeSystem, inferred);
+      }
+
+      if (!success) {
+        errorReporter?.reportErrorForNode(
+            StrongModeCode.COULD_NOT_INFER,
+            errorNode,
+            [typeParam, _formatError(typeParam, inferred, constraints)]);
+
+        // Heuristic: even if we failed, keep the erroneous type.
+        // It should satisfy at least some of the constraints (e.g. the return
+        // context). If we fall back to instantiateToBounds, we'll typically get
+        // more errors (e.g. because `dynamic` is the most common bound).
+      }
+
+      if (UnknownInferredType.isKnown(inferred)) {
+        knownTypes[typeParam] = inferred;
+      }
+    }
+
+    // Use instantiate to bounds to finish things off.
+    var hasError = new List<bool>.filled(fnTypeParams.length, false);
+    var result = _typeSystem.instantiateToBounds(genericType,
+        hasError: hasError, knownTypes: knownTypes) as dynamic/*=T*/;
+
+    // Report any errors from instantiateToBounds.
+    for (int i = 0; i < hasError.length; i++) {
+      if (hasError[i]) {
+        TypeParameterType typeParam = fnTypeParams[i];
+        var typeParamBound =
+            typeParam.bound.substitute2(inferredTypes, fnTypeParams);
+        // TODO(jmesserly): improve this error message.
+        errorReporter
+            ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
+          typeParam,
+          "\nRecursive bound cannot be instantiated: '$typeParamBound'."
+              "\nConsider passing explicit type argument(s) "
+              "to the generic.\n\n'"
+        ]);
+      }
+    }
+    return result;
+  }
+
+  /// Choose the bound that was implied by the return type, if any.
+  ///
+  /// Which bound this is depends on what positions the type parameter
+  /// appears in. If the type only appears only in a contravariant position,
+  /// we will choose the lower bound instead.
+  ///
+  /// For example given:
+  ///
+  ///     Func1<T, bool> makeComparer<T>(T x) => (T y) => x() == y;
+  ///
+  ///     main() {
+  ///       Func1<num, bool> t = makeComparer/* infer <num> */(42);
+  ///       print(t(42.0)); /// false, no error.
+  ///     }
+  ///
+  /// The constraints we collect are:
+  ///
+  /// * `num <: T`
+  /// * `int <: T`
+  ///
+  /// ... and no upper bound. Therefore the lower bound is the best choice.
+  DartType _chooseTypeFromConstraints(Iterable<_TypeConstraint> constraints,
+      {bool toKnownType: false}) {
+    DartType lower = UnknownInferredType.instance;
+    DartType upper = UnknownInferredType.instance;
+    for (var constraint in constraints) {
+      // Given constraints:
+      //
+      //     L1 <: T <: U1
+      //     L2 <: T <: U2
+      //
+      // These can be combined to produce:
+      //
+      //     LUB(L1, L2) <: T <: GLB(U1, U2).
+      //
+      // This can then be done for all constraints in sequence.
+      //
+      // This resulting constraint may be unsatisfiable; in that case inference
+      // will fail.
+      upper = _getGreatestLowerBound(upper, constraint.upperBound);
+      lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
+    }
+
+    // Prefer the known bound, if any.
+    // Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
+    //
+    // For both of those, prefer the lower bound (arbitrary heuristic).
+    if (UnknownInferredType.isKnown(lower)) {
+      return lower;
+    }
+    if (UnknownInferredType.isKnown(upper)) {
+      return upper;
+    }
+    if (!identical(UnknownInferredType.instance, lower)) {
+      return toKnownType ? _typeSystem.lowerBoundForType(lower) : lower;
+    }
+    if (!identical(UnknownInferredType.instance, upper)) {
+      return toKnownType ? _typeSystem.upperBoundForType(upper) : upper;
+    }
+    return lower;
+  }
+
+  String _formatError(TypeParameterType typeParam, DartType inferred,
+      Iterable<_TypeConstraint> constraints) {
+    var intro = "Tried to infer '$inferred' for '$typeParam'"
+        " which doesn't work:";
+
+    var constraintsByOrigin = <_TypeConstraintOrigin, List<_TypeConstraint>>{};
+    for (var c in constraints) {
+      constraintsByOrigin.putIfAbsent(c.origin, () => []).add(c);
+    }
+
+    // Only report unique constraint origins.
+    Iterable<_TypeConstraint> isSatisified(bool expected) => constraintsByOrigin
+        .values
+        .where((l) =>
+            l.every((c) => c.isSatisifedBy(_typeSystem, inferred)) == expected)
+        .expand((i) => i);
+
+    String unsatisified = _formatConstraints(isSatisified(false));
+    String satisified = _formatConstraints(isSatisified(true));
+
+    assert(unsatisified.isNotEmpty);
+    if (satisified.isNotEmpty) {
+      satisified = "\nThe type '$inferred' was inferred from:\n$satisified";
+    }
+
+    return '\n\n$intro\n$unsatisified$satisified\n\n'
+        'Consider passing explicit type argument(s) to the generic.\n\n';
+  }
+
+  /// This is first calls strong mode's GLB, but if it fails to find anything
+  /// (i.e. returns the bottom type), we kick in a few additional rules:
+  ///
+  /// - `GLB(FutureOr<A>, B)` is defined as:
+  ///   - `GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>`
+  ///   - `GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>`
+  ///   - else `GLB(FutureOr<A>, B) == GLB(A, B)`
+  /// - `GLB(A, FutureOr<B>) ==  GLB(FutureOr<A>, B)` (defined above),
+  /// - else `GLB(A, B) == Null`
+  DartType _getGreatestLowerBound(DartType t1, DartType t2) {
+    var result = _typeSystem.getGreatestLowerBound(t1, t2);
+    if (result.isBottom) {
+      // See if we can do better by considering FutureOr rules.
+      if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
+        var t1TypeArg = t1.typeArguments[0];
+        if (t2 is InterfaceType) {
+          //  GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
+          if (t2.isDartAsyncFutureOr) {
+            var t2TypeArg = t2.typeArguments[0];
+            return typeProvider.futureOrType
+                .instantiate([_getGreatestLowerBound(t1TypeArg, t2TypeArg)]);
+          }
+          // GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
+          if (t2.isDartAsyncFuture) {
+            var t2TypeArg = t2.typeArguments[0];
+            return typeProvider.futureType
+                .instantiate([_getGreatestLowerBound(t1TypeArg, t2TypeArg)]);
+          }
+        }
+        // GLB(FutureOr<A>, B) == GLB(A, B)
+        return _getGreatestLowerBound(t1TypeArg, t2);
+      }
+      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+        // GLB(A, FutureOr<B>) ==  GLB(FutureOr<A>, B)
+        return _getGreatestLowerBound(t2, t1);
+      }
+      // TODO(jmesserly): fix this rule once we support non-nullable types.
+      return typeProvider.nullType;
+    }
+    return result;
+  }
+
+  DartType _inferTypeParameterFromAll(
+      List<_TypeConstraint> constraints, _TypeConstraint extendsClause) {
+    // See if we already fixed this type from downwards inference.
+    // If so, then we aren't allowed to change it based on argument types.
+    DartType t = _inferTypeParameterFromContext(
+        constraints.where((c) => c.isDownwards), extendsClause);
+    if (UnknownInferredType.isKnown(t)) {
+      // Remove constraints that aren't downward ones; we'll ignore these for
+      // error reporting, because inference already succeeded.
+      constraints.removeWhere((c) => !c.isDownwards);
+      return t;
+    }
+
+    if (extendsClause != null) {
+      constraints = constraints.toList()..add(extendsClause);
+    }
+
+    var choice = _chooseTypeFromConstraints(constraints, toKnownType: true);
+    return choice;
+  }
+
+  DartType _inferTypeParameterFromContext(
+      Iterable<_TypeConstraint> constraints, _TypeConstraint extendsClause) {
+    DartType t = _chooseTypeFromConstraints(constraints);
+    if (UnknownInferredType.isUnknown(t)) {
+      return t;
+    }
+
+    // If we're about to make our final choice, apply the extends clause.
+    // This gives us a chance to refine the choice, in case it would violate
+    // the `extends` clause. For example:
+    //
+    //     Object obj = math.min/*<infer Object, error>*/(1, 2);
+    //
+    // If we consider the `T extends num` we conclude `<num>`, which works.
+    if (extendsClause != null) {
+      constraints = constraints.toList()..add(extendsClause);
+      return _chooseTypeFromConstraints(constraints);
+    }
+    return t;
+  }
+
+  void _matchInterfaceSubtypeOf(InterfaceType i1, InterfaceType i2,
+      Set<Element> visited, _TypeConstraintOrigin origin,
+      {bool covariant}) {
+    if (identical(i1, i2)) {
+      return;
+    }
+
+    if (i1.element == i2.element) {
+      List<DartType> tArgs1 = i1.typeArguments;
+      List<DartType> tArgs2 = i2.typeArguments;
+      assert(tArgs1.length == tArgs2.length);
+      for (int i = 0; i < tArgs1.length; i++) {
+        _matchSubtypeOf(tArgs1[i], tArgs2[i], visited, origin,
+            covariant: covariant);
+      }
+      return;
+    }
+    if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) {
+      return;
+    }
+    if (i1.isObject) {
+      return;
+    }
+
+    // Guard against loops in the class hierarchy
+    void guardedInterfaceSubtype(InterfaceType t1) {
+      var visitedSet = visited ?? new HashSet<Element>();
+      if (visitedSet.add(t1.element)) {
+        _matchInterfaceSubtypeOf(t1, i2, visited, origin, covariant: covariant);
+        visitedSet.remove(t1.element);
+      }
+    }
+
+    guardedInterfaceSubtype(i1.superclass);
+    for (final parent in i1.interfaces) {
+      guardedInterfaceSubtype(parent);
+    }
+    for (final parent in i1.mixins) {
+      guardedInterfaceSubtype(parent);
+    }
   }
 
   /// Assert that [t1] will be a subtype of [t2], and returns if the constraint
@@ -1760,331 +2191,6 @@
     }
   }
 
-  void _matchInterfaceSubtypeOf(InterfaceType i1, InterfaceType i2,
-      Set<Element> visited, _TypeConstraintOrigin origin,
-      {bool covariant}) {
-    if (identical(i1, i2)) {
-      return;
-    }
-
-    if (i1.element == i2.element) {
-      List<DartType> tArgs1 = i1.typeArguments;
-      List<DartType> tArgs2 = i2.typeArguments;
-      assert(tArgs1.length == tArgs2.length);
-      for (int i = 0; i < tArgs1.length; i++) {
-        _matchSubtypeOf(tArgs1[i], tArgs2[i], visited, origin,
-            covariant: covariant);
-      }
-      return;
-    }
-    if (i2.isDartCoreFunction && i1.element.getMethod("call") != null) {
-      return;
-    }
-    if (i1.isObject) {
-      return;
-    }
-
-    // Guard against loops in the class hierarchy
-    void guardedInterfaceSubtype(InterfaceType t1) {
-      var visitedSet = visited ?? new HashSet<Element>();
-      if (visitedSet.add(t1.element)) {
-        _matchInterfaceSubtypeOf(t1, i2, visited, origin, covariant: covariant);
-        visitedSet.remove(t1.element);
-      }
-    }
-
-    guardedInterfaceSubtype(i1.superclass);
-    for (final parent in i1.interfaces) {
-      guardedInterfaceSubtype(parent);
-    }
-    for (final parent in i1.mixins) {
-      guardedInterfaceSubtype(parent);
-    }
-  }
-
-  /// Given the constraints that were given by calling [isSubtypeOf], find the
-  /// instantiation of the generic function that satisfies these constraints.
-  ///
-  /// If [downwardsInferPhase] is set, we are in the first pass of inference,
-  /// pushing context types down. At that point we are allowed to push down
-  /// `?` to precisely represent an unknown type. If [downwardsInferPhase] is
-  /// false, we are on our final inference pass, have all available information
-  /// including argument types, and must not conclude `?` for any type formal.
-  /*=T*/ infer/*<T extends ParameterizedType>*/(
-      /*=T*/ genericType,
-      List<TypeParameterElement> typeFormals,
-      {ErrorReporter errorReporter,
-      AstNode errorNode,
-      bool downwardsInferPhase: false}) {
-    var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals);
-
-    // Initialize the inferred type array.
-    //
-    // In the downwards phase, they all start as `?` to offer reasonable
-    // degradation for f-bounded type parameters.
-    var inferredTypes = new List<DartType>.filled(
-        fnTypeParams.length, UnknownInferredType.instance);
-    var _inferTypeParameter = downwardsInferPhase
-        ? _inferTypeParameterFromContext
-        : _inferTypeParameterFromAll;
-
-    for (int i = 0; i < fnTypeParams.length; i++) {
-      TypeParameterType typeParam = fnTypeParams[i];
-
-      var typeParamBound = typeParam.bound;
-      _TypeConstraint extendsClause;
-      if (!typeParamBound.isDynamic) {
-        extendsClause = new _TypeConstraint.fromExtends(typeParam,
-            typeParam.bound.substitute2(inferredTypes, fnTypeParams));
-      }
-
-      var constraints = _constraints[typeParam.element];
-      inferredTypes[i] = _inferTypeParameter(constraints, extendsClause);
-    }
-
-    // If the downwards infer phase has failed, we'll catch this in the upwards
-    // phase later on.
-    if (downwardsInferPhase) {
-      return genericType.instantiate(inferredTypes) as dynamic/*=T*/;
-    }
-
-    // Check the inferred types against all of the constraints.
-    var knownTypes = new HashMap<TypeParameterType, DartType>(
-        equals: (x, y) => x.element == y.element,
-        hashCode: (x) => x.element.hashCode);
-    for (int i = 0; i < fnTypeParams.length; i++) {
-      TypeParameterType typeParam = fnTypeParams[i];
-      var constraints = _constraints[typeParam.element];
-      var typeParamBound =
-          typeParam.bound.substitute2(inferredTypes, fnTypeParams);
-
-      var inferred = inferredTypes[i];
-      bool success =
-          constraints.every((c) => c.isSatisifedBy(_typeSystem, inferred));
-      if (success && !typeParamBound.isDynamic) {
-        // If everything else succeeded, check the `extends` constraint.
-        var extendsConstraint =
-            new _TypeConstraint.fromExtends(typeParam, typeParamBound);
-        constraints.add(extendsConstraint);
-        success = extendsConstraint.isSatisifedBy(_typeSystem, inferred);
-      }
-
-      if (!success) {
-        errorReporter?.reportErrorForNode(
-            StrongModeCode.COULD_NOT_INFER,
-            errorNode,
-            [typeParam, _formatError(typeParam, inferred, constraints)]);
-
-        // Heuristic: even if we failed, keep the erroneous type.
-        // It should satisfy at least some of the constraints (e.g. the return
-        // context). If we fall back to instantiateToBounds, we'll typically get
-        // more errors (e.g. because `dynamic` is the most common bound).
-      }
-
-      if (UnknownInferredType.isKnown(inferred)) {
-        knownTypes[typeParam] = inferred;
-      }
-    }
-
-    // Use instantiate to bounds to finish things off.
-    var hasError = new List<bool>.filled(fnTypeParams.length, false);
-    var result = _typeSystem.instantiateToBounds(genericType,
-        hasError: hasError, knownTypes: knownTypes) as dynamic/*=T*/;
-
-    // Report any errors from instantiateToBounds.
-    for (int i = 0; i < hasError.length; i++) {
-      if (hasError[i]) {
-        TypeParameterType typeParam = fnTypeParams[i];
-        var typeParamBound =
-            typeParam.bound.substitute2(inferredTypes, fnTypeParams);
-        // TODO(jmesserly): improve this error message.
-        errorReporter
-            ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
-          typeParam,
-          "\nRecursive bound cannot be instantiated: '$typeParamBound'."
-              "\nConsider passing explicit type argument(s) "
-              "to the generic.\n\n'"
-        ]);
-      }
-    }
-    return result;
-  }
-
-  DartType _inferTypeParameterFromContext(
-      Iterable<_TypeConstraint> constraints, _TypeConstraint extendsClause) {
-    DartType t = _chooseTypeFromConstraints(constraints);
-    if (UnknownInferredType.isUnknown(t)) {
-      return t;
-    }
-
-    // If we're about to make our final choice, apply the extends clause.
-    // This gives us a chance to refine the choice, in case it would violate
-    // the `extends` clause. For example:
-    //
-    //     Object obj = math.min/*<infer Object, error>*/(1, 2);
-    //
-    // If we consider the `T extends num` we conclude `<num>`, which works.
-    if (extendsClause != null) {
-      constraints = constraints.toList()..add(extendsClause);
-      return _chooseTypeFromConstraints(constraints);
-    }
-    return t;
-  }
-
-  DartType _inferTypeParameterFromAll(
-      List<_TypeConstraint> constraints, _TypeConstraint extendsClause) {
-    // See if we already fixed this type from downwards inference.
-    // If so, then we aren't allowed to change it based on argument types.
-    DartType t = _inferTypeParameterFromContext(
-        constraints.where((c) => c.isDownwards), extendsClause);
-    if (UnknownInferredType.isKnown(t)) {
-      // Remove constraints that aren't downward ones; we'll ignore these for
-      // error reporting, because inference already succeeded.
-      constraints.removeWhere((c) => !c.isDownwards);
-      return t;
-    }
-
-    if (extendsClause != null) {
-      constraints = constraints.toList()..add(extendsClause);
-    }
-
-    var choice = _chooseTypeFromConstraints(constraints, toKnownType: true);
-    return choice;
-  }
-
-  /// Choose the bound that was implied by the return type, if any.
-  ///
-  /// Which bound this is depends on what positions the type parameter
-  /// appears in. If the type only appears only in a contravariant position,
-  /// we will choose the lower bound instead.
-  ///
-  /// For example given:
-  ///
-  ///     Func1<T, bool> makeComparer<T>(T x) => (T y) => x() == y;
-  ///
-  ///     main() {
-  ///       Func1<num, bool> t = makeComparer/* infer <num> */(42);
-  ///       print(t(42.0)); /// false, no error.
-  ///     }
-  ///
-  /// The constraints we collect are:
-  ///
-  /// * `num <: T`
-  /// * `int <: T`
-  ///
-  /// ... and no upper bound. Therefore the lower bound is the best choice.
-  DartType _chooseTypeFromConstraints(Iterable<_TypeConstraint> constraints,
-      {bool toKnownType: false}) {
-    DartType lower = UnknownInferredType.instance;
-    DartType upper = UnknownInferredType.instance;
-    for (var constraint in constraints) {
-      // Given constraints:
-      //
-      //     L1 <: T <: U1
-      //     L2 <: T <: U2
-      //
-      // These can be combined to produce:
-      //
-      //     LUB(L1, L2) <: T <: GLB(U1, U2).
-      //
-      // This can then be done for all constraints in sequence.
-      //
-      // This resulting constraint may be unsatisfiable; in that case inference
-      // will fail.
-      upper = _getGreatestLowerBound(upper, constraint.upperBound);
-      lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
-    }
-
-    // Prefer the known bound, if any.
-    // Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
-    //
-    // For both of those, prefer the lower bound (arbitrary heuristic).
-    if (UnknownInferredType.isKnown(lower)) {
-      return lower;
-    }
-    if (UnknownInferredType.isKnown(upper)) {
-      return upper;
-    }
-    if (!identical(UnknownInferredType.instance, lower)) {
-      return toKnownType ? _typeSystem.lowerBoundForType(lower) : lower;
-    }
-    if (!identical(UnknownInferredType.instance, upper)) {
-      return toKnownType ? _typeSystem.upperBoundForType(upper) : upper;
-    }
-    return lower;
-  }
-
-  /// This is first calls strong mode's GLB, but if it fails to find anything
-  /// (i.e. returns the bottom type), we kick in a few additional rules:
-  ///
-  /// - `GLB(FutureOr<A>, B)` is defined as:
-  ///   - `GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>`
-  ///   - `GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>`
-  ///   - else `GLB(FutureOr<A>, B) == GLB(A, B)`
-  /// - `GLB(A, FutureOr<B>) ==  GLB(FutureOr<A>, B)` (defined above),
-  /// - else `GLB(A, B) == Null`
-  DartType _getGreatestLowerBound(DartType t1, DartType t2) {
-    var result = _typeSystem.getGreatestLowerBound(t1, t2);
-    if (result.isBottom) {
-      // See if we can do better by considering FutureOr rules.
-      if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
-        var t1TypeArg = t1.typeArguments[0];
-        if (t2 is InterfaceType) {
-          //  GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
-          if (t2.isDartAsyncFutureOr) {
-            var t2TypeArg = t2.typeArguments[0];
-            return typeProvider.futureOrType
-                .instantiate([_getGreatestLowerBound(t1TypeArg, t2TypeArg)]);
-          }
-          // GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
-          if (t2.isDartAsyncFuture) {
-            var t2TypeArg = t2.typeArguments[0];
-            return typeProvider.futureType
-                .instantiate([_getGreatestLowerBound(t1TypeArg, t2TypeArg)]);
-          }
-        }
-        // GLB(FutureOr<A>, B) == GLB(A, B)
-        return _getGreatestLowerBound(t1TypeArg, t2);
-      }
-      if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
-        // GLB(A, FutureOr<B>) ==  GLB(FutureOr<A>, B)
-        return _getGreatestLowerBound(t2, t1);
-      }
-      // TODO(jmesserly): fix this rule once we support non-nullable types.
-      return typeProvider.nullType;
-    }
-    return result;
-  }
-
-  String _formatError(TypeParameterType typeParam, DartType inferred,
-      Iterable<_TypeConstraint> constraints) {
-    var intro = "Tried to infer '$inferred' for '$typeParam'"
-        " which doesn't work:";
-
-    var constraintsByOrigin = <_TypeConstraintOrigin, List<_TypeConstraint>>{};
-    for (var c in constraints) {
-      constraintsByOrigin.putIfAbsent(c.origin, () => []).add(c);
-    }
-
-    // Only report unique constraint origins.
-    Iterable<_TypeConstraint> isSatisified(bool expected) => constraintsByOrigin
-        .values
-        .where((l) =>
-            l.every((c) => c.isSatisifedBy(_typeSystem, inferred)) == expected)
-        .expand((i) => i);
-
-    String unsatisified = _formatConstraints(isSatisified(false));
-    String satisified = _formatConstraints(isSatisified(true));
-
-    assert(unsatisified.isNotEmpty);
-    if (satisified.isNotEmpty) {
-      satisified = "\nThe type '$inferred' was inferred from:\n$satisified";
-    }
-
-    return '\n\n$intro\n$unsatisified$satisified\n\n'
-        'Consider passing explicit type argument(s) to the generic.\n\n';
-  }
-
   static String _formatConstraints(Iterable<_TypeConstraint> constraints) {
     List<List<String>> lineParts =
         new Set<_TypeConstraintOrigin>.from(constraints.map((c) => c.origin))
@@ -2111,11 +2217,34 @@
   }
 }
 
-/// The origin of a type constraint, for the purposes of producing a human
-/// readable error message during type inference as well as determining whether
-/// the constraint was used to fix the type parameter or not.
-abstract class _TypeConstraintOrigin {
-  List<String> formatError();
+/// A constraint on a type parameter that we're inferring.
+class _TypeConstraint extends _TypeRange {
+  /// The type parameter that is constrained by [lowerBound] or [upperBound].
+  final TypeParameterType typeParameter;
+
+  /// Where this constraint comes from, used for error messages.
+  ///
+  /// See [toString].
+  final _TypeConstraintOrigin origin;
+
+  _TypeConstraint(this.origin, this.typeParameter,
+      {DartType upper, DartType lower})
+      : super(upper: upper, lower: lower);
+
+  _TypeConstraint.fromExtends(TypeParameterType type, DartType extendsType)
+      : this(new _TypeConstraintFromExtendsClause(type, extendsType), type,
+            upper: extendsType);
+
+  bool get isDownwards => origin is! _TypeConstraintFromArgument;
+
+  bool isSatisifedBy(TypeSystem ts, DartType type) =>
+      ts.isSubtypeOf(lowerBound, type) && ts.isSubtypeOf(type, upperBound);
+
+  /// Converts this constraint to a message suitable for a type inference error.
+  @override
+  String toString() => !identical(upperBound, UnknownInferredType.instance)
+      ? "'$typeParameter' must extend '$upperBound'"
+      : "'$lowerBound' must extend '$typeParameter'";
 }
 
 class _TypeConstraintFromArgument extends _TypeConstraintOrigin {
@@ -2153,18 +2282,17 @@
   }
 }
 
-class _TypeConstraintFromReturnType extends _TypeConstraintOrigin {
-  final DartType contextType;
-  final DartType declaredType;
+class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
+  final TypeParameterType typeParam;
+  final DartType extendsType;
 
-  _TypeConstraintFromReturnType(this.declaredType, this.contextType);
+  _TypeConstraintFromExtendsClause(this.typeParam, this.extendsType);
 
   @override
   formatError() {
     return [
-      "Return type",
-      "declared as '$declaredType'",
-      "used where  '$contextType' is required."
+      "Type parameter '$typeParam'",
+      "declared to extend '$extendsType'."
     ];
   }
 }
@@ -2185,21 +2313,29 @@
   }
 }
 
-class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
-  final TypeParameterType typeParam;
-  final DartType extendsType;
+class _TypeConstraintFromReturnType extends _TypeConstraintOrigin {
+  final DartType contextType;
+  final DartType declaredType;
 
-  _TypeConstraintFromExtendsClause(this.typeParam, this.extendsType);
+  _TypeConstraintFromReturnType(this.declaredType, this.contextType);
 
   @override
   formatError() {
     return [
-      "Type parameter '$typeParam'",
-      "declared to extend '$extendsType'."
+      "Return type",
+      "declared as '$declaredType'",
+      "used where  '$contextType' is required."
     ];
   }
 }
 
+/// The origin of a type constraint, for the purposes of producing a human
+/// readable error message during type inference as well as determining whether
+/// the constraint was used to fix the type parameter or not.
+abstract class _TypeConstraintOrigin {
+  List<String> formatError();
+}
+
 class _TypeRange {
   /// The upper bound of the type parameter. In other words, T <: upperBound.
   ///
@@ -2247,131 +2383,3 @@
       : lowerBound = lower ?? UnknownInferredType.instance,
         upperBound = upper ?? UnknownInferredType.instance;
 }
-
-/// A constraint on a type parameter that we're inferring.
-class _TypeConstraint extends _TypeRange {
-  /// The type parameter that is constrained by [lowerBound] or [upperBound].
-  final TypeParameterType typeParameter;
-
-  /// Where this constraint comes from, used for error messages.
-  ///
-  /// See [toString].
-  final _TypeConstraintOrigin origin;
-
-  _TypeConstraint(this.origin, this.typeParameter,
-      {DartType upper, DartType lower})
-      : super(upper: upper, lower: lower);
-
-  _TypeConstraint.fromExtends(TypeParameterType type, DartType extendsType)
-      : this(new _TypeConstraintFromExtendsClause(type, extendsType), type,
-            upper: extendsType);
-
-  bool get isDownwards => origin is! _TypeConstraintFromArgument;
-
-  bool isSatisifedBy(TypeSystem ts, DartType type) =>
-      ts.isSubtypeOf(lowerBound, type) && ts.isSubtypeOf(type, upperBound);
-
-  /// Converts this constraint to a message suitable for a type inference error.
-  @override
-  String toString() => !identical(upperBound, UnknownInferredType.instance)
-      ? "'$typeParameter' must extend '$upperBound'"
-      : "'$lowerBound' must extend '$typeParameter'";
-}
-
-/// The synthetic element for [UnknownInferredType].
-class UnknownInferredTypeElement extends ElementImpl
-    implements TypeDefiningElement {
-  static final UnknownInferredTypeElement instance =
-      new UnknownInferredTypeElement._();
-
-  @override
-  UnknownInferredType get type => UnknownInferredType.instance;
-
-  UnknownInferredTypeElement._() : super(Keyword.DYNAMIC.syntax, -1) {
-    setModifier(Modifier.SYNTHETIC, true);
-  }
-
-  @override
-  ElementKind get kind => ElementKind.DYNAMIC;
-
-  @override
-  /*=T*/ accept/*<T>*/(ElementVisitor visitor) => null;
-}
-
-/// A type that is being inferred but is not currently known.
-///
-/// This type will only appear in a downward inference context for type
-/// parameters that we do not know yet. Notationally it is written `?`, for
-/// example `List<?>`. This is distinct from `List<dynamic>`. These types will
-/// never appear in the final resolved AST.
-class UnknownInferredType extends TypeImpl {
-  static final UnknownInferredType instance = new UnknownInferredType._();
-
-  UnknownInferredType._()
-      : super(UnknownInferredTypeElement.instance, Keyword.DYNAMIC.syntax);
-
-  @override
-  int get hashCode => 1;
-
-  @override
-  bool get isDynamic => true;
-
-  @override
-  bool operator ==(Object object) => identical(object, this);
-
-  @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    // T is S
-    if (identical(this, type)) {
-      return true;
-    }
-    // else
-    return withDynamic;
-  }
-
-  @override
-  bool isSubtypeOf(DartType type) => true;
-
-  @override
-  bool isSupertypeOf(DartType type) => true;
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
-  DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
-    int length = parameterTypes.length;
-    for (int i = 0; i < length; i++) {
-      if (parameterTypes[i] == this) {
-        return argumentTypes[i];
-      }
-    }
-    return this;
-  }
-
-  @override
-  void appendTo(StringBuffer buffer, Set<TypeImpl> types) {
-    buffer.write('?');
-  }
-
-  /// Given a [type] T, return true if it does not have an unknown type `?`.
-  static bool isKnown(DartType type) => !isUnknown(type);
-
-  /// Given a [type] T, return true if it has an unknown type `?`.
-  static bool isUnknown(DartType type) {
-    if (identical(type, UnknownInferredType.instance)) {
-      return true;
-    }
-    if (type is InterfaceTypeImpl) {
-      return type.typeArguments.any(isUnknown);
-    }
-    if (type is FunctionType) {
-      return isUnknown(type.returnType) ||
-          type.parameters.any((p) => isUnknown(p.type));
-    }
-    return false;
-  }
-}
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 57d85e2..84a8a3c 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -21,7 +21,7 @@
 import 'package:analyzer/src/lint/project.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart';
-import 'package:cli_util/cli_util.dart' as cli_util;
+import 'package:analyzer/src/util/sdk.dart';
 import 'package:package_config/packages.dart' show Packages;
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
 import 'package:package_config/src/packages_impl.dart' show MapPackages;
@@ -134,12 +134,8 @@
   }
 
   String get sdkDir {
-    if (options.dartSdkPath != null) {
-      return options.dartSdkPath;
-    }
-    // In case no SDK has been specified, fall back to inferring it
-    // TODO: pass args to cli_util
-    return cli_util.getSdkDir().path;
+    // In case no SDK has been specified, fall back to inferring it.
+    return options.dartSdkPath ?? getSdkPath();
   }
 
   List<AnalysisErrorInfo> analyze(Iterable<io.File> files) {
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index ce323b9..7bda04c 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -4798,8 +4798,8 @@
 }
 
 /**
- * Specialization of [DependencyWalker] for performing type inferrence
- * on static and top level variables.
+ * Specialization of [DependencyWalker] for performing type inference on static
+ * and top level variables.
  */
 class TypeInferenceDependencyWalker
     extends DependencyWalker<TypeInferenceNode> {
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index 04d21bd..19ada97 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -21,6 +21,56 @@
 import 'package:front_end/src/base/source.dart';
 
 /**
+ * A [ConflictingSummaryException] indicates that two different summaries
+ * provided to a [SummaryDataStore] conflict.
+ */
+class ConflictingSummaryException implements Exception {
+  final String duplicatedUri;
+  final String summary1Uri;
+  final String summary2Uri;
+  String _message;
+
+  ConflictingSummaryException(Iterable<String> summaryPaths, this.duplicatedUri,
+      this.summary1Uri, this.summary2Uri) {
+    // Paths are often quite long.  Find and extract out a common prefix to
+    // build a more readable error message.
+    var prefix = _commonPrefix(summaryPaths.toList());
+    _message = '''
+These summaries conflict because they overlap:
+- ${summary1Uri.substring(prefix)}
+- ${summary2Uri.substring(prefix)}
+Both contain the file: ${duplicatedUri}.
+This typically indicates an invalid build rule where two or more targets
+include the same source.
+  ''';
+  }
+
+  String toString() => _message;
+
+  /// Given a set of file paths, find a common prefix.
+  int _commonPrefix(List<String> strings) {
+    if (strings.isEmpty) return 0;
+    var first = strings.first;
+    int common = first.length;
+    for (int i = 1; i < strings.length; ++i) {
+      var current = strings[i];
+      common = min(common, current.length);
+      for (int j = 0; j < common; ++j) {
+        if (first[j] != current[j]) {
+          common = j;
+          if (common == 0) return 0;
+          break;
+        }
+      }
+    }
+    // The prefix should end with a file separator.
+    var last =
+        first.substring(0, common).lastIndexOf(io.Platform.pathSeparator);
+    return last < 0 ? 0 : last + 1;
+  }
+}
+
+/**
  * The [ResultProvider] that provides results from input package summaries.
  */
 class InputPackagesResultProvider extends ResynthesizerResultProvider {
@@ -307,56 +357,6 @@
 }
 
 /**
- * A [ConflictingSummaryException] indicates that two different summaries
- * provided to a [SummaryDataStore] conflict.
- */
-class ConflictingSummaryException implements Exception {
-  final String duplicatedUri;
-  final String summary1Uri;
-  final String summary2Uri;
-  String _message;
-
-  ConflictingSummaryException(Iterable<String> summaryPaths, this.duplicatedUri,
-      this.summary1Uri, this.summary2Uri) {
-    // Paths are often quite long.  Find and extract out a common prefix to
-    // build a more readable error message.
-    var prefix = _commonPrefix(summaryPaths.toList());
-    _message = '''
-These summaries conflict because they overlap:
-- ${summary1Uri.substring(prefix)}
-- ${summary2Uri.substring(prefix)}
-Both contain the file: ${duplicatedUri}.
-This typically indicates an invalid build rule where two or more targets
-include the same source.
-  ''';
-  }
-
-  /// Given a set of file paths, find a common prefix.
-  int _commonPrefix(List<String> strings) {
-    if (strings.isEmpty) return 0;
-    var first = strings.first;
-    int common = first.length;
-    for (int i = 1; i < strings.length; ++i) {
-      var current = strings[i];
-      common = min(common, current.length);
-      for (int j = 0; j < common; ++j) {
-        if (first[j] != current[j]) {
-          common = j;
-          if (common == 0) return 0;
-          break;
-        }
-      }
-    }
-    // The prefix should end with a file separator.
-    var last =
-        first.substring(0, common).lastIndexOf(io.Platform.pathSeparator);
-    return last < 0 ? 0 : last + 1;
-  }
-
-  String toString() => _message;
-}
-
-/**
  * A [SummaryDataStore] is a container for the data extracted from a set of
  * summary package bundles.  It contains maps which can be used to find linked
  * and unlinked summaries by URI.
@@ -472,6 +472,14 @@
   }
 
   /**
+   * Add into this store the unlinked units and linked libraries of [other].
+   */
+  void addStore(SummaryDataStore other) {
+    unlinkedMap.addAll(other.unlinkedMap);
+    linkedMap.addAll(other.linkedMap);
+  }
+
+  /**
    * Add the given [unlinkedUnit] with the given [uri].
    */
   void addUnlinkedUnit(String uri, UnlinkedUnit unlinkedUnit) {
@@ -503,6 +511,14 @@
     return libraryUriStrings.isNotEmpty ? libraryUriStrings : null;
   }
 
+  /**
+   * Return `true` if the store contains the unlinked summary for the unit
+   * with the given absolute [uri].
+   */
+  bool hasUnlinkedUnit(String uri) {
+    return unlinkedMap.containsKey(uri);
+  }
+
   void _fillMaps(String path, ResourceProvider resourceProvider) {
     List<int> buffer;
     if (resourceProvider != null) {
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 234f46a..b3f32cda 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1221,7 +1221,7 @@
    * If this reference refers to a non-generic type, the type it refers to.
    * Otherwise `null`.
    */
-  DartType type;
+  DartType _type;
 
   /**
    * The number of type parameters accepted by the entity referred to by this
@@ -1229,6 +1229,9 @@
    */
   final int numTypeParameters;
 
+  bool _isBeingInstantiatedToBounds = false;
+  bool _isRecursiveWhileInstantiateToBounds = false;
+
   /**
    * Create a new [_ReferenceInfo] object referring to an element called [name]
    * via the element handle [element], and having [numTypeParameters] type
@@ -1247,13 +1250,25 @@
       DartType specialType,
       this.numTypeParameters) {
     if (specialType != null) {
-      type = specialType;
-    } else {
-      type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
+      _type = specialType;
     }
   }
 
   /**
+   * If this reference refers to a non-generic type, the type it refers to.
+   * Otherwise `null`.
+   */
+  DartType get type {
+    if (_type == null) {
+      _type = _buildType(true, 0, (_) => DynamicTypeImpl.instance, const []);
+    }
+    return _type;
+  }
+
+  List<DartType> get _dynamicTypeArguments =>
+      new List<DartType>.filled(numTypeParameters, DynamicTypeImpl.instance);
+
+  /**
    * Build a [DartType] corresponding to the result of applying some type
    * arguments to the entity referred to by this [_ReferenceInfo].  The type
    * arguments are retrieved by calling [getTypeArgument].
@@ -1313,8 +1328,7 @@
                 .instantiateToBounds(element.type) as InterfaceType;
             return instantiatedToBounds.typeArguments;
           } else {
-            return new List<DartType>.filled(
-                numTypeParameters, DynamicTypeImpl.instance);
+            return _dynamicTypeArguments;
           }
         }
         return typeArguments;
@@ -1339,13 +1353,27 @@
               _buildTypeArguments(numTypeArguments, getTypeArgument);
         } else if (libraryResynthesizer.summaryResynthesizer.strongMode &&
             instantiateToBoundsAllowed) {
-          FunctionType instantiatedToBounds = libraryResynthesizer
-              .summaryResynthesizer.context.typeSystem
-              .instantiateToBounds(element.type) as FunctionType;
-          typeArguments = instantiatedToBounds.typeArguments;
+          if (!_isBeingInstantiatedToBounds) {
+            _isBeingInstantiatedToBounds = true;
+            _isRecursiveWhileInstantiateToBounds = false;
+            try {
+              FunctionType instantiatedToBounds = libraryResynthesizer
+                  .summaryResynthesizer.context.typeSystem
+                  .instantiateToBounds(element.type) as FunctionType;
+              if (!_isRecursiveWhileInstantiateToBounds) {
+                typeArguments = instantiatedToBounds.typeArguments;
+              } else {
+                typeArguments = _dynamicTypeArguments;
+              }
+            } finally {
+              _isBeingInstantiatedToBounds = false;
+            }
+          } else {
+            _isRecursiveWhileInstantiateToBounds = true;
+            typeArguments = _dynamicTypeArguments;
+          }
         } else {
-          typeArguments = new List<DartType>.filled(
-              numTypeParameters, DynamicTypeImpl.instance);
+          typeArguments = _dynamicTypeArguments;
         }
         return new FunctionTypeImpl.elementWithNameAndArgs(
             element, name, typeArguments, numTypeParameters != 0);
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index a7856f9..2de68f1 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -43,7 +43,6 @@
 import 'package:analyzer/src/task/driver.dart';
 import 'package:analyzer/src/task/general.dart';
 import 'package:analyzer/src/task/html.dart';
-import 'package:analyzer/src/task/incremental_element_builder.dart';
 import 'package:analyzer/src/task/inputs.dart';
 import 'package:analyzer/src/task/model.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
@@ -677,14 +676,6 @@
     new ResultDescriptor<bool>('READY_RESOLVED_UNIT', false);
 
 /**
- * The names (resolved and not) referenced by a unit.
- *
- * The result is only available for [Source]s representing a compilation unit.
- */
-final ResultDescriptor<ReferencedNames> REFERENCED_NAMES =
-    new ResultDescriptor<ReferencedNames>('REFERENCED_NAMES', null);
-
-/**
  * The sources of the Dart files that a library references.
  *
  * The list is the union of [IMPORTED_LIBRARIES], [EXPORTED_LIBRARIES] and
@@ -2466,338 +2457,6 @@
 }
 
 /**
- * The description for a change in a Dart source.
- */
-class DartDelta extends Delta {
-  final Set<String> changedNames = new Set<String>();
-  final Map<Source, Set<String>> changedPrivateNames = <Source, Set<String>>{};
-
-  final Map<String, ClassElementDelta> changedClasses =
-      <String, ClassElementDelta>{};
-
-  /**
-   * The cache of libraries in which all results are invalid.
-   */
-  final Set<Source> librariesWithAllInvalidResults = new Set<Source>();
-
-  /**
-   * The cache of libraries in which all results are valid.
-   */
-  final Set<Source> librariesWithAllValidResults = new Set<Source>();
-
-  /**
-   * The cache of libraries with all, but [HINTS] and [VERIFY_ERRORS] results
-   * are valid.
-   */
-  final Set<Source> libraryWithInvalidErrors = new Set<Source>();
-
-  /**
-   * This set is cleared in every [gatherEnd], and [gatherChanges] uses it
-   * to find changes in every source only once per visit process.
-   */
-  final Set<Source> currentVisitUnits = new Set<Source>();
-
-  DartDelta(Source source) : super(source);
-
-  @override
-  bool get shouldGatherChanges => true;
-
-  /**
-   * Add names that are changed in the given [references].
-   * Return `true` if any change was added.
-   */
-  bool addChangedElements(ReferencedNames references, Source refLibrary) {
-    int numberOfChanges = 0;
-    int lastNumberOfChange = -1;
-    while (numberOfChanges != lastNumberOfChange) {
-      lastNumberOfChange = numberOfChanges;
-      // Classes that extend changed classes are also changed.
-      // If there is a delta for a superclass, use it for the subclass.
-      // Otherwise mark the subclass as "general name change".
-      references.superToSubs.forEach((String superName, Set<String> subNames) {
-        ClassElementDelta superDelta = changedClasses[superName];
-        for (String subName in subNames) {
-          if (superDelta != null) {
-            ClassElementDelta subDelta = changedClasses.putIfAbsent(subName,
-                () => new ClassElementDelta(null, refLibrary, subName));
-            _log(() => '$subName in $refLibrary has delta because of its '
-                'superclass $superName has delta');
-            if (subDelta.superDeltas.add(superDelta)) {
-              numberOfChanges++;
-            }
-          } else if (isChanged(refLibrary, superName)) {
-            if (nameChanged(refLibrary, subName)) {
-              _log(() => '$subName in $refLibrary is changed because its '
-                  'superclass $superName is changed');
-              numberOfChanges++;
-            }
-          }
-        }
-      });
-      // If a user element uses a changed top-level element, then the user is
-      // also changed. Note that if a changed class with delta is used, this
-      // does not make the user changed - classes with delta keep their
-      // original elements, so resolution of their names does not change.
-      references.userToDependsOn.forEach((user, dependencies) {
-        for (String dependency in dependencies) {
-          if (isChangedOrClassMember(refLibrary, dependency)) {
-            if (nameChanged(refLibrary, user)) {
-              _log(() => '$user in $refLibrary is changed because '
-                  'of $dependency in $dependencies');
-              numberOfChanges++;
-            }
-          }
-        }
-      });
-    }
-    return numberOfChanges != 0;
-  }
-
-  void classChanged(ClassElementDelta classDelta) {
-    changedClasses[classDelta.name] = classDelta;
-  }
-
-  void elementChanged(Element element) {
-    Source librarySource = element.library.source;
-    nameChanged(librarySource, element.name);
-  }
-
-  @override
-  bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
-      ResultDescriptor descriptor, Object value) {
-    // Prepare target source.
-    Source targetUnit = target.source;
-    Source targetLibrary = target.librarySource;
-    if (target is Source) {
-      if (context.getKindOf(target) == SourceKind.LIBRARY) {
-        targetLibrary = target;
-      }
-    }
-    // We don't know what to do with the given target.
-    if (targetUnit == null || targetUnit != targetLibrary) {
-      return false;
-    }
-    // Attempt to find new changed names for the unit only once.
-    if (!currentVisitUnits.add(targetUnit)) {
-      return false;
-    }
-    // Add changes.
-    ReferencedNames referencedNames =
-        context.getResult(targetUnit, REFERENCED_NAMES);
-    if (referencedNames == null) {
-      return false;
-    }
-    return addChangedElements(referencedNames, targetLibrary);
-  }
-
-  @override
-  void gatherEnd() {
-    currentVisitUnits.clear();
-  }
-
-  bool hasAffectedHintsVerifyErrors(
-      ReferencedNames references, Source refLibrary) {
-    for (String superName in references.superToSubs.keys) {
-      if (isChangedOrClass(refLibrary, superName)) {
-        _log(() => '$refLibrary hints/verify errors are affected because '
-            '${references.superToSubs[superName]} subclasses $superName');
-        return true;
-      }
-    }
-    for (String name in references.names) {
-      ClassElementDelta classDelta = changedClasses[name];
-      if (classDelta != null && classDelta.hasAnnotationChanges) {
-        _log(() => '$refLibrary hints/verify errors are  affected because '
-            '$name has a class delta with annotation changes');
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool hasAffectedReferences(ReferencedNames references, Source refLibrary) {
-    // Resolution must be performed when a referenced element changes.
-    for (String name in references.names) {
-      if (isChangedOrClassMember(refLibrary, name)) {
-        _log(() => '$refLibrary is affected by $name');
-        return true;
-      }
-    }
-    // Resolution must be performed when the unnamed constructor of
-    // an instantiated class is added/changed/removed.
-    // TODO(scheglov) Use only instantiations with default constructor.
-    for (String name in references.instantiatedNames) {
-      for (ClassElementDelta classDelta in changedClasses.values) {
-        if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
-          _log(() =>
-              '$refLibrary is affected by the default constructor of $name');
-          return true;
-        }
-      }
-    }
-    for (String name in references.extendedUsedUnnamedConstructorNames) {
-      for (ClassElementDelta classDelta in changedClasses.values) {
-        if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
-          _log(() =>
-              '$refLibrary is affected by the default constructor of $name');
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Return `true` if the given [name], used in a unit of the [librarySource],
-   * is affected by a changed top-level element, excluding classes.
-   */
-  bool isChanged(Source librarySource, String name) {
-    if (_isPrivateName(name)) {
-      if (changedPrivateNames[librarySource]?.contains(name) ?? false) {
-        return true;
-      }
-    }
-    return changedNames.contains(name);
-  }
-
-  /**
-   * Return `true` if the given [name], used in a unit of the [librarySource],
-   * is affected by a changed top-level element or a class.
-   */
-  bool isChangedOrClass(Source librarySource, String name) {
-    if (isChanged(librarySource, name)) {
-      return true;
-    }
-    return changedClasses[name] != null;
-  }
-
-  /**
-   * Return `true` if the given [name], used in a unit of the [librarySource],
-   * is affected by a changed top-level element or a class member.
-   */
-  bool isChangedOrClassMember(Source librarySource, String name) {
-    if (isChanged(librarySource, name)) {
-      return true;
-    }
-    // TODO(scheglov) Optimize this.
-    for (ClassElementDelta classDelta in changedClasses.values) {
-      if (classDelta.hasChanges(librarySource, name)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Register the fact that the given [name], defined in the [librarySource]
-   * is changed.  Return `true` if the [name] is a new name, not yet registered.
-   */
-  bool nameChanged(Source librarySource, String name) {
-    if (_isPrivateName(name)) {
-      return changedPrivateNames
-          .putIfAbsent(librarySource, () => new Set<String>())
-          .add(name);
-    } else {
-      return changedNames.add(name);
-    }
-  }
-
-  @override
-  DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
-      ResultDescriptor descriptor, Object value) {
-    // Always invalidate compounding results.
-    if (descriptor == LIBRARY_ELEMENT4 ||
-        descriptor == READY_LIBRARY_ELEMENT6 ||
-        descriptor == READY_LIBRARY_ELEMENT7) {
-      return DeltaResult.INVALIDATE_KEEP_DEPENDENCIES;
-    }
-    // Prepare target source.
-    Source targetUnit = target.source;
-    Source targetLibrary = target.librarySource;
-    if (target is Source) {
-      if (context.getKindOf(target) == SourceKind.LIBRARY) {
-        targetLibrary = target;
-      }
-    }
-    // We don't know what to do with the given target, invalidate it.
-    if (targetUnit == null || targetUnit != targetLibrary) {
-      return DeltaResult.INVALIDATE;
-    }
-    // Keep results that don't change: any library.
-    if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(BuildDirectiveElementsTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(ResolveDirectiveElementsTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(BuildEnumMemberElementsTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(BuildSourceExportClosureTask.DESCRIPTOR, descriptor) ||
-        _isTaskResult(ReadyLibraryElement2Task.DESCRIPTOR, descriptor) ||
-        _isTaskResult(ComputeLibraryCycleTask.DESCRIPTOR, descriptor)) {
-      return DeltaResult.KEEP_CONTINUE;
-    }
-    // Keep results that don't change: changed library.
-    if (targetUnit == source) {
-      return DeltaResult.INVALIDATE;
-    }
-    // Keep results that don't change: dependent library.
-    if (targetUnit != source) {
-      if (_isTaskResult(BuildPublicNamespaceTask.DESCRIPTOR, descriptor)) {
-        return DeltaResult.KEEP_CONTINUE;
-      }
-    }
-    // Handle in-library results only for now.
-    if (targetLibrary != null) {
-      // Use cached library results.
-      if (librariesWithAllInvalidResults.contains(targetLibrary)) {
-        return DeltaResult.INVALIDATE;
-      }
-      if (librariesWithAllValidResults.contains(targetLibrary)) {
-        return DeltaResult.KEEP_CONTINUE;
-      }
-      // The library is almost, but not completely valid.
-      // Some error results are invalid.
-      if (libraryWithInvalidErrors.contains(targetLibrary)) {
-        if (descriptor == HINTS || descriptor == VERIFY_ERRORS) {
-          return DeltaResult.INVALIDATE_NO_DELTA;
-        }
-        return DeltaResult.KEEP_CONTINUE;
-      }
-      // Compute the library result.
-      ReferencedNames referencedNames =
-          context.getResult(targetUnit, REFERENCED_NAMES);
-      if (referencedNames == null) {
-        return DeltaResult.INVALIDATE_NO_DELTA;
-      }
-      if (hasAffectedReferences(referencedNames, targetLibrary)) {
-        librariesWithAllInvalidResults.add(targetLibrary);
-        return DeltaResult.INVALIDATE;
-      }
-      if (hasAffectedHintsVerifyErrors(referencedNames, targetLibrary)) {
-        libraryWithInvalidErrors.add(targetLibrary);
-        return DeltaResult.KEEP_CONTINUE;
-      }
-      librariesWithAllValidResults.add(targetLibrary);
-      return DeltaResult.KEEP_CONTINUE;
-    }
-    // We don't know what to do with the given target, invalidate it.
-    return DeltaResult.INVALIDATE;
-  }
-
-  void _log(String getMessage()) {
-//    String message = getMessage();
-//    print(message);
-  }
-
-  static bool _isPrivateName(String name) => name.startsWith('_');
-
-  static bool _isTaskResult(
-      TaskDescriptor taskDescriptor, ResultDescriptor result) {
-    return taskDescriptor.results.contains(result);
-  }
-}
-
-/**
  * A task that merges all of the errors for a single source into a single list
  * of errors.
  */
@@ -4068,7 +3727,6 @@
     LIBRARY_SPECIFIC_UNITS,
     PARSE_ERRORS,
     PARSED_UNIT,
-    REFERENCED_NAMES,
     REFERENCED_SOURCES,
     SOURCE_KIND,
     UNITS,
@@ -4184,11 +3842,6 @@
       sourceKind = SourceKind.PART;
     }
     //
-    // Compute referenced names.
-    //
-    ReferencedNames referencedNames = new ReferencedNames(_source);
-    new ReferencedNamesBuilder(referencedNames).build(unit);
-    //
     // Compute source lists.
     //
     List<Source> explicitlyImportedSources =
@@ -4225,7 +3878,6 @@
     outputs[LIBRARY_SPECIFIC_UNITS] = librarySpecificUnits;
     outputs[PARSE_ERRORS] = parseErrors;
     outputs[PARSED_UNIT] = unit;
-    outputs[REFERENCED_NAMES] = referencedNames;
     outputs[REFERENCED_SOURCES] = referencedSources.toList();
     outputs[SOURCE_KIND] = sourceKind;
     outputs[UNITS] = unitSources;
@@ -4599,408 +4251,6 @@
 }
 
 /**
- * Information about a Dart [source] - which names it uses, which names it
- * defines with their externally visible dependencies.
- */
-class ReferencedNames {
-  final Source source;
-
-  /**
-   * The mapping from the name of a class to the set of names of other classes
-   * that extend, mix-in, or implement it.
-   *
-   * If the set of member of a class is changed, these changes might change
-   * the list of unimplemented inherited members in the class and classes that
-   * extend, mix-in, or implement it. So, we might need to report (or stop
-   * reporting) the corresponding warning.
-   */
-  final Map<String, Set<String>> superToSubs = <String, Set<String>>{};
-
-  /**
-   * The names of extended classes for which the unnamed constructor is
-   * invoked. Because we cannot use the name of the constructor to identify
-   * whether the unit is affected, we need to use the class name.
-   */
-  final Set<String> extendedUsedUnnamedConstructorNames = new Set<String>();
-
-  /**
-   * The names of instantiated classes.
-   *
-   * If one of these classes changes its set of members, it might change
-   * its list of unimplemented inherited members. So, we might need to report
-   * (or stop reporting) the corresponding warning.
-   */
-  final Set<String> instantiatedNames = new Set<String>();
-
-  /**
-   * The set of names that are referenced by the library, both inside and
-   * outside of method bodies.
-   */
-  final Set<String> names = new Set<String>();
-
-  /**
-   * The mapping from the name of a top-level element to the set of names that
-   * the element uses in a way that is visible outside of the element, e.g.
-   * the return type, or a parameter type.
-   */
-  final Map<String, Set<String>> userToDependsOn = <String, Set<String>>{};
-
-  ReferencedNames(this.source);
-
-  void addSubclass(String subName, String superName) {
-    superToSubs.putIfAbsent(superName, () => new Set<String>()).add(subName);
-  }
-}
-
-/**
- * A builder for creating [ReferencedNames].
- */
-class ReferencedNamesBuilder extends GeneralizingAstVisitor {
-  final Set<String> importPrefixNames = new Set<String>();
-  final ReferencedNames names;
-
-  String enclosingSuperClassName;
-  ReferencedNamesScope scope = new ReferencedNamesScope(null);
-
-  int localLevel = 0;
-  Set<String> dependsOn;
-
-  ReferencedNamesBuilder(this.names);
-
-  ReferencedNames build(CompilationUnit unit) {
-    unit.accept(this);
-    return names;
-  }
-
-  @override
-  visitBlock(Block node) {
-    ReferencedNamesScope outerScope = scope;
-    try {
-      scope = new ReferencedNamesScope.forBlock(scope, node);
-      super.visitBlock(node);
-    } finally {
-      scope = outerScope;
-    }
-  }
-
-  @override
-  visitClassDeclaration(ClassDeclaration node) {
-    ReferencedNamesScope outerScope = scope;
-    try {
-      scope = new ReferencedNamesScope.forClass(scope, node);
-      dependsOn = new Set<String>();
-      enclosingSuperClassName =
-          _getSimpleName(node.extendsClause?.superclass?.name);
-      super.visitClassDeclaration(node);
-      String className = node.name.name;
-      names.userToDependsOn[className] = dependsOn;
-      _addSuperName(className, node.extendsClause?.superclass);
-      _addSuperNames(className, node.withClause?.mixinTypes);
-      _addSuperNames(className, node.implementsClause?.interfaces);
-    } finally {
-      enclosingSuperClassName = null;
-      dependsOn = null;
-      scope = outerScope;
-    }
-  }
-
-  @override
-  visitClassTypeAlias(ClassTypeAlias node) {
-    ReferencedNamesScope outerScope = scope;
-    try {
-      scope = new ReferencedNamesScope.forClassTypeAlias(scope, node);
-      dependsOn = new Set<String>();
-      super.visitClassTypeAlias(node);
-      String className = node.name.name;
-      names.userToDependsOn[className] = dependsOn;
-      _addSuperName(className, node.superclass);
-      _addSuperNames(className, node.withClause?.mixinTypes);
-      _addSuperNames(className, node.implementsClause?.interfaces);
-    } finally {
-      dependsOn = null;
-      scope = outerScope;
-    }
-  }
-
-  @override
-  visitComment(Comment node) {
-    try {
-      localLevel++;
-      super.visitComment(node);
-    } finally {
-      localLevel--;
-    }
-  }
-
-  @override
-  visitConstructorName(ConstructorName node) {
-    if (node.parent is! ConstructorDeclaration) {
-      super.visitConstructorName(node);
-    }
-  }
-
-  @override
-  visitFunctionBody(FunctionBody node) {
-    try {
-      localLevel++;
-      super.visitFunctionBody(node);
-    } finally {
-      localLevel--;
-    }
-  }
-
-  @override
-  visitFunctionDeclaration(FunctionDeclaration node) {
-    if (localLevel == 0) {
-      ReferencedNamesScope outerScope = scope;
-      try {
-        scope = new ReferencedNamesScope.forFunction(scope, node);
-        dependsOn = new Set<String>();
-        super.visitFunctionDeclaration(node);
-        names.userToDependsOn[node.name.name] = dependsOn;
-      } finally {
-        dependsOn = null;
-        scope = outerScope;
-      }
-    } else {
-      super.visitFunctionDeclaration(node);
-    }
-  }
-
-  @override
-  visitFunctionTypeAlias(FunctionTypeAlias node) {
-    if (localLevel == 0) {
-      ReferencedNamesScope outerScope = scope;
-      try {
-        scope = new ReferencedNamesScope.forFunctionTypeAlias(scope, node);
-        dependsOn = new Set<String>();
-        super.visitFunctionTypeAlias(node);
-        names.userToDependsOn[node.name.name] = dependsOn;
-      } finally {
-        dependsOn = null;
-        scope = outerScope;
-      }
-    } else {
-      super.visitFunctionTypeAlias(node);
-    }
-  }
-
-  @override
-  visitImportDirective(ImportDirective node) {
-    if (node.prefix != null) {
-      importPrefixNames.add(node.prefix.name);
-    }
-    super.visitImportDirective(node);
-  }
-
-  @override
-  visitInstanceCreationExpression(InstanceCreationExpression node) {
-    ConstructorName constructorName = node.constructorName;
-    Identifier typeName = constructorName.type.name;
-    if (typeName is SimpleIdentifier) {
-      names.instantiatedNames.add(typeName.name);
-    }
-    if (typeName is PrefixedIdentifier) {
-      String prefixName = typeName.prefix.name;
-      if (importPrefixNames.contains(prefixName)) {
-        names.instantiatedNames.add(typeName.identifier.name);
-      } else {
-        names.instantiatedNames.add(prefixName);
-      }
-    }
-    super.visitInstanceCreationExpression(node);
-  }
-
-  @override
-  visitMethodDeclaration(MethodDeclaration node) {
-    ReferencedNamesScope outerScope = scope;
-    try {
-      scope = new ReferencedNamesScope.forMethod(scope, node);
-      super.visitMethodDeclaration(node);
-    } finally {
-      scope = outerScope;
-    }
-  }
-
-  @override
-  visitSimpleIdentifier(SimpleIdentifier node) {
-    // Ignore all declarations.
-    if (node.inDeclarationContext()) {
-      return;
-    }
-    // Ignore class names references from constructors.
-    AstNode parent = node.parent;
-    if (parent is ConstructorDeclaration && parent.returnType == node) {
-      return;
-    }
-    // Prepare name.
-    String name = node.name;
-    // Ignore unqualified names shadowed by local elements.
-    if (!node.isQualified) {
-      if (scope.contains(name)) {
-        return;
-      }
-      if (importPrefixNames.contains(name)) {
-        return;
-      }
-    }
-    // Do add the dependency.
-    names.names.add(name);
-    if (dependsOn != null && localLevel == 0) {
-      dependsOn.add(name);
-    }
-  }
-
-  @override
-  visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    if (node.constructorName == null && enclosingSuperClassName != null) {
-      names.extendedUsedUnnamedConstructorNames.add(enclosingSuperClassName);
-    }
-    super.visitSuperConstructorInvocation(node);
-  }
-
-  @override
-  visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    VariableDeclarationList variableList = node.variables;
-    // Prepare type dependencies.
-    Set<String> typeDependencies = new Set<String>();
-    dependsOn = typeDependencies;
-    variableList.type?.accept(this);
-    // Combine individual variable dependencies with the type dependencies.
-    for (VariableDeclaration variable in variableList.variables) {
-      dependsOn = new Set<String>();
-      variable.accept(this);
-      dependsOn.addAll(typeDependencies);
-      names.userToDependsOn[variable.name.name] = dependsOn;
-    }
-    dependsOn = null;
-  }
-
-  void _addSuperName(String className, TypeName type) {
-    if (type != null) {
-      Identifier typeName = type.name;
-      if (typeName is SimpleIdentifier) {
-        names.addSubclass(className, typeName.name);
-      }
-      if (typeName is PrefixedIdentifier) {
-        names.addSubclass(className, typeName.identifier.name);
-      }
-    }
-  }
-
-  void _addSuperNames(String className, List<TypeName> types) {
-    types?.forEach((type) => _addSuperName(className, type));
-  }
-
-  static String _getSimpleName(Identifier identifier) {
-    if (identifier is SimpleIdentifier) {
-      return identifier.name;
-    }
-    if (identifier is PrefixedIdentifier) {
-      return identifier.identifier.name;
-    }
-    return null;
-  }
-}
-
-class ReferencedNamesScope {
-  final ReferencedNamesScope enclosing;
-  Set<String> names;
-
-  ReferencedNamesScope(this.enclosing);
-
-  factory ReferencedNamesScope.forBlock(
-      ReferencedNamesScope enclosing, Block node) {
-    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
-    for (Statement statement in node.statements) {
-      if (statement is FunctionDeclarationStatement) {
-        scope.add(statement.functionDeclaration.name.name);
-      } else if (statement is VariableDeclarationStatement) {
-        for (VariableDeclaration variable in statement.variables.variables) {
-          scope.add(variable.name.name);
-        }
-      }
-    }
-    return scope;
-  }
-
-  factory ReferencedNamesScope.forClass(
-      ReferencedNamesScope enclosing, ClassDeclaration node) {
-    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
-    scope._addTypeParameters(node.typeParameters);
-    for (ClassMember member in node.members) {
-      if (member is FieldDeclaration) {
-        for (VariableDeclaration variable in member.fields.variables) {
-          scope.add(variable.name.name);
-        }
-      } else if (member is MethodDeclaration) {
-        scope.add(member.name.name);
-      }
-    }
-    return scope;
-  }
-
-  factory ReferencedNamesScope.forClassTypeAlias(
-      ReferencedNamesScope enclosing, ClassTypeAlias node) {
-    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
-    scope._addTypeParameters(node.typeParameters);
-    return scope;
-  }
-
-  factory ReferencedNamesScope.forFunction(
-      ReferencedNamesScope enclosing, FunctionDeclaration node) {
-    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
-    scope._addTypeParameters(node.functionExpression.typeParameters);
-    scope._addFormalParameters(node.functionExpression.parameters);
-    return scope;
-  }
-
-  factory ReferencedNamesScope.forFunctionTypeAlias(
-      ReferencedNamesScope enclosing, FunctionTypeAlias node) {
-    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
-    scope._addTypeParameters(node.typeParameters);
-    return scope;
-  }
-
-  factory ReferencedNamesScope.forMethod(
-      ReferencedNamesScope enclosing, MethodDeclaration node) {
-    ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
-    scope._addTypeParameters(node.typeParameters);
-    scope._addFormalParameters(node.parameters);
-    return scope;
-  }
-
-  void add(String name) {
-    names ??= new Set<String>();
-    names.add(name);
-  }
-
-  bool contains(String name) {
-    if (names != null && names.contains(name)) {
-      return true;
-    }
-    if (enclosing != null) {
-      return enclosing.contains(name);
-    }
-    return false;
-  }
-
-  void _addFormalParameters(FormalParameterList parameterList) {
-    if (parameterList != null) {
-      parameterList.parameters
-          .map((p) => p is NormalFormalParameter ? p.identifier.name : '')
-          .forEach(add);
-    }
-  }
-
-  void _addTypeParameters(TypeParameterList typeParameterList) {
-    if (typeParameterList != null) {
-      typeParameterList.typeParameters.map((p) => p.name.name).forEach(add);
-    }
-  }
-}
-
-/**
  * A task that ensures that the expression AST for a constant is resolved and
  * sets the [CONSTANT_EXPRESSION_RESOLVED] result.
  */
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
deleted file mode 100644
index bbb460e..0000000
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ /dev/null
@@ -1,784 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyzer.src.task.incremental_element_builder;
-
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/constant/utilities.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/dart.dart';
-
-/**
- * The change of a single [ClassElement].
- */
-class ClassElementDelta {
-  final ClassElement _element;
-  final Source librarySource;
-  final String name;
-
-  final Set<ClassElementDelta> superDeltas = new Set<ClassElementDelta>();
-
-  bool hasAnnotationChanges = false;
-
-  final List<PropertyAccessorElement> addedAccessors =
-      <PropertyAccessorElement>[];
-  final List<PropertyAccessorElement> removedAccessors =
-      <PropertyAccessorElement>[];
-
-  final List<ConstructorElement> addedConstructors = <ConstructorElement>[];
-  final List<ConstructorElement> removedConstructors = <ConstructorElement>[];
-  bool hasUnnamedConstructorChange = false;
-
-  final List<MethodElement> addedMethods = <MethodElement>[];
-  final List<MethodElement> removedMethods = <MethodElement>[];
-
-  ClassElementDelta(this._element, this.librarySource, this.name);
-
-  /**
-   * Return `true` if this delta has changes to the [name] visible in the
-   * given [librarySource].
-   */
-  bool hasChanges(Source librarySource, String name) {
-    if (Identifier.isPrivateName(name) && librarySource != this.librarySource) {
-      return false;
-    }
-    return _hasElementWithName(addedAccessors, name) ||
-        _hasElementWithName(removedAccessors, name) ||
-        _hasElementWithName(addedConstructors, name) ||
-        _hasElementWithName(removedConstructors, name) ||
-        _hasElementWithName(addedMethods, name) ||
-        _hasElementWithName(removedMethods, name);
-  }
-
-  static bool _hasElementWithName(List<Element> elements, String name) {
-    return elements.any((e) => e.displayName == name);
-  }
-}
-
-/**
- * The change of a single [CompilationUnitElement].
- */
-class CompilationUnitElementDelta {
-  /**
-   * One or more directives were added/removed.
-   */
-  bool hasDirectiveChange = false;
-
-  /**
-   * The list of added top-level element.
-   */
-  final List<Element> addedDeclarations = <Element>[];
-
-  /**
-   * The list of removed top-level elements.
-   */
-  final List<Element> removedDeclarations = <Element>[];
-
-  /**
-   * The map from names of changed classes to the change deltas.
-   */
-  final Map<String, ClassElementDelta> classDeltas =
-      <String, ClassElementDelta>{};
-}
-
-/**
- * Incrementally updates the existing [unitElement] and builds elements for
- * the [newUnit].
- */
-class IncrementalCompilationUnitElementBuilder {
-  final Source unitSource;
-  final Source librarySource;
-  final CompilationUnit oldUnit;
-  final CompilationUnitElementImpl unitElement;
-  final CompilationUnit newUnit;
-  final ElementHolder unitElementHolder = new ElementHolder();
-
-  final List<ConstantEvaluationTarget> unitConstants =
-      <ConstantEvaluationTarget>[];
-
-  /**
-   * The change between element models of [oldUnit] and [newUnit].
-   */
-  final CompilationUnitElementDelta unitDelta =
-      new CompilationUnitElementDelta();
-
-  factory IncrementalCompilationUnitElementBuilder(
-      CompilationUnit oldUnit, CompilationUnit newUnit) {
-    CompilationUnitElementImpl unitElement = oldUnit.element;
-    return new IncrementalCompilationUnitElementBuilder._(unitElement.source,
-        unitElement.librarySource, oldUnit, newUnit, unitElement);
-  }
-
-  IncrementalCompilationUnitElementBuilder._(this.unitSource,
-      this.librarySource, this.oldUnit, this.newUnit, this.unitElement);
-
-  /**
-   * Updates [oldUnit] to have the same directives and declarations, in the
-   * same order as in [newUnit]. Existing resolution is kept where possible.
-   *
-   * Updates [unitElement] by adding/removing elements as needed.
-   *
-   * Fills [unitDelta] with added/remove elements.
-   */
-  void build() {
-    _materializeLazyElements();
-    new CompilationUnitBuilder()
-        .buildCompilationUnit(unitSource, newUnit, librarySource);
-    newUnit.accept(new EnumMemberBuilder(unitElement.context.typeProvider));
-    _processDirectives();
-    _processUnitMembers();
-    _replaceUnitContents(oldUnit, newUnit);
-    _findConstants();
-    newUnit.element = unitElement;
-    unitElement.setCodeRange(0, newUnit.endToken.end);
-  }
-
-  void _addElementToUnitHolder(Element element) {
-    if (element is ClassElement) {
-      if (element.isEnum) {
-        unitElementHolder.addEnum(element);
-      } else {
-        unitElementHolder.addType(element);
-      }
-    } else if (element is FunctionElement) {
-      unitElementHolder.addFunction(element);
-    } else if (element is FunctionTypeAliasElement) {
-      unitElementHolder.addTypeAlias(element);
-    } else if (element is PropertyAccessorElement) {
-      unitElementHolder.addAccessor(element);
-    } else if (element is TopLevelVariableElement) {
-      unitElementHolder.addTopLevelVariable(element);
-    }
-  }
-
-  void _findConstants() {
-    ConstantFinder finder = new ConstantFinder();
-    oldUnit.accept(finder);
-    unitConstants.addAll(finder.constantsToCompute);
-    // Update annotation constants to using the old unit element.
-    for (ConstantEvaluationTarget constant in unitConstants) {
-      if (constant is ElementAnnotationImpl) {
-        constant.compilationUnit = unitElement;
-      }
-    }
-  }
-
-  void _materializeLazyElements() {
-    unitElement.accept(new RecursiveElementVisitor());
-  }
-
-  ClassElementDelta _processClassMembers(
-      ClassDeclaration oldClass, ClassDeclaration newClass) {
-    // If the class hierarchy or type parameters are changed,
-    // then the class changed too much - don't compute the delta.
-    if (newClass.abstractKeyword != null && oldClass.abstractKeyword == null ||
-        newClass.abstractKeyword == null && oldClass.abstractKeyword != null ||
-        TokenUtils.getFullCode(newClass.typeParameters) !=
-            TokenUtils.getFullCode(oldClass.typeParameters) ||
-        TokenUtils.getFullCode(newClass.extendsClause) !=
-            TokenUtils.getFullCode(oldClass.extendsClause) ||
-        TokenUtils.getFullCode(newClass.withClause) !=
-            TokenUtils.getFullCode(oldClass.withClause) ||
-        TokenUtils.getFullCode(newClass.implementsClause) !=
-            TokenUtils.getFullCode(oldClass.implementsClause)) {
-      return null;
-    }
-    // Build the old class members map.
-    Map<String, ClassMember> oldNodeMap = new HashMap<String, ClassMember>();
-    for (ClassMember oldNode in oldClass.members) {
-      String code = TokenUtils.getFullCode(oldNode);
-      oldNodeMap[code] = oldNode;
-    }
-    // Prepare elements.
-    ClassElement newElement = newClass.element;
-    ClassElement oldElement = oldClass.element;
-    // Use the old element for the new node.
-    newClass.name.staticElement = oldElement;
-    if (newElement is ClassElementImpl && oldElement is ClassElementImpl) {
-      oldElement.nameOffset = newElement.nameOffset;
-      oldElement.setCodeRange(newElement.codeOffset, newElement.codeLength);
-      oldElement.typeParameters = newElement.typeParameters;
-    }
-    // Prepare delta.
-    ClassElementImpl classElement = oldClass.element;
-    ElementHolder classElementHolder = new ElementHolder();
-    ClassElementDelta classDelta =
-        new ClassElementDelta(classElement, librarySource, classElement.name);
-    // Check for annotation changes.
-    {
-      String oldAnnotationsCode =
-          TokenUtils.getFullCodeOfList(oldClass.metadata);
-      String newAnnotationsCode =
-          TokenUtils.getFullCodeOfList(newClass.metadata);
-      classDelta.hasAnnotationChanges =
-          oldAnnotationsCode != newAnnotationsCode;
-    }
-    // Prepare all old member elements.
-    var removedAccessors = new Set<PropertyAccessorElement>.identity();
-    var removedConstructors = new Set<ConstructorElement>.identity();
-    var removedMethods = new Set<MethodElement>.identity();
-    removedAccessors.addAll(classElement.accessors);
-    removedConstructors.addAll(classElement.constructors);
-    removedMethods.addAll(classElement.methods);
-    // Utilities.
-    void processConstructorDeclaration(
-        ConstructorDeclaration node, bool isNew) {
-      ConstructorElement element = node.element;
-      if (element != null) {
-        classElementHolder.addConstructor(element);
-        if (isNew) {
-          classDelta.addedConstructors.add(element);
-        } else {
-          removedConstructors.remove(element);
-        }
-      }
-    }
-
-    void processFieldDeclaration(FieldDeclaration node, bool isNew) {
-      for (VariableDeclaration field in node.fields.variables) {
-        PropertyInducingElement element = field.element;
-        if (element != null) {
-          PropertyAccessorElement getter = element.getter;
-          PropertyAccessorElement setter = element.setter;
-          if (getter != null) {
-            classElementHolder.addAccessor(getter);
-            if (isNew) {
-              classDelta.addedAccessors.add(getter);
-            } else {
-              removedAccessors.remove(getter);
-            }
-          }
-          if (setter != null) {
-            classElementHolder.addAccessor(setter);
-            if (isNew) {
-              classDelta.addedAccessors.add(setter);
-            } else {
-              removedAccessors.remove(setter);
-            }
-          }
-        }
-      }
-    }
-
-    void processMethodDeclaration(MethodDeclaration node, bool isNew) {
-      Element element = node.element;
-      if (element is MethodElement) {
-        classElementHolder.addMethod(element);
-        if (isNew) {
-          classDelta.addedMethods.add(element);
-        } else {
-          removedMethods.remove(element);
-        }
-      } else if (element is PropertyAccessorElement) {
-        classElementHolder.addAccessor(element);
-        if (isNew) {
-          classDelta.addedAccessors.add(element);
-        } else {
-          removedAccessors.remove(element);
-        }
-      }
-    }
-
-    // Replace new nodes with the identical old nodes.
-    bool newHasConstructor = false;
-    for (ClassMember newNode in newClass.members) {
-      String code = TokenUtils.getFullCode(newNode);
-      ClassMember oldNode = oldNodeMap.remove(code);
-      // When we type a name before a constructor with a documentation
-      // comment, this makes the comment disappear from AST. So, even though
-      // tokens are the same, the nodes are not the same.
-      if (oldNode != null) {
-        if (oldNode.documentationComment == null &&
-                newNode.documentationComment != null ||
-            oldNode.documentationComment != null &&
-                newNode.documentationComment == null) {
-          oldNode = null;
-        }
-      }
-      // Add the new element.
-      if (oldNode == null) {
-        if (newNode is ConstructorDeclaration) {
-          newHasConstructor = true;
-          processConstructorDeclaration(newNode, true);
-        }
-        if (newNode is FieldDeclaration) {
-          processFieldDeclaration(newNode, true);
-        }
-        if (newNode is MethodDeclaration) {
-          processMethodDeclaration(newNode, true);
-        }
-        continue;
-      }
-      // Do replacement.
-      _replaceNode(newNode, oldNode);
-      if (oldNode is ConstructorDeclaration) {
-        processConstructorDeclaration(oldNode, false);
-      }
-      if (oldNode is FieldDeclaration) {
-        processFieldDeclaration(oldNode, false);
-      }
-      if (oldNode is MethodDeclaration) {
-        processMethodDeclaration(oldNode, false);
-      }
-    }
-    // If the class had only a default synthetic constructor, and there are
-    // no explicit constructors in the new AST, keep the constructor.
-    if (!newHasConstructor) {
-      List<ConstructorElement> constructors = classElement.constructors;
-      if (constructors.length == 1) {
-        ConstructorElement constructor = constructors[0];
-        if (constructor.isSynthetic && constructor.isDefaultConstructor) {
-          classElementHolder.addConstructor(constructor);
-          removedConstructors.remove(constructor);
-        }
-      }
-    }
-    // Update the delta.
-    classDelta.removedAccessors.addAll(removedAccessors);
-    classDelta.removedConstructors.addAll(removedConstructors);
-    classDelta.removedMethods.addAll(removedMethods);
-    // Prepare fields.
-    List<PropertyAccessorElement> newAccessors = classElementHolder.accessors;
-    Map<String, FieldElement> newFields = <String, FieldElement>{};
-    for (PropertyAccessorElement accessor in newAccessors) {
-      newFields[accessor.displayName] = accessor.variable;
-    }
-    // Update references to fields from constructors.
-    for (ClassMember member in newClass.members) {
-      if (member is ConstructorDeclaration) {
-        for (FormalParameter parameter in member.parameters.parameters) {
-          FormalParameter normalParameter = parameter;
-          if (parameter is DefaultFormalParameter) {
-            normalParameter = parameter.parameter;
-          }
-          if (normalParameter is FieldFormalParameter) {
-            FieldFormalParameterElementImpl parameterElement =
-                normalParameter.element as FieldFormalParameterElementImpl;
-            parameterElement.field = newFields[parameterElement.name];
-          }
-        }
-      }
-    }
-    // Update ClassElement.
-    classElement.metadata = newElement.metadata;
-    classElement.accessors = newAccessors;
-    classElement.constructors = classElementHolder.constructors;
-    classElement.fields = newFields.values.toList();
-    classElement.methods = classElementHolder.methods;
-    classElement.version++;
-    classElementHolder.validate();
-    // Ensure at least a default synthetic constructor.
-    if (classElement.constructors.isEmpty) {
-      ConstructorElementImpl constructor =
-          new ConstructorElementImpl.forNode(null);
-      constructor.isSynthetic = true;
-      classElement.constructors = <ConstructorElement>[constructor];
-      classDelta.addedConstructors.add(constructor);
-    }
-    classDelta.hasUnnamedConstructorChange =
-        classDelta.addedConstructors.any((c) => c.name == '') ||
-            classDelta.removedConstructors.any((c) => c.name == '');
-    // OK
-    return classDelta;
-  }
-
-  void _processDirectives() {
-    Map<String, Directive> oldDirectiveMap = new HashMap<String, Directive>();
-    for (Directive oldDirective in oldUnit.directives) {
-      String code = TokenUtils.getFullCode(oldDirective);
-      oldDirectiveMap[code] = oldDirective;
-    }
-    // Replace new nodes with the identical old nodes.
-    Set<Directive> removedDirectives = oldUnit.directives.toSet();
-    for (Directive newDirective in newUnit.directives) {
-      String code = TokenUtils.getFullCode(newDirective);
-      // Prepare an old directive.
-      Directive oldDirective = oldDirectiveMap[code];
-      if (oldDirective == null) {
-        unitDelta.hasDirectiveChange = true;
-        continue;
-      }
-      // URI's must be resolved to the same sources.
-      if (newDirective is UriBasedDirective &&
-          oldDirective is UriBasedDirective) {
-        Source source(UriBasedDirective directive) =>
-            directive is NamespaceDirective
-                ? directive.selectedSource
-                : directive.uriSource;
-        if (source(oldDirective) != source(newDirective)) {
-          continue;
-        }
-      }
-      // Do replacement.
-      _replaceNode(newDirective, oldDirective);
-      removedDirectives.remove(oldDirective);
-    }
-    // If there are any directives left, then these directives were removed.
-    if (removedDirectives.isNotEmpty) {
-      unitDelta.hasDirectiveChange = true;
-    }
-  }
-
-  void _processUnitMembers() {
-    Map<String, CompilationUnitMember> oldNodeMap =
-        new HashMap<String, CompilationUnitMember>();
-    Map<String, ClassDeclaration> nameToOldClassMap =
-        new HashMap<String, ClassDeclaration>();
-    for (CompilationUnitMember oldNode in oldUnit.declarations) {
-      String code = TokenUtils.getFullCode(oldNode);
-      oldNodeMap[code] = oldNode;
-      if (oldNode is ClassDeclaration) {
-        nameToOldClassMap[oldNode.name.name] = oldNode;
-      }
-    }
-    // Prepare all old top-level elements.
-    Set<Element> removedElements = new Set<Element>();
-    removedElements.addAll(unitElement.accessors);
-    removedElements.addAll(unitElement.enums);
-    removedElements.addAll(unitElement.functions);
-    removedElements.addAll(unitElement.functionTypeAliases);
-    removedElements.addAll(unitElement.types);
-    removedElements.addAll(unitElement.topLevelVariables);
-    // Replace new nodes with the identical old nodes.
-    for (CompilationUnitMember newNode in newUnit.declarations) {
-      String code = TokenUtils.getFullCode(newNode);
-      CompilationUnitMember oldNode = oldNodeMap[code];
-      // Add the new element.
-      if (oldNode == null) {
-        // Compute a delta for the class.
-        if (newNode is ClassDeclaration) {
-          ClassDeclaration oldClass = nameToOldClassMap[newNode.name.name];
-          if (oldClass != null) {
-            ClassElementDelta delta = _processClassMembers(oldClass, newNode);
-            if (delta != null) {
-              unitDelta.classDeltas[delta._element.name] = delta;
-              _addElementToUnitHolder(delta._element);
-              removedElements.remove(delta._element);
-              continue;
-            }
-          }
-        }
-        // Add the new node elements.
-        List<Element> elements = _getElements(newNode);
-        elements.forEach(_addElementToUnitHolder);
-        elements.forEach(unitDelta.addedDeclarations.add);
-        continue;
-      }
-      // Do replacement.
-      _replaceNode(newNode, oldNode);
-      List<Element> elements = _getElements(oldNode);
-      elements.forEach(_addElementToUnitHolder);
-      elements.forEach(removedElements.remove);
-    }
-    unitDelta.removedDeclarations.addAll(removedElements);
-    // Update CompilationUnitElement.
-    unitElement.accessors = unitElementHolder.accessors;
-    unitElement.enums = unitElementHolder.enums;
-    unitElement.functions = unitElementHolder.functions;
-    unitElement.typeAliases = unitElementHolder.typeAliases;
-    unitElement.types = unitElementHolder.types;
-    unitElement.topLevelVariables = unitElementHolder.topLevelVariables;
-    unitElementHolder.validate();
-  }
-
-  /**
-   * Replaces [newNode] with [oldNode], updates tokens and elements.
-   * The nodes must have the same tokens, but offsets may be different.
-   */
-  void _replaceNode(AstNode newNode, AstNode oldNode) {
-    // Replace node.
-    NodeReplacer.replace(newNode, oldNode);
-    // Replace tokens.
-    Token oldBeginToken = TokenUtils.getBeginTokenNotComment(oldNode);
-    Token newBeginToken = TokenUtils.getBeginTokenNotComment(newNode);
-    newBeginToken.previous.setNext(oldBeginToken);
-    oldNode.endToken.setNext(newNode.endToken.next);
-    // Change tokens offsets.
-    Map<int, int> offsetMap = new HashMap<int, int>();
-    TokenUtils.copyTokenOffsets(offsetMap, oldBeginToken, newBeginToken,
-        oldNode.endToken, newNode.endToken);
-    // Change elements offsets.
-    {
-      var visitor = new _UpdateElementOffsetsVisitor(offsetMap);
-      List<Element> elements = _getElements(oldNode);
-      for (Element element in elements) {
-        element.accept(visitor);
-      }
-    }
-  }
-
-  /**
-   * Returns [Element]s that are declared directly by the given [node].
-   * This does not include any child elements - parameters, local variables.
-   *
-   * Usually just one [Element] is returned, but [VariableDeclarationList]
-   * nodes may declare more than one.
-   */
-  static List<Element> _getElements(AstNode node) {
-    List<Element> elements = <Element>[];
-    void addPropertyAccessors(VariableDeclarationList variableList) {
-      if (variableList != null) {
-        for (VariableDeclaration variable in variableList.variables) {
-          PropertyInducingElement element = variable.element;
-          if (element != null) {
-            elements.add(element);
-            if (element.getter != null) {
-              elements.add(element.getter);
-            }
-            if (element.setter != null) {
-              elements.add(element.setter);
-            }
-          }
-        }
-      }
-    }
-
-    if (node is FieldDeclaration) {
-      addPropertyAccessors(node.fields);
-    } else if (node is TopLevelVariableDeclaration) {
-      addPropertyAccessors(node.variables);
-    } else if (node is PartDirective || node is PartOfDirective) {
-      // Ignore.
-    } else if (node is Directive && node.element != null) {
-      elements.add(node.element);
-    } else if (node is Declaration && node.element != null) {
-      Element element = node.element;
-      elements.add(element);
-      if (element is PropertyAccessorElement) {
-        elements.add(element.variable);
-      }
-    }
-    return elements;
-  }
-
-  /**
-   * Replaces contents of the [to] unit with the contexts of the [from] unit.
-   */
-  static void _replaceUnitContents(CompilationUnit to, CompilationUnit from) {
-    to.directives.clear();
-    to.declarations.clear();
-    to.beginToken = from.beginToken;
-    to.scriptTag = from.scriptTag;
-    to.directives.addAll(from.directives);
-    to.declarations.addAll(from.declarations);
-    to.element = to.element;
-    to.lineInfo = from.lineInfo;
-    to.endToken = from.endToken;
-  }
-}
-
-/**
- * Utilities for [Token] manipulations.
- */
-class TokenUtils {
-  static const String _SEPARATOR = "\uFFFF";
-
-  /**
-   * Copy offsets from [newToken]s to [oldToken]s.
-   */
-  static void copyTokenOffsets(Map<int, int> offsetMap, Token oldToken,
-      Token newToken, Token oldEndToken, Token newEndToken) {
-    if (oldToken is CommentToken && newToken is CommentToken) {
-      // Update documentation tokens.
-      while (oldToken != null) {
-        offsetMap[oldToken.offset] = newToken.offset;
-        offsetMap[oldToken.end] = newToken.end;
-        oldToken.offset = newToken.offset;
-        // Update (otherwise unlinked) reference tokens in documentation.
-        if (oldToken is DocumentationCommentToken &&
-            newToken is DocumentationCommentToken) {
-          List<Token> oldReferences = oldToken.references;
-          List<Token> newReferences = newToken.references;
-          assert(oldReferences.length == newReferences.length);
-          for (int i = 0; i < oldReferences.length; i++) {
-            Token oldToken = oldReferences[i];
-            Token newToken = newReferences[i];
-            // For [new Name] the 'Name' token is the reference.
-            // But we need to process all tokens, including 'new'.
-            while (oldToken.previous != null &&
-                oldToken.previous.type != TokenType.EOF) {
-              oldToken = oldToken.previous;
-            }
-            while (newToken.previous != null &&
-                newToken.previous.type != TokenType.EOF) {
-              newToken = newToken.previous;
-            }
-            copyTokenOffsets(
-                offsetMap, oldToken, newToken, oldEndToken, newEndToken);
-          }
-        }
-        // Next tokens.
-        oldToken = oldToken.next;
-        newToken = newToken.next;
-      }
-      assert(oldToken == null);
-      assert(newToken == null);
-      return;
-    }
-    while (true) {
-      if (oldToken.precedingComments != null) {
-        assert(newToken.precedingComments != null);
-        copyTokenOffsets(offsetMap, oldToken.precedingComments,
-            newToken.precedingComments, oldEndToken, newEndToken);
-      }
-      offsetMap[oldToken.offset] = newToken.offset;
-      offsetMap[oldToken.end] = newToken.end;
-      oldToken.offset = newToken.offset;
-      if (oldToken.type == TokenType.EOF) {
-        assert(newToken.type == TokenType.EOF);
-        break;
-      }
-      if (oldToken == oldEndToken) {
-        assert(newToken == newEndToken);
-        break;
-      }
-      oldToken = oldToken.next;
-      newToken = newToken.next;
-    }
-  }
-
-  static Token getBeginTokenNotComment(AstNode node) {
-    Token oldBeginToken = node.beginToken;
-    if (oldBeginToken is CommentToken) {
-      return oldBeginToken.parent;
-    }
-    return oldBeginToken;
-  }
-
-  /**
-   * Return the token string of all the [node].
-   */
-  static String getFullCode(AstNode node) {
-    if (node == null) {
-      return '';
-    }
-    List<Token> tokens = getTokens(node);
-    return joinTokens(tokens);
-  }
-
-  /**
-   * Return the token string of all the [nodes].
-   */
-  static String getFullCodeOfList(List<AstNode> nodes) {
-    if (nodes == null) {
-      return '';
-    }
-    return nodes.map(getFullCode).join(_SEPARATOR);
-  }
-
-  /**
-   * Returns all tokens (including comments) of the given [node].
-   */
-  static List<Token> getTokens(AstNode node) {
-    List<Token> tokens = <Token>[];
-    Token token = getBeginTokenNotComment(node);
-    Token endToken = node.endToken;
-    while (true) {
-      // stop if past the end token
-      if (token.offset > endToken.end) {
-        break;
-      }
-      // append comment tokens
-      for (Token commentToken = token.precedingComments;
-          commentToken != null;
-          commentToken = commentToken.next) {
-        tokens.add(commentToken);
-      }
-      // append token
-      tokens.add(token);
-      // next token
-      if (token == endToken) {
-        break;
-      }
-      token = token.next;
-    }
-    return tokens;
-  }
-
-  static String joinTokens(List<Token> tokens) {
-    return tokens.map((token) => token.lexeme).join(_SEPARATOR);
-  }
-}
-
-/**
- * Updates name offsets of [Element]s according to the [map].
- */
-class _UpdateElementOffsetsVisitor extends GeneralizingElementVisitor {
-  final Map<int, int> map;
-
-  _UpdateElementOffsetsVisitor(this.map);
-
-  void visitElement(Element element) {
-    if (element is ElementImpl) {
-      // name offset
-      {
-        int oldOffset = element.nameOffset;
-        int newOffset = map[oldOffset];
-        // Some synthetic elements have new offsets, e.g. synthetic accessors
-        // of property inducing elements.  But some are purely synthetic, e.g.
-        // synthetic enum fields and their accessors.
-        // PrefixElement(s) can be shared between import directives, so
-        // their name offsets are outside of the second and subsequent import
-        // directives. But we update the name offsets while visiting the first
-        // import directive.
-        if (newOffset == null) {
-          assert(element.isSynthetic || element is PrefixElement);
-          return;
-        }
-        element.nameOffset = newOffset;
-      }
-      // stop here for LibraryElement
-      if (element is LibraryElementImpl) {
-        return;
-      }
-      // code range
-      {
-        int oldOffset = element.codeOffset;
-        if (oldOffset != null) {
-          int oldEnd = oldOffset + element.codeLength;
-          int newOffset = map[oldOffset];
-          int newEnd = map[oldEnd];
-          assert(newOffset != null);
-          assert(newEnd != null);
-          int newLength = newEnd - newOffset;
-          element.setCodeRange(newOffset, newLength);
-        }
-      }
-      // visible range
-      if (element is LocalElement) {
-        SourceRange oldVisibleRange = (element as LocalElement).visibleRange;
-        if (oldVisibleRange != null) {
-          int oldOffset = oldVisibleRange.offset;
-          int oldLength = oldVisibleRange.length;
-          int oldEnd = oldOffset + oldLength;
-          int newOffset = map[oldOffset];
-          int newEnd = map[oldEnd];
-          assert(newOffset != null);
-          assert(newEnd != null);
-          int newLength = newEnd - newOffset;
-          if (newOffset != oldOffset || newLength != oldLength) {
-            if (element is FunctionElementImpl) {
-              element.setVisibleRange(newOffset, newLength);
-            } else if (element is LocalVariableElementImpl) {
-              element.setVisibleRange(newOffset, newLength);
-            } else if (element is ParameterElementImpl) {
-              element.setVisibleRange(newOffset, newLength);
-            }
-          }
-        }
-      }
-    }
-    super.visitElement(element);
-  }
-}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 6f9d81c..9148839 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -297,6 +297,12 @@
   }
 
   @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    _overrideChecker.check(node);
+    super.visitClassTypeAlias(node);
+  }
+
+  @override
   void visitComment(Comment node) {
     // skip, no need to do typechecking inside comments (they may contain
     // comment references which would require resolution).
@@ -1114,7 +1120,8 @@
         n is DoubleLiteral ||
         n is IntegerLiteral ||
         n is StringLiteral ||
-        n is SymbolLiteral) {
+        n is SymbolLiteral ||
+        n is IndexExpression) {
       // Nothing to validate.
     } else if (n is AwaitExpression) {
       _validateTopLevelInitializer(name, n.expression);
@@ -1233,12 +1240,15 @@
       : _checker = checker,
         rules = checker.rules;
 
-  void check(ClassDeclaration node) {
-    if (resolutionMap.elementDeclaredByClassDeclaration(node).type.isObject)
+  void check(Declaration node) {
+    var element =
+        resolutionMap.elementDeclaredByDeclaration(node) as ClassElement;
+    if (element.type.isObject) {
       return;
-    _checkSuperOverrides(node);
-    _checkMixinApplicationOverrides(node);
-    _checkAllInterfaceOverrides(node);
+    }
+    _checkSuperOverrides(node, element);
+    _checkMixinApplicationOverrides(node, element);
+    _checkAllInterfaceOverrides(node, element);
   }
 
   /// Checks that implementations correctly override all reachable interfaces.
@@ -1256,7 +1266,7 @@
   ///     E against H and I // no check against G because B is a concrete class
   ///     F against H and I
   ///     A against H and I
-  void _checkAllInterfaceOverrides(ClassDeclaration node) {
+  void _checkAllInterfaceOverrides(Declaration node, ClassElement element) {
     var seen = new Set<String>();
     // Helper function to collect all reachable interfaces.
     find(InterfaceType interfaceType, Set result) {
@@ -1271,10 +1281,10 @@
     // Check all interfaces reachable from the `implements` clause in the
     // current class against definitions here and in superclasses.
     var localInterfaces = new Set<InterfaceType>();
-    var type = resolutionMap.elementDeclaredByClassDeclaration(node).type;
+    var type = element.type;
     type.interfaces.forEach((i) => find(i, localInterfaces));
-    _checkInterfacesOverrides(node, localInterfaces, seen,
-        includeParents: true);
+    _checkInterfacesOverrides(type, localInterfaces, seen,
+        includeParents: true, classNode: node);
 
     // Check also how we override locally the interfaces from parent classes if
     // the parent class is abstract. Otherwise, these will be checked as
@@ -1288,8 +1298,8 @@
       parent.interfaces.forEach((i) => find(i, superInterfaces));
       parent = parent.superclass;
     }
-    _checkInterfacesOverrides(node, superInterfaces, seen,
-        includeParents: false);
+    _checkInterfacesOverrides(type, superInterfaces, seen,
+        includeParents: false, classNode: node);
   }
 
   /// Check that individual methods and fields in [node] correctly override
@@ -1297,9 +1307,9 @@
   ///
   /// The [errorLocation] node indicates where errors are reported, see
   /// [_checkSingleOverride] for more details.
-  _checkIndividualOverridesFromClass(ClassDeclaration node,
-      InterfaceType baseType, Set<String> seen, bool isSubclass) {
-    for (var member in node.members) {
+  _checkIndividualOverridesFromClass(Declaration node, InterfaceType baseType,
+      Set<String> seen, bool isSubclass) {
+    for (var member in _classMembers(node)) {
       if (member is FieldDeclaration) {
         if (member.isStatic) {
           continue;
@@ -1379,15 +1389,11 @@
   /// [ClassDeclaration]s errors are reported on the member that contains the
   /// invalid override, for [InterfaceType]s we use [errorLocation] instead.
   void _checkInterfacesOverrides(
-      cls, Iterable<InterfaceType> interfaces, Set<String> seen,
+      InterfaceType type, Iterable<InterfaceType> interfaces, Set<String> seen,
       {Set<InterfaceType> visited,
       bool includeParents: true,
-      AstNode errorLocation}) {
-    var node = cls is ClassDeclaration ? cls : null;
-    var type = cls is InterfaceType
-        ? cls
-        : resolutionMap.elementDeclaredByClassDeclaration(node).type;
-
+      AstNode errorLocation,
+      Declaration classNode}) {
     if (visited == null) {
       visited = new Set<InterfaceType>();
     } else if (visited.contains(type)) {
@@ -1399,8 +1405,9 @@
 
     // Check direct overrides on [type]
     for (var interfaceType in interfaces) {
-      if (node != null) {
-        _checkIndividualOverridesFromClass(node, interfaceType, seen, false);
+      if (classNode != null) {
+        _checkIndividualOverridesFromClass(
+            classNode, interfaceType, seen, false);
       } else {
         _checkIndividualOverridesFromType(
             type, interfaceType, errorLocation, seen, false);
@@ -1409,7 +1416,7 @@
 
     // Check overrides from its mixins
     for (int i = 0; i < type.mixins.length; i++) {
-      var loc = errorLocation ?? node.withClause.mixinTypes[i];
+      var loc = errorLocation ?? _withClause(classNode).mixinTypes[i];
       for (var interfaceType in interfaces) {
         // We copy [seen] so we can report separately if more than one mixin or
         // the base class have an invalid override.
@@ -1424,7 +1431,7 @@
       if (parent.isObject) {
         return;
       }
-      var loc = errorLocation ?? node.extendsClause;
+      var loc = errorLocation ?? _extendsErrorLocation(classNode);
       // No need to copy [seen] here because we made copies above when reporting
       // errors on mixins.
       _checkInterfacesOverrides(parent, interfaces, seen,
@@ -1440,8 +1447,8 @@
   ///
   ///      B & E against B (equivalently how E overrides B)
   ///      B & E & F against B & E (equivalently how F overrides both B and E)
-  void _checkMixinApplicationOverrides(ClassDeclaration node) {
-    var type = resolutionMap.elementDeclaredByClassDeclaration(node).type;
+  void _checkMixinApplicationOverrides(Declaration node, ClassElement element) {
+    var type = element.type;
     var parent = type.superclass;
     var mixins = type.mixins;
 
@@ -1449,7 +1456,7 @@
     for (int i = 0; i < mixins.length; i++) {
       var seen = new Set<String>();
       var current = mixins[i];
-      var errorLocation = node.withClause.mixinTypes[i];
+      var errorLocation = _withClause(node).mixinTypes[i];
       for (int j = i - 1; j >= 0; j--) {
         _checkIndividualOverridesFromType(
             current, mixins[j], errorLocation, seen, true);
@@ -1512,9 +1519,11 @@
     }
     if (!rules.isOverrideSubtypeOf(subType, baseType)) {
       ErrorCode errorCode;
-      if (errorLocation is ExtendsClause) {
+      var parent = errorLocation?.parent;
+      if (errorLocation is ExtendsClause ||
+          parent is ClassTypeAlias && parent.superclass == errorLocation) {
         errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_BASE;
-      } else if (errorLocation.parent is WithClause) {
+      } else if (parent is WithClause) {
         errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE_FROM_MIXIN;
       } else {
         errorCode = StrongModeCode.INVALID_METHOD_OVERRIDE;
@@ -1558,9 +1567,9 @@
   ///     class Test extends Parent {
   ///         m(B a) {} // invalid override
   ///     }
-  void _checkSuperOverrides(ClassDeclaration node) {
+  void _checkSuperOverrides(Declaration node, ClassElement element) {
     var seen = new Set<String>();
-    var current = resolutionMap.elementDeclaredByClassDeclaration(node).type;
+    var current = element.type;
     var visited = new Set<InterfaceType>();
     do {
       visited.add(current);
@@ -1570,4 +1579,26 @@
       current = current.superclass;
     } while (!current.isObject && !visited.contains(current));
   }
+
+  /// If node is a [ClassDeclaration] returns its members, otherwise if node is
+  /// a [ClassTypeAlias] this returns an empty list.
+  Iterable<ClassMember> _classMembers(Declaration node) {
+    return node is ClassDeclaration ? node.members : [];
+  }
+
+  /// If node is a [ClassDeclaration] returns its members, otherwise if node is
+  /// a [ClassTypeAlias] this returns an empty list.
+  WithClause _withClause(Declaration node) {
+    return node is ClassDeclaration
+        ? node.withClause
+        : (node as ClassTypeAlias).withClause;
+  }
+
+  /// If node is a [ClassDeclaration] returns its members, otherwise if node is
+  /// a [ClassTypeAlias] this returns an empty list.
+  AstNode _extendsErrorLocation(Declaration node) {
+    return node is ClassDeclaration
+        ? node.extendsClause
+        : (node as ClassTypeAlias).superclass;
+  }
 }
diff --git a/pkg/analyzer/lib/src/util/sdk.dart b/pkg/analyzer/lib/src/util/sdk.dart
new file mode 100644
index 0000000..8e8494e
--- /dev/null
+++ b/pkg/analyzer/lib/src/util/sdk.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+import 'package:path/path.dart' as path;
+
+String getSdkPath([List<String> args]) {
+  // Look for --dart-sdk on the command line.
+  if (args != null) {
+    int index = args.indexOf('--dart-sdk');
+
+    if (index != -1 && (index + 1 < args.length)) {
+      return args[index + 1];
+    }
+
+    for (String arg in args) {
+      if (arg.startsWith('--dart-sdk=')) {
+        return arg.substring('--dart-sdk='.length);
+      }
+    }
+  }
+
+  // Look in env['DART_SDK']
+  if (Platform.environment['DART_SDK'] != null) {
+    return Platform.environment['DART_SDK'];
+  }
+
+  // Use Platform.resolvedExecutable.
+  return path.dirname(path.dirname(Platform.resolvedExecutable));
+}
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 494cb07..fa719e5 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -631,6 +631,13 @@
     expect(identifier.inGetterContext(), isFalse);
   }
 
+  void test_inGetterContext_fieldFormalParameter() {
+    FieldFormalParameter parameter =
+        AstTestFactory.fieldFormalParameter2('test');
+    SimpleIdentifier identifier = parameter.identifier;
+    expect(identifier.inGetterContext(), isFalse);
+  }
+
   void test_inGetterContext_forEachLoop() {
     SimpleIdentifier identifier = AstTestFactory.identifier3("a");
     Expression iterator = AstTestFactory.listLiteral();
@@ -639,6 +646,12 @@
     expect(identifier.inGetterContext(), isFalse);
   }
 
+  void test_inGetterContext_variableDeclaration() {
+    VariableDeclaration variable = AstTestFactory.variableDeclaration('test');
+    SimpleIdentifier identifier = variable.name;
+    expect(identifier.inGetterContext(), isFalse);
+  }
+
   void test_inReferenceContext() {
     SimpleIdentifier identifier = AstTestFactory.identifier3("id");
     AstTestFactory.namedExpression(
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 1b755f9..5889c8f 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -889,6 +889,23 @@
     verify([source]);
   }
 
+  test_constConstructor_redirect_generic() async {
+    Source source = addSource(r'''
+class A<T> {
+  const A(T value) : this._(value);
+  const A._(T value) : value = value;
+  final T value;
+}
+
+void main(){
+  const A<int>(1);
+}
+''');
+    await computeAnalysisResult(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   test_constConstructorWithFieldInitializedByNonConst() async {
     Source source = addSource(r'''
 class A {
@@ -1260,25 +1277,6 @@
     verify([source]);
   }
 
-  test_nonConstValueInInitializer_instanceCreation_inDifferentFile() async {
-    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
-    Source source = addNamedSource(
-        '/a.dart',
-        r'''
-import 'b.dart';
-const v = const MyClass();
-''');
-    addNamedSource(
-        '/b.dart',
-        r'''
-class MyClass {
-  const MyClass([p = foo]);
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
-  }
-
   test_constInitializedWithNonConstValue() async {
     Source source = addSource(r'''
 f(p) {
@@ -2784,6 +2782,26 @@
     verify([source]);
   }
 
+  test_implementsSuperClass_typeAlias() async {
+    Source source = addSource(r'''
+class A {}
+class M {}
+class B = A with M implements A;''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
+    verify([source]);
+  }
+
+  test_implementsSuperClass_Object_typeAlias() async {
+    Source source = addSource(r'''
+class M {}
+class A = Object with M implements Object;
+    ''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS]);
+    verify([source]);
+  }
+
   test_implicitThisReferenceInInitializer_field() async {
     Source source = addSource(r'''
 class A {
@@ -4803,6 +4821,25 @@
     verify([source]);
   }
 
+  test_nonConstValueInInitializer_instanceCreation_inDifferentFile() async {
+    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+    Source source = addNamedSource(
+        '/a.dart',
+        r'''
+import 'b.dart';
+const v = const MyClass();
+''');
+    addNamedSource(
+        '/b.dart',
+        r'''
+class MyClass {
+  const MyClass([p = foo]);
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+  }
+
   test_nonConstValueInInitializer_redirecting() async {
     Source source = addSource(r'''
 class A {
@@ -5320,97 +5357,62 @@
     verify([source]);
   }
 
-  test_privateCollisionInMixinApplication_mixinAndMixin() async {
-    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
-    addNamedSource(
-        '/lib1.dart',
-        '''
-class A {
-  int _x;
-}
-
-class B {
-  int _x;
-}
-''');
-    Source source = addSource('''
+  test_privateCollisionInMixinApplication_mixinAndMixin() {
+    return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends Object with A, B {}
 ''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION]);
-    verify([source]);
   }
 
-  test_privateCollisionInMixinApplication_mixinAndMixin_indirect() async {
-    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
-    addNamedSource(
-        '/lib1.dart',
-        '''
-class A {
-  int _x;
-}
-
-class B {
-  int _x;
-}
-''');
-    Source source = addSource('''
+  test_privateCollisionInMixinApplication_mixinAndMixin_indirect() {
+    return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends Object with A {}
 class D extends C with B {}
 ''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION]);
-    verify([source]);
   }
 
-  test_privateCollisionInMixinApplication_superclassAndMixin() async {
-    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
-    addNamedSource(
-        '/lib1.dart',
-        '''
-class A {
-  int _x;
-}
-
-class B {
-  int _x;
-}
-''');
-    Source source = addSource('''
+  test_privateCollisionInMixinApplication_superclassAndMixin() {
+    return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends A with B {}
 ''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION]);
-    verify([source]);
   }
 
-  test_privateCollisionInMixinApplication_superclassAndMixin_same() async {
-    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
-    addNamedSource(
-        '/lib1.dart',
-        '''
-class A {
-  int _x;
-}
-
-class B {
-  int _x;
-}
-''');
-    Source source = addSource('''
+  test_privateCollisionInMixinApplication_superclassAndMixin_same() {
+    return _privateCollisionInMixinApplicationTest('''
 import 'lib1.dart';
 class C extends A with A {}
 ''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION]);
-    verify([source]);
+  }
+
+  test_privateCollisionInClassTypeAlias_mixinAndMixin() {
+    return _privateCollisionInMixinApplicationTest('''
+import 'lib1.dart';
+class C = Object with A, B;
+''');
+  }
+
+  test_privateCollisionInClassTypeAlias_mixinAndMixin_indirect() {
+    return _privateCollisionInMixinApplicationTest('''
+import 'lib1.dart';
+class C = Object with A;
+class D = C with B;
+''');
+  }
+
+  test_privateCollisionInClassTypeAlias_superclassAndMixin() {
+    return _privateCollisionInMixinApplicationTest('''
+import 'lib1.dart';
+class C = A with B;
+''');
+  }
+
+  test_privateCollisionInClassTypeAlias_superclassAndMixin_same() {
+    return _privateCollisionInMixinApplicationTest('''
+import 'lib1.dart';
+class C = A with A;
+''');
   }
 
   test_privateOptionalParameter() async {
@@ -6645,4 +6647,24 @@
     await _check_wrongNumberOfParametersForOperator(name, "");
     await _check_wrongNumberOfParametersForOperator(name, "a, b");
   }
+
+  Future<Null> _privateCollisionInMixinApplicationTest(String testCode) async {
+    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+    addNamedSource(
+        '/lib1.dart',
+        '''
+class A {
+  int _x;
+}
+
+class B {
+  int _x;
+}
+''');
+    Source source = addSource(testCode);
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION]);
+    verify([source]);
+  }
 }
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 954966d..9c4db3a 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -49,7 +49,6 @@
     modifiedOptions.enableUriInPartOf = true;
     modifiedOptions.errorProcessors = [null];
     modifiedOptions.excludePatterns = ['a'];
-    modifiedOptions.finerGrainedInvalidation = true;
     modifiedOptions.generateImplicitErrors = false;
     modifiedOptions.generateSdkErrors = true;
     modifiedOptions.hint = false;
@@ -81,8 +80,6 @@
     expect(modifiedOptions.enableUriInPartOf, defaultOptions.enableUriInPartOf);
     expect(modifiedOptions.errorProcessors, defaultOptions.errorProcessors);
     expect(modifiedOptions.excludePatterns, defaultOptions.excludePatterns);
-    expect(modifiedOptions.finerGrainedInvalidation,
-        defaultOptions.finerGrainedInvalidation);
     expect(modifiedOptions.generateImplicitErrors,
         defaultOptions.generateImplicitErrors);
     expect(modifiedOptions.generateSdkErrors, defaultOptions.generateSdkErrors);
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 381d3c2..e3605f7 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -514,20 +514,6 @@
   CompilationUnit oldUnit;
   CompilationUnitElement oldUnitElement;
 
-  void assertSameReferencedNames(
-      ReferencedNames incNames, ReferencedNames fullNames) {
-    expectEqualSets(Iterable actual, Iterable expected) {
-      expect(actual, unorderedEquals(expected));
-    }
-
-    expectEqualSets(incNames.names, fullNames.names);
-    expectEqualSets(incNames.instantiatedNames, fullNames.instantiatedNames);
-    expectEqualSets(incNames.superToSubs.keys, fullNames.superToSubs.keys);
-    for (String key in fullNames.superToSubs.keys) {
-      expectEqualSets(incNames.superToSubs[key], fullNames.superToSubs[key]);
-    }
-  }
-
   @override
   void setUp() {
     super.setUp();
@@ -2097,8 +2083,6 @@
     logger.expectNoErrors();
     List<AnalysisError> newErrors = analysisContext.computeErrors(source);
     LineInfo newLineInfo = analysisContext.getLineInfo(source);
-    ReferencedNames newReferencedNames =
-        analysisContext.getResult(source, REFERENCED_NAMES);
     // check for expected failure
     if (!expectedSuccess) {
       expect(newUnit.element, isNot(same(oldUnitElement)));
@@ -2131,10 +2115,6 @@
       _assertEqualTokens(newUnit, fullNewUnit);
       // Validate LineInfo
       _assertEqualLineInfo(newLineInfo, analysisContext.getLineInfo(source));
-      // Validate referenced names.
-      ReferencedNames fullReferencedNames =
-          analysisContext.getResult(source, REFERENCED_NAMES);
-      assertSameReferencedNames(newReferencedNames, fullReferencedNames);
       // Validate that "incremental" and "full" units have the same resolution.
       try {
         assertSameResolution(newUnit, fullNewUnit, validateTypes: true);
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 1486898..87b9f05 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -15,7 +15,6 @@
 import 'package:front_end/src/fasta/parser/identifier_context.dart'
     show IdentifierContext;
 import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/precedence.dart' as fasta;
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
 import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
 import 'package:test/test.dart';
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 8dd001a..8636556 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -65,7 +65,7 @@
 
   /**
    * Assert that the number and codes of errors occurred during parsing is the
-   * same the the [expectedErrorCodes].
+   * same as the [expectedErrorCodes].
    */
   void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes);
 
@@ -3946,6 +3946,36 @@
     ]);
   }
 
+  void test_typedef_incomplete() {
+    // TODO(brianwilkerson) Improve recovery for this case.
+    parseCompilationUnit(
+        '''
+class A {}
+class B extends A {}
+
+typedef T
+
+main() {
+  Function<
+}
+''',
+        [
+          ParserErrorCode.EXPECTED_TOKEN,
+          ParserErrorCode.UNEXPECTED_TOKEN,
+          ParserErrorCode.EXPECTED_EXECUTABLE
+        ]);
+  }
+
+  void test_typedef_namedFunction() {
+    // TODO(brianwilkerson) Improve recovery for this case.
+    parseCompilationUnit('typedef void Function();', [
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_EXECUTABLE,
+      ParserErrorCode.MISSING_TYPEDEF_PARAMETERS
+    ]);
+  }
+
   void test_typedefInClass_withoutReturnType() {
     parseCompilationUnit(
         "class C { typedef F(x); }", [ParserErrorCode.TYPEDEF_IN_CLASS]);
@@ -10849,7 +10879,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.CONST);
     expect(result.type, isNotNull);
   }
@@ -10861,7 +10891,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.CONST);
     expect(result.type, isNotNull);
   }
@@ -10873,7 +10903,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.CONST);
     expect(result.type, isNull);
   }
@@ -10885,7 +10915,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNotNull);
   }
@@ -10897,7 +10927,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNotNull);
   }
@@ -10909,7 +10939,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNull);
   }
@@ -10921,7 +10951,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.FINAL);
     expect(result.type, isNotNull);
   }
@@ -10997,7 +11027,7 @@
     listener.assertNoErrors();
     Token keyword = result.keyword;
     expect(keyword, isNotNull);
-    expect(keyword.type, TokenType.KEYWORD);
+    expect(keyword.type.isKeyword, true);
     expect(keyword.keyword, Keyword.VAR);
     expect(result.type, isNull);
   }
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index b6aecef..6b26293 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -1526,6 +1526,53 @@
     verify([source]);
   }
 
+  test_functionWithoutCall_mixin_implements() async {
+    Source source = addSource(r'''
+abstract class A implements Function {}
+class B extends Object with A {}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+
+  test_functionWithoutCall_direct_typeAlias() async {
+    Source source = addSource(r'''
+class M {}
+class A = Object with M implements Function;''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+
+  test_functionWithoutCall_indirect_extends_typeAlias() async {
+    Source source = addSource(r'''
+abstract class A implements Function {}
+class M {}
+class B = A with M;''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+
+  test_functionWithoutCall_indirect_implements_typeAlias() async {
+    Source source = addSource(r'''
+abstract class A implements Function {}
+class M {}
+class B = Object with M implements A;''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+
+  test_functionWithoutCall_mixin_implements_typeAlias() async {
+    Source source = addSource(r'''
+abstract class A implements Function {}
+class B = Object with A;''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    verify([source]);
+  }
+
   test_importDuplicatedLibraryNamed() async {
     Source source = addSource(r'''
 library test;
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 2854fb6..431c6fd 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -1025,7 +1025,6 @@
     expect(actual.implicitDynamic, expected.implicitDynamic);
     expect(actual.trackCacheDependencies, expected.trackCacheDependencies);
     expect(actual.disableCacheFlushing, expected.disableCacheFlushing);
-    expect(actual.finerGrainedInvalidation, expected.finerGrainedInvalidation);
   }
 
   Uri _relativeUri(String path, {String from}) {
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 441cad9..26ceedf 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -20,7 +20,6 @@
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -29,7 +28,6 @@
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/html.dart';
 import 'package:analyzer/task/dart.dart';
-import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:html/dom.dart' show Document;
 import 'package:test/test.dart';
@@ -38,13 +36,11 @@
 
 import '../../generated/engine_test.dart';
 import '../../generated/test_support.dart';
-import '../../utils.dart';
 import 'abstract_context.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisContextImplTest);
-    defineReflectiveTests(LimitedInvalidateTest);
   });
 }
 
@@ -2237,48 +2233,28 @@
         reason: "part resolved 1");
     // update and analyze #1
     context.setContents(partSource, "part of lib; // 1");
-    if (context.analysisOptions.finerGrainedInvalidation) {
-      expect(
-          context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
-          reason: "library changed 2");
-      expect(
-          context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
-          reason: "part changed 2");
-    } else {
-      expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull,
-          reason: "library changed 2");
-      expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull,
-          reason: "part changed 2");
-      _analyzeAll_assertFinished();
-      expect(
-          context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
-          reason: "library resolved 2");
-      expect(
-          context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
-          reason: "part resolved 2");
-    }
+    expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull,
+        reason: "library changed 2");
+    expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull,
+        reason: "part changed 2");
+    _analyzeAll_assertFinished();
+    expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
+        reason: "library resolved 2");
+    expect(
+        context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
+        reason: "part resolved 2");
     // update and analyze #2
     context.setContents(partSource, "part of lib; // 12");
-    if (context.analysisOptions.finerGrainedInvalidation) {
-      expect(
-          context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
-          reason: "library changed 3");
-      expect(
-          context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
-          reason: "part changed 3");
-    } else {
-      expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull,
-          reason: "library changed 3");
-      expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull,
-          reason: "part changed 3");
-      _analyzeAll_assertFinished();
-      expect(
-          context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
-          reason: "library resolved 3");
-      expect(
-          context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
-          reason: "part resolved 3");
-    }
+    expect(context.getResolvedCompilationUnit2(libSource, libSource), isNull,
+        reason: "library changed 3");
+    expect(context.getResolvedCompilationUnit2(partSource, libSource), isNull,
+        reason: "part changed 3");
+    _analyzeAll_assertFinished();
+    expect(context.getResolvedCompilationUnit2(libSource, libSource), isNotNull,
+        reason: "library resolved 3");
+    expect(
+        context.getResolvedCompilationUnit2(partSource, libSource), isNotNull,
+        reason: "part resolved 3");
   }
 
   void test_performAnalysisTask_getContentException_dart() {
@@ -2415,11 +2391,7 @@
     _changeSource(source, "");
     source.generateExceptionOnRead = true;
     _analyzeAll_assertFinished();
-    if (context.analysisOptions.finerGrainedInvalidation) {
-      expect(source.readCount, 7);
-    } else {
-      expect(source.readCount, 5);
-    }
+    expect(source.readCount, 5);
   }
 
   void test_performAnalysisTask_missingPart() {
@@ -3022,2308 +2994,6 @@
   }
 }
 
-@reflectiveTest
-class LimitedInvalidateTest extends AbstractContextTest {
-  @override
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options =
-        new AnalysisOptionsImpl.from(context.analysisOptions);
-    options.incremental = true;
-    options.finerGrainedInvalidation = true;
-    context.analysisOptions = options;
-  }
-
-  void test_applyChanges_changedSource_removeFile() {
-    File file = resourceProvider.newFile('/test.dart', 'main() {}');
-    Source source = file.createSource();
-    context.applyChanges(new ChangeSet()..addedSource(source));
-    // Analyze all.
-    _performPendingAnalysisTasks();
-    expect(context.getResolvedCompilationUnit2(source, source), isNotNull);
-    // Delete the file, but tell the context that it is changed.
-    // This might happen as a race condition.
-    // Or it might be a mishandling of file notification events.
-    file.delete();
-    context.applyChanges(new ChangeSet()..changedSource(source));
-    // All the analysis results are gone.
-    void noResolvedUnits() {
-      LibrarySpecificUnit unit = new LibrarySpecificUnit(source, source);
-      RESOLVED_UNIT_RESULTS.forEach((result) {
-        expect(context.getResult(unit, result), isNull);
-      });
-    }
-
-    noResolvedUnits();
-    // Analyze again.
-    // The source does not exist, so still no resolution.
-    _performPendingAnalysisTasks();
-    noResolvedUnits();
-    expect(context.getModificationStamp(source), -1);
-  }
-
-  void test_class_addMethod_useAsHole_inTopLevelVariable() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-var B = A.foo;
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'b.dart';
-var C = B;
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-    // Update a.dart: add A.foo.
-    //   'B' in b.dart is invalid, because 'B' references 'foo'
-    //   c.dart is invalid, because 'C' references 'B'
-    context.setContents(
-        a,
-        r'''
-class A {
-  static void foo(int p) {}
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-
-    _assertValidForDependentLibrary(c);
-    _assertInvalid(c, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(c, RESOLVED_UNIT4);
-  }
-
-  void test_class_addMethod_useClass() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B extends A {
-  foo() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-B b = null;
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove add A.bar.
-    //   b.dart is valid, because though it uses A, it has the same element.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B extends A {
-  foo() {}
-  bar() {}
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_class_annotation_add_deprecated() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-List<A> foo() => [];
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(0));
-    // Add @deprecated annotation.
-    // b.dart has valid resolution, because A is still A, so only errors are
-    // invalidated.
-    context.setContents(
-        a,
-        r'''
-@deprecated
-class A {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertValidAllResolution(b);
-    // Analysis is done successfully.
-    _performPendingAnalysisTasks();
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(a, READY_RESOLVED_UNIT);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    _assertValid(b, READY_RESOLVED_UNIT);
-    expect(context.getErrors(b).errors, hasLength(1));
-  }
-
-  void test_class_annotation_remove_deprecated() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-@deprecated
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-List<A> foo() => [];
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-    // Add @deprecated annotation.
-    // b.dart has valid resolution, because A is still A, so only errors are
-    // invalidated.
-    context.setContents(
-        a,
-        r'''
-class A {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertValidAllResolution(b);
-    // Analysis is done successfully.
-    _performPendingAnalysisTasks();
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(a, READY_RESOLVED_UNIT);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    _assertValid(b, READY_RESOLVED_UNIT);
-    expect(context.getErrors(b).errors, hasLength(0));
-  }
-
-  void test_class_constructor_named_changeName() {
-    // Update a.dart: change A.named() to A.named2().
-    //   b.dart is invalid, because it references A.named().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A.named();
-}
-''',
-        r'''
-class A {
-  A.named2();
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A.named();
-}
-''');
-  }
-
-  void test_class_constructor_named_parameters_add() {
-    // Update a.dart: add a new parameter to A.named().
-    //   b.dart is invalid, because it references A.named().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A.named();
-}
-''',
-        r'''
-class A {
-  A.named(int p);
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A.named();
-}
-''');
-  }
-
-  void test_class_constructor_named_parameters_change_usedSuper() {
-    // Update a.dart: change A.named().
-    //   b.dart is invalid, because it references A.named().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A.named(int a);
-}
-''',
-        r'''
-class A {
-  A.named(String a);
-}
-''',
-        r'''
-import 'a.dart';
-class B extends A {
-  B() : super.named(42);
-}
-''');
-  }
-
-  void test_class_constructor_named_parameters_remove() {
-    // Update a.dart: remove a new parameter of A.named().
-    //   b.dart is invalid, because it references A.named().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A.named(int p);
-}
-''',
-        r'''
-class A {
-  A.named();
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A.named();
-}
-''');
-  }
-
-  void test_class_constructor_named_remove_notUsed() {
-    // Update a.dart: remove A.foo().
-    //   b.dart is valid, because it does not reference A.foo().
-    _verifyTwoLibrariesAllValid(
-        r'''
-class A {
-  A.foo();
-  A.bar();
-}
-''',
-        r'''
-class A {
-  A.bar();
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A.bar();
-}
-''');
-  }
-
-  void test_class_constructor_named_remove_used() {
-    // Update a.dart: remove A.named().
-    //   b.dart is invalid, because it references A.named().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A.named();
-}
-''',
-        r'''
-class A {
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A.named();
-}
-''');
-  }
-
-  void test_class_constructor_unnamed_parameters_change_notUsedSuper() {
-    // Update a.dart: change A().
-    //   Resolution of b.dart is valid, because it does not reference A().
-    //   Hints and verify errors are invalid, because it extends A.
-    // TODO(scheglov) we could keep valid hints and verify errors,
-    // because only constructor is changed - this cannot add/remove
-    // inherited unimplemented members.
-    _verifyTwoLibrariesInvalidHintsVerifyErrors(
-        r'''
-class A {
-  A(int a);
-  A.named(int a);
-}
-''',
-        r'''
-class A {
-  A(String a);
-  A.named(int a);
-}
-''',
-        r'''
-import 'a.dart';
-class B extends A {
-  B() : super.named(42);
-}
-''');
-  }
-
-  void test_class_constructor_unnamed_parameters_change_usedSuper() {
-    // Update a.dart: change A().
-    //   b.dart is invalid, because it references A().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A(int a);
-}
-''',
-        r'''
-class A {
-  A(String a);
-}
-''',
-        r'''
-import 'a.dart';
-class B extends A {
-  B() : super(42);
-}
-''');
-  }
-
-  void test_class_constructor_unnamed_parameters_remove() {
-    // Update a.dart: change A().
-    //   b.dart is invalid, because it references A().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A(int a, int b);
-}
-''',
-        r'''
-class A {
-  A(int a);
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A(1, 2);
-}
-''');
-  }
-
-  void test_class_constructor_unnamed_remove_notUsed() {
-    // Update a.dart: remove A().
-    //   b.dart is invalid, because it instantiates A.
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A();
-  A.named();
-}
-''',
-        r'''
-class A {
-  A.named();
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A.named();
-}
-''');
-  }
-
-  void test_class_constructor_unnamed_remove_used() {
-    // Update a.dart: remove A().
-    //   b.dart is invalid, because it references A().
-    _verifyTwoLibrariesInvalidatesResolution(
-        r'''
-class A {
-  A();
-}
-''',
-        r'''
-class A {
-}
-''',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-}
-''');
-  }
-
-  void test_class_method_change_notUsed() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  foo() {}
-  bar() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main(A a) {
-  a.foo();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A.bar, add A.bar2.
-    //   b.dart is valid, because it doesn't references 'bar' or 'bar2'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  foo() {}
-  bar2() {}
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_class_method_change_notUsed_throughSubclass_extends() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  foo() {}
-  bar() {}
-}
-class B extends A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main(B b) {
-  a.foo();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A.bar, add A.bar2.
-    //   b.dart is valid, because it doesn't references 'bar' or 'bar2'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  foo() {}
-  bar2() {}
-}
-class B extends A {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_class_method_definedInSuper_sameLibrary() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  m() {}
-}
-class B extends A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main(B b) {
-  b.m();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: change A.m
-    //   This makes B changed.
-    //   b.dart is invalid, because it references B.
-    context.setContents(
-        a,
-        r'''
-class A {
-  m2() {}
-}
-class B extends A {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_class_method_remove_notUsed_instantiated() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-abstract class I {
- void foo();
-}
-class A implements I {
- void foo() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove 'A.foo'.
-    //   b.dart is valid because it does not reference 'foo'.
-    //     The class 'A' has a warning, but it is still not abstract.
-    context.setContents(
-        a,
-        r'''
-abstract class I {
- void fo();
-}
-class A implements I {
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValidAllResolution(b);
-    _assertValidAllErrors(b);
-  }
-
-  void test_class_method_remove_subclass() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-abstract class I {
- void foo();
-}
-class A implements I {
- void foo() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B extends A {}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A.bar, add A.bar2.
-    //   b.dart
-    //     Resolution is valid because 'foo' is not referenced.
-    //     HINTS are invalid because 'B' might have invalid @override.
-    //     VERIFY_ERRORS are invalid because 'B' might not implement something.
-    //     Other errors are also invalid.
-    context.setContents(
-        a,
-        r'''
-abstract class I {
- void foo();
-}
-class A implements I {
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertInvalidHintsVerifyErrors(b);
-  }
-
-  void test_class_private_member() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  A();
-  A._privateConstructor();
-
-  foo() {}
-
-  int _privateField;
-  _privateMethod() {}
-  int get _privateGetter => null;
-  void set _privateSetter(_) {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main(A a) {
-  a.foo();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: rename private members of A
-    //   b.dart is valid, it cannot see these private members.
-    context.setContents(
-        a,
-        r'''
-class A {
-  A();
-  A._privateConstructor2();
-
-  foo() {}
-
-  int _privateField2;
-  _privateMethod2() {}
-  int get _privateGetter2 => null;
-  void set _privateSetter2(_) {}
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_enum_add() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-main() {
-  print(MyEnum.A);
-}
-''');
-    _performPendingAnalysisTasks();
-    // Insert a new enum declaration.
-    // No errors expected.
-    context.setContents(
-        a,
-        r'''
-main() {
-  print(MyEnum.A);
-}
-enum MyEnum { A, B, C }
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, isEmpty);
-  }
-
-  void test_private_class() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class _A {}
-class _B2 {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new _A();
-  new _B();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: change _A and _B2
-    //   b.dart is valid, because _A, _B, _A2 and _B2 are all private,
-    //   so b.dart cannot see them.
-    context.setContents(
-        a,
-        r'''
-class _A2 {}
-class _B {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_private_topLevelVariable() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-int _V = 1;
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  print(_A);
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: change _V
-    //   b.dart is valid, because _V is private and b.dart cannot see it.
-    context.setContents(
-        a,
-        r'''
-int _V = 2;
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_private_topLevelVariable_throughPublic() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-int _A = 1;
-int B = _A + 1;
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  print(B);
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: change _A
-    //   b.dart is invalid, because it uses B, which uses _A.
-    context.setContents(
-        a,
-        r'''
-int _A = 2;
-int B = _A + 1;
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_applyChanges_changedSource() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-  new B();
-}
-''');
-    _performPendingAnalysisTasks();
-    resourceProvider.updateFile(
-        resourceProvider.convertPath('/a.dart'),
-        r'''
-class A2 {}
-class B {}
-''');
-    // Update a.dart: remove A, add A2.
-    //   b.dart is invalid, because it references A.
-    var changeSet = new ChangeSet()..changedSource(a);
-    context.applyChanges(changeSet);
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    // Analyze.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, hasLength(0));
-    expect(context.getErrors(b).errors, hasLength(1));
-    _assertValid(a, READY_RESOLVED_UNIT);
-    _assertValid(b, READY_RESOLVED_UNIT);
-    _assertValidAllLibraryUnitResults(a);
-    _assertValidAllLibraryUnitResults(b);
-  }
-
-  void test_sequence_class_give_take() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-class C {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-  new C2();
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-    // Update a.dart: remove C, add C2.
-    //   b.dart is invalid, because it references C2.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B {}
-class C2 {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    // Now b.dart is analyzed and the error is fixed.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(0));
-    // Update a.dart: remove C2, add C.
-    //   b.dart is invalid, because it references C2.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B {}
-class C {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    // Now b.dart is analyzed and it again has the error.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-  }
-
-  void test_sequence_class_removeMethod_overridden() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  void foo() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B extends A {
-  @override
-  void foo() {}
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(0));
-    // Update a.dart: remove add A.foo.
-    //   b.dart has a new hint, because B.foo does not override anything
-    context.setContents(
-        a,
-        r'''
-class A {
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertInvalidHintsVerifyErrors(b);
-
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-  }
-
-  void test_sequence_clearParameterElements() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  foo(int p) {}
-}
-final a = new A();
-main() {
-  a.foo(42);
-}
-''');
-    _performPendingAnalysisTasks();
-    Expression find42() {
-      CompilationUnit unit =
-          context.getResult(new LibrarySpecificUnit(a, a), RESOLVED_UNIT);
-      ExpressionStatement statement =
-          AstFinder.getStatementsInTopLevelFunction(unit, 'main').single;
-      MethodInvocation invocation = statement.expression;
-      return invocation.argumentList.arguments[0];
-    }
-
-    {
-      Expression argument = find42();
-      expect(argument.staticParameterElement, isNull);
-    }
-
-    // Update a.dart: add type annotation for 'a'.
-    // '42' has 'staticParameterElement'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  foo(int p) {}
-}
-final A a = new A();
-main() {
-  a.foo(42);
-}
-''');
-    _performPendingAnalysisTasks();
-    {
-      Expression argument = find42();
-      expect(argument.staticParameterElement, isNotNull);
-    }
-
-    // Update a.dart: remove type annotation for 'a'.
-    // '42' doesn't have 'staticParameterElement'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  foo(int p) {}
-}
-final a = new A();
-main() {
-  a.foo(42);
-}
-''');
-    _performPendingAnalysisTasks();
-    {
-      Expression argument = find42();
-      expect(argument.staticParameterElement, isNull);
-    }
-  }
-
-  void test_sequence_closureParameterTypesPropagation() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-main() {
-  f((p) => 4.2);
-}
-f(c(int p)) {}
-''');
-    _performPendingAnalysisTasks();
-    LibrarySpecificUnit targetA = new LibrarySpecificUnit(a, a);
-    // Update and analyze.
-    String newCode = r'''
-newFunction() {}
-main() {
-  f((p) => 4.2);
-}
-f(c(int p)) {}
-''';
-    context.setContents(a, newCode);
-    _performPendingAnalysisTasks();
-    // Validate "(p) => 4.2" types.
-    CompilationUnit unit = context.getResult(targetA, RESOLVED_UNIT2);
-    SimpleIdentifier parameterName =
-        EngineTestCase.findSimpleIdentifier(unit, newCode, 'p) => 4.2);');
-    expect(parameterName.staticType, context.typeProvider.dynamicType);
-    expect(parameterName.propagatedType, context.typeProvider.intType);
-  }
-
-  void test_sequence_closureParameterTypesPropagation2() {
-    var code = r'''
-import 'b.dart';
-main(x) {
-  x.toMap();
-  f((p) => 'z');
-}
-f(double c(int p)) {}
-''';
-    Source a = addSource('/a.dart', code);
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'c.dart';
-''');
-    addSource(
-        '/c.dart',
-        r'''
-import 'd.dart';
-''');
-    Source d = addSource(
-        '/d.dart',
-        r'''
-class D {}
-''');
-    _performPendingAnalysisTasks();
-    LibrarySpecificUnit targetA = new LibrarySpecificUnit(a, a);
-    // Update b.dart, resolution in a.dart is not affected.
-    context.setContents(
-        b,
-        r'''
-import 'c.dart';
-class B {}
-''');
-    _assertValidAllResolution(a);
-    _performPendingAnalysisTasks();
-    // Update d.dart, this should invalidate a.dart and type propagation
-    // performed for the closure parameter.
-    context.setContents(
-        d,
-        r'''
-class D {
-  toMap() {}
-}
-''');
-    _assertValidUnits(a, RESOLVED_UNIT6);
-    _assertInvalidUnits(a, RESOLVED_UNIT7);
-    _performPendingAnalysisTasks();
-    // Validate "(p) =>" types.
-    {
-      CompilationUnit unit = context.getResult(targetA, RESOLVED_UNIT2);
-      SimpleIdentifier parameterName =
-          EngineTestCase.findSimpleIdentifier(unit, code, 'p) =>');
-      expect(parameterName.staticType, context.typeProvider.dynamicType);
-      expect(parameterName.propagatedType, context.typeProvider.intType);
-    }
-  }
-
-  void test_sequence_compoundingResults_exportNamespace() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A<T> {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-export 'a.dart';
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'b.dart';
-main() {
-  new A<int>();
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(c).errors, isEmpty);
-    // Update a.dart, so that `A<T>` has a type bound.
-    //   This should invalidate export namespace for b.dart.
-    //   Currently we invalidate the whole LIBRARY_ELEMENT4.
-    //   So, c.dart will see the new `A<T extends B>` and report an error.
-    context.setContents(
-        a,
-        r'''
-class A<T extends B> {}
-class B {}
-''');
-    _assertInvalid(b, LIBRARY_ELEMENT4);
-    // Analyze and validate that a new error is reported.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(c).errors, hasLength(1));
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    _assertValid(c, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_compoundingResults_invalidateButKeepDependency() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-import 'b.dart';
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-import 'c.dart';
-class B {}
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-class C {}
-''');
-    Source d = addSource(
-        '/d.dart',
-        r'''
-export 'b.dart';
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(c).errors, isEmpty);
-    // Update: a.dart (limited) and b.dart (limited).
-    //   This should invalidate LIBRARY_ELEMENT4 in d.dart, but it should be
-    //   done in a way that keep dependency of other results od d.dart on
-    //   LIBRARY_ELEMENT4 of d.dart, so that when we perform unlimited
-    //   invalidation of c.dart, this makes d.dart invalid.
-    context.setContents(
-        a,
-        r'''
-import 'b.dart';
-class A2 {}
-''');
-    context.setContents(
-        b,
-        r'''
-import 'a.dart';
-import 'c.dart';
-class B2 {}
-''');
-    context.setContents(
-        c,
-        r'''
-import 'dart:async';
-class C {}
-''');
-    _assertInvalid(d, LIBRARY_ELEMENT4);
-    _assertInvalid(d, LIBRARY_ERRORS_READY);
-    // Analyze and validate that a new error is reported.
-    _performPendingAnalysisTasks();
-    _assertValid(a, EXPORT_SOURCE_CLOSURE);
-    _assertValid(b, EXPORT_SOURCE_CLOSURE);
-    _assertValid(c, EXPORT_SOURCE_CLOSURE);
-    _assertValid(d, EXPORT_SOURCE_CLOSURE);
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    _assertValid(c, LIBRARY_ERRORS_READY);
-    _assertValid(d, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_compoundingResults_resolvedTypeNames() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-class B<T> {
-  B(p);
-}
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-export 'a.dart';
-export 'b.dart';
-''');
-    Source d = addSource(
-        '/d.dart',
-        r'''
-import 'c.dart';
-main() {
-  new B<int>(null);
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart and b.dart
-    //   This should invalidate most results in a.dart and b.dart
-    //
-    //   This should also invalidate "compounding" results in c.dart, such as
-    //   READY_LIBRARY_ELEMENT6, which represent a state of the whole source
-    //   closure, not a result of this single unit or a library.
-    //
-    //   The reason is that although type names (RESOLVED_UNIT5) b.dart will be
-    //   eventually resolved and set into b.dart elements, it may happen
-    //   after we attempted to re-resolve c.dart, which created Member(s), and
-    //   attempts to use elements without types set.
-    context.setContents(
-        a,
-        r'''
-class A2 {}
-''');
-    context.setContents(
-        b,
-        r'''
-class B<T> {
-  B(T p);
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForChangedLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalid(c, READY_LIBRARY_ELEMENT6);
-    _assertInvalid(c, READY_LIBRARY_ELEMENT7);
-    // Analyze and validate that all results are valid.
-    _performPendingAnalysisTasks();
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    _assertValid(c, LIBRARY_ERRORS_READY);
-    _assertValid(d, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_dependenciesWithCycles() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-const A = 1;
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'c.dart';
-const B = C1 + 1;
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'a.dart';
-import 'b.dart';
-const C1 = A + 1;
-const C2 = B + 2;
-''');
-    Source d = addSource(
-        '/d.dart',
-        r'''
-import 'c.dart';
-const D = C2 + 1;
-''');
-    _performPendingAnalysisTasks();
-    // Update "A" constant.
-    // This should invalidate results in all sources.
-    context.setContents(
-        a,
-        r'''
-const A = 2;
-''');
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalid(c, LIBRARY_ERRORS_READY);
-    _assertInvalid(d, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_duplicateField_syntheticAndNot_renameNotSynthetic() {
-    context.analysisOptions =
-        new AnalysisOptionsImpl.from(context.analysisOptions)
-          ..strongMode = true;
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  int foo;
-  int get foo => 1;
-}
-class B extends A {
-  int get foo => 2;
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, hasLength(1));
-    // Update a.dart: rename "int foo" to "int bar".
-    context.setContents(
-        a,
-        r'''
-class A {
-  int bar;
-  int get foo => 1;
-}
-class B extends A {
-  int get foo => 2;
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, isEmpty);
-  }
-
-  void test_sequence_inBodyChange_addRef_deltaChange() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main(A a) {
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(0));
-    // Update b.dart: in-body incremental change - start referencing 'foo'.
-    //   Should update referenced names.
-    context.setContents(
-        b,
-        r'''
-import 'a.dart';
-main(A a) {
-  a.foo;
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-    // Update a.dart: add A.foo
-    //   b.dart is invalid, because it references 'foo'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  int foo;
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    // No errors after analysis.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(0));
-  }
-
-  void test_sequence_inBodyChange_removeRef_deltaChange() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main(A a) {
-  a.foo;
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(1));
-    // Update b.dart: in-body incremental change - stop referencing 'foo'.
-    //   Should update referenced names.
-    context.setContents(
-        b,
-        r'''
-import 'a.dart';
-main(A a) {
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(b).errors, hasLength(0));
-    // Update a.dart: add A.foo
-    //   b.dart is still valid, because it does references 'foo' anymore.
-    context.setContents(
-        a,
-        r'''
-class A {
-  int foo;
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_middleLimited_thenFirstFull() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-export 'a.dart';
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'b.dart';
-A a;
-''');
-    _performPendingAnalysisTasks();
-    // Update b.dart: limited invalidation.
-    // Results in c.dart are valid, because the change in b.dart does not
-    // affect anything in c.dart.
-    context.setContents(
-        b,
-        r'''
-export 'a.dart';
-class B {}
-''');
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertValid(c, LIBRARY_ERRORS_READY);
-    _assertUnitValid(c, RESOLVED_UNIT4);
-    _assertUnitValid(c, RESOLVED_UNIT5);
-    // Update a.dart: unlimited invalidation.
-    // Results RESOLVED_UNIT4, RESOLVED_UNIT5, and RESOLVED_UNIT6 in c.dart
-    // are invalid, because after unlimited change to a.dart everything
-    // should be invalidated.
-    // This fixes the problem that c.dart was not re-resolving type names.
-    context.setContents(
-        a,
-        r'''
-import 'dart:async';
-class A {}
-''');
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalid(c, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(c, RESOLVED_UNIT4);
-  }
-
-  void test_sequence_noChange_thenChange() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  A();
-}
-
-class B {
-  B();
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-}
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, hasLength(0));
-    expect(context.getErrors(b).errors, hasLength(0));
-    var unitA = context.getResolvedCompilationUnit2(a, a);
-    var unitElementA = resolutionMap.elementDeclaredByCompilationUnit(unitA);
-    var libraryElementA = unitElementA.library;
-    // Update a.dart, no declaration changes.
-    context.setContents(
-        a,
-        r'''
-class A {
-  A();
-}
-class B {
-  B();
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    // The a.dart's unit and element are updated incrementally.
-    // They are the same instances as initially.
-    // So, all the references from other units are still valid.
-    {
-      LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
-      expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA));
-      expect(unitA.element, same(unitElementA));
-      expect(unitElementA.library, same(libraryElementA));
-    }
-    // Analyze.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, hasLength(0));
-    expect(context.getErrors(b).errors, hasLength(0));
-    // The a.dart's unit and element are the same.
-    {
-      LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
-      expect(analysisCache.getValue(target, RESOLVED_UNIT), same(unitA));
-      expect(unitA.element, same(unitElementA));
-      expect(unitElementA.library, same(libraryElementA));
-    }
-    // Add a new method to a.dart. This invalidates b.dart, so
-    // we know that the previous update did not damage dependencies.
-    context.setContents(
-        a,
-        r'''
-class A {
-  A();
-  m() {}
-}
-class B {
-  B();
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertValidAllErrors(b);
-    // The a.dart's unit and element are the same.
-    {
-      LibrarySpecificUnit target = new LibrarySpecificUnit(a, a);
-      expect(analysisCache.getValue(target, RESOLVED_UNIT1), same(unitA));
-      expect(unitA.element, same(unitElementA));
-      expect(unitElementA.library, same(libraryElementA));
-    }
-    // Analyze.
-    _performPendingAnalysisTasks();
-    expect(context.getErrors(a).errors, hasLength(0));
-    expect(context.getErrors(b).errors, hasLength(0));
-  }
-
-  void test_sequence_parts_disableForPart() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-library my_lib;
-part 'b.dart';
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-part of my_lib;
-class A {}
-''');
-    _performPendingAnalysisTasks();
-    // Update b.dart - it is a part, which we don't support.
-    // So, invalidate everything.
-    context.setContents(
-        b,
-        r'''
-part of my_lib;
-class A {}
-class B {}
-''');
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(a, RESOLVED_UNIT2);
-    _assertInvalidUnits(b, RESOLVED_UNIT1);
-  }
-
-  void test_sequence_parts_disableWithPart() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-library my_lib;
-part 'b.dart';
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-part of my_lib;
-class B {}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart - it is a library with a part, which we don't support.
-    // So, invalidate everything.
-    context.setContents(
-        a,
-        r'''
-library my_lib;
-part 'b.dart';
-class A {}
-''');
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(a, RESOLVED_UNIT1);
-    _assertInvalidUnits(b, RESOLVED_UNIT1);
-  }
-
-  void test_sequence_reorder_localFunctions() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-f1() {
-  localFunction() {
-    const C = 1;
-  }
-}
-f2() {}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: reorder functions.
-    // This should not fail with FrozenHashCodeException, because identifiers
-    // of local elements should be relative to the enclosing top-level elements.
-    context.setContents(
-        a,
-        r'''
-f2() {}
-f1() {
-  localFunction() {
-    const C = 1;
-  }
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_unitConstants_addRemove() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-const A = 1;
-const B = 2;
-const C = 3;
-foo() {
-  const V1 = 10;
-}
-bar() {
-  const V2 = 20;
-}
-''');
-    _performPendingAnalysisTasks();
-    LibrarySpecificUnit unitA = new LibrarySpecificUnit(a, a);
-    List<ConstantEvaluationTarget> oldConstants =
-        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
-    expect(oldConstants, hasLength(5));
-    ConstVariableElement oldA = _findConstVariable(oldConstants, 'A');
-    ConstVariableElement oldB = _findConstVariable(oldConstants, 'B');
-    ConstVariableElement oldC = _findConstVariable(oldConstants, 'C');
-    ConstVariableElement oldV1 = _findConstVariable(oldConstants, 'V1');
-    ConstVariableElement oldV2 = _findConstVariable(oldConstants, 'V2');
-    expect(context.analysisCache.get(oldA), isNotNull);
-    expect(context.analysisCache.get(oldB), isNotNull);
-    expect(context.analysisCache.get(oldC), isNotNull);
-    expect(context.analysisCache.get(oldV1), isNotNull);
-    // Update and validate new constants.
-    context.setContents(
-        a,
-        r'''
-const A = 1;
-const B = 2;
-const D = 4;
-foo() {
-  const V1 = 10;
-}
-baz() {
-  const V3 = 30;
-}
-''');
-    List<ConstantEvaluationTarget> newConstants =
-        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
-    expect(newConstants, hasLength(5));
-    expect(newConstants, contains(same(oldA)));
-    expect(newConstants, contains(same(oldB)));
-    expect(newConstants, contains(same(oldV1)));
-    ConstVariableElement newD = _findConstVariable(newConstants, 'D');
-    ConstVariableElement newV3 = _findConstVariable(newConstants, 'V3');
-    // Perform analysis, compute constant values.
-    _performPendingAnalysisTasks();
-    // Validate const variable values.
-    expect(context.analysisCache.get(oldA), isNotNull);
-    expect(context.analysisCache.get(oldB), isNotNull);
-    expect(context.analysisCache.get(oldV1), isNotNull);
-    expect(context.analysisCache.get(oldC), isNull);
-    expect(context.analysisCache.get(oldV2), isNull);
-    expect(context.analysisCache.get(newD), isNotNull);
-    expect(context.analysisCache.get(newV3), isNotNull);
-    expect(oldA.evaluationResult.value.toIntValue(), 1);
-    expect(oldB.evaluationResult.value.toIntValue(), 2);
-    expect(newD.evaluationResult.value.toIntValue(), 4);
-    expect(oldV1.evaluationResult.value.toIntValue(), 10);
-    expect(newV3.evaluationResult.value.toIntValue(), 30);
-  }
-
-  void test_sequence_unitConstants_local_insertSpace() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-main() {
-  const C = 1;
-}
-''');
-    _performPendingAnalysisTasks();
-    LibrarySpecificUnit unitA = new LibrarySpecificUnit(a, a);
-    List<ConstantEvaluationTarget> oldConstants =
-        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
-    expect(oldConstants, hasLength(1));
-    ConstVariableElement C = _findConstVariable(oldConstants, 'C');
-    expect(context.analysisCache.get(C), isNotNull);
-    // Insert a space before the name.
-    context.setContents(
-        a,
-        r'''
-main() {
-  const  C = 1;
-}
-''');
-    List<ConstantEvaluationTarget> newConstants =
-        context.getResult(unitA, COMPILATION_UNIT_CONSTANTS);
-    expect(newConstants, hasLength(1));
-    expect(newConstants, contains(same(C)));
-    // Perform analysis, compute constant values.
-    _performPendingAnalysisTasks();
-    // Validate const variable values.
-    expect(context.analysisCache.get(C), isNotNull);
-    expect(C.evaluationResult.value.toIntValue(), 1);
-  }
-
-  void test_sequence_useAnyResolvedUnit() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-}
-''');
-    _performPendingAnalysisTasks();
-    _assertValid(a, LIBRARY_ERRORS_READY);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-    // Invalidate RESOLVED_UNIT
-    CacheEntry entryA = context.getCacheEntry(new LibrarySpecificUnit(a, a));
-    entryA.setState(RESOLVED_UNIT, CacheState.FLUSHED);
-    entryA.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
-    entryA.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
-    entryA.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B2 {}
-''');
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_sequence_useAnyResolvedUnit_needsLibraryElement() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-''');
-    // Perform analysis until we get RESOLVED_UNIT1.
-    // But it does not have 'library' set, so `unitElement.context` is `null`.
-    LibrarySpecificUnit aUnitTarget = new LibrarySpecificUnit(a, a);
-    while (context.getResult(aUnitTarget, RESOLVED_UNIT1) == null) {
-      context.performAnalysisTask();
-    }
-    // There was a bug with exception in incremental element builder.
-    // We should not attempt to use `unitElement.context`.
-    // It calls `unitElement.library`, which might be not set yet.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B2 {}
-''');
-    // OK, no exceptions.
-  }
-
-  void test_unusedName_class_add() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-class C {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-  new C();
-}
-''');
-    _performPendingAnalysisTasks();
-    _assertValid(a, LINE_INFO);
-    // The class B is not referenced.
-    //   a.dart is invalid.
-    //   b.dart is valid.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B2 {}
-class C {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertUnitInvalid(a, RESOLVED_UNIT);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllLibraryUnitResults(b);
-    _assertValid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_usedName_class_name_asHole_inBody() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-class C {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-  new C2();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove C, add C2.
-    //   b.dart is invalid, because it references C2.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B {}
-class C2 {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-  }
-
-  void test_usedName_class_name_asSuper() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B extends A {}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A, add A2.
-    //   b.dart is invalid, because it references A.
-    context.setContents(
-        a,
-        r'''
-class A2 {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-  }
-
-  void test_usedName_class_name_asTypeBound() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B<T extends A> {
-  T f;
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A, add A2.
-    //   b.dart is invalid, because it references A.
-    context.setContents(
-        a,
-        r'''
-class A2 {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-  }
-
-  void test_usedName_class_name_inBody() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {}
-class B {}
-class C {}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  new A();
-  new C();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove C, add C2.
-    //   b.dart is invalid, because it references C.
-    context.setContents(
-        a,
-        r'''
-class A {}
-class B {}
-class C2 {}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-  }
-
-  void test_usedName_classMethod_name_inBody() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  m() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-main() {
-  A a = new A();
-  a.m();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A.m, add A.m2.
-    //   b.dart is invalid, because it references 'm'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  m2() {}
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalidLibraryElements(b, LIBRARY_ELEMENT4);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-  }
-
-  void test_usedName_indirect_classMethod_name_inBody() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  m() {}
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B extends A {}
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'b.dart';
-main() {
-  B b = new B();
-  b.m();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A.m, add A.m2.
-    //   b.dart has valid resolution, and invalid errors.
-    //   c.dart is invalid, because 'main' references 'm'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  m2() {}
-}
-''');
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertInvalidHintsVerifyErrors(b);
-
-    _assertValidForDependentLibrary(c);
-    _assertInvalidLibraryElements(c, LIBRARY_ELEMENT5);
-    _assertInvalidUnits(c, RESOLVED_UNIT4);
-    _assertInvalid(c, LIBRARY_ERRORS_READY);
-  }
-
-  void test_usedName_indirect_classMethod_returnType_inBody() {
-    Source a = addSource(
-        '/a.dart',
-        r'''
-class A {
-  int m() {
-    return 1;
-  }
-}
-''');
-    Source b = addSource(
-        '/b.dart',
-        r'''
-import 'a.dart';
-class B extends A {}
-''');
-    Source c = addSource(
-        '/c.dart',
-        r'''
-import 'b.dart';
-main() {
-  B b = new B();
-  b.m();
-}
-''');
-    _performPendingAnalysisTasks();
-    // Update a.dart: remove A.m, add A.m2.
-    //   b.dart is invalid, because B extends A.
-    //   c.dart is invalid, because 'main' references 'm'.
-    context.setContents(
-        a,
-        r'''
-class A {
-  double m() {
-    return 1.2;
-  }
-}
-''');
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertInvalidHintsVerifyErrors(b);
-
-    _assertValidForDependentLibrary(c);
-    _assertInvalidLibraryElements(c, LIBRARY_ELEMENT5);
-    _assertInvalidUnits(c, RESOLVED_UNIT4);
-    _assertInvalid(c, LIBRARY_ERRORS_READY);
-  }
-
-  void _assertInvalid(AnalysisTarget target, ResultDescriptor descriptor) {
-    CacheState actual = analysisCache.getState(target, descriptor);
-    if (actual != CacheState.INVALID) {
-      fail("cache state of $target $descriptor: wanted INVALID, got: $actual");
-    }
-  }
-
-  /**
-   * Assert that [VERIFY_ERRORS] and other error results that include it,
-   * are invalid.
-   */
-  void _assertInvalidHintsVerifyErrors(Source unit) {
-    _assertUnitInvalid(unit, HINTS);
-    _assertUnitInvalid(unit, VERIFY_ERRORS);
-    _assertUnitInvalid(unit, LIBRARY_UNIT_ERRORS);
-    _assertInvalid(unit, DART_ERRORS);
-    _assertInvalid(unit, LIBRARY_ERRORS_READY);
-  }
-
-  /**
-   * Assert that [LIBRARY_ELEMENT_RESULTS] for [first] and after it are invalid.
-   */
-  void _assertInvalidLibraryElements(
-      Source source, ResultDescriptor<LibraryElement> first) {
-    bool foundFirst = false;
-    for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) {
-      foundFirst = foundFirst || result == first;
-      if (foundFirst) {
-        _assertInvalid(source, result);
-      }
-    }
-  }
-
-  void _assertInvalidUnits(Source unit, ResultDescriptor<CompilationUnit> first,
-      {Source library}) {
-    var target = new LibrarySpecificUnit(library ?? unit, unit);
-    bool foundFirst = false;
-    for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) {
-      foundFirst = foundFirst || result == first;
-      if (foundFirst) {
-        _assertInvalid(target, result);
-      }
-    }
-  }
-
-  void _assertUnitInvalid(Source unitSource, ResultDescriptor descriptor,
-      {Source librarySource}) {
-    librarySource ??= unitSource;
-    _assertInvalid(
-        new LibrarySpecificUnit(librarySource, unitSource), descriptor);
-  }
-
-  void _assertUnitValid(Source unitSource, ResultDescriptor descriptor,
-      {Source librarySource}) {
-    librarySource ??= unitSource;
-    _assertValid(
-        new LibrarySpecificUnit(librarySource, unitSource), descriptor);
-  }
-
-  void _assertUnitValidTaskResults(Source unitSource, TaskDescriptor descriptor,
-      {Source librarySource}) {
-    librarySource ??= unitSource;
-    for (ResultDescriptor result in descriptor.results) {
-      _assertUnitValid(unitSource, result, librarySource: librarySource);
-    }
-  }
-
-  void _assertValid(AnalysisTarget target, ResultDescriptor descriptor) {
-    CacheState state = analysisCache.getState(target, descriptor);
-    expect(state, isIn([CacheState.VALID, CacheState.FLUSHED]),
-        reason: '$descriptor in $target');
-  }
-
-  /**
-   * Assert that all error results for the given [unit] are valid.
-   */
-  void _assertValidAllErrors(Source unit) {
-    for (ListResultDescriptor<AnalysisError> result in ERROR_SOURCE_RESULTS) {
-      _assertValid(unit, result);
-    }
-    for (ListResultDescriptor<AnalysisError> result in ERROR_UNIT_RESULTS) {
-      _assertUnitValid(unit, result);
-    }
-  }
-
-  void _assertValidAllLibraryUnitResults(Source source, {Source library}) {
-    library ??= source;
-    for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) {
-      if (result == LIBRARY_ELEMENT4) {
-        continue;
-      }
-      _assertValid(library, result);
-    }
-    LibrarySpecificUnit target = new LibrarySpecificUnit(library, source);
-    for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) {
-      _assertValid(target, result);
-    }
-  }
-
-  void _assertValidAllResolution(Source unit) {
-    _assertValidUnits(unit, null);
-    _assertUnitValidTaskResults(unit, ResolveUnitTypeNamesTask.DESCRIPTOR);
-    _assertUnitValidTaskResults(unit, ResolveUnitTask.DESCRIPTOR);
-    _assertValidTaskResults(unit, ResolveLibraryReferencesTask.DESCRIPTOR);
-    _assertValidTaskResults(unit, ResolveLibraryTask.DESCRIPTOR);
-  }
-
-  void _assertValidForAnyLibrary(Source source) {
-    // Source results.
-    _assertValidTaskResults(source, ScanDartTask.DESCRIPTOR);
-    // Library results.
-    _assertValidTaskResults(source, BuildLibraryElementTask.DESCRIPTOR);
-    _assertValidTaskResults(source, BuildDirectiveElementsTask.DESCRIPTOR);
-    _assertValidTaskResults(source, BuildSourceExportClosureTask.DESCRIPTOR);
-    _assertValidTaskResults(source, ReadyLibraryElement2Task.DESCRIPTOR);
-    _assertValidTaskResults(source, ComputeLibraryCycleTask.DESCRIPTOR);
-    // Unit results.
-    _assertUnitValidTaskResults(
-        source, BuildCompilationUnitElementTask.DESCRIPTOR);
-    _assertUnitValidTaskResults(
-        source, ResolveDirectiveElementsTask.DESCRIPTOR);
-    _assertUnitValidTaskResults(source, BuildEnumMemberElementsTask.DESCRIPTOR);
-  }
-
-  void _assertValidForChangedLibrary(Source source) {
-    _assertValidForAnyLibrary(source);
-  }
-
-  void _assertValidForDependentLibrary(Source source) {
-    _assertValidForAnyLibrary(source);
-    // Library results.
-    _assertValidTaskResults(source, BuildPublicNamespaceTask.DESCRIPTOR);
-  }
-
-  void _assertValidTaskResults(AnalysisTarget target, TaskDescriptor task) {
-    for (ResultDescriptor result in task.results) {
-      _assertValid(target, result);
-    }
-  }
-
-  void _assertValidUnits(Source unit, ResultDescriptor<CompilationUnit> last,
-      {Source library}) {
-    var target = new LibrarySpecificUnit(library ?? unit, unit);
-    bool foundLast = false;
-    for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) {
-      if (!foundLast) {
-        _assertValid(target, result);
-      }
-      foundLast = foundLast || result == last;
-    }
-  }
-
-  ConstVariableElement _findConstVariable(
-      List<ConstantEvaluationTarget> constants, String name) {
-    return constants.singleWhere((c) {
-      return c is ConstVariableElement && c.name == name;
-    });
-  }
-
-  void _performPendingAnalysisTasks([int maxTasks = 512]) {
-    for (int i = 0; context.performAnalysisTask().hasMoreWork; i++) {
-      if (i > maxTasks) {
-        fail('Analysis did not terminate.');
-      }
-    }
-  }
-
-  void _verifyTwoLibrariesAllValid(
-      String firstCodeA, String secondCodeA, String codeB) {
-    Source a = addSource('/a.dart', firstCodeA);
-    Source b = addSource('/b.dart', codeB);
-    _performPendingAnalysisTasks();
-    context.setContents(a, secondCodeA);
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertValidAllErrors(b);
-  }
-
-  void _verifyTwoLibrariesInvalidatesResolution(
-      String firstCodeA, String secondCodeA, String codeB) {
-    Source a = addSource('/a.dart', firstCodeA);
-    Source b = addSource('/b.dart', codeB);
-    _performPendingAnalysisTasks();
-    context.setContents(a, secondCodeA);
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertInvalid(b, LIBRARY_ERRORS_READY);
-    _assertInvalidUnits(b, RESOLVED_UNIT4);
-  }
-
-  void _verifyTwoLibrariesInvalidHintsVerifyErrors(
-      String firstCodeA, String secondCodeA, String codeB) {
-    Source a = addSource('/a.dart', firstCodeA);
-    Source b = addSource('/b.dart', codeB);
-    _performPendingAnalysisTasks();
-    context.setContents(a, secondCodeA);
-    _assertValidForChangedLibrary(a);
-    _assertInvalid(a, LIBRARY_ERRORS_READY);
-    _assertValidForDependentLibrary(b);
-    _assertValidAllResolution(b);
-    _assertUnitValid(b, RESOLVE_UNIT_ERRORS);
-    _assertInvalidHintsVerifyErrors(b);
-  }
-}
-
 class _AnalysisContextImplTest_Source_exists_true extends TestSource {
   @override
   bool exists() => true;
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index 6270250..e1b6a04 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:test/test.dart';
 import 'package:typed_mock/typed_mock.dart';
 
@@ -74,6 +75,29 @@
     }
   }
 
+  AnalysisDriver createAnalysisDriver({SummaryDataStore externalSummaries}) {
+    return new AnalysisDriver(
+        scheduler,
+        logger,
+        provider,
+        byteStore,
+        contentOverlay,
+        null,
+        new SourceFactory([
+          new DartUriResolver(sdk),
+          generatedUriResolver,
+          new PackageMapUriResolver(provider, <String, List<Folder>>{
+            'test': [provider.getFolder(testProject)]
+          }),
+          new ResourceUriResolver(provider)
+        ], null, provider),
+        new AnalysisOptionsImpl()
+          ..strongMode = true
+          ..enableUriInPartOf = true,
+        disableChangesAndCacheAllResults: disableChangesAndCacheAllResults,
+        externalSummaries: externalSummaries);
+  }
+
   int findOffset(String search) {
     int offset = testCode.indexOf(search);
     if (offset < 0) {
@@ -109,31 +133,15 @@
     testFile = _p('/test/lib/test.dart');
     logger = new PerformanceLog(logBuffer);
     scheduler = new AnalysisDriverScheduler(logger);
-    driver = new AnalysisDriver(
-        scheduler,
-        logger,
-        provider,
-        byteStore,
-        contentOverlay,
-        null,
-        new SourceFactory([
-          new DartUriResolver(sdk),
-          generatedUriResolver,
-          new PackageMapUriResolver(provider, <String, List<Folder>>{
-            'test': [provider.getFolder(testProject)]
-          }),
-          new ResourceUriResolver(provider)
-        ], null, provider),
-        new AnalysisOptionsImpl()
-          ..strongMode = true
-          ..enableUriInPartOf = true,
-        disableChangesAndCacheAllResults: disableChangesAndCacheAllResults);
+    driver = createAnalysisDriver();
     scheduler.start();
     scheduler.status.listen(allStatuses.add);
     driver.results.listen(allResults.add);
     driver.exceptions.listen(allExceptions.add);
   }
 
+  void tearDown() {}
+
   String _p(String path) => provider.convertPath(path);
 }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 4f3b2af..624b497 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -27,6 +27,7 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:test/test.dart';
@@ -988,6 +989,43 @@
     expect(errors[0].errorCode, CompileTimeErrorCode.URI_DOES_NOT_EXIST);
   }
 
+  test_externalSummaries() async {
+    var a = _p('/a.dart');
+    var b = _p('/b.dart');
+    provider.newFile(
+        a,
+        r'''
+class A {}
+''');
+    provider.newFile(
+        b,
+        r'''
+import 'a.dart';
+var a = new A();
+''');
+
+    // Prepare the store with a.dart and everything it needs.
+    SummaryDataStore summaryStore =
+        createAnalysisDriver().test.getSummaryStore(a);
+
+    // There are at least a.dart and dart:core libraries.
+    String aUri = provider.pathContext.toUri(a).toString();
+    expect(summaryStore.unlinkedMap.keys, contains(aUri));
+    expect(summaryStore.linkedMap.keys, contains(aUri));
+    expect(summaryStore.unlinkedMap.keys, contains('dart:core'));
+    expect(summaryStore.linkedMap.keys, contains('dart:core'));
+
+    // Remove a.dart from the file system.
+    provider.deleteFile(a);
+
+    // We don't need a.dart file when we analyze with the summary store.
+    // Still no analysis errors.
+    AnalysisDriver driver =
+        createAnalysisDriver(externalSummaries: summaryStore);
+    AnalysisResult result = await driver.getResult(b);
+    expect(result.errors, isEmpty);
+  }
+
   test_generatedFile() async {
     Uri uri = Uri.parse('package:aaa/foo.dart');
     String templatePath = _p('/aaa/lib/foo.dart');
@@ -1133,6 +1171,63 @@
     expect(fooId, isNonNegative);
   }
 
+  test_getLibraryByUri_external_resynthesize() async {
+    provider.newFile(
+        testFile,
+        r'''
+class Test {}
+''');
+
+    // Prepare the store with package:test/test.dart URI.
+    SummaryDataStore summaryStore =
+        createAnalysisDriver().test.getSummaryStore(testFile);
+
+    // package:test/test.dart is in the store.
+    String uri = 'package:test/test.dart';
+    expect(summaryStore.unlinkedMap.keys, contains(uri));
+    expect(summaryStore.linkedMap.keys, contains(uri));
+
+    // Remove the file from the file system.
+    provider.deleteFile(testFile);
+
+    // We can resynthesize the library from the store without reading the file.
+    AnalysisDriver driver =
+        createAnalysisDriver(externalSummaries: summaryStore);
+    expect(driver.test.numOfCreatedLibraryContexts, 0);
+    LibraryElement library = await driver.getLibraryByUri(uri);
+    expect(library.getType('Test'), isNotNull);
+  }
+
+  test_getLibraryByUri_sdk_analyze() async {
+    LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
+    expect(coreLibrary, isNotNull);
+    expect(coreLibrary.getType('Object'), isNotNull);
+    expect(coreLibrary.getType('int'), isNotNull);
+  }
+
+  test_getLibraryByUri_sdk_resynthesize() async {
+    SummaryDataStore sdkStore;
+    {
+      String corePath = sdk.mapDartUri('dart:core').fullName;
+      sdkStore = createAnalysisDriver().test.getSummaryStore(corePath);
+    }
+
+    // There are dart:core and dart:async in the store.
+    expect(sdkStore.unlinkedMap.keys, contains('dart:core'));
+    expect(sdkStore.unlinkedMap.keys, contains('dart:async'));
+    expect(sdkStore.linkedMap.keys, contains('dart:core'));
+    expect(sdkStore.linkedMap.keys, contains('dart:async'));
+
+    // We don't create new library context (so, don't parse, summarize and
+    // link) for dart:core. The library is resynthesized from the provided
+    // external store.
+    AnalysisDriver driver = createAnalysisDriver(externalSummaries: sdkStore);
+    LibraryElement coreLibrary = await driver.getLibraryByUri('dart:core');
+    expect(driver.test.numOfCreatedLibraryContexts, 0);
+    expect(coreLibrary, isNotNull);
+    expect(coreLibrary.getType('Object'), isNotNull);
+  }
+
   test_getResult() async {
     String content = 'int f() => 42;';
     addTestFile(content, priority: true);
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 6f64231..45b2986 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -724,6 +724,68 @@
     _assertValidNull(await _check_fromEnvironment_string(null, "null"));
   }
 
+  test_getConstructor_redirectingFactory() async {
+    CompilationUnit compilationUnit = await resolveSource(r'''
+class A {
+  factory const A() = B;
+}
+
+class B implements A {
+  const B();
+}
+
+class C {
+  @A()
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(result.value.getInvocation().constructor.isFactory, isTrue);
+  }
+
+  test_getConstructor_withArgs() async {
+    CompilationUnit compilationUnit = await resolveSource(r'''
+class A {
+  final int i;
+  const A(this.i);
+}
+
+class C {
+  @A(5)
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    ConstructorInvocation invocation = result.value.getInvocation();
+    expect(invocation.constructor, isNotNull);
+    expect(invocation.positionalArguments, hasLength(1));
+    expect(invocation.positionalArguments.single.toIntValue(), 5);
+    expect(invocation.namedArguments, isEmpty);
+  }
+
+  test_getConstructor_withNamedArgs() async {
+    CompilationUnit compilationUnit = await resolveSource(r'''
+class A {
+  final int i;
+  const A({this.i});
+}
+
+class C {
+  @A(i: 5)
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    ConstructorInvocation invocation = result.value.getInvocation();
+    expect(invocation.constructor, isNotNull);
+    expect(invocation.positionalArguments, isEmpty);
+    expect(invocation.namedArguments, isNotEmpty);
+    expect(invocation.namedArguments['i'].toIntValue(), 5);
+  }
+
   test_instanceCreationExpression_computedField() async {
     CompilationUnit compilationUnit = await resolveSource(r'''
 const foo = const A(4, 5);
@@ -1005,6 +1067,17 @@
     _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
   }
 
+  test_instanceCreationExpression_redirect_generic() async {
+    CompilationUnit compilationUnit = await resolveSource(r'''
+const foo = const A<int>();
+class A<T> {
+  const A() : this._();
+  const A._();
+}
+''');
+    _assertType(_evaluateTopLevelVariable(compilationUnit, 'foo'), 'A<int>');
+  }
+
   test_instanceCreationExpression_redirect_nonConst() async {
     // It is an error for a const factory constructor redirect to a non-const
     // constructor; however, we need to make sure that even if the error
@@ -1181,68 +1254,6 @@
     expect(value.toSymbolValue(), "void");
   }
 
-  test_getConstructor_withArgs() async {
-    CompilationUnit compilationUnit = await resolveSource(r'''
-class A {
-  final int i;
-  const A(this.i);
-}
-
-class C {
-  @A(5)
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    ConstructorInvocation invocation = result.value.getInvocation();
-    expect(invocation.constructor, isNotNull);
-    expect(invocation.positionalArguments, hasLength(1));
-    expect(invocation.positionalArguments.single.toIntValue(), 5);
-    expect(invocation.namedArguments, isEmpty);
-  }
-
-  test_getConstructor_withNamedArgs() async {
-    CompilationUnit compilationUnit = await resolveSource(r'''
-class A {
-  final int i;
-  const A({this.i});
-}
-
-class C {
-  @A(i: 5)
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    ConstructorInvocation invocation = result.value.getInvocation();
-    expect(invocation.constructor, isNotNull);
-    expect(invocation.positionalArguments, isEmpty);
-    expect(invocation.namedArguments, isNotEmpty);
-    expect(invocation.namedArguments['i'].toIntValue(), 5);
-  }
-
-  test_getConstructor_redirectingFactory() async {
-    CompilationUnit compilationUnit = await resolveSource(r'''
-class A {
-  factory const A() = B;
-}
-
-class B implements A {
-  const B();
-}
-
-class C {
-  @A()
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(result.value.getInvocation().constructor.isFactory, isTrue);
-  }
-
   Map<String, DartObjectImpl> _assertFieldType(
       Map<String, DartObjectImpl> fields,
       String fieldName,
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index aee2ada..e45e9ba 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -14307,6 +14307,26 @@
     }
   }
 
+  test_typedef_type_parameters_bound_recursive() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary('typedef void F<T extends F>();');
+    checkElementText(
+        library,
+        r'''
+typedef void F<T extends F>();
+''');
+  }
+
+  test_typedef_type_parameters_bound_recursive2() {
+    shouldCompareLibraryElements = false;
+    var library = checkLibrary('typedef void F<T extends List<F>>();');
+    checkElementText(
+        library,
+        r'''
+typedef void F<T extends List<F>>();
+''');
+  }
+
   test_typedef_type_parameters_f_bound_complex() {
     var library = checkLibrary('typedef U F<T extends List<U>, U>(T t);');
     if (isStrongMode) {
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index c0ef180..b817ac0 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -127,6 +127,15 @@
     await checkFile(content);
   }
 
+  test_initializer_extractIndex() async {
+    var content = r'''
+var a = /*info:INFERRED_TYPE_LITERAL*/[0, 1.2];
+var b0 = a[0];
+var b1 = a[1];
+''';
+    await checkFile(content);
+  }
+
   test_initializer_functionLiteral_blockBody() async {
     var content = r'''
 var t = /*error:TOP_LEVEL_FUNCTION_LITERAL_BLOCK*/
@@ -871,6 +880,21 @@
 ''');
   }
 
+  test_initializer_extractIndex() async {
+    var library = await _encodeDecodeLibrary(r'''
+var a = [0, 1.2];
+var b0 = a[0];
+var b1 = a[1];
+''');
+    checkElementText(
+        library,
+        r'''
+List<num> a;
+num b0;
+num b1;
+''');
+  }
+
   test_initializer_functionExpression() async {
     var library = await _encodeDecodeLibrary(r'''
 import 'dart:async';
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index f4349cb..2a2f84d 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -63,7 +63,6 @@
     defineReflectiveTests(LibraryUnitErrorsTaskTest);
     defineReflectiveTests(ParseDartTaskTest);
     defineReflectiveTests(PartiallyResolveUnitReferencesTaskTest);
-    defineReflectiveTests(ReferencedNamesBuilderTest);
     defineReflectiveTests(ResolveDirectiveElementsTaskTest);
     defineReflectiveTests(ResolveInstanceFieldsInUnitTaskTest);
     defineReflectiveTests(ResolveLibraryTaskTest);
@@ -3173,7 +3172,7 @@
     _performParseTask(r'''
 part of lib;
 class B {}''');
-    expect(outputs, hasLength(11));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3181,7 +3180,6 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
     expect(outputs[REFERENCED_SOURCES], hasLength(2));
     expect(outputs[SOURCE_KIND], SourceKind.PART);
     expect(outputs[UNITS], hasLength(1));
@@ -3209,7 +3207,7 @@
 
   test_perform_doesNotExist() {
     _performParseTask(null);
-    expect(outputs, hasLength(11));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3217,7 +3215,6 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
     expect(outputs[REFERENCED_SOURCES], hasLength(2));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(1));
@@ -3238,7 +3235,7 @@
 export '${a}lib3.dart';
 part 'part.dart';
 class A {}''');
-    expect(outputs, hasLength(11));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3246,7 +3243,6 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(2));
     expect(outputs[PARSE_ERRORS], hasLength(2));
     expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
     expect(outputs[REFERENCED_SOURCES], hasLength(4));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(2));
@@ -3259,7 +3255,7 @@
 export 'lib3.dart';
 part 'part.dart';
 class A {''');
-    expect(outputs, hasLength(11));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(1));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
@@ -3267,7 +3263,6 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(2));
     expect(outputs[PARSE_ERRORS], hasLength(1));
     expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
     expect(outputs[REFERENCED_SOURCES], hasLength(5));
     expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
     expect(outputs[UNITS], hasLength(2));
@@ -3397,7 +3392,7 @@
     _performParseTask(r'''
 part of lib;
 class B {}''');
-    expect(outputs, hasLength(11));
+    expect(outputs, hasLength(10));
     expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
     expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
     _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
@@ -3405,7 +3400,6 @@
     expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
     expect(outputs[PARSE_ERRORS], hasLength(0));
     expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[REFERENCED_NAMES], isNotNull);
     expect(outputs[REFERENCED_SOURCES], hasLength(2));
     expect(outputs[SOURCE_KIND], SourceKind.PART);
     expect(outputs[UNITS], hasLength(1));
@@ -3589,466 +3583,6 @@
 }
 
 @reflectiveTest
-class ReferencedNamesBuilderTest extends _AbstractDartTaskTest {
-  void setUp() {
-    super.setUp();
-    context.analysisOptions = new AnalysisOptionsImpl()..strongMode = true;
-  }
-
-  test_class_constructor() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  U.named(A a, B b) {
-    C c = null;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
-  }
-
-  test_class_extendedUsedUnnamedConstructorNames() {
-    ReferencedNames info = _computeReferencedNames('''
-class U1 extends A {
-  U1() : super();
-}
-class U2 extends p.B {
-  U2() : super();
-}
-class U3 extends p.C {
-  U3() : super.named();
-}
-''');
-    expect(
-        info.extendedUsedUnnamedConstructorNames, unorderedEquals(['A', 'B']));
-  }
-
-  test_class_field() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  A f = new B();
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['B']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
-  }
-
-  test_class_getter() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  A get a => new B();
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['B']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
-  }
-
-  test_class_members() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  int a;
-  int get b;
-  set c(_) {}
-  m(D d) {
-    a;
-    b;
-    c = 1;
-    m();
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['int', 'D']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['int', 'D']));
-  }
-
-  test_class_members_dontHideQualified() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  int a;
-  int get b;
-  set c(_) {}
-  m(D d) {
-    d.a;
-    d.b;
-    d.c;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['int', 'D', 'a', 'b', 'c']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['int', 'D']));
-  }
-
-  test_class_method() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  A m(B p) {
-    C v = 0;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
-  }
-
-  test_class_method_localVariables() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  A m() {
-    B b = null;
-    b;
-    {
-      C c = null;
-      b;
-      c;
-    }
-    d;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C', 'd']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
-  }
-
-  test_class_method_parameters() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  m(A a) {
-    a;
-    b;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'b']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
-  }
-
-  test_class_method_typeParameters() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  A m<T>(B b, T t) {
-    C c = 0;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
-  }
-
-  test_class_setter() {
-    ReferencedNames info = _computeReferencedNames('''
-class U {
-  set a(A a) {
-    B b = null;
-  }
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
-  }
-
-  test_class_typeParameters() {
-    ReferencedNames info = _computeReferencedNames('''
-class U<T> {
-  T f = new A<T>();
-}
-''');
-    expect(info.names, unorderedEquals(['A']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['A']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A']));
-  }
-
-  test_instantiatedNames_importPrefix() {
-    ReferencedNames info = _computeReferencedNames('''
-import 'a.dart' as p1;
-import 'b.dart' as p2;
-main() {
-  new p1.A();
-  new p1.A.c1();
-  new p1.B();
-  new p2.C();
-  new D();
-  new D.c2();
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C', 'D', 'c1', 'c2']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['A', 'B', 'C', 'D']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['main']));
-    expect(info.userToDependsOn['main'], isEmpty);
-  }
-
-  test_localFunction() {
-    ReferencedNames info = _computeReferencedNames('''
-f(A a) {
-  g(B b) {}
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A']));
-  }
-
-  test_superToSubs_importPrefix() {
-    ReferencedNames info = _computeReferencedNames('''
-import 'a.dart' as p1;
-import 'b.dart' as p2;
-class U extends p1.A with p2.B implements p2.C {}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs['A'], unorderedEquals(['U']));
-    expect(info.superToSubs['B'], unorderedEquals(['U']));
-    expect(info.superToSubs['C'], unorderedEquals(['U']));
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C']));
-  }
-
-  test_topLevelVariable() {
-    ReferencedNames info = _computeReferencedNames('''
-A v = new B(c);
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'c']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['B']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['v']));
-    expect(info.userToDependsOn['v'], unorderedEquals(['A', 'B', 'c']));
-  }
-
-  test_topLevelVariable_multiple() {
-    ReferencedNames info = _computeReferencedNames('''
-A v1 = new B(c), v2 = new D<E>(f);
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'c', 'D', 'E', 'f']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['B', 'D']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['v1', 'v2']));
-    expect(info.userToDependsOn['v1'], unorderedEquals(['A', 'B', 'c']));
-    expect(info.userToDependsOn['v2'], unorderedEquals(['A', 'D', 'E', 'f']));
-  }
-
-  test_unit_classTypeAlias() {
-    ReferencedNames info = _computeReferencedNames('''
-class U = A with B implements C;
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs['A'], unorderedEquals(['U']));
-    expect(info.superToSubs['B'], unorderedEquals(['U']));
-    expect(info.superToSubs['C'], unorderedEquals(['U']));
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C']));
-  }
-
-  test_unit_classTypeAlias_typeParameters() {
-    ReferencedNames info = _computeReferencedNames('''
-class U<T1, T2 extends D> = A<T1> with B<T2> implements C<T1, T2>;
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C', 'D']));
-    expect(info.superToSubs.keys, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs['A'], unorderedEquals(['U']));
-    expect(info.superToSubs['B'], unorderedEquals(['U']));
-    expect(info.superToSubs['C'], unorderedEquals(['U']));
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['U']));
-    expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B', 'C', 'D']));
-  }
-
-  test_unit_function() {
-    ReferencedNames info = _computeReferencedNames('''
-A f(B b) {
-  C c = 0;
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
-  }
-
-  test_unit_function_doc() {
-    ReferencedNames info = _computeReferencedNames('''
-/**
- * Documentation [C.d] reference.
- */
-A f(B b) {}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C', 'd']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
-  }
-
-  test_unit_function_localFunctions() {
-    ReferencedNames info = _computeReferencedNames('''
-A f() {
-  B b = null;
-  C g() {}
-  g();
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A']));
-  }
-
-  test_unit_function_localsDontHideQualified() {
-    ReferencedNames info = _computeReferencedNames('''
-f(A a, B b) {
-  var v = 0;
-  a.v;
-  a.b;
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'v', 'b']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
-  }
-
-  test_unit_function_localVariables() {
-    ReferencedNames info = _computeReferencedNames('''
-A f() {
-  B b = null;
-  b;
-  {
-    C c = null;
-    b;
-    c;
-  }
-  d;
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C', 'd']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A']));
-  }
-
-  test_unit_function_parameters() {
-    ReferencedNames info = _computeReferencedNames('''
-A f(B b) {
-  C c = 0;
-  b;
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
-  }
-
-  test_unit_function_typeParameters() {
-    ReferencedNames info = _computeReferencedNames('''
-A f<T>(B b, T t) {
-  C c = 0;
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['f']));
-    expect(info.userToDependsOn['f'], unorderedEquals(['A', 'B']));
-  }
-
-  test_unit_functionTypeAlias() {
-    ReferencedNames info = _computeReferencedNames('''
-typedef A F(B B, C c(D d));
-''');
-    expect(info.names, unorderedEquals(['A', 'B', 'C', 'D']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['F']));
-    expect(info.userToDependsOn['F'], unorderedEquals(['A', 'B', 'C', 'D']));
-  }
-
-  test_unit_functionTypeAlias_typeParameters() {
-    ReferencedNames info = _computeReferencedNames('''
-typedef A F<T>(B b, T t);
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['F']));
-    expect(info.userToDependsOn['F'], unorderedEquals(['A', 'B']));
-  }
-
-  test_unit_getter() {
-    ReferencedNames info = _computeReferencedNames('''
-A get aaa {
-  return new B();
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, unorderedEquals(['B']));
-    expect(info.userToDependsOn.keys, unorderedEquals(['aaa']));
-    expect(info.userToDependsOn['aaa'], unorderedEquals(['A']));
-  }
-
-  test_unit_setter() {
-    ReferencedNames info = _computeReferencedNames('''
-set aaa(A a) {
-  B b = null;
-}
-''');
-    expect(info.names, unorderedEquals(['A', 'B']));
-    expect(info.superToSubs.keys, isEmpty);
-    expect(info.instantiatedNames, isEmpty);
-    expect(info.userToDependsOn.keys, unorderedEquals(['aaa']));
-    expect(info.userToDependsOn['aaa'], unorderedEquals(['A']));
-  }
-
-  ReferencedNames _computeReferencedNames(String code) {
-    Source source = newSource('/test.dart', code);
-    computeResult(source, REFERENCED_NAMES, matcher: isParseDartTask);
-    return outputs[REFERENCED_NAMES];
-  }
-}
-
-@reflectiveTest
 class ResolveDirectiveElementsTaskTest extends _AbstractDartTaskTest {
   test_perform() {
     List<Source> sources = newSources({
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
deleted file mode 100644
index 05b0807..0000000
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ /dev/null
@@ -1,2369 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyzer.test.src.task.incremental_element_builder_test;
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/incremental_element_builder.dart';
-import 'package:analyzer/task/dart.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../context/abstract_context.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(IncrementalCompilationUnitElementBuilderTest);
-  });
-}
-
-@reflectiveTest
-class IncrementalCompilationUnitElementBuilderTest extends AbstractContextTest {
-  Source source;
-
-  String oldCode;
-  CompilationUnit oldUnit;
-  CompilationUnitElement unitElement;
-
-  String newCode;
-  CompilationUnit newUnit;
-
-  CompilationUnitElementDelta unitDelta;
-
-  String getNodeText(AstNode node) {
-    return newCode.substring(node.offset, node.end);
-  }
-
-  test_classDelta_annotation_add() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {}
-''');
-    helper.initOld(oldUnit);
-    expect(helper.element.metadata, isEmpty);
-    _buildNewUnit(r'''
-@deprecated
-class A {}
-''');
-    helper.initNew(newUnit, unitDelta);
-    expect(helper.delta.hasAnnotationChanges, isTrue);
-    expect(helper.element.metadata, hasLength(1));
-  }
-
-  test_classDelta_annotation_remove() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-@deprecated
-class A {}
-''');
-    helper.initOld(oldUnit);
-    expect(helper.element.metadata, hasLength(1));
-    _buildNewUnit(r'''
-class A {}
-''');
-    helper.initNew(newUnit, unitDelta);
-    expect(helper.delta.hasAnnotationChanges, isTrue);
-    expect(helper.element.metadata, isEmpty);
-  }
-
-  test_classDelta_constructor_0to1() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-}
-''');
-    helper.initOld(oldUnit);
-    ConstructorElement oldConstructorElement =
-        helper.element.unnamedConstructor;
-    _buildNewUnit(r'''
-class A {
-  A.a();
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember newConstructorNode = helper.newMembers[0];
-    // elements
-    ConstructorElement newConstructorElement = newConstructorNode.element;
-    expect(newConstructorElement, isNotNull);
-    expect(newConstructorElement.name, 'a');
-    // classElement.constructors
-    ClassElement classElement = helper.element;
-    expect(classElement.constructors, [newConstructorElement]);
-    // verify delta
-    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
-    expect(helper.delta.addedConstructors,
-        unorderedEquals([newConstructorElement]));
-    expect(helper.delta.removedConstructors,
-        unorderedEquals([oldConstructorElement]));
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_1to0() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  A.a();
-}
-''');
-    helper.initOld(oldUnit);
-    ConstructorElement oldElementA = helper.element.getNamedConstructor('a');
-    _buildNewUnit(r'''
-class A {
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // classElement.constructors
-    ClassElement classElement = helper.element;
-    {
-      List<ConstructorElement> constructors = classElement.constructors;
-      expect(constructors, hasLength(1));
-      expect(constructors[0].isDefaultConstructor, isTrue);
-      expect(constructors[0].isSynthetic, isTrue);
-    }
-    // verify delta
-    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
-    expect(helper.delta.addedConstructors,
-        unorderedEquals([classElement.unnamedConstructor]));
-    expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_1to1_unnamed_addParameter() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  A();
-}
-''');
-    helper.initOld(oldUnit);
-    ConstructorElement oldConstructor = helper.element.unnamedConstructor;
-    _buildNewUnit(r'''
-class A {
-  A(int p);
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    ClassElement classElement = helper.element;
-    ConstructorElement newConstructor = classElement.unnamedConstructor;
-    expect(classElement.constructors, [newConstructor]);
-    // verify delta
-    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
-    expect(helper.delta.addedConstructors, unorderedEquals([newConstructor]));
-    expect(helper.delta.removedConstructors, unorderedEquals([oldConstructor]));
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_1to1_unnamed_removeParameter() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  final int a;
-  final int b;
-  A(this.a, this.b);
-}
-''');
-    helper.initOld(oldUnit);
-    ConstructorElement oldConstructor = helper.element.unnamedConstructor;
-    _buildNewUnit(r'''
-class A {
-  final int a;
-  final int b;
-  A(this.a);
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    ClassElement classElement = helper.element;
-    ConstructorElement newConstructor = classElement.unnamedConstructor;
-    expect(classElement.constructors, [newConstructor]);
-    // verify delta
-    expect(helper.delta.hasUnnamedConstructorChange, isTrue);
-    expect(helper.delta.addedConstructors, unorderedEquals([newConstructor]));
-    expect(helper.delta.removedConstructors, unorderedEquals([oldConstructor]));
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_1to2() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  A.a();
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  A.a();
-  A.b();
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember nodeA = helper.newMembers[0];
-    ClassMember nodeB = helper.newMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    ConstructorElement elementA = nodeA.element;
-    ConstructorElement elementB = nodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementB, isNotNull);
-    expect(elementA.name, 'a');
-    expect(elementB.name, 'b');
-    // classElement.constructors
-    ClassElement classElement = helper.element;
-    expect(classElement.constructors, [elementA, elementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, unorderedEquals([elementB]));
-    expect(helper.delta.removedConstructors, unorderedEquals([]));
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_2to1() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  A.a();
-  A.b();
-}
-''');
-    helper.initOld(oldUnit);
-    ConstructorElement oldElementA = helper.element.getNamedConstructor('a');
-    _buildNewUnit(r'''
-class A {
-  A.b();
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    expect(helper.delta.hasUnnamedConstructorChange, isFalse);
-    // nodes
-    ClassMember nodeB = helper.newMembers[0];
-    expect(nodeB, same(helper.oldMembers[1]));
-    // elements
-    ConstructorElement elementB = nodeB.element;
-    expect(elementB, isNotNull);
-    expect(elementB.name, 'b');
-    // classElement.constructors
-    ClassElement classElement = helper.element;
-    expect(classElement.constructors, [elementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, unorderedEquals([]));
-    expect(helper.delta.removedConstructors, unorderedEquals([oldElementA]));
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_2to2_reorder() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  A.a();
-  A.b();
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  A.b();
-  A.a();
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember nodeB = helper.newMembers[0];
-    ClassMember nodeA = helper.newMembers[1];
-    expect(nodeB, same(helper.oldMembers[1]));
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    ConstructorElement elementB = nodeB.element;
-    ConstructorElement elementA = nodeA.element;
-    expect(elementB, isNotNull);
-    expect(elementA, isNotNull);
-    expect(elementB.name, 'b');
-    expect(elementA.name, 'a');
-    // classElement.constructors
-    ClassElement classElement = helper.element;
-    expect(classElement.constructors, [elementB, elementA]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_constructor_fieldReference_initializer() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  final int f;
-  A() : f = 1 {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  final int f;
-  A() : f = 1;
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-  }
-
-  test_classDelta_constructor_fieldReference_parameter() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  final int f;
-  A(this.f) {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  final int f;
-  A(this.f);
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-  }
-
-  test_classDelta_constructor_fieldReference_parameter_default() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  final int f;
-  A([this.f = 1]) {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  final int f;
-  A([this.f = 1]);
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-  }
-
-  test_classDelta_duplicate_constructor() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  A() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  A() {}
-  A() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ConstructorDeclaration oldNode = helper.oldMembers[0];
-    ConstructorDeclaration newNode1 = helper.newMembers[0];
-    ConstructorDeclaration newNode2 = helper.newMembers[1];
-    // elements
-    ConstructorElement oldElement = oldNode.element;
-    ConstructorElement newElement1 = newNode1.element;
-    ConstructorElement newElement2 = newNode2.element;
-    expect(newElement1, same(oldElement));
-    expect(newElement2, isNot(same(oldElement)));
-    expect(oldElement.name, '');
-    expect(newElement1.name, '');
-    expect(newElement2.name, '');
-    // verify delta
-    expect(helper.delta.addedConstructors, unorderedEquals([newElement2]));
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_duplicate_method() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  m() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  m() {}
-  m() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    MethodDeclaration oldNode = helper.oldMembers[0];
-    MethodDeclaration newNode1 = helper.newMembers[0];
-    MethodDeclaration newNode2 = helper.newMembers[1];
-    // elements
-    MethodElement oldElement = oldNode.element;
-    MethodElement newElement1 = newNode1.element;
-    MethodElement newElement2 = newNode2.element;
-    expect(newElement1, same(oldElement));
-    expect(newElement2, isNot(same(oldElement)));
-    expect(oldElement.name, 'm');
-    expect(newElement1.name, 'm');
-    expect(newElement2.name, 'm');
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, unorderedEquals([newElement2]));
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_field_add() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  int aaa;
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  int aaa;
-  int bbb;
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    FieldDeclaration nodeA = helper.newMembers[0];
-    FieldDeclaration newNodeB = helper.newMembers[1];
-    List<VariableDeclaration> fieldsA = nodeA.fields.variables;
-    List<VariableDeclaration> newFieldsB = newNodeB.fields.variables;
-    expect(nodeA, same(helper.oldMembers[0]));
-    expect(newFieldsB, hasLength(1));
-    // elements
-    FieldElement fieldElementA = fieldsA[0].name.staticElement;
-    FieldElement newFieldElementB = newFieldsB[0].name.staticElement;
-    expect(newFieldElementB.name, 'bbb');
-    // members
-    ClassElement classElement = helper.element;
-    expect(classElement.fields, [fieldElementA, newFieldElementB]);
-    // verify delta
-    expect(helper.delta.hasAnnotationChanges, isFalse);
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors,
-        unorderedEquals([newFieldElementB.getter, newFieldElementB.setter]));
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_field_remove() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  int aaa;
-  int bbb;
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  int aaa;
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    FieldDeclaration nodeA = helper.newMembers[0];
-    FieldDeclaration oldNodeB = helper.oldMembers[1];
-    List<VariableDeclaration> oldFieldsB = oldNodeB.fields.variables;
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    FieldElement oldFieldElementB = oldFieldsB[0].name.staticElement;
-    expect(oldFieldElementB.name, 'bbb');
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors,
-        unorderedEquals([oldFieldElementB.getter, oldFieldElementB.setter]));
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_field_syntheticAndNot_renameNonSynthetic() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  int foo;
-  int get foo => 1;
-}
-''');
-    helper.initOld(oldUnit);
-    FieldDeclaration oldFieldDeclNode = helper.oldMembers[0];
-    VariableDeclaration oldFieldNode = oldFieldDeclNode.fields.variables.single;
-    FieldElement oldFieldElement = oldFieldNode.name.staticElement;
-    _buildNewUnit(r'''
-class A {
-  int _foo;
-  int get foo => 1;
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    FieldDeclaration newFieldDeclNode = helper.newMembers[0];
-    VariableDeclaration newFieldNode = newFieldDeclNode.fields.variables.single;
-    MethodDeclaration getterNode = helper.newMembers[1];
-    expect(getterNode, same(helper.oldMembers[1]));
-    // elements
-    FieldElement newFieldElement = newFieldNode.name.staticElement;
-    PropertyAccessorElement getterElement = getterNode.element;
-    expect(newFieldElement.name, '_foo');
-    expect(helper.element.fields,
-        [same(newFieldElement), same(getterElement.variable)]);
-    expect(helper.element.accessors, [
-      same(newFieldElement.getter),
-      same(newFieldElement.setter),
-      same(getterElement)
-    ]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors,
-        unorderedEquals([newFieldElement.getter, newFieldElement.setter]));
-    expect(helper.delta.removedAccessors,
-        [oldFieldElement.getter, oldFieldElement.setter]);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_getter_add() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  int get aaa => 1;
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  int get aaa => 1;
-  int get bbb => 2;
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    MethodDeclaration nodeA = helper.oldMembers[0];
-    MethodDeclaration newNodeB = helper.newMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    PropertyAccessorElement elementA = nodeA.element;
-    PropertyAccessorElement newElementB = newNodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementA.name, 'aaa');
-    expect(newElementB, isNotNull);
-    expect(newElementB.name, 'bbb');
-    expect(helper.element.accessors, [elementA, newElementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, unorderedEquals([newElementB]));
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_getter_remove() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  int get aaa => 1;
-  int get bbb => 2;
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  int get aaa => 1;
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    MethodDeclaration nodeA = helper.oldMembers[0];
-    MethodDeclaration oldNodeB = helper.oldMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    PropertyAccessorElement elementA = nodeA.element;
-    PropertyAccessorElement oldElementB = oldNodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementA.name, 'aaa');
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, unorderedEquals([oldElementB]));
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_method_add() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  aaa() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  aaa() {}
-  bbb() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember nodeA = helper.oldMembers[0];
-    ClassMember newNodeB = helper.newMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    MethodElement elementA = nodeA.element;
-    MethodElement newElementB = newNodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementA.name, 'aaa');
-    expect(newElementB, isNotNull);
-    expect(newElementB.name, 'bbb');
-    expect(helper.element.methods, [elementA, newElementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, unorderedEquals([newElementB]));
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_method_addParameter() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  aaa() {}
-  bbb() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  aaa(int p) {}
-  bbb() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember oldNodeA = helper.oldMembers[0];
-    ClassMember newNodeA = helper.newMembers[0];
-    ClassMember nodeB = helper.newMembers[1];
-    expect(newNodeA, isNot(same(oldNodeA)));
-    expect(nodeB, same(helper.oldMembers[1]));
-    // elements
-    MethodElement oldElementA = oldNodeA.element;
-    MethodElement newElementA = newNodeA.element;
-    MethodElement elementB = nodeB.element;
-    expect(newElementA, isNotNull);
-    expect(newElementA.name, 'aaa');
-    expect(oldElementA.parameters, hasLength(0));
-    expect(newElementA.parameters, hasLength(1));
-    expect(elementB, isNotNull);
-    expect(elementB.name, 'bbb');
-    expect(helper.element.methods, [newElementA, elementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
-    expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
-  }
-
-  test_classDelta_method_async_addStar() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  Stream test() async {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  Stream test() async* {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember oldNodeA = helper.oldMembers[0];
-    ClassMember newNodeA = helper.newMembers[0];
-    expect(newNodeA, isNot(same(oldNodeA)));
-    // elements
-    MethodElement oldElement = oldNodeA.element;
-    MethodElement newElement = newNodeA.element;
-    expect(newElement, isNotNull);
-    expect(newElement.name, 'test');
-    expect(oldElement.isAsynchronous, isTrue);
-    expect(oldElement.isGenerator, isFalse);
-    expect(newElement.isAsynchronous, isTrue);
-    expect(newElement.isGenerator, isTrue);
-    expect(helper.element.methods, [newElement]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, unorderedEquals([newElement]));
-    expect(helper.delta.removedMethods, unorderedEquals([oldElement]));
-  }
-
-  test_classDelta_method_changeName() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  aaa(int ap) {
-    int av = 1;
-    af(afp) {}
-  }
-  bbb(int bp) {
-    int bv = 1;
-    bf(bfp) {}
-  }
-}
-''');
-    helper.initOld(oldUnit);
-    ConstructorElement oldConstructor = helper.element.unnamedConstructor;
-    _buildNewUnit(r'''
-class A {
-  aaa2(int ap) {
-    int av = 1;
-    af(afp) {}
-  }
-  bbb(int bp) {
-    int bv = 1;
-    bf(bfp) {}
-  }
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    expect(helper.element.unnamedConstructor, same(oldConstructor));
-    // nodes
-    ClassMember oldNodeA = helper.oldMembers[0];
-    ClassMember newNodeA = helper.newMembers[0];
-    ClassMember nodeB = helper.newMembers[1];
-    expect(nodeB, same(helper.oldMembers[1]));
-    // elements
-    MethodElement oldElementA = oldNodeA.element;
-    MethodElement newElementA = newNodeA.element;
-    MethodElement elementB = nodeB.element;
-    expect(newElementA, isNotNull);
-    expect(newElementA.name, 'aaa2');
-    expect(elementB, isNotNull);
-    expect(elementB.name, 'bbb');
-    expect(helper.element.methods, [newElementA, elementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
-    expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
-  }
-
-  test_classDelta_method_remove() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  aaa() {}
-  bbb() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  aaa() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember nodeA = helper.oldMembers[0];
-    ClassMember oldNodeB = helper.oldMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    MethodElement elementA = nodeA.element;
-    MethodElement oldElementB = oldNodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementA.name, 'aaa');
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, unorderedEquals([oldElementB]));
-  }
-
-  test_classDelta_method_removeParameter() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  aaa(int p) {}
-  bbb() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  aaa() {}
-  bbb() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember oldNodeA = helper.oldMembers[0];
-    ClassMember newNodeA = helper.newMembers[0];
-    ClassMember nodeB = helper.newMembers[1];
-    expect(newNodeA, isNot(same(oldNodeA)));
-    expect(nodeB, same(helper.oldMembers[1]));
-    // elements
-    MethodElement oldElementA = oldNodeA.element;
-    MethodElement newElementA = newNodeA.element;
-    MethodElement elementB = nodeB.element;
-    expect(newElementA, isNotNull);
-    expect(newElementA.name, 'aaa');
-    expect(oldElementA.parameters, hasLength(1));
-    expect(newElementA.parameters, hasLength(0));
-    expect(elementB, isNotNull);
-    expect(elementB.name, 'bbb');
-    expect(helper.element.methods, [newElementA, elementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, unorderedEquals([newElementA]));
-    expect(helper.delta.removedMethods, unorderedEquals([oldElementA]));
-  }
-
-  test_classDelta_newOrder() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  bbb() {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  aaa() {}
-  bbb() {}
-  ccc() {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    ClassMember newNodeA = helper.newMembers[0];
-    ClassMember nodeB = helper.oldMembers[0];
-    ClassMember newNodeC = helper.newMembers[2];
-    expect(nodeB, same(helper.oldMembers[0]));
-    // elements
-    MethodElement newElementA = newNodeA.element;
-    MethodElement elementB = nodeB.element;
-    MethodElement newElementC = newNodeC.element;
-    expect(newElementA, isNotNull);
-    expect(newElementA.name, 'aaa');
-    expect(elementB, isNotNull);
-    expect(elementB.name, 'bbb');
-    expect(newElementC, isNotNull);
-    expect(newElementC.name, 'ccc');
-    expect(helper.element.methods, [newElementA, elementB, newElementC]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(
-        helper.delta.addedMethods, unorderedEquals([newElementA, newElementC]));
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_null_abstractKeyword_add() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-''',
-        r'''
-abstract class A {}
-''');
-  }
-
-  test_classDelta_null_abstractKeyword_remove() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-abstract class A {}
-''',
-        r'''
-class A {}
-''');
-  }
-
-  test_classDelta_null_extendsClause_add() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class B {}
-''',
-        r'''
-class A {}
-class B extends A {}
-''');
-  }
-
-  test_classDelta_null_extendsClause_change() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A1 {}
-class A2 {}
-class B extends A1 {}
-''',
-        r'''
-class A1 {}
-class A2 {}
-class B extends A2 {}
-''');
-  }
-
-  test_classDelta_null_extendsClause_remove() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class B extends A {}
-''',
-        r'''
-class A {}
-class B {}
-''');
-  }
-
-  test_classDelta_null_implementsClause_add() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class B {}
-''',
-        r'''
-class A {}
-class B implements A {}
-''');
-  }
-
-  test_classDelta_null_implementsClause_change() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A1 {}
-class A2 {}
-class B implements A1 {}
-''',
-        r'''
-class A1 {}
-class A2 {}
-class B implements A2 {}
-''');
-  }
-
-  test_classDelta_null_implementsClause_remove() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class B implements A {}
-''',
-        r'''
-class A {}
-class B {}
-''');
-  }
-
-  test_classDelta_null_typeParameters_change() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class B<T> {}
-''',
-        r'''
-class A {}
-class B<T extends A> {}
-''');
-  }
-
-  test_classDelta_null_withClause_add() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class M {}
-class B extends A {}
-''',
-        r'''
-class A {}
-class M {}
-class B extends A with M {}
-''');
-  }
-
-  test_classDelta_null_withClause_change1() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class M1 {}
-class M2 {}
-class B extends A with M1 {}
-''',
-        r'''
-class A {}
-class M1 {}
-class M2 {}
-class B extends A with M2 {}
-''');
-  }
-
-  test_classDelta_null_withClause_change2() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class M1 {}
-class M2 {}
-class B extends A with M1, M2 {}
-''',
-        r'''
-class A {}
-class M1 {}
-class M2 {}
-class B extends A with M2, M1 {}
-''');
-  }
-
-  test_classDelta_null_withClause_remove() {
-    _verifyNoClassDeltaForTheLast(
-        r'''
-class A {}
-class M {}
-class B extends A with M {}
-''',
-        r'''
-class A {}
-class M {}
-class B extends A {}
-''');
-  }
-
-  test_classDelta_setter_add() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  void set aaa(int pa) {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  void set aaa(int pa) {}
-  void set bbb(int pb) {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    MethodDeclaration nodeA = helper.oldMembers[0];
-    MethodDeclaration newNodeB = helper.newMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    PropertyAccessorElement elementA = nodeA.element;
-    PropertyAccessorElement newElementB = newNodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementA.name, 'aaa=');
-    expect(newElementB, isNotNull);
-    expect(newElementB.name, 'bbb=');
-    expect(helper.element.accessors, [elementA, newElementB]);
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, unorderedEquals([newElementB]));
-    expect(helper.delta.removedAccessors, isEmpty);
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_setter_remove() {
-    var helper = new _ClassDeltaHelper('A');
-    _buildOldUnit(r'''
-class A {
-  void set aaa(int pa) {}
-  void set bbb(int pb) {}
-}
-''');
-    helper.initOld(oldUnit);
-    _buildNewUnit(r'''
-class A {
-  void set aaa(int pa) {}
-}
-''');
-    helper.initNew(newUnit, unitDelta);
-    // nodes
-    MethodDeclaration nodeA = helper.oldMembers[0];
-    MethodDeclaration oldNodeB = helper.oldMembers[1];
-    expect(nodeA, same(helper.oldMembers[0]));
-    // elements
-    PropertyAccessorElement elementA = nodeA.element;
-    PropertyAccessorElement oldElementB = oldNodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementA.name, 'aaa=');
-    // verify delta
-    expect(helper.delta.addedConstructors, isEmpty);
-    expect(helper.delta.removedConstructors, isEmpty);
-    expect(helper.delta.addedAccessors, isEmpty);
-    expect(helper.delta.removedAccessors, unorderedEquals([oldElementB]));
-    expect(helper.delta.addedMethods, isEmpty);
-    expect(helper.delta.removedMethods, isEmpty);
-  }
-
-  test_classDelta_typeParameter_same() {
-    _buildOldUnit(r'''
-class A<T> {
-  m() {}
-}
-''');
-    _buildNewUnit(r'''
-class A<T> {
-  m2() {}
-}
-''');
-  }
-
-  test_directives_add() {
-    _buildOldUnit(r'''
-library test;
-import 'dart:math';
-''');
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    _buildNewUnit(r'''
-library test;
-import 'dart:async';
-import 'dart:math';
-''');
-    List<Directive> newDirectives = newUnit.directives;
-    {
-      Directive newNode = newDirectives[0];
-      expect(newNode, same(oldDirectives[0]));
-      expect(getNodeText(newNode), "library test;");
-      LibraryElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf('test;'));
-    }
-    {
-      Directive newNode = newDirectives[1];
-      expect(getNodeText(newNode), "import 'dart:async';");
-      ImportElement element = newNode.element;
-      expect(element, isNull);
-    }
-    {
-      Directive newNode = newDirectives[2];
-      expect(newNode, same(oldDirectives[1]));
-      expect(getNodeText(newNode), "import 'dart:math';");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:math';"));
-    }
-    expect(unitDelta.hasDirectiveChange, isTrue);
-  }
-
-  test_directives_keepOffset_partOf() {
-    String libCode = '''
-// comment to shift tokens
-library my_lib;
-part 'test.dart';
-''';
-    Source libSource = newSource('/lib.dart', libCode);
-    _buildOldUnit(
-        r'''
-part of my_lib;
-class A {}
-''',
-        libSource);
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    _buildNewUnit(r'''
-part of my_lib;
-class A {}
-''');
-    List<Directive> newDirectives = newUnit.directives;
-    {
-      Directive newNode = newDirectives[0];
-      expect(newNode, same(oldDirectives[0]));
-      expect(getNodeText(newNode), 'part of my_lib;');
-      LibraryElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, libCode.indexOf('my_lib;'));
-    }
-  }
-
-  test_directives_library_updateOffset() {
-    _buildOldUnit(r'''
-#!/bin/sh
-library my_lib;
-class A {}
-''');
-    LibraryDirective libraryDirective = oldUnit.directives.single;
-    // Set the LibraryElement and check that its nameOffset is correct.
-    libraryDirective.element =
-        new LibraryElementImpl.forNode(context, libraryDirective.name);
-    expect(
-        resolutionMap.elementDeclaredByDirective(libraryDirective).nameOffset,
-        libraryDirective.name.offset);
-    // Update and check again that the nameOffset is correct.
-    _buildNewUnit(r'''
-#!/bin/sh
-
-library my_lib;
-class A {}
-''');
-    expect(
-        resolutionMap.elementDeclaredByDirective(libraryDirective).nameOffset,
-        libraryDirective.name.offset);
-  }
-
-  test_directives_remove() {
-    _buildOldUnit(r'''
-library test;
-import 'dart:async';
-import 'dart:math';
-''');
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    _buildNewUnit(r'''
-library test;
-import 'dart:math';
-''');
-    List<Directive> newDirectives = newUnit.directives;
-    {
-      Directive newNode = newDirectives[0];
-      expect(newNode, same(oldDirectives[0]));
-      expect(getNodeText(newNode), "library test;");
-      LibraryElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf('test;'));
-    }
-    {
-      Directive newNode = newDirectives[1];
-      expect(newNode, same(oldDirectives[2]));
-      expect(getNodeText(newNode), "import 'dart:math';");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:math';"));
-    }
-    expect(unitDelta.hasDirectiveChange, isTrue);
-  }
-
-  test_directives_reorder() {
-    _buildOldUnit(r'''
-library test;
-import  'dart:math' as m;
-import 'dart:async';
-''');
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    _buildNewUnit(r'''
-library test;
-import 'dart:async';
-import 'dart:math' as m;
-''');
-    List<Directive> newDirectives = newUnit.directives;
-    {
-      Directive newNode = newDirectives[0];
-      expect(newNode, same(oldDirectives[0]));
-      expect(getNodeText(newNode), "library test;");
-      LibraryElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf('test;'));
-    }
-    {
-      Directive newNode = newDirectives[1];
-      expect(newNode, same(oldDirectives[2]));
-      expect(getNodeText(newNode), "import 'dart:async';");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:async';"));
-    }
-    {
-      Directive newNode = newDirectives[2];
-      expect(newNode, same(oldDirectives[1]));
-      expect(getNodeText(newNode), "import 'dart:math' as m;");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:math' as m;"));
-      expect(element.prefix.nameOffset, newCode.indexOf("m;"));
-    }
-    expect(unitDelta.hasDirectiveChange, isFalse);
-  }
-
-  test_directives_sameImportPrefix_sameOrder() {
-    _buildOldUnit(r'''
-import 'test1.dart' as m;
-import 'test2.dart' as m;
-''');
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    ImportDirective import1 = oldDirectives[0];
-    ImportDirective import2 = oldDirectives[1];
-    ImportElementImpl importElement1 = new ImportElementImpl(import1.offset);
-    ImportElementImpl importElement2 = new ImportElementImpl(import2.offset);
-    PrefixElement prefixElement = new PrefixElementImpl.forNode(import1.prefix);
-    importElement1.prefix = prefixElement;
-    importElement2.prefix = prefixElement;
-    import1.element = importElement1;
-    import2.element = importElement2;
-    import1.prefix.staticElement = prefixElement;
-    import2.prefix.staticElement = prefixElement;
-    _buildNewUnit(r'''
-import 'test1.dart' as m;
-import 'test2.dart' as m;
-class A {}
-''');
-    int expectedPrefixOffset = 23;
-    expect(resolutionMap.staticElementForIdentifier(import1.prefix).nameOffset,
-        expectedPrefixOffset);
-    expect(resolutionMap.staticElementForIdentifier(import2.prefix).nameOffset,
-        expectedPrefixOffset);
-    expect(importElement1.prefix.nameOffset, expectedPrefixOffset);
-    expect(importElement2.prefix.nameOffset, expectedPrefixOffset);
-  }
-
-  test_directives_sameOrder_insertSpaces() {
-    _buildOldUnit(r'''
-library test;
-import 'dart:async';
-import 'dart:math';
-''');
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    _buildNewUnit(r'''
-library test;
-
-import 'dart:async' ;
-import  'dart:math';
-''');
-    List<Directive> newDirectives = newUnit.directives;
-    {
-      Directive newNode = newDirectives[0];
-      expect(newNode, same(oldDirectives[0]));
-      expect(getNodeText(newNode), "library test;");
-      LibraryElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf('test;'));
-    }
-    {
-      Directive newNode = newDirectives[1];
-      expect(newNode, same(oldDirectives[1]));
-      expect(getNodeText(newNode), "import 'dart:async' ;");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:async' ;"));
-    }
-    {
-      Directive newNode = newDirectives[2];
-      expect(newNode, same(oldDirectives[2]));
-      expect(getNodeText(newNode), "import  'dart:math';");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import  'dart:math';"));
-    }
-    expect(unitDelta.hasDirectiveChange, isFalse);
-  }
-
-  test_directives_sameOrder_removeSpaces() {
-    _buildOldUnit(r'''
-library test;
-
-import 'dart:async' ;
-import  'dart:math';
-''');
-    List<Directive> oldDirectives = oldUnit.directives.toList();
-    _buildNewUnit(r'''
-library test;
-import 'dart:async';
-import 'dart:math';
-''');
-    List<Directive> newDirectives = newUnit.directives;
-    {
-      Directive newNode = newDirectives[0];
-      expect(newNode, same(oldDirectives[0]));
-      expect(getNodeText(newNode), "library test;");
-      LibraryElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf('test;'));
-    }
-    {
-      Directive newNode = newDirectives[1];
-      expect(newNode, same(oldDirectives[1]));
-      expect(getNodeText(newNode), "import 'dart:async';");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:async';"));
-    }
-    {
-      Directive newNode = newDirectives[2];
-      expect(newNode, same(oldDirectives[2]));
-      expect(getNodeText(newNode), "import 'dart:math';");
-      ImportElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nameOffset, newCode.indexOf("import 'dart:math';"));
-    }
-    expect(unitDelta.hasDirectiveChange, isFalse);
-  }
-
-  test_unitMembers_accessor_add() {
-    _buildOldUnit(r'''
-get a => 1;
-''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
-    _buildNewUnit(r'''
-get a => 1;
-get b => 2;
-''');
-    List<CompilationUnitMember> newNodes = newUnit.declarations;
-    // nodes
-    FunctionDeclaration node1 = newNodes[0];
-    FunctionDeclaration node2 = newNodes[1];
-    expect(node1, same(oldNodes[0]));
-    // elements
-    PropertyAccessorElement elementA = node1.element;
-    PropertyAccessorElement elementB = node2.element;
-    expect(elementA, isNotNull);
-    expect(elementB, isNotNull);
-    expect(elementA.name, 'a');
-    expect(elementB.name, 'b');
-    // unit.types
-    expect(
-        unitElement.topLevelVariables, [elementA.variable, elementB.variable]);
-    expect(unitElement.accessors, [elementA, elementB]);
-  }
-
-  test_unitMembers_class_add() {
-    _buildOldUnit(r'''
-class A {}
-''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
-    _buildNewUnit(r'''
-class A {}
-class B {}
-''');
-    List<CompilationUnitMember> newNodes = newUnit.declarations;
-    // nodes
-    CompilationUnitMember nodeA = newNodes[0];
-    CompilationUnitMember nodeB = newNodes[1];
-    expect(nodeA, same(oldNodes[0]));
-    // elements
-    ClassElement elementA = nodeA.element;
-    ClassElement elementB = nodeB.element;
-    expect(elementA, isNotNull);
-    expect(elementB, isNotNull);
-    expect(elementA.name, 'A');
-    expect(elementB.name, 'B');
-    // unit.types
-    expect(unitElement.types, [elementA, elementB]);
-    // verify delta
-    expect(unitDelta.addedDeclarations, unorderedEquals([elementB]));
-    expect(unitDelta.removedDeclarations, unorderedEquals([]));
-  }
-
-  test_unitMembers_class_comments() {
-    _buildOldUnit(r'''
-/// reference [bool] type.
-class A {}
-/// reference [int] type.
-class B {}
-/// reference [double] and [B] types.
-class C {}
-''');
-    List<CompilationUnitMember> oldNodes = oldUnit.declarations.toList();
-    _buildNewUnit(r'''
-/// reference [double] and [B] types.
-class C {}
-/// reference [bool] type.
-class A {}
-/// reference [int] type.
-class B {}
-''');
-    List<CompilationUnitMember> newNodes = newUnit.declarations;
-    {
-      CompilationUnitMember newNode = newNodes[0];
-      expect(newNode, same(oldNodes[2]));
-      expect(
-          getNodeText(newNode),
-          r'''
-/// reference [double] and [B] types.
-class C {}''');
-      ClassElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.name, 'C');
-      expect(element.nameOffset, newCode.indexOf('C {}'));
-      // [double] and [B] are still resolved
-      {
-        var docReferences = newNode.documentationComment.references;
-        expect(docReferences, hasLength(2));
-        expect(
-            resolutionMap
-                .staticElementForIdentifier(docReferences[0].identifier)
-                .name,
-            'double');
-        expect(docReferences[1].identifier.staticElement,
-            same(newNodes[2].element));
-      }
-    }
-    {
-      CompilationUnitMember newNode = newNodes[1];
-      expect(newNode, same(oldNodes[0]));
-      expect(
-          getNodeText(newNode),
-          r'''
-/// reference [bool] type.
-class A {}''');
-      ClassElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.name, 'A');
-      expect(element.nameOffset, newCode.indexOf('A {}'));
-      // [bool] is still resolved
-      {
-        var docReferences = newNode.documentationComment.references;
-        expect(docReferences, hasLength(1));
-        expect(
-            resolutionMap
-                .staticElementForIdentifier(docReferences[0].identifier)
-                .name,
-            'bool');
-      }
-    }
-    {
-      CompilationUnitMember newNode = newNodes[2];
-      expect(newNode, same(oldNodes[1]));
-      expect(
-          getNodeText(newNode),
-          r'''
-/// reference [int] type.
-class B {}''');
-      ClassElement element = newNode.element;
-      expect(element, isNotNull);
-      expect(element.nam