Version 1.15.0-dev.4.0

Merge commit '78b0f6f353b5349a50c3e38ef5f44ded1f7e1ee4' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55db4b3..a4cf5bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,10 @@
     The method now only supports one argument for the PEM file name containing
     the trusted certificates.
   * Added support to SecurityContext for PKCS12 certificate and key containers.
+  * All calls in `SecurityContext` that accept certificate data now accept an
+    optional named parameter `password`, similar to
+    `SecurityContext.usePrivateKeyBytes`, for use as the password for PKCS12
+    data.
 * `dart:async`
   * Made `StreamView` class a `const` class.
 
diff --git a/DEPS b/DEPS
index 702e439..274afa0 100644
--- a/DEPS
+++ b/DEPS
@@ -38,7 +38,7 @@
   "crypto_rev" : "@2df57a1e26dd88e8d0614207d4b062c73209917d",
   "csslib_tag" : "@0.12.0",
   "dart2js_info_rev" : "@0a221eaf16aec3879c45719de656680ccb80d8a1",
-  "dartdoc_tag" : "@v0.8.5",
+  "dartdoc_tag" : "@v0.9.0",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
   "dev_compiler_rev": "@0.1.9",
@@ -52,7 +52,7 @@
   "intl_rev": "@a8b480b9c436f6c0ec16730804c914bdb4e30d53",
   "jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "@1.1.1",
-  "linter_rev": "@87f066f9243b36540c33186e742a798b87e76f8e",
+  "linter_rev": "@ce7aa0ec03ee738f4d314138228e0b4742845810",
   "logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
   "markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
   "matcher_tag": "@0.12.0",
@@ -71,6 +71,7 @@
   "pub_cache_tag": "@v0.1.0",
   "pub_semver_tag": "@1.2.1",
   "quiver_tag": "@0.21.4",
+  "resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
   "root_certificates_rev": "@c3a41df63afacec62fcb8135196177e35fe72f71",
   "scheduled_test_tag": "@0.12.4+2",
   "shelf_tag": "@0.6.4+3",
@@ -224,6 +225,8 @@
       Var("chromium_git")
       + "/external/github.com/google/quiver-dart.git"
       + Var("quiver_tag"),
+  Var("dart_root") + "/third_party/pkg/resource":
+    "https://github.com/dart-lang/resource.git" + Var("resource_rev"),
   Var("dart_root") + "/third_party/pkg/scheduled_test":
       (Var("github_mirror") % "scheduled_test") + Var("scheduled_test_tag"),
   Var("dart_root") + "/third_party/pkg/shelf":
diff --git a/create_sdk.gyp b/create_sdk.gyp
index 749cda5..b13adda 100644
--- a/create_sdk.gyp
+++ b/create_sdk.gyp
@@ -41,6 +41,8 @@
             '<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/analysis_server.dart.snapshot',
             '<(SHARED_INTERMEDIATE_DIR)/dartdoc.dart.snapshot',
+            '<(SHARED_INTERMEDIATE_DIR)/spec.sum',
+            '<(SHARED_INTERMEDIATE_DIR)/strong.sum',
             'tools/VERSION'
           ],
           'outputs': [
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index f2c4df2..fd1e1ef 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -757,17 +757,28 @@
           </dd><dt class="field"><b><i>packageRoots ( <span style="color:#999999">optional</span> Map&lt;<a href="#type_FilePath">FilePath</a>, <a href="#type_FilePath">FilePath</a>&gt; )</i></b></dt><dd>
             
             <p>
-              A mapping from source directories to target directories
+              A mapping from source directories to package roots
               that should override the normal package: URI resolution
-              mechanism.  The analyzer will behave as though each
+              mechanism.
+            </p>
+            <p>
+              If a package root is a directory, then
+              the analyzer will behave as though the associated
               source directory in the map contains a special
               pubspec.yaml file which resolves any package: URI to the
-              corresponding path within the target directory.  The
-              effect is the same as specifying the target directory as
+              corresponding path within that package root directory.  The
+              effect is the same as specifying the package root directory as
               a "--package_root" parameter to the Dart VM when
               executing any Dart file inside the source directory.
             </p>
             <p>
+              If a package root is a file, then the analyzer
+              will behave as though that file is a ".packages" file in the
+              source directory. The effect is the same as specifying the file
+              as a "--packages" parameter to the Dart VM when
+              executing any Dart file inside the source directory.
+            </p>
+            <p>
               Files in any directories that are not overridden by this
               mapping have their package: URI's resolved using the
               normal pubspec.yaml mechanism.  If this field is absent,
diff --git a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
index d90344f..eab48cd 100644
--- a/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/generated_protocol.dart
@@ -1663,12 +1663,19 @@
   }
 
   /**
-   * A mapping from source directories to target directories that should
-   * override the normal package: URI resolution mechanism. The analyzer will
-   * behave as though each source directory in the map contains a special
-   * pubspec.yaml file which resolves any package: URI to the corresponding
-   * path within the target directory. The effect is the same as specifying the
-   * target directory as a "--package_root" parameter to the Dart VM when
+   * A mapping from source directories to package roots that should override
+   * the normal package: URI resolution mechanism.
+   *
+   * If a package root is a directory, then the analyzer will behave as though
+   * the associated source directory in the map contains a special pubspec.yaml
+   * file which resolves any package: URI to the corresponding path within that
+   * package root directory. The effect is the same as specifying the package
+   * root directory as a "--package_root" parameter to the Dart VM when
+   * executing any Dart file inside the source directory.
+   *
+   * If a package root is a file, then the analyzer will behave as though that
+   * file is a ".packages" file in the source directory. The effect is the same
+   * as specifying the file as a "--packages" parameter to the Dart VM when
    * executing any Dart file inside the source directory.
    *
    * Files in any directories that are not overridden by this mapping have
@@ -1679,12 +1686,19 @@
   Map<String, String> get packageRoots => _packageRoots;
 
   /**
-   * A mapping from source directories to target directories that should
-   * override the normal package: URI resolution mechanism. The analyzer will
-   * behave as though each source directory in the map contains a special
-   * pubspec.yaml file which resolves any package: URI to the corresponding
-   * path within the target directory. The effect is the same as specifying the
-   * target directory as a "--package_root" parameter to the Dart VM when
+   * A mapping from source directories to package roots that should override
+   * the normal package: URI resolution mechanism.
+   *
+   * If a package root is a directory, then the analyzer will behave as though
+   * the associated source directory in the map contains a special pubspec.yaml
+   * file which resolves any package: URI to the corresponding path within that
+   * package root directory. The effect is the same as specifying the package
+   * root directory as a "--package_root" parameter to the Dart VM when
+   * executing any Dart file inside the source directory.
+   *
+   * If a package root is a file, then the analyzer will behave as though that
+   * file is a ".packages" file in the source directory. The effect is the same
+   * as specifying the file as a "--packages" parameter to the Dart VM when
    * executing any Dart file inside the source directory.
    *
    * Files in any directories that are not overridden by this mapping have
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 992cf55..8575086 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -960,10 +960,10 @@
     if (packageRoot != null) {
       // TODO(paulberry): We shouldn't be using JavaFile here because it
       // makes the code untestable (see dartbug.com/23909).
-      JavaFile packagesDir = new JavaFile(packageRoot);
+      JavaFile packagesDirOrFile = new JavaFile(packageRoot);
       Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>();
-      if (packagesDir.isDirectory()) {
-        for (JavaFile file in packagesDir.listFiles()) {
+      if (packagesDirOrFile.isDirectory()) {
+        for (JavaFile file in packagesDirOrFile.listFiles()) {
           // Ensure symlinks in packages directory are canonicalized
           // to prevent 'type X cannot be assigned to type X' warnings
           String path;
@@ -980,6 +980,12 @@
           }
         }
         return new PackageMapDisposition(packageMap, packageRoot: packageRoot);
+      } else if (packagesDirOrFile.isFile()) {
+        File packageSpecFile = resourceProvider.getFile(packageRoot);
+        Packages packages = _readPackagespec(packageSpecFile);
+        if (packages != null) {
+          return new PackagesFileDisposition(packages);
+        }
       }
       // The package root does not exist (or is not a folder).  Since
       // [setRoots] ignores any package roots that don't exist (or aren't
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 36eb5b9..01ddada 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1239,6 +1239,7 @@
       isFirst = false;
     }
     // merge getter/setter pairs into fields
+    String prefix = utils.getIndent(1);
     for (int i = 0; i < elements.length; i++) {
       ExecutableElement element = elements[i];
       if (element.kind == ElementKind.GETTER && i + 1 < elements.length) {
@@ -1249,9 +1250,16 @@
           elements.removeAt(i);
           i--;
           numElements--;
-          // add field
+          // separator
           addEolIfNotFirst();
-          sb.append(utils.getIndent(1));
+          // @override
+          {
+            sb.append(prefix);
+            sb.append('@override');
+            sb.append(eol);
+          }
+          // add field
+          sb.append(prefix);
           _appendType(sb, element.type.returnType, orVar: true);
           sb.append(element.name);
           sb.append(';');
diff --git a/pkg/analysis_server/lib/src/status/validator.dart b/pkg/analysis_server/lib/src/status/validator.dart
index 07f34b3..5651b8e 100644
--- a/pkg/analysis_server/lib/src/status/validator.dart
+++ b/pkg/analysis_server/lib/src/status/validator.dart
@@ -708,24 +708,6 @@
           (VariableElement element) =>
               element.isFinal ? 'a final $kind' : 'a non-final $kind');
     }
-    if (expected.isPotentiallyMutatedInClosure !=
-        actual.isPotentiallyMutatedInClosure) {
-      _writeMismatch(
-          expected,
-          actual,
-          (VariableElement element) => element.isPotentiallyMutatedInClosure
-              ? 'a $kind that is potentially mutated in a closure'
-              : 'a $kind that is not mutated in a closure');
-    }
-    if (expected.isPotentiallyMutatedInScope !=
-        actual.isPotentiallyMutatedInScope) {
-      _writeMismatch(
-          expected,
-          actual,
-          (VariableElement element) => element.isPotentiallyMutatedInScope
-              ? 'a $kind that is potentially mutated in its scope'
-              : 'a $kind that is not mutated in its scope');
-    }
     if (expected.isStatic != actual.isStatic) {
       _writeMismatch(
           expected,
diff --git a/pkg/analysis_server/test/integration/integration_test_methods.dart b/pkg/analysis_server/test/integration/integration_test_methods.dart
index af165f2..2508d56 100644
--- a/pkg/analysis_server/test/integration/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/integration_test_methods.dart
@@ -429,13 +429,20 @@
    *
    * packageRoots ( optional Map<FilePath, FilePath> )
    *
-   *   A mapping from source directories to target directories that should
-   *   override the normal package: URI resolution mechanism. The analyzer will
-   *   behave as though each source directory in the map contains a special
+   *   A mapping from source directories to package roots that should override
+   *   the normal package: URI resolution mechanism.
+   *
+   *   If a package root is a directory, then the analyzer will behave as
+   *   though the associated source directory in the map contains a special
    *   pubspec.yaml file which resolves any package: URI to the corresponding
-   *   path within the target directory. The effect is the same as specifying
-   *   the target directory as a "--package_root" parameter to the Dart VM when
-   *   executing any Dart file inside the source directory.
+   *   path within that package root directory. The effect is the same as
+   *   specifying the package root directory as a "--package_root" parameter to
+   *   the Dart VM when executing any Dart file inside the source directory.
+   *
+   *   If a package root is a file, then the analyzer will behave as though
+   *   that file is a ".packages" file in the source directory. The effect is
+   *   the same as specifying the file as a "--packages" parameter to the Dart
+   *   VM when executing any Dart file inside the source directory.
    *
    *   Files in any directories that are not overridden by this mapping have
    *   their package: URI's resolved using the normal pubspec.yaml mechanism.
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index dfb6a60..0d89134 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -2144,6 +2144,7 @@
 }
 
 class B implements A {
+  @override
   var f;
 }
 ''');
@@ -2336,8 +2337,10 @@
 }
 
 class B implements A {
+  @override
   int ma;
 
+  @override
   double mc;
 
   @override
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index e465571..8fb6d55 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -174,13 +174,17 @@
    * @param included A list of the files and directories that should be analyzed.
    * @param excluded A list of the files and directories within the included directories that should
    *         not be analyzed.
-   * @param packageRoots A mapping from source directories to target directories that should override
-   *         the normal package: URI resolution mechanism. The analyzer will behave as though each
-   *         source directory in the map contains a special pubspec.yaml file which resolves any
-   *         package: URI to the corresponding path within the target directory. The effect is the
-   *         same as specifying the target directory as a "--package_root" parameter to the Dart VM
-   *         when executing any Dart file inside the source directory. Files in any directories that
-   *         are not overridden by this mapping have their package: URI's resolved using the normal
+   * @param packageRoots A mapping from source directories to package roots that should override the
+   *         normal package: URI resolution mechanism. If a package root is a directory, then the
+   *         analyzer will behave as though the associated source directory in the map contains a
+   *         special pubspec.yaml file which resolves any package: URI to the corresponding path
+   *         within that package root directory. The effect is the same as specifying the package
+   *         root directory as a "--package_root" parameter to the Dart VM when executing any Dart
+   *         file inside the source directory. If a package root is a file, then the analyzer will
+   *         behave as though that file is a ".packages" file in the source directory. The effect is
+   *         the same as specifying the file as a "--packages" parameter to the Dart VM when
+   *         executing any Dart file inside the source directory. Files in any directories that are
+   *         not overridden by this mapping have their package: URI's resolved using the normal
    *         pubspec.yaml mechanism. If this field is absent, or the empty map is specified, that
    *         indicates that the normal pubspec.yaml mechanism should always be used.
    */
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index c26da51..fa4664f 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -615,17 +615,28 @@
               <value><ref>FilePath</ref></value>
             </map>
             <p>
-              A mapping from source directories to target directories
+              A mapping from source directories to package roots
               that should override the normal package: URI resolution
-              mechanism.  The analyzer will behave as though each
+              mechanism.
+            </p>
+            <p>
+              If a package root is a directory, then
+              the analyzer will behave as though the associated
               source directory in the map contains a special
               pubspec.yaml file which resolves any package: URI to the
-              corresponding path within the target directory.  The
-              effect is the same as specifying the target directory as
+              corresponding path within that package root directory.  The
+              effect is the same as specifying the package root directory as
               a "--package_root" parameter to the Dart VM when
               executing any Dart file inside the source directory.
             </p>
             <p>
+              If a package root is a file, then the analyzer
+              will behave as though that file is a ".packages" file in the
+              source directory. The effect is the same as specifying the file
+              as a "--packages" parameter to the Dart VM when
+              executing any Dart file inside the source directory.
+            </p>
+            <p>
               Files in any directories that are not overridden by this
               mapping have their package: URI's resolved using the
               normal pubspec.yaml mechanism.  If this field is absent,
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 598d611..547094b 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -536,7 +536,7 @@
    * (either AST nodes or tokens) that make up the contents of this node,
    * including doc comments but excluding other comments.
    */
-  Iterable /*<AstNode | Token>*/ get childEntities;
+  Iterable/*<AstNode | Token>*/ get childEntities;
 
   /**
    * Return the offset of the character immediately following the last character
@@ -591,7 +591,7 @@
    * Use the given [visitor] to visit this node. Return the value returned by
    * the visitor as a result of visiting this node.
    */
-  dynamic /* =E */ accept /*<E>*/ (AstVisitor /*<E>*/ visitor);
+  dynamic /* =E */ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
 
   /**
    * Return the most immediate ancestor of this node for which the [predicate]
@@ -3994,7 +3994,7 @@
  *
  * Clients may not extend, implement or mix-in this class.
  */
-abstract class FunctionExpressionInvocation extends Expression {
+abstract class FunctionExpressionInvocation extends InvocationExpression {
   /**
    * Initialize a newly created function expression invocation.
    */
@@ -4004,11 +4004,6 @@
       ArgumentList argumentList) = FunctionExpressionInvocationImpl;
 
   /**
-   * Return the list of arguments to the method.
-   */
-  ArgumentList get argumentList;
-
-  /**
    * Set the list of arguments to the method to the given [argumentList].
    */
   void set argumentList(ArgumentList argumentList);
@@ -4094,12 +4089,6 @@
   void set staticInvokeType(DartType type);
 
   /**
-   * Return the type arguments to be applied to the method being invoked, or
-   * `null` if no type arguments were provided.
-   */
-  TypeArgumentList get typeArguments;
-
-  /**
    * Set the type arguments to be applied to the method being invoked to the
    * given [typeArguments].
    */
@@ -4978,6 +4967,73 @@
 }
 
 /**
+ * The invocation of a function or method; either a
+ * [FunctionExpressionInvocation] or a [MethodInvocation].
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class InvocationExpression extends Expression {
+  /**
+   * Return the list of arguments to the method.
+   */
+  ArgumentList get argumentList;
+
+  /**
+   * The expression that identifies the function or method being invoked.
+   * For example:
+   *
+   *     (o.m)<TArgs>(args); // target will be `o.m`
+   *     o.m<TArgs>(args);   // target will be `m`
+   *
+   * In either case, the [function.staticType] will be the
+   * [staticInvokeType] before applying type arguments `TArgs`. Similarly,
+   * [function.propagatedType] will be the [propagatedInvokeType]
+   * before applying type arguments `TArgs`.
+   */
+  Expression get function;
+
+  /**
+   * Return the function type of the invocation based on the propagated type
+   * information, or `null` if the AST structure has not been resolved, or if
+   * the invoke could not be resolved.
+   *
+   * This will usually be a [FunctionType], but it can also be an
+   * [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
+   * interface type that implements `Function`.
+   */
+  DartType get propagatedInvokeType;
+
+  /**
+   * Sets the function type of the invocation based on the propagated type
+   * information.
+   */
+  void set propagatedInvokeType(DartType value);
+
+  /**
+   * Return the function type of the invocation based on the static type
+   * information, or `null` if the AST structure has not been resolved, or if
+   * the invoke could not be resolved.
+   *
+   * This will usually be a [FunctionType], but it can also be an
+   * [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
+   * interface type that implements `Function`.
+   */
+  DartType get staticInvokeType;
+
+  /**
+   * Sets the function type of the invocation based on the static type
+   * information.
+   */
+  void set staticInvokeType(DartType value);
+
+  /**
+   * Return the type arguments to be applied to the method being invoked, or
+   * `null` if no type arguments were provided.
+   */
+  TypeArgumentList get typeArguments;
+}
+
+/**
  * An is expression.
  *
  * > isExpression ::=
@@ -5519,7 +5575,7 @@
  *
  * Clients may not extend, implement or mix-in this class.
  */
-abstract class MethodInvocation extends Expression {
+abstract class MethodInvocation extends InvocationExpression {
   /**
    * Initialize a newly created method invocation. The [target] and [operator]
    * can be `null` if there is no target.
@@ -5532,11 +5588,6 @@
       ArgumentList argumentList) = MethodInvocationImpl;
 
   /**
-   * Return the list of arguments to the method.
-   */
-  ArgumentList get argumentList;
-
-  /**
    * Set the list of arguments to the method to the given [argumentList].
    */
   void set argumentList(ArgumentList argumentList);
@@ -5631,12 +5682,6 @@
   void set target(Expression expression);
 
   /**
-   * Return the type arguments to be applied to the method being invoked, or
-   * `null` if no type arguments were provided.
-   */
-  TypeArgumentList get typeArguments;
-
-  /**
    * Set the type arguments to be applied to the method being invoked to the
    * given [typeArguments].
    */
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 370f53e..d210229 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1911,7 +1911,12 @@
    * closure. This information is only available for local variables (including
    * parameters) and only after the compilation unit containing the variable has
    * been resolved.
+   *
+   * This getter is deprecated--it now returns `true` for all local variables
+   * and parameters.  Please use [FunctionBody.isPotentiallyMutatedInClosure]
+   * instead.
    */
+  @deprecated
   bool get isPotentiallyMutatedInClosure;
 
   /**
@@ -1919,7 +1924,12 @@
    * scope. This information is only available for local variables (including
    * parameters) and only after the compilation unit containing the variable has
    * been resolved.
+   *
+   * This getter is deprecated--it now returns `true` for all local variables
+   * and parameters.  Please use [FunctionBody.isPotentiallyMutatedInClosure]
+   * instead.
    */
+  @deprecated
   bool get isPotentiallyMutatedInScope;
 
   /**
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index afe0216..bbb0e69 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -7,6 +7,8 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analyzer/src/dart/element/element.dart'
+    show ElementImpl, Modifier;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -239,7 +241,11 @@
           AnalysisEngine.instance.logger
               .logInformation('Removed the cache entry for $target.');
         }
-        return partition.remove(target);
+        CacheEntry entry = partition.remove(target);
+        if (entry != null) {
+          entry.dispose();
+        }
+        return entry;
       }
     }
     return null;
@@ -307,7 +313,11 @@
   Map<ResultDescriptor, ResultData> _resultMap =
       new HashMap<ResultDescriptor, ResultData>();
 
-  CacheEntry(this.target);
+  CacheEntry(this.target) {
+    if (target is ElementImpl) {
+      (target as ElementImpl).setModifier(Modifier.CACHE_KEY, true);
+    }
+  }
 
   /**
    * The exception that caused one or more values to have a state of
@@ -350,6 +360,9 @@
       }
     });
     _resultMap.clear();
+    if (target is ElementImpl) {
+      (target as ElementImpl).setModifier(Modifier.CACHE_KEY, false);
+    }
   }
 
   /**
@@ -384,7 +397,7 @@
    * Return the value of the result represented by the given [descriptor], or
    * the default value for the result if this entry does not have a valid value.
    */
-  dynamic /*=V*/ getValue /*<V>*/ (ResultDescriptor /*<V>*/ descriptor) {
+  dynamic/*=V*/ getValue/*<V>*/(ResultDescriptor/*<V>*/ descriptor) {
     ResultData data = _resultMap[descriptor];
     if (data == null) {
       return descriptor.defaultValue;
@@ -482,8 +495,8 @@
    * Set the value of the result represented by the given [descriptor] to the
    * given [value].
    */
-  void setValue /*<V>*/ (ResultDescriptor /*<V>*/ descriptor,
-      dynamic /*=V*/ value, List<TargetedResult> dependedOn) {
+  void setValue/*<V>*/(ResultDescriptor/*<V>*/ descriptor, dynamic/*=V*/ value,
+      List<TargetedResult> dependedOn) {
 //    {
 //      String valueStr = '$value';
 //      if (valueStr.length > 20) {
@@ -581,7 +594,10 @@
     _invalidateDependentResults(id, thisData, delta, level + 1);
     // If empty and not explicitly added, remove the entry altogether.
     if (_resultMap.isEmpty && !explicitlyAdded) {
-      _partition.entryMap.remove(target);
+      CacheEntry entry = _partition.entryMap.remove(target);
+      if (entry != null) {
+        entry.dispose();
+      }
       _partition._removeIfSource(target);
     }
     // Notify controller.
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index e931197..cc1d41e 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -725,7 +725,8 @@
     LibraryElementImpl mockLib = new LibraryElementImpl.forNode(
         this, AstFactory.libraryIdentifier2(["dart.async"]));
     mockLib.definingCompilationUnit = asyncUnit;
-    mockLib.publicNamespace = new PublicNamespaceBuilder().build(mockLib);
+    mockLib.publicNamespace =
+        new NamespaceBuilder().createPublicNamespaceForLibrary(mockLib);
     return mockLib;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 4a9826e..48332fb 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5054,7 +5054,7 @@
  * > functionExpressionInvocation ::=
  * >     [Expression] [TypeArgumentList]? [ArgumentList]
  */
-class FunctionExpressionInvocationImpl extends ExpressionImpl
+class FunctionExpressionInvocationImpl extends InvocationExpressionImpl
     implements FunctionExpressionInvocation {
   /**
    * The expression producing the function being invoked.
@@ -5062,17 +5062,6 @@
   Expression _function;
 
   /**
-   * The type arguments to be applied to the method being invoked, or `null` if
-   * no type arguments were provided.
-   */
-  TypeArgumentList _typeArguments;
-
-  /**
-   * The list of arguments to the function.
-   */
-  ArgumentList _argumentList;
-
-  /**
    * The element associated with the function being invoked based on static type
    * information, or `null` if the AST structure has not been resolved or the
    * function could not be resolved.
@@ -5080,16 +5069,6 @@
   ExecutableElement staticElement;
 
   /**
-   * The function type of the method invocation, or `null` if the AST
-   * structure has not been resolved, or if the invoke could not be resolved.
-   *
-   * This will usually be a [FunctionType], but it can also be an
-   * [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
-   * interface type that implements `Function`.
-   */
-  DartType staticInvokeType;
-
-  /**
    * The element associated with the function being invoked based on propagated
    * type information, or `null` if the AST structure has not been resolved or
    * the function could not be resolved.
@@ -5097,26 +5076,12 @@
   ExecutableElement propagatedElement;
 
   /**
-   * Like [staticInvokeType], but reflects propagated type information.
-   */
-  DartType propagatedInvokeType;
-
-  /**
    * Initialize a newly created function expression invocation.
    */
   FunctionExpressionInvocationImpl(Expression function,
-      TypeArgumentList typeArguments, ArgumentList argumentList) {
+      TypeArgumentList typeArguments, ArgumentList argumentList)
+      : super(typeArguments, argumentList) {
     _function = _becomeParentOf(function);
-    _typeArguments = _becomeParentOf(typeArguments);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  ArgumentList get argumentList => _argumentList;
-
-  @override
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
   }
 
   @override
@@ -5150,14 +5115,6 @@
   int get precedence => 15;
 
   @override
-  TypeArgumentList get typeArguments => _typeArguments;
-
-  @override
-  void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  @override
   accept(AstVisitor visitor) => visitor.visitFunctionExpressionInvocation(this);
 
   @override
@@ -6167,6 +6124,55 @@
 }
 
 /**
+ * Common base class for [FunctionExpressionInvocationImpl] and
+ * [MethodInvocationImpl].
+ */
+abstract class InvocationExpressionImpl extends ExpressionImpl
+    implements InvocationExpression {
+  /**
+   * The list of arguments to the function.
+   */
+  ArgumentList _argumentList;
+
+  /**
+   * The type arguments to be applied to the method being invoked, or `null` if
+   * no type arguments were provided.
+   */
+  TypeArgumentList _typeArguments;
+
+  @override
+  DartType propagatedInvokeType;
+
+  @override
+  DartType staticInvokeType;
+
+  /**
+   * Initialize a newly created invocation.
+   */
+  InvocationExpressionImpl(
+      TypeArgumentList typeArguments, ArgumentList argumentList) {
+    _typeArguments = _becomeParentOf(typeArguments);
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  ArgumentList get argumentList => _argumentList;
+
+  @override
+  void set argumentList(ArgumentList argumentList) {
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  TypeArgumentList get typeArguments => _typeArguments;
+
+  @override
+  void set typeArguments(TypeArgumentList typeArguments) {
+    _typeArguments = _becomeParentOf(typeArguments);
+  }
+}
+
+/**
  * An is expression.
  *
  * > isExpression ::=
@@ -6959,7 +6965,8 @@
  * > methodInvocation ::=
  * >     ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
  */
-class MethodInvocationImpl extends ExpressionImpl implements MethodInvocation {
+class MethodInvocationImpl extends InvocationExpressionImpl
+    implements MethodInvocation {
   /**
    * The expression producing the object on which the method is defined, or
    * `null` if there is no target (that is, the target is implicitly `this`).
@@ -6980,32 +6987,6 @@
   SimpleIdentifier _methodName;
 
   /**
-   * The type arguments to be applied to the method being invoked, or `null` if
-   * no type arguments were provided.
-   */
-  TypeArgumentList _typeArguments;
-
-  /**
-   * The list of arguments to the method.
-   */
-  ArgumentList _argumentList;
-
-  /**
-   * The function type of the method invocation, or `null` if the AST
-   * structure has not been resolved, or if the invoke could not be resolved.
-   *
-   * This will usually be a [FunctionType], but it can also be an
-   * [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
-   * interface type that implements `Function`.
-   */
-  DartType staticInvokeType;
-
-  /**
-   * Like [staticInvokeType], but reflects propagated type information.
-   */
-  DartType propagatedInvokeType;
-
-  /**
    * Initialize a newly created method invocation. The [target] and [operator]
    * can be `null` if there is no target.
    */
@@ -7014,19 +6995,10 @@
       this.operator,
       SimpleIdentifier methodName,
       TypeArgumentList typeArguments,
-      ArgumentList argumentList) {
+      ArgumentList argumentList)
+      : super(typeArguments, argumentList) {
     _target = _becomeParentOf(target);
     _methodName = _becomeParentOf(methodName);
-    _typeArguments = _becomeParentOf(typeArguments);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  ArgumentList get argumentList => _argumentList;
-
-  @override
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
   }
 
   @override
@@ -7050,6 +7022,9 @@
   Token get endToken => _argumentList.endToken;
 
   @override
+  Expression get function => methodName;
+
+  @override
   bool get isCascaded =>
       operator != null && operator.type == TokenType.PERIOD_PERIOD;
 
@@ -7088,14 +7063,6 @@
   }
 
   @override
-  TypeArgumentList get typeArguments => _typeArguments;
-
-  @override
-  void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  @override
   accept(AstVisitor visitor) => visitor.visitMethodInvocation(this);
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index 607df7b..02d28e5 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -35,7 +35,7 @@
 /**
  * A begin token that is preceded by comments.
  */
-class BeginTokenWithComment extends BeginToken {
+class BeginTokenWithComment extends BeginToken implements TokenWithComment {
   /**
    * The first comment in the list of comments that precede this token.
    */
@@ -79,9 +79,9 @@
  */
 class CommentToken extends StringToken {
   /**
-   * The [Token] that contains this comment.
+   * The token that contains this comment.
    */
-  Token parent;
+  TokenWithComment parent;
 
   /**
    * Initialize a newly created token to represent a token of the given [type]
@@ -92,6 +92,21 @@
 
   @override
   CommentToken copy() => new CommentToken(type, _value, offset);
+
+  /**
+   * Remove this comment token from the list.
+   *
+   * This is used when we decide to interpret the comment as syntax.
+   */
+  void remove() {
+    if (previous != null) {
+      previous.setNextWithoutSettingPrevious(next);
+      next?.previous = previous;
+    } else {
+      assert(parent.precedingComments == this);
+      parent.precedingComments = next;
+    }
+  }
 }
 
 /**
@@ -149,7 +164,7 @@
 /**
  * A keyword token that is preceded by comments.
  */
-class KeywordTokenWithComment extends KeywordToken {
+class KeywordTokenWithComment extends KeywordToken implements TokenWithComment {
   /**
    * The first comment in the list of comments that precede this token.
    */
@@ -340,7 +355,7 @@
 /**
  * A string token that is preceded by comments.
  */
-class StringTokenWithComment extends StringToken {
+class StringTokenWithComment extends StringToken implements TokenWithComment {
   /**
    * The first comment in the list of comments that precede this token.
    */
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 05ff07f..dbbba10 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -934,6 +934,10 @@
     if (token is CommentToken) {
       token = (token as CommentToken).parent;
     }
+    if (_lastCloned == null) {
+      _lastCloned = new Token(TokenType.EOF, -1);
+      _lastCloned.setNext(_lastCloned);
+    }
     while (token != null) {
       Token clone = token.copy();
       {
@@ -952,7 +956,7 @@
         }
       }
       _clonedTokens[token] = clone;
-      _lastCloned?.setNext(clone);
+      _lastCloned.setNext(clone);
       _lastCloned = clone;
       if (token.type == TokenType.EOF) {
         break;
@@ -4946,7 +4950,7 @@
     } else if (_replaceInList(node.variables)) {
       return true;
     }
-    return visitNode(node);
+    return visitAnnotatedNode(node);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index ef51b61..82d3761 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -331,6 +331,24 @@
   }
 
   @override
+  Object visitAnnotation(Annotation node) {
+    // Although it isn't valid to do so because closures are not constant
+    // expressions, it's possible for one of the arguments to the constructor to
+    // contain a closure. Wrapping the processing of the annotation this way
+    // prevents these closures from being added to the list of functions in the
+    // annotated declaration.
+    ElementHolder holder = new ElementHolder();
+    ElementHolder previousHolder = _currentHolder;
+    _currentHolder = holder;
+    try {
+      super.visitAnnotation(node);
+    } finally {
+      _currentHolder = previousHolder;
+    }
+    return null;
+  }
+
+  @override
   Object visitCatchClause(CatchClause node) {
     SimpleIdentifier exceptionParameter = node.exceptionParameter;
     if (exceptionParameter != null) {
@@ -539,11 +557,13 @@
       _visit(holder, defaultValue);
       FunctionElementImpl initializer =
           new FunctionElementImpl.forOffset(defaultValue.beginToken.offset);
+      initializer.hasImplicitReturnType = true;
       initializer.functions = holder.functions;
       initializer.labels = holder.labels;
       initializer.localVariables = holder.localVariables;
       initializer.parameters = holder.parameters;
       initializer.synthetic = true;
+      initializer.type = new FunctionTypeImpl(initializer);
       parameter.initializer = initializer;
       parameter.defaultValueCode = defaultValue.toSource();
     }
@@ -846,7 +866,7 @@
     for (Label label in node.labels) {
       SimpleIdentifier labelName = label.label;
       LabelElementImpl element =
-          new LabelElementImpl(labelName, onSwitchStatement, false);
+          new LabelElementImpl.forNode(labelName, onSwitchStatement, false);
       _currentHolder.addLabel(element);
       labelName.staticElement = element;
     }
@@ -1045,7 +1065,7 @@
   Object visitSwitchCase(SwitchCase node) {
     for (Label label in node.labels) {
       SimpleIdentifier labelName = label.label;
-      LabelElementImpl element = new LabelElementImpl(labelName, false, true);
+      LabelElementImpl element = new LabelElementImpl.forNode(labelName, false, true);
       _currentHolder.addLabel(element);
       labelName.staticElement = element;
     }
@@ -1056,7 +1076,7 @@
   Object visitSwitchDefault(SwitchDefault node) {
     for (Label label in node.labels) {
       SimpleIdentifier labelName = label.label;
-      LabelElementImpl element = new LabelElementImpl(labelName, false, true);
+      LabelElementImpl element = new LabelElementImpl.forNode(labelName, false, true);
       _currentHolder.addLabel(element);
       labelName.staticElement = element;
     }
@@ -1139,10 +1159,12 @@
       _visit(holder, node.initializer);
       FunctionElementImpl initializer =
           new FunctionElementImpl.forOffset(node.initializer.beginToken.offset);
+      initializer.hasImplicitReturnType = true;
       initializer.functions = holder.functions;
       initializer.labels = holder.labels;
       initializer.localVariables = holder.localVariables;
       initializer.synthetic = true;
+      initializer.type = new FunctionTypeImpl(initializer);
       element.initializer = initializer;
       holder.validate();
     }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9677e89..5305395 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -114,11 +114,6 @@
   List<TypeParameterElement> _typeParameters = TypeParameterElement.EMPTY_LIST;
 
   /**
-   * The [SourceRange] of the `with` clause, `null` if there is no one.
-   */
-  SourceRange withClauseRange;
-
-  /**
    * A flag indicating whether the types associated with the instance members of
    * this class have been inferred.
    */
@@ -710,7 +705,6 @@
           new ConstructorElementImpl(superclassConstructor.name, -1);
       implicitConstructor.synthetic = true;
       implicitConstructor.redirectedConstructor = superclassConstructor;
-      implicitConstructor.const2 = superclassConstructor.isConst;
       implicitConstructor.returnType = type;
       List<ParameterElement> superParameters = superclassConstructor.parameters;
       int count = superParameters.length;
@@ -1789,11 +1783,12 @@
 
   /**
    * Set the enclosing element of this element to the given [element].
+   *
+   * Throws [FrozenHashCodeException] if the hashCode can't be changed.
    */
   void set enclosingElement(Element element) {
     _enclosingElement = element as ElementImpl;
-    _cachedLocation = null;
-    _cachedHashCode = null;
+    _updateCaches();
   }
 
   @override
@@ -1865,10 +1860,14 @@
   @override
   String get name => _name;
 
+  /**
+   * Changes the name of this element.
+   *
+   * Throws [FrozenHashCodeException] if the hashCode can't be changed.
+   */
   void set name(String name) {
     this._name = name;
-    _cachedLocation = null;
-    _cachedHashCode = null;
+    _updateCaches();
   }
 
   @override
@@ -1880,11 +1879,12 @@
   /**
    * Sets the offset of the name of this element in the file that contains the
    * declaration of this element.
+   *
+   * Throws [FrozenHashCodeException] if the hashCode can't be changed.
    */
   void set nameOffset(int offset) {
     _nameOffset = offset;
-    _cachedHashCode = null;
-    _cachedLocation = null;
+    _updateCaches();
   }
 
   @override
@@ -2045,6 +2045,35 @@
   void visitChildren(ElementVisitor visitor) {
     // There are no children to visit
   }
+
+  /**
+   *  Updates cached values after an input changed.
+   *
+   *  Throws [FrozenHashCodeException] if not allowed.
+   */
+  void _updateCaches() {
+    if (!hasModifier(Modifier.CACHE_KEY)) {
+      // Fast path.
+      _cachedLocation = null;
+      _cachedHashCode = null;
+      return;
+    }
+
+    // Save originals.
+    ElementLocation oldLocation = _cachedLocation;
+    int oldHashCode = _cachedHashCode;
+
+    _cachedLocation = null;
+    _cachedHashCode = null;
+
+    if (oldHashCode != hashCode) {
+      // Prevent cache corruption by restoring originals.
+      _cachedLocation = oldLocation;
+      _cachedHashCode = oldHashCode;
+      throw new FrozenHashCodeException(
+          "can't update hashCode for a cache key: $this ($runtimeType)");
+    }
+  }
 }
 
 /**
@@ -2575,6 +2604,18 @@
 }
 
 /**
+ * Indicates that an ElementImpl's hashCode cannot currently be changed.
+ */
+class FrozenHashCodeException implements Exception {
+  final String _message;
+
+  FrozenHashCodeException(this._message);
+
+  @override
+  String toString() => "FrozenHashCodeException($_message)";
+}
+
+/**
  * A concrete implementation of a [FunctionElement].
  */
 class FunctionElementImpl extends ExecutableElementImpl
@@ -2935,7 +2976,17 @@
    * `switch` statement and [onSwitchMember] should be `true` if this label is
    * associated with a `switch` member.
    */
-  LabelElementImpl(
+  LabelElementImpl(String name, int nameOffset, this._onSwitchStatement,
+      this._onSwitchMember)
+      : super(name, nameOffset);
+
+  /**
+   * Initialize a newly created label element to have the given [name].
+   * [onSwitchStatement] should be `true` if this label is associated with a
+   * `switch` statement and [onSwitchMember] should be `true` if this label is
+   * associated with a `switch` member.
+   */
+  LabelElementImpl.forNode(
       Identifier name, this._onSwitchStatement, this._onSwitchMember)
       : super.forNode(name);
 
@@ -3557,12 +3608,10 @@
   }
 
   @override
-  bool get isPotentiallyMutatedInClosure =>
-      hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT);
+  bool get isPotentiallyMutatedInClosure => true;
 
   @override
-  bool get isPotentiallyMutatedInScope =>
-      hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE);
+  bool get isPotentiallyMutatedInScope => true;
 
   @override
   ElementKind get kind => ElementKind.LOCAL_VARIABLE;
@@ -3590,20 +3639,6 @@
       getNodeMatching((node) => node is VariableDeclaration);
 
   /**
-   * Specifies that this variable is potentially mutated somewhere in closure.
-   */
-  void markPotentiallyMutatedInClosure() {
-    setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true);
-  }
-
-  /**
-   * Specifies that this variable is potentially mutated somewhere in its scope.
-   */
-  void markPotentiallyMutatedInScope() {
-    setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true);
-  }
-
-  /**
    * Set the visible range for this element to the range starting at the given
    * [offset] with the given [length].
    */
@@ -3778,34 +3813,20 @@
       const Modifier('MIXIN_APPLICATION', 12);
 
   /**
-   * Indicates that the value of a parameter or local variable might be mutated
-   * within the context.
-   */
-  static const Modifier POTENTIALLY_MUTATED_IN_CONTEXT =
-      const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 13);
-
-  /**
-   * Indicates that the value of a parameter or local variable might be mutated
-   * within the scope.
-   */
-  static const Modifier POTENTIALLY_MUTATED_IN_SCOPE =
-      const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 14);
-
-  /**
    * Indicates that a class contains an explicit reference to 'super'.
    */
   static const Modifier REFERENCES_SUPER =
-      const Modifier('REFERENCES_SUPER', 15);
+      const Modifier('REFERENCES_SUPER', 13);
 
   /**
    * Indicates that the pseudo-modifier 'set' was applied to the element.
    */
-  static const Modifier SETTER = const Modifier('SETTER', 16);
+  static const Modifier SETTER = const Modifier('SETTER', 14);
 
   /**
    * Indicates that the modifier 'static' was applied to the element.
    */
-  static const Modifier STATIC = const Modifier('STATIC', 17);
+  static const Modifier STATIC = const Modifier('STATIC', 15);
 
   /**
    * Indicates that the element does not appear in the source code but was
@@ -3813,9 +3834,14 @@
    * constructors, an implicit zero-argument constructor will be created and it
    * will be marked as being synthetic.
    */
-  static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 18);
+  static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16);
 
-  static const List<Modifier> values = const [
+  /**
+   * Indicates that this element is being used as an analyzer cache key.
+   */
+  static const Modifier CACHE_KEY = const Modifier('CACHE_KEY', 17);
+
+  static const List<Modifier> persistedValues = const [
     ABSTRACT,
     ASYNCHRONOUS,
     CONST,
@@ -3829,14 +3855,17 @@
     HAS_EXT_URI,
     IMPLICIT_TYPE,
     MIXIN_APPLICATION,
-    POTENTIALLY_MUTATED_IN_CONTEXT,
-    POTENTIALLY_MUTATED_IN_SCOPE,
     REFERENCES_SUPER,
     SETTER,
     STATIC,
     SYNTHETIC
   ];
 
+  static const List<Modifier> transientValues = const [CACHE_KEY];
+
+  static final values = new List.unmodifiable(
+      []..addAll(persistedValues)..addAll(transientValues));
+
   const Modifier(String name, int ordinal) : super(name, ordinal);
 }
 
@@ -4161,12 +4190,10 @@
   bool get isInitializingFormal => false;
 
   @override
-  bool get isPotentiallyMutatedInClosure =>
-      hasModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT);
+  bool get isPotentiallyMutatedInClosure => true;
 
   @override
-  bool get isPotentiallyMutatedInScope =>
-      hasModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE);
+  bool get isPotentiallyMutatedInScope => true;
 
   @override
   ElementKind get kind => ElementKind.PARAMETER;
@@ -4244,20 +4271,6 @@
   }
 
   /**
-   * Specifies that this variable is potentially mutated somewhere in closure.
-   */
-  void markPotentiallyMutatedInClosure() {
-    setModifier(Modifier.POTENTIALLY_MUTATED_IN_CONTEXT, true);
-  }
-
-  /**
-   * Specifies that this variable is potentially mutated somewhere in its scope.
-   */
-  void markPotentiallyMutatedInScope() {
-    setModifier(Modifier.POTENTIALLY_MUTATED_IN_SCOPE, true);
-  }
-
-  /**
    * Set the visible range for this element to the range starting at the given
    * [offset] with the given [length].
    */
@@ -4600,6 +4613,11 @@
   TypeParameterElementImpl(String name, int offset) : super(name, offset);
 
   /**
+   * Initialize a newly created type parameter element to have the given [name].
+   */
+  TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name);
+
+  /**
    * Initialize a newly created synthetic type parameter element to have the
    * given [name], and with [synthetic] set to true.
    */
@@ -4607,11 +4625,6 @@
     synthetic = true;
   }
 
-  /**
-   * Initialize a newly created type parameter element to have the given [name].
-   */
-  TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name);
-
   @override
   ElementKind get kind => ElementKind.TYPE_PARAMETER;
 
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 938aa23..446ca59 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -12,6 +12,8 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart' show ScannerErrorCode;
+import 'package:analyzer/src/generated/generated/shared_messages.dart'
+    as shared_messages;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/source.dart';
@@ -2220,24 +2222,21 @@
    * <i>rethrow;</i> is not enclosed within a on-catch clause.
    */
   static const CompileTimeErrorCode RETHROW_OUTSIDE_CATCH =
-      const CompileTimeErrorCode(
-          'RETHROW_OUTSIDE_CATCH', "rethrow must be inside of a catch clause");
+      shared_messages.RETHROW_OUTSIDE_CATCH;
 
   /**
    * 13.12 Return: It is a compile-time error if a return statement of the form
    * <i>return e;</i> appears in a generative constructor.
    */
   static const CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR =
-      const CompileTimeErrorCode('RETURN_IN_GENERATIVE_CONSTRUCTOR',
-          "Constructors cannot return a value");
+      shared_messages.RETURN_IN_GENERATIVE_CONSTRUCTOR;
 
   /**
    * 13.12 Return: It is a compile-time error if a return statement of the form
    * <i>return e;</i> appears in a generator function.
    */
   static const CompileTimeErrorCode RETURN_IN_GENERATOR =
-      const CompileTimeErrorCode('RETURN_IN_GENERATOR',
-          "Cannot return a value from a generator function (one marked with either 'async*' or 'sync*')");
+      shared_messages.RETURN_IN_GENERATOR;
 
   /**
    * 14.1 Imports: It is a compile-time error if a prefix used in a deferred
@@ -2961,6 +2960,7 @@
     ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS,
     ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT,
     ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP,
+    ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY,
     ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
     ParserErrorCode.SETTER_IN_FUNCTION,
     ParserErrorCode.STATIC_AFTER_CONST,
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 5de25974..32b4d31 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -682,6 +682,14 @@
   }
 
   @override
+  Object visitForStatement(ForStatement node) {
+    if (node.condition != null) {
+      _checkForNonBoolCondition(node.condition);
+    }
+    return super.visitForStatement(node);
+  }
+
+  @override
   Object visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
     try {
@@ -1928,7 +1936,9 @@
     } else if (_inGenerator) {
       // RETURN_IN_GENERATOR
       _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.RETURN_IN_GENERATOR, statement);
+          CompileTimeErrorCode.RETURN_IN_GENERATOR,
+          statement,
+          [_inAsync ? "async*" : "sync*"]);
     }
     // RETURN_OF_INVALID_TYPE
     return _checkForReturnOfInvalidType(returnExpression, expectedReturnType);
diff --git a/pkg/analyzer/lib/src/generated/generated/shared_messages.dart b/pkg/analyzer/lib/src/generated/generated/shared_messages.dart
index 5faa0c0..c0be1d2 100644
--- a/pkg/analyzer/lib/src/generated/generated/shared_messages.dart
+++ b/pkg/analyzer/lib/src/generated/generated/shared_messages.dart
@@ -9,6 +9,7 @@
 After any change to that file, run `bin/publish.dart` to generate a new version
 of the json, dart2js and analyzer representations.
 */
+import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 
 const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY = const ParserErrorCode(
@@ -19,4 +20,64 @@
 const ParserErrorCode CONST_FACTORY = const ParserErrorCode(
     'CONST_FACTORY',
     "Only redirecting factory constructors can be declared to be 'const'.",
-    "Try removing the 'const' keyword or replacing the body with '=' followed by a valid target");  // Generated. Don't edit.
+    "Try removing the 'const' keyword or replacing the body with '=' followed by a valid target.");  // Generated. Don't edit.
+
+const ParserErrorCode CONST_CLASS = const ParserErrorCode(
+    'CONST_CLASS',
+    "Classes can't be declared to be 'const'",
+    "Try removing the 'const' keyword or moving to the class' constructor(s).");  // Generated. Don't edit.
+
+const ParserErrorCode CONST_METHOD = const ParserErrorCode(
+    'CONST_METHOD',
+    "Getters, setters and methods can't be declared to be 'const'",
+    "Try removing the 'const' keyword.");  // Generated. Don't edit.
+
+const ParserErrorCode CONST_ENUM = const ParserErrorCode(
+    'CONST_ENUM',
+    "Enums can't be declared to be 'const'",
+    "Try removing the 'const' keyword.");  // Generated. Don't edit.
+
+const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode(
+    'CONST_TYPEDEF',
+    "Type aliases can't be declared to be 'const'",
+    "Try removing the 'const' keyword.");  // Generated. Don't edit.
+
+const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode(
+    'CONST_AND_FINAL',
+    "Members can't be declared to be both 'const' and 'final'",
+    "Try removing either the 'const' or 'final' keyword.");  // Generated. Don't edit.
+
+const ParserErrorCode CONST_AND_VAR = const ParserErrorCode(
+    'CONST_AND_VAR',
+    "Members can't be declared to be both 'const' and 'var'",
+    "Try removing either the 'const' or 'var' keyword.");  // Generated. Don't edit.
+
+const ParserErrorCode CLASS_IN_CLASS = const ParserErrorCode(
+    'CLASS_IN_CLASS',
+    "Classes can't be declared inside other classes.",
+    "Try moving the class to the top-level.");  // Generated. Don't edit.
+
+const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE = const ParserErrorCode(
+    'CONSTRUCTOR_WITH_RETURN_TYPE',
+    "Constructors can't have a return type",
+    "Try removing the return type.");  // Generated. Don't edit.
+
+const ParserErrorCode MISSING_EXPRESSION_IN_THROW = const ParserErrorCode(
+    'MISSING_EXPRESSION_IN_THROW',
+    "Missing expression after 'throw'.",
+    "Did you mean 'rethrow'?");  // Generated. Don't edit.
+
+const CompileTimeErrorCode RETHROW_OUTSIDE_CATCH = const CompileTimeErrorCode(
+    'RETHROW_OUTSIDE_CATCH',
+    "Rethrow must be inside of catch clause",
+    "Try moving the expression into a catch clause, or using a 'throw' expression.");  // Generated. Don't edit.
+
+const CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR = const CompileTimeErrorCode(
+    'RETURN_IN_GENERATIVE_CONSTRUCTOR',
+    "Constructors can't return values.",
+    "Try removing the return statement or using a factory constructor.");  // Generated. Don't edit.
+
+const CompileTimeErrorCode RETURN_IN_GENERATOR = const CompileTimeErrorCode(
+    'RETURN_IN_GENERATOR',
+    "Can't return a value from a generator function (using the '{0}' modifier).",
+    "Try removing the value, replacing 'return' with 'yield' or changing the method body modifier");  // Generated. Don't edit.
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
index f0f7a4c7..cf2c0dd 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
@@ -28,10 +28,15 @@
 class IncrementalResolutionMismatch {
   final String message;
   IncrementalResolutionMismatch(this.message);
+
+  @override
+  String toString() => "IncrementalResolutionMismatch: $message";
 }
 
 class _SameResolutionValidator implements AstVisitor {
   final bool validateTypes;
+
+  /// The expected node to compare with the visted node.
   AstNode other;
 
   _SameResolutionValidator(this.validateTypes, this.other);
@@ -887,11 +892,11 @@
     _assertNode(a, b);
   }
 
-  void _visitList(NodeList nodeList, NodeList otherList) {
+  void _visitList(NodeList nodeList, NodeList expected) {
     int length = nodeList.length;
-    _expectLength(otherList, length);
+    _expectLength(nodeList, expected.length);
     for (int i = 0; i < length; i++) {
-      _visitNode(nodeList[i], otherList[i]);
+      _visitNode(nodeList[i], expected[i]);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index f102201..7cc84d3 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -118,12 +118,14 @@
       _gatherElements(element);
       node.accept(this);
     } on _DeclarationMismatchException {
+      logger.log("mismatched");
       return DeclarationMatchKind.MISMATCH;
     } finally {
       logger.exit();
     }
     // no API changes
     if (_removedElements.isEmpty && _addedElements.isEmpty) {
+      logger.log("no API changes");
       return DeclarationMatchKind.MATCH;
     }
     // simple API change
@@ -2070,12 +2072,12 @@
     if (nameOffset > updateOffset) {
       // TODO(scheglov) make sure that we don't put local variables
       // and functions into the cache at all.
-      if (element is LocalVariableElement ||
-          element is FunctionElement &&
-              element.enclosingElement is ExecutableElement) {
+      try {
+        (element as ElementImpl).nameOffset = nameOffset + updateDelta;
+      } on FrozenHashCodeException {
         cache.remove(element);
+        (element as ElementImpl).nameOffset = nameOffset + updateDelta;
       }
-      (element as ElementImpl).nameOffset = nameOffset + updateDelta;
       if (element is ConstVariableElement) {
         ConstVariableElement constVariable = element as ConstVariableElement;
         Expression initializer = constVariable.constantInitializer;
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index ad18d2c..8ec719a 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -3951,6 +3951,8 @@
           String comment = t.lexeme.substring(prefixLen, t.lexeme.length - 2);
           Token list = _scanGenericMethodComment(comment, t.offset + prefixLen);
           if (list != null) {
+            // Remove the token from the comment stream.
+            t.remove();
             // Insert the tokens into the stream.
             _injectTokenList(list);
             return true;
@@ -5457,9 +5459,12 @@
         if (constKeyword != null) {
           _reportErrorForNode(
               ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body);
-        } else if (!bodyAllowed) {
+        } else if (externalKeyword != null) {
           _reportErrorForNode(
               ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body);
+        } else if (!bodyAllowed) {
+          _reportErrorForNode(
+              ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, body);
         }
       }
     }
@@ -9398,41 +9403,31 @@
       'BREAK_OUTSIDE_OF_LOOP',
       "A break statement cannot be used outside of a loop or switch statement");
 
-  static const ParserErrorCode CLASS_IN_CLASS = const ParserErrorCode(
-      'CLASS_IN_CLASS', "Classes cannot be declared inside other classes");
+  static const ParserErrorCode CLASS_IN_CLASS = shared_messages.CLASS_IN_CLASS;
 
   static const ParserErrorCode COLON_IN_PLACE_OF_IN = const ParserErrorCode(
       'COLON_IN_PLACE_OF_IN', "For-in loops use 'in' rather than a colon");
 
-  static const ParserErrorCode CONST_AND_FINAL = const ParserErrorCode(
-      'CONST_AND_FINAL',
-      "Members cannot be declared to be both 'const' and 'final'");
+  static const ParserErrorCode CONST_AND_FINAL =
+      shared_messages.CONST_AND_FINAL;
 
-  static const ParserErrorCode CONST_AND_VAR = const ParserErrorCode(
-      'CONST_AND_VAR',
-      "Members cannot be declared to be both 'const' and 'var'");
+  static const ParserErrorCode CONST_AND_VAR = shared_messages.CONST_AND_VAR;
 
-  static const ParserErrorCode CONST_CLASS = const ParserErrorCode(
-      'CONST_CLASS', "Classes cannot be declared to be 'const'");
+  static const ParserErrorCode CONST_CLASS = shared_messages.CONST_CLASS;
 
   static const ParserErrorCode CONST_CONSTRUCTOR_WITH_BODY =
       shared_messages.CONST_CONSTRUCTOR_WITH_BODY;
 
-  static const ParserErrorCode CONST_ENUM = const ParserErrorCode(
-      'CONST_ENUM', "Enums cannot be declared to be 'const'");
+  static const ParserErrorCode CONST_ENUM = shared_messages.CONST_ENUM;
 
   static const ParserErrorCode CONST_FACTORY = shared_messages.CONST_FACTORY;
 
-  static const ParserErrorCode CONST_METHOD = const ParserErrorCode(
-      'CONST_METHOD',
-      "Getters, setters and methods cannot be declared to be 'const'");
+  static const ParserErrorCode CONST_METHOD = shared_messages.CONST_METHOD;
 
-  static const ParserErrorCode CONST_TYPEDEF = const ParserErrorCode(
-      'CONST_TYPEDEF', "Type aliases cannot be declared to be 'const'");
+  static const ParserErrorCode CONST_TYPEDEF = shared_messages.CONST_TYPEDEF;
 
   static const ParserErrorCode CONSTRUCTOR_WITH_RETURN_TYPE =
-      const ParserErrorCode('CONSTRUCTOR_WITH_RETURN_TYPE',
-          "Constructors cannot have a return type");
+      shared_messages.CONSTRUCTOR_WITH_RETURN_TYPE;
 
   static const ParserErrorCode CONTINUE_OUTSIDE_OF_LOOP = const ParserErrorCode(
       'CONTINUE_OUTSIDE_OF_LOOP',
@@ -9692,8 +9687,7 @@
           "Expected an expression after the assignment operator");
 
   static const ParserErrorCode MISSING_EXPRESSION_IN_THROW =
-      const ParserErrorCode('MISSING_EXPRESSION_IN_THROW',
-          "Throw expressions must compute the object to be thrown");
+      shared_messages.MISSING_EXPRESSION_IN_THROW;
 
   static const ParserErrorCode MISSING_FUNCTION_BODY = const ParserErrorCode(
       'MISSING_FUNCTION_BODY', "A function body must be provided");
@@ -9838,6 +9832,10 @@
       const ParserErrorCode('POSITIONAL_PARAMETER_OUTSIDE_GROUP',
           "Positional parameters must be enclosed in square brackets ('[' and ']')");
 
+  static const ParserErrorCode REDIRECTING_CONSTRUCTOR_WITH_BODY =
+      const ParserErrorCode('REDIRECTING_CONSTRUCTOR_WITH_BODY',
+          "Redirecting constructors cannot have a body");
+
   static const ParserErrorCode REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR =
       const ParserErrorCode('REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR',
           "Only factory constructor can specify '=' redirection.");
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index fab4ed1..45c75b2 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2394,8 +2394,11 @@
       SimpleIdentifier methodName = node.name;
       String nameOfMethod = methodName.name;
       if (property == null) {
+        String elementName = nameOfMethod == '-' &&
+            node.parameters != null &&
+            node.parameters.parameters.isEmpty ? 'unary-' : nameOfMethod;
         _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods,
-            methodName, nameOfMethod, methodName.offset);
+            methodName, elementName, methodName.offset);
         _expectedElements.remove(_enclosingExecutable);
         methodName.staticElement = _enclosingExecutable;
       } else {
@@ -2404,7 +2407,7 @@
           accessor = _findIdentifier(_enclosingClass.accessors, methodName);
         } else if ((property as KeywordToken).keyword == Keyword.SET) {
           accessor = _findWithNameAndOffset(_enclosingClass.accessors,
-              methodName, methodName.name + '=', methodName.offset);
+              methodName, nameOfMethod + '=', methodName.offset);
           _expectedElements.remove(accessor);
           methodName.staticElement = accessor;
         }
@@ -2500,6 +2503,12 @@
             _findIdentifier(_enclosingAlias.typeParameters, parameterName);
       }
     }
+    if (element == null) {
+      String name = parameterName.name;
+      int offset = parameterName.offset;
+      _mismatch(
+          'Could not find type parameter with name "$name" at $offset', node);
+    }
     super.visitTypeParameter(node);
     _resolveMetadata(node.metadata, element);
     return null;
@@ -4006,7 +4015,6 @@
  * An [AstVisitor] that fills [UsedLocalElements].
  */
 class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
-  final List<Element> definedElements = <Element>[];
   final UsedLocalElements usedElements = new UsedLocalElements();
 
   final LibraryElement _enclosingLibrary;
@@ -4076,13 +4084,10 @@
 
   @override
   visitSimpleIdentifier(SimpleIdentifier node) {
-    Element element = node.staticElement;
     if (node.inDeclarationContext()) {
-      if (element != null) {
-        definedElements.add(element);
-      }
       return;
     }
+    Element element = node.staticElement;
     bool isIdentifierRead = _isReadIdentifier(node);
     if (element is LocalVariableElement) {
       if (isIdentifierRead) {
@@ -6571,14 +6576,6 @@
    */
   HashMap<String, Element> _createExportMapping(
       LibraryElement library, HashSet<LibraryElement> visitedElements) {
-    // Check if the export namespace has been already computed.
-    {
-      Namespace exportNamespace = library.exportNamespace;
-      if (exportNamespace != null) {
-        return exportNamespace.definedNames;
-      }
-    }
-    // TODO(scheglov) Remove this after switching to the new task model.
     visitedElements.add(library);
     try {
       HashMap<String, Element> definedNames = new HashMap<String, Element>();
@@ -7108,7 +7105,7 @@
    */
   StaticTypeAnalyzer typeAnalyzer;
 
-  /*
+  /**
    * The type system in use during resolution.
    */
   TypeSystem typeSystem;
@@ -7160,6 +7157,11 @@
   bool resolveOnlyCommentInFunctionBody = false;
 
   /**
+   * Body of the function currently being analyzed, if any.
+   */
+  FunctionBody _currentFunctionBody;
+
+  /**
    * Initialize a newly created visitor to resolve the nodes in an AST node.
    *
    * The [definingLibrary] is the element for the library containing the node
@@ -7291,13 +7293,7 @@
   /**
    * Prepares this [ResolverVisitor] to using it for incremental resolution.
    */
-  void initForIncrementalResolution([Declaration declaration = null]) {
-    if (declaration != null) {
-      Element element = declaration.element;
-      if (element is ExecutableElement) {
-        _enclosingFunction = element;
-      }
-    }
+  void initForIncrementalResolution() {
     _overrideManager.enterScope();
   }
 
@@ -7851,12 +7847,15 @@
   @override
   Object visitConstructorDeclaration(ConstructorDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
+    FunctionBody outerFunctionBody = _currentFunctionBody;
     try {
+      _currentFunctionBody = node.body;
       _enclosingFunction = node.element;
       FunctionType type = _enclosingFunction.type;
       InferenceContext.setType(node.body, type.returnType);
       super.visitConstructorDeclaration(node);
     } finally {
+      _currentFunctionBody = outerFunctionBody;
       _enclosingFunction = outerFunction;
     }
     ConstructorElementImpl constructor = node.element;
@@ -8100,13 +8099,16 @@
   @override
   Object visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
+    FunctionBody outerFunctionBody = _currentFunctionBody;
     try {
       SimpleIdentifier functionName = node.name;
+      _currentFunctionBody = node.functionExpression.body;
       _enclosingFunction = functionName.staticElement as ExecutableElement;
       InferenceContext.setType(
           node.functionExpression, _enclosingFunction.type);
       super.visitFunctionDeclaration(node);
     } finally {
+      _currentFunctionBody = outerFunctionBody;
       _enclosingFunction = outerFunction;
     }
     return null;
@@ -8121,7 +8123,9 @@
   @override
   Object visitFunctionExpression(FunctionExpression node) {
     ExecutableElement outerFunction = _enclosingFunction;
+    FunctionBody outerFunctionBody = _currentFunctionBody;
     try {
+      _currentFunctionBody = node.body;
       _enclosingFunction = node.element;
       _overrideManager.enterScope();
       try {
@@ -8143,6 +8147,7 @@
         _overrideManager.exitScope();
       }
     } finally {
+      _currentFunctionBody = outerFunctionBody;
       _enclosingFunction = outerFunction;
     }
     return null;
@@ -8153,7 +8158,7 @@
     safelyVisit(node.function);
     node.accept(elementResolver);
     _inferFunctionExpressionsParametersTypes(node.argumentList);
-    InferenceContext.setType(node.argumentList, node.function.staticType);
+    _inferArgumentTypesFromContext(node);
     safelyVisit(node.argumentList);
     node.accept(typeAnalyzer);
     return null;
@@ -8339,7 +8344,9 @@
   @override
   Object visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
+    FunctionBody outerFunctionBody = _currentFunctionBody;
     try {
+      _currentFunctionBody = node.body;
       _enclosingFunction = node.element;
       DartType returnType = _computeReturnOrYieldType(
           _enclosingFunction.type?.returnType,
@@ -8348,6 +8355,7 @@
       InferenceContext.setType(node.body, returnType);
       super.visitMethodDeclaration(node);
     } finally {
+      _currentFunctionBody = outerFunctionBody;
       _enclosingFunction = outerFunction;
     }
     return null;
@@ -8369,15 +8377,32 @@
     safelyVisit(node.typeArguments);
     node.accept(elementResolver);
     _inferFunctionExpressionsParametersTypes(node.argumentList);
-    DartType contextType = node.staticInvokeType;
-    if (contextType is FunctionType) {
-      InferenceContext.setType(node.argumentList, contextType);
-    }
+    _inferArgumentTypesFromContext(node);
     safelyVisit(node.argumentList);
     node.accept(typeAnalyzer);
     return null;
   }
 
+  void _inferArgumentTypesFromContext(InvocationExpression node) {
+    DartType contextType = node.staticInvokeType;
+    if (contextType is FunctionType) {
+      DartType originalType = node.function.staticType;
+      DartType returnContextType = InferenceContext.getType(node);
+      TypeSystem ts = typeSystem;
+      if (returnContextType != null &&
+          node.typeArguments == null &&
+          originalType is FunctionType &&
+          originalType.typeFormals.isNotEmpty &&
+          ts is StrongTypeSystemImpl) {
+
+        contextType = ts.inferGenericFunctionCall(typeProvider, originalType,
+            DartType.EMPTY_LIST, DartType.EMPTY_LIST, returnContextType);
+      }
+
+      InferenceContext.setType(node.argumentList, contextType);
+    }
+  }
+
   @override
   Object visitNamedExpression(NamedExpression node) {
     InferenceContext.setType(node.expression, InferenceContext.getType(node));
@@ -8593,7 +8618,7 @@
   void _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
       AstNode target) {
     for (Element element in _promoteManager.promotedElements) {
-      if ((element as VariableElementImpl).isPotentiallyMutatedInScope) {
+      if (_currentFunctionBody.isPotentiallyMutatedInScope(element)) {
         if (_isVariableAccessedInClosure(element, target)) {
           _promoteManager.setType(element, null);
         }
@@ -8886,7 +8911,7 @@
     VariableElement element = getPromotionStaticElement(expression);
     if (element != null) {
       // may be mutated somewhere in closure
-      if (element.isPotentiallyMutatedInClosure) {
+      if (_currentFunctionBody.isPotentiallyMutatedInClosure(element)) {
         return;
       }
       // prepare current variable type
@@ -12037,8 +12062,6 @@
           CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
       if (classElement != null) {
         classElement.mixins = mixinTypes;
-        classElement.withClauseRange =
-            new SourceRange(withClause.offset, withClause.length);
       }
     }
     if (implementsClause != null) {
@@ -12210,7 +12233,7 @@
  * structure looking for cases of [HintCode.UNUSED_ELEMENT],
  * [HintCode.UNUSED_FIELD], [HintCode.UNUSED_LOCAL_VARIABLE], etc.
  */
-class UnusedLocalElementsVerifier extends SimpleElementVisitor {
+class UnusedLocalElementsVerifier extends RecursiveElementVisitor {
   /**
    * The error listener to which errors will be reported.
    */
@@ -12486,6 +12509,12 @@
             nameScope: nameScope);
 
   @override
+  Object visitBlockFunctionBody(BlockFunctionBody node) {
+    assert(_localVariableInfo != null);
+    return super.visitBlockFunctionBody(node);
+  }
+
+  @override
   Object visitConstructorDeclaration(ConstructorDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
     LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
@@ -12504,6 +12533,12 @@
   Object visitExportDirective(ExportDirective node) => null;
 
   @override
+  Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    assert(_localVariableInfo != null);
+    return super.visitExpressionFunctionBody(node);
+  }
+
+  @override
   Object visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
     LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
@@ -12597,29 +12632,11 @@
     }
     // Must be local or parameter.
     ElementKind kind = element.kind;
-    if (kind == ElementKind.LOCAL_VARIABLE) {
+    if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER) {
       node.staticElement = element;
-      LocalVariableElementImpl variableImpl =
-          element as LocalVariableElementImpl;
       if (node.inSetterContext()) {
-        variableImpl.markPotentiallyMutatedInScope();
         _localVariableInfo.potentiallyMutatedInScope.add(element);
         if (element.enclosingElement != _enclosingFunction) {
-          variableImpl.markPotentiallyMutatedInClosure();
-          _localVariableInfo.potentiallyMutatedInClosure.add(element);
-        }
-      }
-    } else if (kind == ElementKind.PARAMETER) {
-      node.staticElement = element;
-      if (node.inSetterContext()) {
-        ParameterElementImpl parameterImpl = element as ParameterElementImpl;
-        parameterImpl.markPotentiallyMutatedInScope();
-        _localVariableInfo.potentiallyMutatedInScope.add(element);
-        // If we are in some closure, check if it is not the same as where
-        // variable is declared.
-        if (_enclosingFunction != null &&
-            (element.enclosingElement != _enclosingFunction)) {
-          parameterImpl.markPotentiallyMutatedInClosure();
           _localVariableInfo.potentiallyMutatedInClosure.add(element);
         }
       }
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index 51c6ccc..7319a72 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -142,8 +142,8 @@
   /**
    * A table mapping Dart library URI's to the library.
    */
-  HashMap<String, SdkLibraryImpl> _libraryMap =
-      new HashMap<String, SdkLibraryImpl>();
+  LinkedHashMap<String, SdkLibraryImpl> _libraryMap =
+      new LinkedHashMap<String, SdkLibraryImpl>();
 
   /**
    * Return a list containing all of the sdk libraries in this mapping.
@@ -153,7 +153,7 @@
   /**
    * Return a list containing the library URI's for which a mapping is available.
    */
-  List<String> get uris => new List.from(_libraryMap.keys.toSet());
+  List<String> get uris => _libraryMap.keys.toList();
 
   /**
    * Return the library with the given 'dart:' [uri], or `null` if the URI does
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 6a1e38d..e7a9dea 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -20,7 +20,7 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/summary/idl.dart' show SdkBundle;
+import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
 import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:path/path.dart' as pathos;
 
@@ -266,7 +266,7 @@
       _analysisContext.sourceFactory = factory;
       // Try to use summaries.
       if (_useSummary) {
-        SdkBundle sdkBundle = _getSummarySdkBundle();
+        PackageBundle sdkBundle = _getSummarySdkBundle();
         if (sdkBundle != null) {
           _analysisContext.resultProvider =
               new SdkSummaryResultProvider(_analysisContext, sdkBundle);
@@ -470,7 +470,7 @@
           return null;
         }
       }
-      libraryPath = new JavaFile(libraryPath).getParent();
+      libraryPath = new JavaFile(library.path).getParent();
       if (filePath.startsWith("$libraryPath${JavaFile.separator}")) {
         String path =
             "${library.shortName}/${filePath.substring(libraryPath.length + 1)}";
@@ -553,16 +553,16 @@
   }
 
   /**
-   * Return the [SdkBundle] for this SDK, if it exists, or `null` otherwise.
+   * Return the [PackageBundle] for this SDK, if it exists, or `null` otherwise.
    */
-  SdkBundle _getSummarySdkBundle() {
+  PackageBundle _getSummarySdkBundle() {
     String rootPath = directory.getAbsolutePath();
     String path = pathos.join(rootPath, 'lib', '_internal', 'spec.sum');
     try {
       File file = new File(path);
       if (file.existsSync()) {
         List<int> bytes = file.readAsBytesSync();
-        return new SdkBundle.fromBuffer(bytes);
+        return new PackageBundle.fromBuffer(bytes);
       }
     } catch (exception, stackTrace) {
       AnalysisEngine.instance.logger.logError(
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 4a2362f..c487796 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -510,7 +510,7 @@
   @override
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     if (_strongMode) {
-      _inferFunctionInvocationGeneric(node);
+      _inferGenericInvoke(node);
     }
     DartType staticType = _computeInvokeReturnType(node.staticInvokeType);
     _recordStaticType(node, staticType);
@@ -626,14 +626,18 @@
           staticType = argumentType;
         }
       }
-    } else {
+    } else if (_strongMode) {
       DartType contextType = InferenceContext.getType(node);
-      if (_strongMode &&
-          contextType is InterfaceType &&
+      if (contextType is InterfaceType &&
           contextType.typeArguments.length == 1 &&
           contextType.element == _typeProvider.listType.element) {
         staticType = contextType.typeArguments[0];
         _resolver.inferenceContext.recordInference(node, contextType);
+      } else if (node.elements.isNotEmpty) {
+        // Infer the list type from the arguments.
+        staticType =
+            node.elements.map((e) => e.staticType).reduce(_leastUpperBound);
+        // TODO(jmesserly): record inference here?
       }
     }
     _recordStaticType(
@@ -672,15 +676,22 @@
           staticValueType = entryValueType;
         }
       }
-    } else {
+    } else if (_strongMode) {
       DartType contextType = InferenceContext.getType(node);
-      if (_strongMode &&
-          contextType is InterfaceType &&
+      if (contextType is InterfaceType &&
           contextType.typeArguments.length == 2 &&
           contextType.element == _typeProvider.mapType.element) {
         staticKeyType = contextType.typeArguments[0] ?? staticKeyType;
         staticValueType = contextType.typeArguments[1] ?? staticValueType;
         _resolver.inferenceContext.recordInference(node, contextType);
+      } else if (node.entries.isNotEmpty) {
+        // Infer the list type from the arguments.
+        staticKeyType =
+            node.entries.map((e) => e.key.staticType).reduce(_leastUpperBound);
+        staticValueType = node.entries
+            .map((e) => e.value.staticType)
+            .reduce(_leastUpperBound);
+        // TODO(jmesserly): record inference here?
       }
     }
     _recordStaticType(
@@ -731,7 +742,7 @@
     SimpleIdentifier methodNameNode = node.methodName;
     Element staticMethodElement = methodNameNode.staticElement;
     if (_strongMode) {
-      _inferMethodInvocationGeneric(node);
+      _inferGenericInvoke(node);
     }
     // Record types of the variable invoked as a function.
     if (staticMethodElement is VariableElement) {
@@ -1535,8 +1546,8 @@
     }
   }
 
-  // TODO(vsm): Use leafp's matchType here?
   DartType _findIteratedType(DartType type, DartType targetType) {
+    // TODO(vsm): Use leafp's matchType here?
     // Set by _find if match is found
     DartType result;
     // Elements we've already visited on a given inheritance path.
@@ -1600,6 +1611,12 @@
       }
       ClassElement returnType = library.getType(elementName);
       if (returnType != null) {
+        if (returnType.typeParameters.isNotEmpty) {
+          // Caller can't deal with unbound type parameters, so substitute
+          // `dynamic`.
+          return returnType.type.substitute4(
+              returnType.typeParameters.map((_) => _dynamicType).toList());
+        }
         return returnType.type;
       }
     }
@@ -1798,26 +1815,6 @@
   }
 
   /**
-   * Similar to [_inferMethodInvocationGeneric] but for function expression
-   * invocations.
-   */
-  // TODO(jmesserly): if we had a common AST interface between these two nodes,
-  // we could remove this duplicated code.
-  bool _inferFunctionInvocationGeneric(FunctionExpressionInvocation node) {
-    DartType instantiatedType = node.staticInvokeType;
-    DartType originalType = node.function.staticType;
-    if (instantiatedType is FunctionType && originalType is FunctionType) {
-      FunctionType inferred = _inferGenericInvoke(instantiatedType,
-          originalType, node.typeArguments, node.argumentList);
-      if (inferred != null) {
-        node.staticInvokeType = inferred;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
    * Given an uninstantiated generic type, try to infer the instantiated generic
    * type from the surrounding context.
    */
@@ -1832,41 +1829,42 @@
     return type;
   }
 
-  FunctionType _inferGenericInvoke(FunctionType invokeType, FunctionType fnType,
-      TypeArgumentList typeArguments, ArgumentList argumentList) {
+  bool _inferGenericInvoke(InvocationExpression node) {
     TypeSystem ts = _typeSystem;
-    if (typeArguments == null && ts is StrongTypeSystemImpl) {
-      if (fnType.typeFormals.isNotEmpty &&
-          ts.instantiateToBounds(fnType) == invokeType) {
-        // Get the parameters that correspond to the uninstantiated generic.
-        List<ParameterElement> rawParameters =
-            ResolverVisitor.resolveArgumentsToParameters(
-                argumentList, fnType.parameters, null);
+    DartType fnType = node.function.staticType;
+    if (node.typeArguments == null &&
+        fnType is FunctionType &&
+        fnType.typeFormals.isNotEmpty &&
+        ts is StrongTypeSystemImpl) {
+      ArgumentList argumentList = node.argumentList;
+      // Get the parameters that correspond to the uninstantiated generic.
+      List<ParameterElement> rawParameters = ResolverVisitor
+          .resolveArgumentsToParameters(argumentList, fnType.parameters, null);
 
-        List<DartType> paramTypes = <DartType>[];
-        List<DartType> argTypes = <DartType>[];
-        for (int i = 0, length = rawParameters.length; i < length; i++) {
-          ParameterElement parameter = rawParameters[i];
-          if (parameter != null) {
-            paramTypes.add(parameter.type);
-            argTypes.add(argumentList.arguments[i].staticType);
-          }
-        }
-
-        FunctionType inferred = ts.inferCallFromArguments(
-            _typeProvider, fnType, paramTypes, argTypes);
-
-        if (inferred != fnType) {
-          // Fix up the parameter elements based on inferred method.
-          List<ParameterElement> inferredParameters =
-              ResolverVisitor.resolveArgumentsToParameters(
-                  argumentList, inferred.parameters, null);
-          argumentList.correspondingStaticParameters = inferredParameters;
-          return inferred;
+      List<DartType> paramTypes = <DartType>[];
+      List<DartType> argTypes = <DartType>[];
+      for (int i = 0, length = rawParameters.length; i < length; i++) {
+        ParameterElement parameter = rawParameters[i];
+        if (parameter != null) {
+          paramTypes.add(parameter.type);
+          argTypes.add(argumentList.arguments[i].staticType);
         }
       }
+
+      FunctionType inferred = ts.inferGenericFunctionCall(_typeProvider, fnType,
+          paramTypes, argTypes, InferenceContext.getType(node));
+
+      if (inferred != node.staticInvokeType) {
+        // Fix up the parameter elements based on inferred method.
+        List<ParameterElement> inferredParameters =
+            ResolverVisitor.resolveArgumentsToParameters(
+                argumentList, inferred.parameters, null);
+        argumentList.correspondingStaticParameters = inferredParameters;
+        node.staticInvokeType = inferred;
+        return true;
+      }
     }
-    return null;
+    return false;
   }
 
   /**
@@ -1889,27 +1887,6 @@
   }
 
   /**
-   * Given a generic method invocation [node], attempt to infer the method's
-   * type variables, using the actual types of the arguments.
-   */
-  bool _inferMethodInvocationGeneric(MethodInvocation node) {
-    DartType instantiatedType = node.staticInvokeType;
-    DartType originalType = node.methodName.staticType;
-    // TODO(jmesserly): support generic `call` methods.
-    // Perhaps we should always record a FunctionType in staticInvokeType
-    // and the methodName's staticType.
-    if (instantiatedType is FunctionType && originalType is FunctionType) {
-      FunctionType inferred = _inferGenericInvoke(instantiatedType,
-          originalType, node.typeArguments, node.argumentList);
-      if (inferred != null) {
-        node.staticInvokeType = inferred;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
    * Given a method invocation [node], attempt to infer a better
    * type for the result if it is an inline JS invocation
    */
@@ -2056,6 +2033,14 @@
   }
 
   /**
+   * Computes the least upper bound between two types.
+   *
+   * See [TypeSystem.getLeastUpperBound].
+   */
+  DartType _leastUpperBound(DartType s, DartType t) =>
+      _typeSystem.getLeastUpperBound(_typeProvider, s, t);
+
+  /**
    * Record that the propagated type of the given node is the given type.
    *
    * @param expression the node whose type is to be recorded
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index b94cb64..d5ac50f 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -100,6 +100,14 @@
     ConstructorElementImpl constructor = name == null
         ? new ConstructorElementImpl("", -1)
         : new ConstructorElementImpl(name, 0);
+    if (name != null) {
+      if (name.isEmpty) {
+        constructor.nameEnd = definingClass.name.length;
+      } else {
+        constructor.periodOffset = definingClass.name.length;
+        constructor.nameEnd = definingClass.name.length + name.length + 1;
+      }
+    }
     constructor.synthetic = name == null;
     constructor.const2 = isConst;
     if (argumentTypes != null) {
@@ -501,12 +509,13 @@
   }
 
   static ParameterElementImpl namedParameter3(String name,
-      {DartType type, Expression initializer}) {
+      {DartType type, Expression initializer, String initializerCode}) {
     DefaultParameterElementImpl parameter =
         new DefaultParameterElementImpl(name, 0);
     parameter.parameterKind = ParameterKind.NAMED;
     parameter.type = type;
     parameter.constantInitializer = initializer;
+    parameter.defaultValueCode = initializerCode;
     return parameter;
   }
 
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 48c4f98..06f4bee 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -171,7 +171,9 @@
       fromEnvironment.parameters = <ParameterElement>[
         ElementFactory.requiredParameter2("name", stringType),
         ElementFactory.namedParameter3("defaultValue",
-            type: _boolType, initializer: AstFactory.booleanLiteral(false))
+            type: _boolType,
+            initializer: AstFactory.booleanLiteral(false),
+            initializerCode: 'false')
       ];
       fromEnvironment.factory = true;
       fromEnvironment.isCycleFree = true;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 851a990..ee4d0a1 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -68,11 +68,12 @@
   /// As a simplification, we do not actually store all constraints on each type
   /// parameter Tj. Instead we track Uj and Lj where U is the upper bound and
   /// L is the lower bound of that type parameter.
-  FunctionType inferCallFromArguments(
+  FunctionType inferGenericFunctionCall(
       TypeProvider typeProvider,
       FunctionType fnType,
       List<DartType> correspondingParameterTypes,
-      List<DartType> argumentTypes) {
+      List<DartType> argumentTypes,
+      DartType returnContextType) {
     if (fnType.typeFormals.isEmpty) {
       return fnType;
     }
@@ -84,6 +85,10 @@
     var inferringTypeSystem =
         new _StrongInferenceTypeSystem(typeProvider, fnType.typeFormals);
 
+    if (returnContextType != null) {
+      inferringTypeSystem.isSubtypeOf(fnType.returnType, returnContextType);
+    }
+
     for (int i = 0; i < argumentTypes.length; i++) {
       // Try to pass each argument to each parameter, recording any type
       // parameter bounds that were implied by this assignment.
@@ -105,7 +110,7 @@
    * Given a generic function type `F<T0, T1, ... Tn>` and a context type C,
    * infer an instantiation of F, such that `F<S0, S1, ..., Sn>` <: C.
    *
-   * This is similar to [inferCallFromArguments], but the return type is also
+   * This is similar to [inferGenericFunctionCall], but the return type is also
    * considered as part of the solution.
    *
    * If this function is called with a [contextType] that is also
@@ -284,18 +289,15 @@
   /**
    * Check that [f1] is a subtype of [f2].
    *
-   * [fuzzyArrows] indicates whether or not the f1 and f2 should be
-   * treated as fuzzy arrow types (and hence dynamic parameters to f2 treated
-   * as bottom).
+   * 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 fuzzyArrows: true}) {
-
+  bool _isFunctionSubtypeOf(FunctionType f1, FunctionType f2) {
     return FunctionTypeImpl.relate(
         f1,
         f2,
         (DartType t1, DartType t2) =>
-            _isSubtypeOf(t2, t1, null, dynamicIsBottom: fuzzyArrows),
+            _isSubtypeOf(t2, t1, null, dynamicIsBottom: true),
         instantiateToBounds,
         returnRelation: isSubtypeOf);
   }
diff --git a/pkg/analyzer/lib/src/string_source.dart b/pkg/analyzer/lib/src/string_source.dart
index b742db9..3cfbd2e 100644
--- a/pkg/analyzer/lib/src/string_source.dart
+++ b/pkg/analyzer/lib/src/string_source.dart
@@ -20,18 +20,22 @@
   final String fullName;
 
   @override
+  final Uri uri;
+
+  @override
   final int modificationStamp;
 
-  StringSource(this._contents, this.fullName)
-      : modificationStamp = new DateTime.now().millisecondsSinceEpoch;
+  StringSource(this._contents, String fullName)
+      : this.fullName = fullName,
+        uri = fullName == null ? null : new Uri.file(fullName),
+        modificationStamp = new DateTime.now().millisecondsSinceEpoch;
 
   @override
   TimestampedData<String> get contents =>
       new TimestampedData(modificationStamp, _contents);
 
   @override
-  String get encoding =>
-      throw new UnsupportedError("StringSource doesn't support encoding.");
+  String get encoding => uri.toString();
 
   @override
   int get hashCode => _contents.hashCode ^ fullName.hashCode;
@@ -43,11 +47,7 @@
   String get shortName => fullName;
 
   @override
-  Uri get uri =>
-      throw new UnsupportedError("StringSource doesn't support uri.");
-
-  UriKind get uriKind =>
-      throw new UnsupportedError("StringSource doesn't support uriKind.");
+  UriKind get uriKind => UriKind.FILE_URI;
 
   /**
    * Return `true` if the given [object] is a string source that is equal to
@@ -63,8 +63,7 @@
   bool exists() => true;
 
   @override
-  Uri resolveRelativeUri(Uri relativeUri) => throw new UnsupportedError(
-      "StringSource doesn't support resolveRelative.");
+  Uri resolveRelativeUri(Uri relativeUri) => uri.resolveUri(relativeUri);
 
   @override
   String toString() => 'StringSource ($fullName)';
diff --git a/pkg/analyzer/lib/src/summary/base.dart b/pkg/analyzer/lib/src/summary/base.dart
index c4a4cdb..1a1626e 100644
--- a/pkg/analyzer/lib/src/summary/base.dart
+++ b/pkg/analyzer/lib/src/summary/base.dart
@@ -33,4 +33,15 @@
    * Intended for testing and debugging only.
    */
   Map<String, Object> toMap();
+
+  /**
+   * Translate the data in this class into a JSON map, whose keys are the names
+   * of fields and whose values are the data stored in those fields,
+   * recursively converted into JSON.
+   *
+   * Fields containing their default value are elided.
+   *
+   * Intended for testing and debugging only.
+   */
+  Map<String, Object> toJson();
 }
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 5507871..99dbbce 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -9,6 +9,7 @@
 
 import 'flat_buffers.dart' as fb;
 import 'idl.dart' as idl;
+import 'dart:convert' as convert;
 
 class _ReferenceKindReader extends fb.Reader<idl.ReferenceKind> {
   const _ReferenceKindReader() : super();
@@ -274,6 +275,17 @@
 
 abstract class _EntityRefMixin implements idl.EntityRef {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (implicitFunctionTypeIndices.isNotEmpty) _result["implicitFunctionTypeIndices"] = implicitFunctionTypeIndices;
+    if (paramReference != 0) _result["paramReference"] = paramReference;
+    if (reference != 0) _result["reference"] = reference;
+    if (slot != 0) _result["slot"] = slot;
+    if (typeArguments.isNotEmpty) _result["typeArguments"] = typeArguments.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "implicitFunctionTypeIndices": implicitFunctionTypeIndices,
     "paramReference": paramReference,
@@ -281,6 +293,9 @@
     "slot": slot,
     "typeArguments": typeArguments,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class LinkedDependencyBuilder extends Object with _LinkedDependencyMixin implements idl.LinkedDependency {
@@ -372,10 +387,21 @@
 
 abstract class _LinkedDependencyMixin implements idl.LinkedDependency {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (parts.isNotEmpty) _result["parts"] = parts;
+    if (uri != '') _result["uri"] = uri;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "parts": parts,
     "uri": uri,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class LinkedExportNameBuilder extends Object with _LinkedExportNameMixin implements idl.LinkedExportName {
@@ -511,12 +537,25 @@
 
 abstract class _LinkedExportNameMixin implements idl.LinkedExportName {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (dependency != 0) _result["dependency"] = dependency;
+    if (kind != idl.ReferenceKind.classOrEnum) _result["kind"] = kind.toString().split('.')[1];
+    if (name != '') _result["name"] = name;
+    if (unit != 0) _result["unit"] = unit;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "dependency": dependency,
     "kind": kind,
     "name": name,
     "unit": unit,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class LinkedLibraryBuilder extends Object with _LinkedLibraryMixin implements idl.LinkedLibrary {
@@ -715,6 +754,17 @@
 
 abstract class _LinkedLibraryMixin implements idl.LinkedLibrary {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (dependencies.isNotEmpty) _result["dependencies"] = dependencies.map((_value) => _value.toJson()).toList();
+    if (exportNames.isNotEmpty) _result["exportNames"] = exportNames.map((_value) => _value.toJson()).toList();
+    if (importDependencies.isNotEmpty) _result["importDependencies"] = importDependencies;
+    if (numPrelinkedDependencies != 0) _result["numPrelinkedDependencies"] = numPrelinkedDependencies;
+    if (units.isNotEmpty) _result["units"] = units.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "dependencies": dependencies,
     "exportNames": exportNames,
@@ -722,6 +772,9 @@
     "numPrelinkedDependencies": numPrelinkedDependencies,
     "units": units,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class LinkedReferenceBuilder extends Object with _LinkedReferenceMixin implements idl.LinkedReference {
@@ -730,6 +783,7 @@
   int _containingReference;
   int _dependency;
   idl.ReferenceKind _kind;
+  int _localIndex;
   String _name;
   int _numTypeParameters;
   int _unit;
@@ -783,6 +837,22 @@
   }
 
   @override
+  int get localIndex => _localIndex ??= 0;
+
+  /**
+   * If [kind] is [ReferenceKind.function] (that is, the entity being referred
+   * to is a local function), the index of the function within
+   * [UnlinkedExecutable.localFunctions].  If [kind] is
+   * [ReferenceKind.variable], the index of the variable within
+   * [UnlinkedExecutable.localVariables].  Otherwise zero.
+   */
+  void set localIndex(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _localIndex = _value;
+  }
+
+  @override
   String get name => _name ??= '';
 
   /**
@@ -800,7 +870,8 @@
 
   /**
    * If the entity being referred to is generic, the number of type parameters
-   * it accepts.  Otherwise zero.
+   * it declares (does not include type parameters of enclosing entities).
+   * Otherwise zero.
    */
   void set numTypeParameters(int _value) {
     assert(!_finished);
@@ -826,10 +897,11 @@
     _unit = _value;
   }
 
-  LinkedReferenceBuilder({int containingReference, int dependency, idl.ReferenceKind kind, String name, int numTypeParameters, int unit})
+  LinkedReferenceBuilder({int containingReference, int dependency, idl.ReferenceKind kind, int localIndex, String name, int numTypeParameters, int unit})
     : _containingReference = containingReference,
       _dependency = dependency,
       _kind = kind,
+      _localIndex = localIndex,
       _name = name,
       _numTypeParameters = numTypeParameters,
       _unit = unit;
@@ -851,6 +923,9 @@
     if (_kind != null && _kind != idl.ReferenceKind.classOrEnum) {
       fbBuilder.addUint8(2, _kind.index);
     }
+    if (_localIndex != null && _localIndex != 0) {
+      fbBuilder.addUint32(6, _localIndex);
+    }
     if (offset_name != null) {
       fbBuilder.addOffset(3, offset_name);
     }
@@ -879,6 +954,7 @@
   int _containingReference;
   int _dependency;
   idl.ReferenceKind _kind;
+  int _localIndex;
   String _name;
   int _numTypeParameters;
   int _unit;
@@ -902,6 +978,12 @@
   }
 
   @override
+  int get localIndex {
+    _localIndex ??= const fb.Uint32Reader().vTableGet(_bp, 6, 0);
+    return _localIndex;
+  }
+
+  @override
   String get name {
     _name ??= const fb.StringReader().vTableGet(_bp, 3, '');
     return _name;
@@ -922,14 +1004,31 @@
 
 abstract class _LinkedReferenceMixin implements idl.LinkedReference {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (containingReference != 0) _result["containingReference"] = containingReference;
+    if (dependency != 0) _result["dependency"] = dependency;
+    if (kind != idl.ReferenceKind.classOrEnum) _result["kind"] = kind.toString().split('.')[1];
+    if (localIndex != 0) _result["localIndex"] = localIndex;
+    if (name != '') _result["name"] = name;
+    if (numTypeParameters != 0) _result["numTypeParameters"] = numTypeParameters;
+    if (unit != 0) _result["unit"] = unit;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "containingReference": containingReference,
     "dependency": dependency,
     "kind": kind,
+    "localIndex": localIndex,
     "name": name,
     "numTypeParameters": numTypeParameters,
     "unit": unit,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class LinkedUnitBuilder extends Object with _LinkedUnitMixin implements idl.LinkedUnit {
@@ -1022,17 +1121,29 @@
 
 abstract class _LinkedUnitMixin implements idl.LinkedUnit {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
+    if (types.isNotEmpty) _result["types"] = types.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "references": references,
     "types": types,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
-class SdkBundleBuilder extends Object with _SdkBundleMixin implements idl.SdkBundle {
+class PackageBundleBuilder extends Object with _PackageBundleMixin implements idl.PackageBundle {
   bool _finished = false;
 
   List<LinkedLibraryBuilder> _linkedLibraries;
   List<String> _linkedLibraryUris;
+  List<String> _unlinkedUnitHashes;
   List<UnlinkedUnitBuilder> _unlinkedUnits;
   List<String> _unlinkedUnitUris;
 
@@ -1051,7 +1162,8 @@
   List<String> get linkedLibraryUris => _linkedLibraryUris ??= <String>[];
 
   /**
-   * The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
+   * The list of URIs of items in [linkedLibraries], e.g. `dart:core` or
+   * `package:foo/bar.dart`.
    */
   void set linkedLibraryUris(List<String> _value) {
     assert(!_finished);
@@ -1059,10 +1171,22 @@
   }
 
   @override
+  List<String> get unlinkedUnitHashes => _unlinkedUnitHashes ??= <String>[];
+
+  /**
+   * List of MD5 hashes of the files listed in [unlinkedUnitUris].  Each hash
+   * is encoded as a hexadecimal string using lower case letters.
+   */
+  void set unlinkedUnitHashes(List<String> _value) {
+    assert(!_finished);
+    _unlinkedUnitHashes = _value;
+  }
+
+  @override
   List<UnlinkedUnitBuilder> get unlinkedUnits => _unlinkedUnits ??= <UnlinkedUnitBuilder>[];
 
   /**
-   * Unlinked information for the compilation units constituting the SDK.
+   * Unlinked information for the compilation units constituting the package.
    */
   void set unlinkedUnits(List<UnlinkedUnitBuilder> _value) {
     assert(!_finished);
@@ -1080,9 +1204,10 @@
     _unlinkedUnitUris = _value;
   }
 
-  SdkBundleBuilder({List<LinkedLibraryBuilder> linkedLibraries, List<String> linkedLibraryUris, List<UnlinkedUnitBuilder> unlinkedUnits, List<String> unlinkedUnitUris})
+  PackageBundleBuilder({List<LinkedLibraryBuilder> linkedLibraries, List<String> linkedLibraryUris, List<String> unlinkedUnitHashes, List<UnlinkedUnitBuilder> unlinkedUnits, List<String> unlinkedUnitUris})
     : _linkedLibraries = linkedLibraries,
       _linkedLibraryUris = linkedLibraryUris,
+      _unlinkedUnitHashes = unlinkedUnitHashes,
       _unlinkedUnits = unlinkedUnits,
       _unlinkedUnitUris = unlinkedUnitUris;
 
@@ -1096,6 +1221,7 @@
     _finished = true;
     fb.Offset offset_linkedLibraries;
     fb.Offset offset_linkedLibraryUris;
+    fb.Offset offset_unlinkedUnitHashes;
     fb.Offset offset_unlinkedUnits;
     fb.Offset offset_unlinkedUnitUris;
     if (!(_linkedLibraries == null || _linkedLibraries.isEmpty)) {
@@ -1104,6 +1230,9 @@
     if (!(_linkedLibraryUris == null || _linkedLibraryUris.isEmpty)) {
       offset_linkedLibraryUris = fbBuilder.writeList(_linkedLibraryUris.map((b) => fbBuilder.writeString(b)).toList());
     }
+    if (!(_unlinkedUnitHashes == null || _unlinkedUnitHashes.isEmpty)) {
+      offset_unlinkedUnitHashes = fbBuilder.writeList(_unlinkedUnitHashes.map((b) => fbBuilder.writeString(b)).toList());
+    }
     if (!(_unlinkedUnits == null || _unlinkedUnits.isEmpty)) {
       offset_unlinkedUnits = fbBuilder.writeList(_unlinkedUnits.map((b) => b.finish(fbBuilder)).toList());
     }
@@ -1117,6 +1246,9 @@
     if (offset_linkedLibraryUris != null) {
       fbBuilder.addOffset(1, offset_linkedLibraryUris);
     }
+    if (offset_unlinkedUnitHashes != null) {
+      fbBuilder.addOffset(4, offset_unlinkedUnitHashes);
+    }
     if (offset_unlinkedUnits != null) {
       fbBuilder.addOffset(2, offset_unlinkedUnits);
     }
@@ -1127,25 +1259,26 @@
   }
 }
 
-idl.SdkBundle readSdkBundle(List<int> buffer) {
+idl.PackageBundle readPackageBundle(List<int> buffer) {
   fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer);
-  return const _SdkBundleReader().read(rootRef);
+  return const _PackageBundleReader().read(rootRef);
 }
 
-class _SdkBundleReader extends fb.TableReader<_SdkBundleImpl> {
-  const _SdkBundleReader();
+class _PackageBundleReader extends fb.TableReader<_PackageBundleImpl> {
+  const _PackageBundleReader();
 
   @override
-  _SdkBundleImpl createObject(fb.BufferPointer bp) => new _SdkBundleImpl(bp);
+  _PackageBundleImpl createObject(fb.BufferPointer bp) => new _PackageBundleImpl(bp);
 }
 
-class _SdkBundleImpl extends Object with _SdkBundleMixin implements idl.SdkBundle {
+class _PackageBundleImpl extends Object with _PackageBundleMixin implements idl.PackageBundle {
   final fb.BufferPointer _bp;
 
-  _SdkBundleImpl(this._bp);
+  _PackageBundleImpl(this._bp);
 
   List<idl.LinkedLibrary> _linkedLibraries;
   List<String> _linkedLibraryUris;
+  List<String> _unlinkedUnitHashes;
   List<idl.UnlinkedUnit> _unlinkedUnits;
   List<String> _unlinkedUnitUris;
 
@@ -1162,6 +1295,12 @@
   }
 
   @override
+  List<String> get unlinkedUnitHashes {
+    _unlinkedUnitHashes ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 4, const <String>[]);
+    return _unlinkedUnitHashes;
+  }
+
+  @override
   List<idl.UnlinkedUnit> get unlinkedUnits {
     _unlinkedUnits ??= const fb.ListReader<idl.UnlinkedUnit>(const _UnlinkedUnitReader()).vTableGet(_bp, 2, const <idl.UnlinkedUnit>[]);
     return _unlinkedUnits;
@@ -1174,14 +1313,29 @@
   }
 }
 
-abstract class _SdkBundleMixin implements idl.SdkBundle {
+abstract class _PackageBundleMixin implements idl.PackageBundle {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (linkedLibraries.isNotEmpty) _result["linkedLibraries"] = linkedLibraries.map((_value) => _value.toJson()).toList();
+    if (linkedLibraryUris.isNotEmpty) _result["linkedLibraryUris"] = linkedLibraryUris;
+    if (unlinkedUnitHashes.isNotEmpty) _result["unlinkedUnitHashes"] = unlinkedUnitHashes;
+    if (unlinkedUnits.isNotEmpty) _result["unlinkedUnits"] = unlinkedUnits.map((_value) => _value.toJson()).toList();
+    if (unlinkedUnitUris.isNotEmpty) _result["unlinkedUnitUris"] = unlinkedUnitUris;
+    return _result;
+  }
+
   @override
   Map<String, Object> toMap() => {
     "linkedLibraries": linkedLibraries,
     "linkedLibraryUris": linkedLibraryUris,
+    "unlinkedUnitHashes": unlinkedUnitHashes,
     "unlinkedUnits": unlinkedUnits,
     "unlinkedUnitUris": unlinkedUnitUris,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedClassBuilder extends Object with _UnlinkedClassMixin implements idl.UnlinkedClass {
@@ -1554,6 +1708,25 @@
 
 abstract class _UnlinkedClassMixin implements idl.UnlinkedClass {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
+    if (executables.isNotEmpty) _result["executables"] = executables.map((_value) => _value.toJson()).toList();
+    if (fields.isNotEmpty) _result["fields"] = fields.map((_value) => _value.toJson()).toList();
+    if (hasNoSupertype != false) _result["hasNoSupertype"] = hasNoSupertype;
+    if (interfaces.isNotEmpty) _result["interfaces"] = interfaces.map((_value) => _value.toJson()).toList();
+    if (isAbstract != false) _result["isAbstract"] = isAbstract;
+    if (isMixinApplication != false) _result["isMixinApplication"] = isMixinApplication;
+    if (mixins.isNotEmpty) _result["mixins"] = mixins.map((_value) => _value.toJson()).toList();
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (supertype != null) _result["supertype"] = supertype.toJson();
+    if (typeParameters.isNotEmpty) _result["typeParameters"] = typeParameters.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "documentationComment": documentationComment,
@@ -1569,15 +1742,33 @@
     "supertype": supertype,
     "typeParameters": typeParameters,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedCombinatorBuilder extends Object with _UnlinkedCombinatorMixin implements idl.UnlinkedCombinator {
   bool _finished = false;
 
+  int _end;
   List<String> _hides;
+  int _offset;
   List<String> _shows;
 
   @override
+  int get end => _end ??= 0;
+
+  /**
+   * If this is a `show` combinator, offset of the end of the list of shown
+   * names.  Otherwise zero.
+   */
+  void set end(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _end = _value;
+  }
+
+  @override
   List<String> get hides => _hides ??= <String>[];
 
   /**
@@ -1589,6 +1780,19 @@
   }
 
   @override
+  int get offset => _offset ??= 0;
+
+  /**
+   * If this is a `show` combinator, offset of the `show` keyword.  Otherwise
+   * zero.
+   */
+  void set offset(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _offset = _value;
+  }
+
+  @override
   List<String> get shows => _shows ??= <String>[];
 
   /**
@@ -1599,8 +1803,10 @@
     _shows = _value;
   }
 
-  UnlinkedCombinatorBuilder({List<String> hides, List<String> shows})
-    : _hides = hides,
+  UnlinkedCombinatorBuilder({int end, List<String> hides, int offset, List<String> shows})
+    : _end = end,
+      _hides = hides,
+      _offset = offset,
       _shows = shows;
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -1615,9 +1821,15 @@
       offset_shows = fbBuilder.writeList(_shows.map((b) => fbBuilder.writeString(b)).toList());
     }
     fbBuilder.startTable();
+    if (_end != null && _end != 0) {
+      fbBuilder.addUint32(3, _end);
+    }
     if (offset_hides != null) {
       fbBuilder.addOffset(1, offset_hides);
     }
+    if (_offset != null && _offset != 0) {
+      fbBuilder.addUint32(2, _offset);
+    }
     if (offset_shows != null) {
       fbBuilder.addOffset(0, offset_shows);
     }
@@ -1637,16 +1849,30 @@
 
   _UnlinkedCombinatorImpl(this._bp);
 
+  int _end;
   List<String> _hides;
+  int _offset;
   List<String> _shows;
 
   @override
+  int get end {
+    _end ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    return _end;
+  }
+
+  @override
   List<String> get hides {
     _hides ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
     return _hides;
   }
 
   @override
+  int get offset {
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    return _offset;
+  }
+
+  @override
   List<String> get shows {
     _shows ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
     return _shows;
@@ -1655,10 +1881,25 @@
 
 abstract class _UnlinkedCombinatorMixin implements idl.UnlinkedCombinator {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (end != 0) _result["end"] = end;
+    if (hides.isNotEmpty) _result["hides"] = hides;
+    if (offset != 0) _result["offset"] = offset;
+    if (shows.isNotEmpty) _result["shows"] = shows;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
+    "end": end,
     "hides": hides,
+    "offset": offset,
     "shows": shows,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedConstBuilder extends Object with _UnlinkedConstMixin implements idl.UnlinkedConst {
@@ -1858,6 +2099,18 @@
 
 abstract class _UnlinkedConstMixin implements idl.UnlinkedConst {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (doubles.isNotEmpty) _result["doubles"] = doubles.map((_value) => _value.isFinite ? _value : _value.toString()).toList();
+    if (ints.isNotEmpty) _result["ints"] = ints;
+    if (isInvalid != false) _result["isInvalid"] = isInvalid;
+    if (operations.isNotEmpty) _result["operations"] = operations.map((_value) => _value.toString().split('.')[1]).toList();
+    if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
+    if (strings.isNotEmpty) _result["strings"] = strings;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "doubles": doubles,
     "ints": ints,
@@ -1866,6 +2119,9 @@
     "references": references,
     "strings": strings,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedConstructorInitializerBuilder extends Object with _UnlinkedConstructorInitializerMixin implements idl.UnlinkedConstructorInitializer {
@@ -2007,12 +2263,25 @@
 
 abstract class _UnlinkedConstructorInitializerMixin implements idl.UnlinkedConstructorInitializer {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (arguments.isNotEmpty) _result["arguments"] = arguments.map((_value) => _value.toJson()).toList();
+    if (expression != null) _result["expression"] = expression.toJson();
+    if (kind != idl.UnlinkedConstructorInitializerKind.field) _result["kind"] = kind.toString().split('.')[1];
+    if (name != '') _result["name"] = name;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "arguments": arguments,
     "expression": expression,
     "kind": kind,
     "name": name,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedDocumentationCommentBuilder extends Object with _UnlinkedDocumentationCommentMixin implements idl.UnlinkedDocumentationComment {
@@ -2124,11 +2393,23 @@
 
 abstract class _UnlinkedDocumentationCommentMixin implements idl.UnlinkedDocumentationComment {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (length != 0) _result["length"] = length;
+    if (offset != 0) _result["offset"] = offset;
+    if (text != '') _result["text"] = text;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "length": length,
     "offset": offset,
     "text": text,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedEnumBuilder extends Object with _UnlinkedEnumMixin implements idl.UnlinkedEnum {
@@ -2294,6 +2575,17 @@
 
 abstract class _UnlinkedEnumMixin implements idl.UnlinkedEnum {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (values.isNotEmpty) _result["values"] = values.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "documentationComment": documentationComment,
@@ -2301,6 +2593,9 @@
     "nameOffset": nameOffset,
     "values": values,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedEnumValueBuilder extends Object with _UnlinkedEnumValueMixin implements idl.UnlinkedEnumValue {
@@ -2412,11 +2707,23 @@
 
 abstract class _UnlinkedEnumValueMixin implements idl.UnlinkedEnumValue {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "documentationComment": documentationComment,
     "name": name,
     "nameOffset": nameOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedExecutableBuilder extends Object with _UnlinkedExecutableMixin implements idl.UnlinkedExecutable {
@@ -2434,10 +2741,13 @@
   bool _isStatic;
   idl.UnlinkedExecutableKind _kind;
   List<UnlinkedExecutableBuilder> _localFunctions;
+  List<UnlinkedLabelBuilder> _localLabels;
   List<UnlinkedVariableBuilder> _localVariables;
   String _name;
+  int _nameEnd;
   int _nameOffset;
   List<UnlinkedParamBuilder> _parameters;
+  int _periodOffset;
   EntityRefBuilder _redirectedConstructor;
   String _redirectedConstructorName;
   EntityRefBuilder _returnType;
@@ -2590,6 +2900,17 @@
   }
 
   @override
+  List<UnlinkedLabelBuilder> get localLabels => _localLabels ??= <UnlinkedLabelBuilder>[];
+
+  /**
+   * The list of local labels.
+   */
+  void set localLabels(List<UnlinkedLabelBuilder> _value) {
+    assert(!_finished);
+    _localLabels = _value;
+  }
+
+  @override
   List<UnlinkedVariableBuilder> get localVariables => _localVariables ??= <UnlinkedVariableBuilder>[];
 
   /**
@@ -2614,6 +2935,19 @@
   }
 
   @override
+  int get nameEnd => _nameEnd ??= 0;
+
+  /**
+   * If [kind] is [UnlinkedExecutableKind.constructor] and [name] is not empty,
+   * the offset of the end of the constructor name.  Otherwise zero.
+   */
+  void set nameEnd(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _nameEnd = _value;
+  }
+
+  @override
   int get nameOffset => _nameOffset ??= 0;
 
   /**
@@ -2642,6 +2976,19 @@
   }
 
   @override
+  int get periodOffset => _periodOffset ??= 0;
+
+  /**
+   * If [kind] is [UnlinkedExecutableKind.constructor] and [name] is not empty,
+   * the offset of the period before the constructor name.  Otherwise zero.
+   */
+  void set periodOffset(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _periodOffset = _value;
+  }
+
+  @override
   EntityRefBuilder get redirectedConstructor => _redirectedConstructor;
 
   /**
@@ -2671,7 +3018,10 @@
 
   /**
    * Declared return type of the executable.  Absent if the executable is a
-   * constructor or the return type is implicit.
+   * constructor or the return type is implicit.  Absent for executables
+   * associated with variable initializers and closures, since these
+   * executables may have return types that are not accessible via direct
+   * imports.
    */
   void set returnType(EntityRefBuilder _value) {
     assert(!_finished);
@@ -2714,7 +3064,7 @@
     _visibleOffset = _value;
   }
 
-  UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedConstructorInitializerBuilder> constantInitializers, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedVariableBuilder> localVariables, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
+  UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedConstructorInitializerBuilder> constantInitializers, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedLabelBuilder> localLabels, List<UnlinkedVariableBuilder> localVariables, String name, int nameEnd, int nameOffset, List<UnlinkedParamBuilder> parameters, int periodOffset, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _constantInitializers = constantInitializers,
       _documentationComment = documentationComment,
@@ -2727,10 +3077,13 @@
       _isStatic = isStatic,
       _kind = kind,
       _localFunctions = localFunctions,
+      _localLabels = localLabels,
       _localVariables = localVariables,
       _name = name,
+      _nameEnd = nameEnd,
       _nameOffset = nameOffset,
       _parameters = parameters,
+      _periodOffset = periodOffset,
       _redirectedConstructor = redirectedConstructor,
       _redirectedConstructorName = redirectedConstructorName,
       _returnType = returnType,
@@ -2745,6 +3098,7 @@
     fb.Offset offset_constantInitializers;
     fb.Offset offset_documentationComment;
     fb.Offset offset_localFunctions;
+    fb.Offset offset_localLabels;
     fb.Offset offset_localVariables;
     fb.Offset offset_name;
     fb.Offset offset_parameters;
@@ -2764,6 +3118,9 @@
     if (!(_localFunctions == null || _localFunctions.isEmpty)) {
       offset_localFunctions = fbBuilder.writeList(_localFunctions.map((b) => b.finish(fbBuilder)).toList());
     }
+    if (!(_localLabels == null || _localLabels.isEmpty)) {
+      offset_localLabels = fbBuilder.writeList(_localLabels.map((b) => b.finish(fbBuilder)).toList());
+    }
     if (!(_localVariables == null || _localVariables.isEmpty)) {
       offset_localVariables = fbBuilder.writeList(_localVariables.map((b) => b.finish(fbBuilder)).toList());
     }
@@ -2822,18 +3179,27 @@
     if (offset_localFunctions != null) {
       fbBuilder.addOffset(18, offset_localFunctions);
     }
+    if (offset_localLabels != null) {
+      fbBuilder.addOffset(22, offset_localLabels);
+    }
     if (offset_localVariables != null) {
       fbBuilder.addOffset(19, offset_localVariables);
     }
     if (offset_name != null) {
       fbBuilder.addOffset(1, offset_name);
     }
+    if (_nameEnd != null && _nameEnd != 0) {
+      fbBuilder.addUint32(23, _nameEnd);
+    }
     if (_nameOffset != null && _nameOffset != 0) {
       fbBuilder.addUint32(0, _nameOffset);
     }
     if (offset_parameters != null) {
       fbBuilder.addOffset(2, offset_parameters);
     }
+    if (_periodOffset != null && _periodOffset != 0) {
+      fbBuilder.addUint32(24, _periodOffset);
+    }
     if (offset_redirectedConstructor != null) {
       fbBuilder.addOffset(15, offset_redirectedConstructor);
     }
@@ -2880,10 +3246,13 @@
   bool _isStatic;
   idl.UnlinkedExecutableKind _kind;
   List<idl.UnlinkedExecutable> _localFunctions;
+  List<idl.UnlinkedLabel> _localLabels;
   List<idl.UnlinkedVariable> _localVariables;
   String _name;
+  int _nameEnd;
   int _nameOffset;
   List<idl.UnlinkedParam> _parameters;
+  int _periodOffset;
   idl.EntityRef _redirectedConstructor;
   String _redirectedConstructorName;
   idl.EntityRef _returnType;
@@ -2964,6 +3333,12 @@
   }
 
   @override
+  List<idl.UnlinkedLabel> get localLabels {
+    _localLabels ??= const fb.ListReader<idl.UnlinkedLabel>(const _UnlinkedLabelReader()).vTableGet(_bp, 22, const <idl.UnlinkedLabel>[]);
+    return _localLabels;
+  }
+
+  @override
   List<idl.UnlinkedVariable> get localVariables {
     _localVariables ??= const fb.ListReader<idl.UnlinkedVariable>(const _UnlinkedVariableReader()).vTableGet(_bp, 19, const <idl.UnlinkedVariable>[]);
     return _localVariables;
@@ -2976,6 +3351,12 @@
   }
 
   @override
+  int get nameEnd {
+    _nameEnd ??= const fb.Uint32Reader().vTableGet(_bp, 23, 0);
+    return _nameEnd;
+  }
+
+  @override
   int get nameOffset {
     _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _nameOffset;
@@ -2988,6 +3369,12 @@
   }
 
   @override
+  int get periodOffset {
+    _periodOffset ??= const fb.Uint32Reader().vTableGet(_bp, 24, 0);
+    return _periodOffset;
+  }
+
+  @override
   idl.EntityRef get redirectedConstructor {
     _redirectedConstructor ??= const _EntityRefReader().vTableGet(_bp, 15, null);
     return _redirectedConstructor;
@@ -3026,6 +3413,37 @@
 
 abstract class _UnlinkedExecutableMixin implements idl.UnlinkedExecutable {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (constantInitializers.isNotEmpty) _result["constantInitializers"] = constantInitializers.map((_value) => _value.toJson()).toList();
+    if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
+    if (inferredReturnTypeSlot != 0) _result["inferredReturnTypeSlot"] = inferredReturnTypeSlot;
+    if (isAbstract != false) _result["isAbstract"] = isAbstract;
+    if (isConst != false) _result["isConst"] = isConst;
+    if (isExternal != false) _result["isExternal"] = isExternal;
+    if (isFactory != false) _result["isFactory"] = isFactory;
+    if (isRedirectedConstructor != false) _result["isRedirectedConstructor"] = isRedirectedConstructor;
+    if (isStatic != false) _result["isStatic"] = isStatic;
+    if (kind != idl.UnlinkedExecutableKind.functionOrMethod) _result["kind"] = kind.toString().split('.')[1];
+    if (localFunctions.isNotEmpty) _result["localFunctions"] = localFunctions.map((_value) => _value.toJson()).toList();
+    if (localLabels.isNotEmpty) _result["localLabels"] = localLabels.map((_value) => _value.toJson()).toList();
+    if (localVariables.isNotEmpty) _result["localVariables"] = localVariables.map((_value) => _value.toJson()).toList();
+    if (name != '') _result["name"] = name;
+    if (nameEnd != 0) _result["nameEnd"] = nameEnd;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (parameters.isNotEmpty) _result["parameters"] = parameters.map((_value) => _value.toJson()).toList();
+    if (periodOffset != 0) _result["periodOffset"] = periodOffset;
+    if (redirectedConstructor != null) _result["redirectedConstructor"] = redirectedConstructor.toJson();
+    if (redirectedConstructorName != '') _result["redirectedConstructorName"] = redirectedConstructorName;
+    if (returnType != null) _result["returnType"] = returnType.toJson();
+    if (typeParameters.isNotEmpty) _result["typeParameters"] = typeParameters.map((_value) => _value.toJson()).toList();
+    if (visibleLength != 0) _result["visibleLength"] = visibleLength;
+    if (visibleOffset != 0) _result["visibleOffset"] = visibleOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "constantInitializers": constantInitializers,
@@ -3039,10 +3457,13 @@
     "isStatic": isStatic,
     "kind": kind,
     "localFunctions": localFunctions,
+    "localLabels": localLabels,
     "localVariables": localVariables,
     "name": name,
+    "nameEnd": nameEnd,
     "nameOffset": nameOffset,
     "parameters": parameters,
+    "periodOffset": periodOffset,
     "redirectedConstructor": redirectedConstructor,
     "redirectedConstructorName": redirectedConstructorName,
     "returnType": returnType,
@@ -3050,6 +3471,9 @@
     "visibleLength": visibleLength,
     "visibleOffset": visibleOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedExportNonPublicBuilder extends Object with _UnlinkedExportNonPublicMixin implements idl.UnlinkedExportNonPublic {
@@ -3183,12 +3607,25 @@
 
 abstract class _UnlinkedExportNonPublicMixin implements idl.UnlinkedExportNonPublic {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (offset != 0) _result["offset"] = offset;
+    if (uriEnd != 0) _result["uriEnd"] = uriEnd;
+    if (uriOffset != 0) _result["uriOffset"] = uriOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "offset": offset,
     "uriEnd": uriEnd,
     "uriOffset": uriOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedExportPublicBuilder extends Object with _UnlinkedExportPublicMixin implements idl.UnlinkedExportPublic {
@@ -3275,10 +3712,21 @@
 
 abstract class _UnlinkedExportPublicMixin implements idl.UnlinkedExportPublic {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (combinators.isNotEmpty) _result["combinators"] = combinators.map((_value) => _value.toJson()).toList();
+    if (uri != '') _result["uri"] = uri;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "combinators": combinators,
     "uri": uri,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedImportBuilder extends Object with _UnlinkedImportMixin implements idl.UnlinkedImport {
@@ -3565,6 +4013,22 @@
 
 abstract class _UnlinkedImportMixin implements idl.UnlinkedImport {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (combinators.isNotEmpty) _result["combinators"] = combinators.map((_value) => _value.toJson()).toList();
+    if (isDeferred != false) _result["isDeferred"] = isDeferred;
+    if (isImplicit != false) _result["isImplicit"] = isImplicit;
+    if (offset != 0) _result["offset"] = offset;
+    if (prefixOffset != 0) _result["prefixOffset"] = prefixOffset;
+    if (prefixReference != 0) _result["prefixReference"] = prefixReference;
+    if (uri != '') _result["uri"] = uri;
+    if (uriEnd != 0) _result["uriEnd"] = uriEnd;
+    if (uriOffset != 0) _result["uriOffset"] = uriOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "combinators": combinators,
@@ -3577,6 +4041,158 @@
     "uriEnd": uriEnd,
     "uriOffset": uriOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
+}
+
+class UnlinkedLabelBuilder extends Object with _UnlinkedLabelMixin implements idl.UnlinkedLabel {
+  bool _finished = false;
+
+  bool _isOnSwitchMember;
+  bool _isOnSwitchStatement;
+  String _name;
+  int _nameOffset;
+
+  @override
+  bool get isOnSwitchMember => _isOnSwitchMember ??= false;
+
+  /**
+   * Return `true` if this label is associated with a `switch` member (`case` or
+   * `default`).
+   */
+  void set isOnSwitchMember(bool _value) {
+    assert(!_finished);
+    _isOnSwitchMember = _value;
+  }
+
+  @override
+  bool get isOnSwitchStatement => _isOnSwitchStatement ??= false;
+
+  /**
+   * Return `true` if this label is associated with a `switch` statement.
+   */
+  void set isOnSwitchStatement(bool _value) {
+    assert(!_finished);
+    _isOnSwitchStatement = _value;
+  }
+
+  @override
+  String get name => _name ??= '';
+
+  /**
+   * Name of the label.
+   */
+  void set name(String _value) {
+    assert(!_finished);
+    _name = _value;
+  }
+
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
+  /**
+   * Offset of the label relative to the beginning of the file.
+   */
+  void set nameOffset(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _nameOffset = _value;
+  }
+
+  UnlinkedLabelBuilder({bool isOnSwitchMember, bool isOnSwitchStatement, String name, int nameOffset})
+    : _isOnSwitchMember = isOnSwitchMember,
+      _isOnSwitchStatement = isOnSwitchStatement,
+      _name = name,
+      _nameOffset = nameOffset;
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    assert(!_finished);
+    _finished = true;
+    fb.Offset offset_name;
+    if (_name != null) {
+      offset_name = fbBuilder.writeString(_name);
+    }
+    fbBuilder.startTable();
+    if (_isOnSwitchMember == true) {
+      fbBuilder.addBool(2, true);
+    }
+    if (_isOnSwitchStatement == true) {
+      fbBuilder.addBool(3, true);
+    }
+    if (offset_name != null) {
+      fbBuilder.addOffset(0, offset_name);
+    }
+    if (_nameOffset != null && _nameOffset != 0) {
+      fbBuilder.addUint32(1, _nameOffset);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _UnlinkedLabelReader extends fb.TableReader<_UnlinkedLabelImpl> {
+  const _UnlinkedLabelReader();
+
+  @override
+  _UnlinkedLabelImpl createObject(fb.BufferPointer bp) => new _UnlinkedLabelImpl(bp);
+}
+
+class _UnlinkedLabelImpl extends Object with _UnlinkedLabelMixin implements idl.UnlinkedLabel {
+  final fb.BufferPointer _bp;
+
+  _UnlinkedLabelImpl(this._bp);
+
+  bool _isOnSwitchMember;
+  bool _isOnSwitchStatement;
+  String _name;
+  int _nameOffset;
+
+  @override
+  bool get isOnSwitchMember {
+    _isOnSwitchMember ??= const fb.BoolReader().vTableGet(_bp, 2, false);
+    return _isOnSwitchMember;
+  }
+
+  @override
+  bool get isOnSwitchStatement {
+    _isOnSwitchStatement ??= const fb.BoolReader().vTableGet(_bp, 3, false);
+    return _isOnSwitchStatement;
+  }
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
+    return _name;
+  }
+
+  @override
+  int get nameOffset {
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    return _nameOffset;
+  }
+}
+
+abstract class _UnlinkedLabelMixin implements idl.UnlinkedLabel {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (isOnSwitchMember != false) _result["isOnSwitchMember"] = isOnSwitchMember;
+    if (isOnSwitchStatement != false) _result["isOnSwitchStatement"] = isOnSwitchStatement;
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+    "isOnSwitchMember": isOnSwitchMember,
+    "isOnSwitchStatement": isOnSwitchStatement,
+    "name": name,
+    "nameOffset": nameOffset,
+  };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedParamBuilder extends Object with _UnlinkedParamMixin implements idl.UnlinkedParam {
@@ -3584,7 +4200,9 @@
 
   List<UnlinkedConstBuilder> _annotations;
   UnlinkedConstBuilder _defaultValue;
+  String _defaultValueCode;
   int _inferredTypeSlot;
+  UnlinkedExecutableBuilder _initializer;
   bool _isFunctionTyped;
   bool _isInitializingFormal;
   idl.UnlinkedParamKind _kind;
@@ -3620,6 +4238,18 @@
   }
 
   @override
+  String get defaultValueCode => _defaultValueCode ??= '';
+
+  /**
+   * If the parameter has a default value, the source text of the constant
+   * expression in the default value.  Otherwise the empty string.
+   */
+  void set defaultValueCode(String _value) {
+    assert(!_finished);
+    _defaultValueCode = _value;
+  }
+
+  @override
   int get inferredTypeSlot => _inferredTypeSlot ??= 0;
 
   /**
@@ -3640,6 +4270,18 @@
   }
 
   @override
+  UnlinkedExecutableBuilder get initializer => _initializer;
+
+  /**
+   * The synthetic initializer function of the parameter.  Absent if the variable
+   * does not have an initializer.
+   */
+  void set initializer(UnlinkedExecutableBuilder _value) {
+    assert(!_finished);
+    _initializer = _value;
+  }
+
+  @override
   bool get isFunctionTyped => _isFunctionTyped ??= false;
 
   /**
@@ -3744,10 +4386,12 @@
     _visibleOffset = _value;
   }
 
-  UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder defaultValue, int inferredTypeSlot, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type, int visibleLength, int visibleOffset})
+  UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder defaultValue, String defaultValueCode, int inferredTypeSlot, UnlinkedExecutableBuilder initializer, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _defaultValue = defaultValue,
+      _defaultValueCode = defaultValueCode,
       _inferredTypeSlot = inferredTypeSlot,
+      _initializer = initializer,
       _isFunctionTyped = isFunctionTyped,
       _isInitializingFormal = isInitializingFormal,
       _kind = kind,
@@ -3763,6 +4407,8 @@
     _finished = true;
     fb.Offset offset_annotations;
     fb.Offset offset_defaultValue;
+    fb.Offset offset_defaultValueCode;
+    fb.Offset offset_initializer;
     fb.Offset offset_name;
     fb.Offset offset_parameters;
     fb.Offset offset_type;
@@ -3772,6 +4418,12 @@
     if (_defaultValue != null) {
       offset_defaultValue = _defaultValue.finish(fbBuilder);
     }
+    if (_defaultValueCode != null) {
+      offset_defaultValueCode = fbBuilder.writeString(_defaultValueCode);
+    }
+    if (_initializer != null) {
+      offset_initializer = _initializer.finish(fbBuilder);
+    }
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
@@ -3788,9 +4440,15 @@
     if (offset_defaultValue != null) {
       fbBuilder.addOffset(7, offset_defaultValue);
     }
+    if (offset_defaultValueCode != null) {
+      fbBuilder.addOffset(13, offset_defaultValueCode);
+    }
     if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
       fbBuilder.addUint32(2, _inferredTypeSlot);
     }
+    if (offset_initializer != null) {
+      fbBuilder.addOffset(12, offset_initializer);
+    }
     if (_isFunctionTyped == true) {
       fbBuilder.addBool(5, true);
     }
@@ -3836,7 +4494,9 @@
 
   List<idl.UnlinkedConst> _annotations;
   idl.UnlinkedConst _defaultValue;
+  String _defaultValueCode;
   int _inferredTypeSlot;
+  idl.UnlinkedExecutable _initializer;
   bool _isFunctionTyped;
   bool _isInitializingFormal;
   idl.UnlinkedParamKind _kind;
@@ -3860,12 +4520,24 @@
   }
 
   @override
+  String get defaultValueCode {
+    _defaultValueCode ??= const fb.StringReader().vTableGet(_bp, 13, '');
+    return _defaultValueCode;
+  }
+
+  @override
   int get inferredTypeSlot {
     _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _inferredTypeSlot;
   }
 
   @override
+  idl.UnlinkedExecutable get initializer {
+    _initializer ??= const _UnlinkedExecutableReader().vTableGet(_bp, 12, null);
+    return _initializer;
+  }
+
+  @override
   bool get isFunctionTyped {
     _isFunctionTyped ??= const fb.BoolReader().vTableGet(_bp, 5, false);
     return _isFunctionTyped;
@@ -3922,10 +4594,32 @@
 
 abstract class _UnlinkedParamMixin implements idl.UnlinkedParam {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (defaultValue != null) _result["defaultValue"] = defaultValue.toJson();
+    if (defaultValueCode != '') _result["defaultValueCode"] = defaultValueCode;
+    if (inferredTypeSlot != 0) _result["inferredTypeSlot"] = inferredTypeSlot;
+    if (initializer != null) _result["initializer"] = initializer.toJson();
+    if (isFunctionTyped != false) _result["isFunctionTyped"] = isFunctionTyped;
+    if (isInitializingFormal != false) _result["isInitializingFormal"] = isInitializingFormal;
+    if (kind != idl.UnlinkedParamKind.required) _result["kind"] = kind.toString().split('.')[1];
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (parameters.isNotEmpty) _result["parameters"] = parameters.map((_value) => _value.toJson()).toList();
+    if (type != null) _result["type"] = type.toJson();
+    if (visibleLength != 0) _result["visibleLength"] = visibleLength;
+    if (visibleOffset != 0) _result["visibleOffset"] = visibleOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "defaultValue": defaultValue,
+    "defaultValueCode": defaultValueCode,
     "inferredTypeSlot": inferredTypeSlot,
+    "initializer": initializer,
     "isFunctionTyped": isFunctionTyped,
     "isInitializingFormal": isInitializingFormal,
     "kind": kind,
@@ -3936,6 +4630,9 @@
     "visibleLength": visibleLength,
     "visibleOffset": visibleOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedPartBuilder extends Object with _UnlinkedPartMixin implements idl.UnlinkedPart {
@@ -4045,11 +4742,23 @@
 
 abstract class _UnlinkedPartMixin implements idl.UnlinkedPart {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (uriEnd != 0) _result["uriEnd"] = uriEnd;
+    if (uriOffset != 0) _result["uriOffset"] = uriOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "uriEnd": uriEnd,
     "uriOffset": uriOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedPublicNameBuilder extends Object with _UnlinkedPublicNameMixin implements idl.UnlinkedPublicName {
@@ -4189,12 +4898,25 @@
 
 abstract class _UnlinkedPublicNameMixin implements idl.UnlinkedPublicName {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (kind != idl.ReferenceKind.classOrEnum) _result["kind"] = kind.toString().split('.')[1];
+    if (members.isNotEmpty) _result["members"] = members.map((_value) => _value.toJson()).toList();
+    if (name != '') _result["name"] = name;
+    if (numTypeParameters != 0) _result["numTypeParameters"] = numTypeParameters;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "kind": kind,
     "members": members,
     "name": name,
     "numTypeParameters": numTypeParameters,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedPublicNamespaceBuilder extends Object with _UnlinkedPublicNamespaceMixin implements idl.UnlinkedPublicNamespace {
@@ -4321,11 +5043,23 @@
 
 abstract class _UnlinkedPublicNamespaceMixin implements idl.UnlinkedPublicNamespace {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (exports.isNotEmpty) _result["exports"] = exports.map((_value) => _value.toJson()).toList();
+    if (names.isNotEmpty) _result["names"] = names.map((_value) => _value.toJson()).toList();
+    if (parts.isNotEmpty) _result["parts"] = parts;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "exports": exports,
     "names": names,
     "parts": parts,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedReferenceBuilder extends Object with _UnlinkedReferenceMixin implements idl.UnlinkedReference {
@@ -4340,6 +5074,7 @@
   /**
    * Name of the entity being referred to.  For the pseudo-type `dynamic`, the
    * string is "dynamic".  For the pseudo-type `void`, the string is "void".
+   * For the pseudo-type `bottom`, the string is "*bottom*".
    */
   void set name(String _value) {
     assert(!_finished);
@@ -4415,10 +5150,21 @@
 
 abstract class _UnlinkedReferenceMixin implements idl.UnlinkedReference {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (name != '') _result["name"] = name;
+    if (prefixReference != 0) _result["prefixReference"] = prefixReference;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "name": name,
     "prefixReference": prefixReference,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedTypedefBuilder extends Object with _UnlinkedTypedefMixin implements idl.UnlinkedTypedef {
@@ -4638,6 +5384,19 @@
 
 abstract class _UnlinkedTypedefMixin implements idl.UnlinkedTypedef {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (parameters.isNotEmpty) _result["parameters"] = parameters.map((_value) => _value.toJson()).toList();
+    if (returnType != null) _result["returnType"] = returnType.toJson();
+    if (typeParameters.isNotEmpty) _result["typeParameters"] = typeParameters.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "documentationComment": documentationComment,
@@ -4647,6 +5406,9 @@
     "returnType": returnType,
     "typeParameters": typeParameters,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedTypeParamBuilder extends Object with _UnlinkedTypeParamMixin implements idl.UnlinkedTypeParam {
@@ -4785,12 +5547,25 @@
 
 abstract class _UnlinkedTypeParamMixin implements idl.UnlinkedTypeParam {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (bound != null) _result["bound"] = bound.toJson();
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "bound": bound,
     "name": name,
     "nameOffset": nameOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedUnitBuilder extends Object with _UnlinkedUnitMixin implements idl.UnlinkedUnit {
@@ -5241,6 +6016,27 @@
 
 abstract class _UnlinkedUnitMixin implements idl.UnlinkedUnit {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (classes.isNotEmpty) _result["classes"] = classes.map((_value) => _value.toJson()).toList();
+    if (enums.isNotEmpty) _result["enums"] = enums.map((_value) => _value.toJson()).toList();
+    if (executables.isNotEmpty) _result["executables"] = executables.map((_value) => _value.toJson()).toList();
+    if (exports.isNotEmpty) _result["exports"] = exports.map((_value) => _value.toJson()).toList();
+    if (imports.isNotEmpty) _result["imports"] = imports.map((_value) => _value.toJson()).toList();
+    if (libraryAnnotations.isNotEmpty) _result["libraryAnnotations"] = libraryAnnotations.map((_value) => _value.toJson()).toList();
+    if (libraryDocumentationComment != null) _result["libraryDocumentationComment"] = libraryDocumentationComment.toJson();
+    if (libraryName != '') _result["libraryName"] = libraryName;
+    if (libraryNameLength != 0) _result["libraryNameLength"] = libraryNameLength;
+    if (libraryNameOffset != 0) _result["libraryNameOffset"] = libraryNameOffset;
+    if (parts.isNotEmpty) _result["parts"] = parts.map((_value) => _value.toJson()).toList();
+    if (publicNamespace != null) _result["publicNamespace"] = publicNamespace.toJson();
+    if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
+    if (typedefs.isNotEmpty) _result["typedefs"] = typedefs.map((_value) => _value.toJson()).toList();
+    if (variables.isNotEmpty) _result["variables"] = variables.map((_value) => _value.toJson()).toList();
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "classes": classes,
     "enums": enums,
@@ -5258,6 +6054,9 @@
     "typedefs": typedefs,
     "variables": variables,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
 class UnlinkedVariableBuilder extends Object with _UnlinkedVariableMixin implements idl.UnlinkedVariable {
@@ -5267,6 +6066,7 @@
   UnlinkedConstBuilder _constExpr;
   UnlinkedDocumentationCommentBuilder _documentationComment;
   int _inferredTypeSlot;
+  UnlinkedExecutableBuilder _initializer;
   bool _isConst;
   bool _isFinal;
   bool _isStatic;
@@ -5329,6 +6129,18 @@
   }
 
   @override
+  UnlinkedExecutableBuilder get initializer => _initializer;
+
+  /**
+   * The synthetic initializer function of the variable.  Absent if the variable
+   * does not have an initializer.
+   */
+  void set initializer(UnlinkedExecutableBuilder _value) {
+    assert(!_finished);
+    _initializer = _value;
+  }
+
+  @override
   bool get isConst => _isConst ??= false;
 
   /**
@@ -5440,11 +6252,12 @@
     _visibleOffset = _value;
   }
 
-  UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder constExpr, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type, int visibleLength, int visibleOffset})
+  UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder constExpr, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, UnlinkedExecutableBuilder initializer, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _constExpr = constExpr,
       _documentationComment = documentationComment,
       _inferredTypeSlot = inferredTypeSlot,
+      _initializer = initializer,
       _isConst = isConst,
       _isFinal = isFinal,
       _isStatic = isStatic,
@@ -5461,6 +6274,7 @@
     fb.Offset offset_annotations;
     fb.Offset offset_constExpr;
     fb.Offset offset_documentationComment;
+    fb.Offset offset_initializer;
     fb.Offset offset_name;
     fb.Offset offset_type;
     if (!(_annotations == null || _annotations.isEmpty)) {
@@ -5472,6 +6286,9 @@
     if (_documentationComment != null) {
       offset_documentationComment = _documentationComment.finish(fbBuilder);
     }
+    if (_initializer != null) {
+      offset_initializer = _initializer.finish(fbBuilder);
+    }
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
@@ -5491,6 +6308,9 @@
     if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
       fbBuilder.addUint32(9, _inferredTypeSlot);
     }
+    if (offset_initializer != null) {
+      fbBuilder.addOffset(13, offset_initializer);
+    }
     if (_isConst == true) {
       fbBuilder.addBool(6, true);
     }
@@ -5538,6 +6358,7 @@
   idl.UnlinkedConst _constExpr;
   idl.UnlinkedDocumentationComment _documentationComment;
   int _inferredTypeSlot;
+  idl.UnlinkedExecutable _initializer;
   bool _isConst;
   bool _isFinal;
   bool _isStatic;
@@ -5573,6 +6394,12 @@
   }
 
   @override
+  idl.UnlinkedExecutable get initializer {
+    _initializer ??= const _UnlinkedExecutableReader().vTableGet(_bp, 13, null);
+    return _initializer;
+  }
+
+  @override
   bool get isConst {
     _isConst ??= const fb.BoolReader().vTableGet(_bp, 6, false);
     return _isConst;
@@ -5629,11 +6456,32 @@
 
 abstract class _UnlinkedVariableMixin implements idl.UnlinkedVariable {
   @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (annotations.isNotEmpty) _result["annotations"] = annotations.map((_value) => _value.toJson()).toList();
+    if (constExpr != null) _result["constExpr"] = constExpr.toJson();
+    if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
+    if (inferredTypeSlot != 0) _result["inferredTypeSlot"] = inferredTypeSlot;
+    if (initializer != null) _result["initializer"] = initializer.toJson();
+    if (isConst != false) _result["isConst"] = isConst;
+    if (isFinal != false) _result["isFinal"] = isFinal;
+    if (isStatic != false) _result["isStatic"] = isStatic;
+    if (name != '') _result["name"] = name;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (propagatedTypeSlot != 0) _result["propagatedTypeSlot"] = propagatedTypeSlot;
+    if (type != null) _result["type"] = type.toJson();
+    if (visibleLength != 0) _result["visibleLength"] = visibleLength;
+    if (visibleOffset != 0) _result["visibleOffset"] = visibleOffset;
+    return _result;
+  }
+
+  @override
   Map<String, Object> toMap() => {
     "annotations": annotations,
     "constExpr": constExpr,
     "documentationComment": documentationComment,
     "inferredTypeSlot": inferredTypeSlot,
+    "initializer": initializer,
     "isConst": isConst,
     "isFinal": isFinal,
     "isStatic": isStatic,
@@ -5644,5 +6492,8 @@
     "visibleLength": visibleLength,
     "visibleOffset": visibleOffset,
   };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
 }
 
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index fca673c..9d840b9 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -292,6 +292,16 @@
   ReferenceKind get kind;
 
   /**
+   * If [kind] is [ReferenceKind.function] (that is, the entity being referred
+   * to is a local function), the index of the function within
+   * [UnlinkedExecutable.localFunctions].  If [kind] is
+   * [ReferenceKind.variable], the index of the variable within
+   * [UnlinkedExecutable.localVariables].  Otherwise zero.
+   */
+  @Id(6)
+  int get localIndex;
+
+  /**
    * If this [LinkedReference] doesn't have an associated [UnlinkedReference],
    * name of the entity being referred to.  For the pseudo-type `dynamic`, the
    * string is "dynamic".  For the pseudo-type `void`, the string is "void".
@@ -301,7 +311,8 @@
 
   /**
    * If the entity being referred to is generic, the number of type parameters
-   * it accepts.  Otherwise zero.
+   * it declares (does not include type parameters of enclosing entities).
+   * Otherwise zero.
    */
   @Id(4)
   int get numTypeParameters;
@@ -343,6 +354,47 @@
 }
 
 /**
+ * Summary information about a package.
+ */
+@topLevel
+abstract class PackageBundle extends base.SummaryClass {
+  factory PackageBundle.fromBuffer(List<int> buffer) =>
+      generated.readPackageBundle(buffer);
+
+  /**
+   * Linked libraries.
+   */
+  @Id(0)
+  List<LinkedLibrary> get linkedLibraries;
+
+  /**
+   * The list of URIs of items in [linkedLibraries], e.g. `dart:core` or
+   * `package:foo/bar.dart`.
+   */
+  @Id(1)
+  List<String> get linkedLibraryUris;
+
+  /**
+   * List of MD5 hashes of the files listed in [unlinkedUnitUris].  Each hash
+   * is encoded as a hexadecimal string using lower case letters.
+   */
+  @Id(4)
+  List<String> get unlinkedUnitHashes;
+
+  /**
+   * Unlinked information for the compilation units constituting the package.
+   */
+  @Id(2)
+  List<UnlinkedUnit> get unlinkedUnits;
+
+  /**
+   * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
+   */
+  @Id(3)
+  List<String> get unlinkedUnitUris;
+}
+
+/**
  * Enum used to indicate the kind of entity referred to by a
  * [LinkedReference].
  */
@@ -380,6 +432,16 @@
   typedef,
 
   /**
+   * The entity is a local function.
+   */
+  function,
+
+  /**
+   * The entity is a local variable.
+   */
+  variable,
+
+  /**
    * The entity is a top level function.
    */
   topLevelFunction,
@@ -401,39 +463,6 @@
 }
 
 /**
- * Information about SDK.
- */
-@topLevel
-abstract class SdkBundle extends base.SummaryClass {
-  factory SdkBundle.fromBuffer(List<int> buffer) =>
-      generated.readSdkBundle(buffer);
-
-  /**
-   * Linked libraries.
-   */
-  @Id(0)
-  List<LinkedLibrary> get linkedLibraries;
-
-  /**
-   * The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
-   */
-  @Id(1)
-  List<String> get linkedLibraryUris;
-
-  /**
-   * Unlinked information for the compilation units constituting the SDK.
-   */
-  @Id(2)
-  List<UnlinkedUnit> get unlinkedUnits;
-
-  /**
-   * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
-   */
-  @Id(3)
-  List<String> get unlinkedUnitUris;
-}
-
-/**
  * Unlinked summary information about a class declaration.
  */
 abstract class UnlinkedClass extends base.SummaryClass {
@@ -528,12 +557,28 @@
  */
 abstract class UnlinkedCombinator extends base.SummaryClass {
   /**
+   * If this is a `show` combinator, offset of the end of the list of shown
+   * names.  Otherwise zero.
+   */
+  @informative
+  @Id(3)
+  int get end;
+
+  /**
    * List of names which are hidden.  Empty if this is a `show` combinator.
    */
   @Id(1)
   List<String> get hides;
 
   /**
+   * If this is a `show` combinator, offset of the `show` keyword.  Otherwise
+   * zero.
+   */
+  @informative
+  @Id(2)
+  int get offset;
+
+  /**
    * List of names which are shown.  Empty if this is a `hide` combinator.
    */
   @Id(0)
@@ -1122,6 +1167,12 @@
   List<UnlinkedExecutable> get localFunctions;
 
   /**
+   * The list of local labels.
+   */
+  @Id(22)
+  List<UnlinkedLabel> get localLabels;
+
+  /**
    * The list of local variables.
    */
   @Id(19)
@@ -1136,6 +1187,14 @@
   String get name;
 
   /**
+   * If [kind] is [UnlinkedExecutableKind.constructor] and [name] is not empty,
+   * the offset of the end of the constructor name.  Otherwise zero.
+   */
+  @informative
+  @Id(23)
+  int get nameEnd;
+
+  /**
    * Offset of the executable name relative to the beginning of the file.  For
    * named constructors, this excludes the class name and excludes the ".".
    * For unnamed constructors, this is the offset of the class name (i.e. the
@@ -1154,6 +1213,14 @@
   List<UnlinkedParam> get parameters;
 
   /**
+   * If [kind] is [UnlinkedExecutableKind.constructor] and [name] is not empty,
+   * the offset of the period before the constructor name.  Otherwise zero.
+   */
+  @informative
+  @Id(24)
+  int get periodOffset;
+
+  /**
    * If [isRedirectedConstructor] and [isFactory] are both `true`, the
    * constructor to which this constructor redirects; otherwise empty.
    */
@@ -1170,7 +1237,10 @@
 
   /**
    * Declared return type of the executable.  Absent if the executable is a
-   * constructor or the return type is implicit.
+   * constructor or the return type is implicit.  Absent for executables
+   * associated with variable initializers and closures, since these
+   * executables may have return types that are not accessible via direct
+   * imports.
    */
   @Id(3)
   EntityRef get returnType;
@@ -1350,6 +1420,37 @@
 }
 
 /**
+ * Unlinked summary information about a label.
+ */
+abstract class UnlinkedLabel extends base.SummaryClass {
+  /**
+   * Return `true` if this label is associated with a `switch` member (`case` or
+   * `default`).
+   */
+  @Id(2)
+  bool get isOnSwitchMember;
+
+  /**
+   * Return `true` if this label is associated with a `switch` statement.
+   */
+  @Id(3)
+  bool get isOnSwitchStatement;
+
+  /**
+   * Name of the label.
+   */
+  @Id(0)
+  String get name;
+
+  /**
+   * Offset of the label relative to the beginning of the file.
+   */
+  @informative
+  @Id(1)
+  int get nameOffset;
+}
+
+/**
  * Unlinked summary information about a function parameter.
  */
 abstract class UnlinkedParam extends base.SummaryClass {
@@ -1368,6 +1469,14 @@
   UnlinkedConst get defaultValue;
 
   /**
+   * If the parameter has a default value, the source text of the constant
+   * expression in the default value.  Otherwise the empty string.
+   */
+  @informative
+  @Id(13)
+  String get defaultValueCode;
+
+  /**
    * If this parameter's type is inferable, nonzero slot id identifying which
    * entry in [LinkedLibrary.types] contains the inferred type.  If there is no
    * matching entry in [LinkedLibrary.types], then no type was inferred for
@@ -1382,6 +1491,13 @@
   int get inferredTypeSlot;
 
   /**
+   * The synthetic initializer function of the parameter.  Absent if the variable
+   * does not have an initializer.
+   */
+  @Id(12)
+  UnlinkedExecutable get initializer;
+
+  /**
    * Indicates whether this is a function-typed parameter.
    */
   @Id(5)
@@ -1567,6 +1683,7 @@
   /**
    * Name of the entity being referred to.  For the pseudo-type `dynamic`, the
    * string is "dynamic".  For the pseudo-type `void`, the string is "void".
+   * For the pseudo-type `bottom`, the string is "*bottom*".
    */
   @Id(0)
   String get name;
@@ -1812,6 +1929,13 @@
   int get inferredTypeSlot;
 
   /**
+   * The synthetic initializer function of the variable.  Absent if the variable
+   * does not have an initializer.
+   */
+  @Id(13)
+  UnlinkedExecutable get initializer;
+
+  /**
    * Indicates whether the variable is declared using the `const` keyword.
    */
   @Id(6)
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
index d6210db..3273c9f 100644
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -32,7 +32,10 @@
 
   @override
   UnlinkedCombinatorBuilder visitShowCombinator(ShowCombinator node) {
-    return new UnlinkedCombinatorBuilder(shows: encodeNames(node.shownNames));
+    return new UnlinkedCombinatorBuilder(
+        shows: encodeNames(node.shownNames),
+        offset: node.offset,
+        end: node.end);
   }
 }
 
@@ -92,8 +95,7 @@
                     member.typeParameters?.typeParameters?.length ?? 0));
           }
         }
-        if (member is ConstructorDeclaration &&
-            member.name != null) {
+        if (member is ConstructorDeclaration && member.name != null) {
           String name = member.name.name;
           if (isPublic(name)) {
             cls.members.add(new UnlinkedPublicNameBuilder(
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index de64232..4f6eb20 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element_handle.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -439,9 +440,20 @@
         case UnlinkedConstOperation.pushReference:
           EntityRef ref = uc.references[refPtr++];
           _ReferenceInfo info = resynthesizer.referenceInfos[ref.reference];
-          SimpleIdentifier node = AstFactory.identifier3(info.name);
-          node.staticElement = info.element;
-          _push(node);
+          if (info.enclosing != null &&
+              info.enclosing.element != null &&
+              info.enclosing.element is! ClassElement) {
+            SimpleIdentifier prefix = AstFactory.identifier3(
+                info.enclosing.name)..staticElement = info.enclosing.element;
+            SimpleIdentifier name = AstFactory.identifier3(info.name)
+              ..staticElement = info.element;
+            PrefixedIdentifier node = AstFactory.identifier(prefix, name);
+            _push(node);
+          } else {
+            SimpleIdentifier node = AstFactory.identifier3(info.name);
+            node.staticElement = info.element;
+            _push(node);
+          }
           break;
         case UnlinkedConstOperation.invokeConstructor:
           _pushInstanceCreation();
@@ -678,6 +690,102 @@
 }
 
 /**
+ * Local function element representing the intializer for a variable that has
+ * been resynthesized from a summary.  The actual element won't be constructed
+ * until it is requested.  But properties [context] and [enclosingElement] can
+ * be used without creating the actual element.
+ */
+class _DeferredInitializerElement extends FunctionElementHandle {
+  /**
+   * The variable element containing this element.
+   */
+  @override
+  final VariableElement enclosingElement;
+
+  _DeferredInitializerElement(this.enclosingElement) : super(null, null);
+
+  @override
+  FunctionElement get actualElement => enclosingElement.initializer;
+
+  @override
+  AnalysisContext get context => enclosingElement.context;
+
+  @override
+  ElementLocation get location => actualElement.location;
+}
+
+/**
+ * Local function element that has been resynthesized from a summary.  The
+ * actual element won't be constructed until it is requested.  But properties
+ * [context] and [enclosingElement] can be used without creating the actual
+ * element.
+ */
+class _DeferredLocalFunctionElement extends FunctionElementHandle {
+  /**
+   * The executable element containing this element.
+   */
+  @override
+  final ExecutableElement enclosingElement;
+
+  /**
+   * The index of this function within [ExecutableElement.functions].
+   */
+  final int _localIndex;
+
+  _DeferredLocalFunctionElement(this.enclosingElement, this._localIndex)
+      : super(null, null);
+
+  @override
+  FunctionElement get actualElement {
+    ExecutableElement enclosingElement = this.enclosingElement;
+    if (enclosingElement is PropertyAccessorElement &&
+        enclosingElement.isSynthetic) {
+      return enclosingElement.variable.initializer;
+    } else {
+      return enclosingElement.functions[_localIndex];
+    }
+  }
+
+  @override
+  AnalysisContext get context => enclosingElement.context;
+
+  @override
+  ElementLocation get location => actualElement.location;
+}
+
+/**
+ * Local variable element that has been resynthesized from a summary.  The
+ * actual element won't be constructed until it is requested.  But properties
+ * [context] and [enclosingElement] can be used without creating the actual
+ * element.
+ */
+class _DeferredLocalVariableElement extends LocalVariableElementHandle {
+  /**
+   * The executable element containing this element.
+   */
+  @override
+  final ExecutableElement enclosingElement;
+
+  /**
+   * The index of this variable within [ExecutableElement.localVariables].
+   */
+  final int _localIndex;
+
+  _DeferredLocalVariableElement(this.enclosingElement, this._localIndex)
+      : super(null, null);
+
+  @override
+  LocalVariableElement get actualElement =>
+      enclosingElement.localVariables[_localIndex];
+
+  @override
+  AnalysisContext get context => enclosingElement.context;
+
+  @override
+  ElementLocation get location => actualElement.location;
+}
+
+/**
  * An instance of [_LibraryResynthesizer] is responsible for resynthesizing the
  * elements in a single library from that library's summary.
  */
@@ -922,6 +1030,8 @@
       // Note: we call toList() so that we don't retain a reference to the
       // deserialized data structure.
       combinator.shownNames = serializedCombinator.shows.toList();
+      combinator.offset = serializedCombinator.offset;
+      combinator.end = serializedCombinator.end;
       return combinator;
     } else {
       HideElementCombinatorImpl combinator = new HideElementCombinatorImpl();
@@ -965,6 +1075,13 @@
     assert(serializedExecutable.kind == UnlinkedExecutableKind.constructor);
     currentConstructor = new ConstructorElementImpl(
         serializedExecutable.name, serializedExecutable.nameOffset);
+    if (serializedExecutable.name.isEmpty) {
+      currentConstructor.nameEnd =
+          serializedExecutable.nameOffset + classType.name.length;
+    } else {
+      currentConstructor.nameEnd = serializedExecutable.nameEnd;
+      currentConstructor.periodOffset = serializedExecutable.periodOffset;
+    }
     constructors[serializedExecutable.name] = currentConstructor;
     currentConstructor.returnType = classType;
     buildExecutableCommonParts(currentConstructor, serializedExecutable);
@@ -1026,12 +1143,14 @@
     buildDocumentation(classElement, serializedEnum.documentationComment);
     buildAnnotations(classElement, serializedEnum.annotations);
     ElementHolder memberHolder = new ElementHolder();
+    // Build the 'index' field.
     FieldElementImpl indexField = new FieldElementImpl('index', -1);
     indexField.final2 = true;
     indexField.synthetic = true;
     indexField.type = summaryResynthesizer.typeProvider.intType;
     memberHolder.addField(indexField);
     buildImplicitAccessors(indexField, memberHolder);
+    // Build the 'values' field.
     FieldElementImpl valuesField = new ConstFieldElementImpl('values', -1);
     valuesField.synthetic = true;
     valuesField.const3 = true;
@@ -1040,16 +1159,34 @@
         .substitute4(<DartType>[enumType]);
     memberHolder.addField(valuesField);
     buildImplicitAccessors(valuesField, memberHolder);
-    for (UnlinkedEnumValue serializedEnumValue in serializedEnum.values) {
-      ConstFieldElementImpl valueField = new ConstFieldElementImpl(
-          serializedEnumValue.name, serializedEnumValue.nameOffset);
-      buildDocumentation(valueField, serializedEnumValue.documentationComment);
-      valueField.const3 = true;
-      valueField.static = true;
-      valueField.type = enumType;
-      memberHolder.addField(valueField);
-      buildImplicitAccessors(valueField, memberHolder);
+    // Build fields for all enum constants.
+    List<DartObjectImpl> constantValues = <DartObjectImpl>[];
+    for (int i = 0; i < serializedEnum.values.length; i++) {
+      UnlinkedEnumValue serializedEnumValue = serializedEnum.values[i];
+      String fieldName = serializedEnumValue.name;
+      ConstFieldElementImpl field =
+          new ConstFieldElementImpl(fieldName, serializedEnumValue.nameOffset);
+      buildDocumentation(field, serializedEnumValue.documentationComment);
+      field.const3 = true;
+      field.static = true;
+      field.type = enumType;
+      // Create a value for the constant.
+      Map<String, DartObjectImpl> fieldMap = <String, DartObjectImpl>{
+        fieldName: new DartObjectImpl(
+            summaryResynthesizer.typeProvider.intType, new IntState(i))
+      };
+      DartObjectImpl value =
+          new DartObjectImpl(enumType, new GenericState(fieldMap));
+      constantValues.add(value);
+      field.evaluationResult = new EvaluationResultImpl(value);
+      // Add the field.
+      memberHolder.addField(field);
+      buildImplicitAccessors(field, memberHolder);
     }
+    // Build the value of the 'values' field.
+    valuesField.evaluationResult = new EvaluationResultImpl(
+        new DartObjectImpl(valuesField.type, new ListState(constantValues)));
+    // done
     classElement.fields = memberHolder.fields;
     classElement.accessors = memberHolder.accessors;
     classElement.constructors = <ConstructorElement>[];
@@ -1162,6 +1299,8 @@
     buildAnnotations(executableElement, serializedExecutable.annotations);
     executableElement.functions =
         serializedExecutable.localFunctions.map(buildLocalFunction).toList();
+    executableElement.labels =
+        serializedExecutable.localLabels.map(buildLocalLabel).toList();
     executableElement.localVariables =
         serializedExecutable.localVariables.map(buildLocalVariable).toList();
     currentTypeParameters.removeLast();
@@ -1215,11 +1354,13 @@
         return new PropertyAccessorElementHandle(
             summaryResynthesizer, location);
       case ReferenceKind.constructor:
+      case ReferenceKind.function:
       case ReferenceKind.propertyAccessor:
       case ReferenceKind.method:
       case ReferenceKind.length:
       case ReferenceKind.prefix:
       case ReferenceKind.unresolved:
+      case ReferenceKind.variable:
         // Should never happen.  Exported names never refer to import prefixes,
         // and they always refer to defined top-level entities.
         throw new StateError('Unexpected export name kind: ${exportName.kind}');
@@ -1465,7 +1606,8 @@
   /**
    * Resynthesize a local [FunctionElement].
    */
-  FunctionElement buildLocalFunction(UnlinkedExecutable serializedExecutable) {
+  FunctionElementImpl buildLocalFunction(
+      UnlinkedExecutable serializedExecutable) {
     FunctionElementImpl element = new FunctionElementImpl(
         serializedExecutable.name, serializedExecutable.nameOffset);
     if (serializedExecutable.visibleOffset != 0) {
@@ -1477,6 +1619,17 @@
   }
 
   /**
+   * Resynthesize a [LabelElement].
+   */
+  LabelElement buildLocalLabel(UnlinkedLabel serializedLabel) {
+    return new LabelElementImpl(
+        serializedLabel.name,
+        serializedLabel.nameOffset,
+        serializedLabel.isOnSwitchStatement,
+        serializedLabel.isOnSwitchMember);
+  }
+
+  /**
    * Resynthesize a [LocalVariableElement].
    */
   LocalVariableElement buildLocalVariable(UnlinkedVariable serializedVariable) {
@@ -1518,6 +1671,8 @@
         if (serializedParameter.defaultValue != null) {
           defaultParameter.constantInitializer =
               _buildConstExpression(serializedParameter.defaultValue);
+          defaultParameter.defaultValueCode =
+              serializedParameter.defaultValueCode;
         }
       }
       parameterElement = initializingParameter;
@@ -1534,6 +1689,8 @@
         if (serializedParameter.defaultValue != null) {
           defaultParameter.constantInitializer =
               _buildConstExpression(serializedParameter.defaultValue);
+          defaultParameter.defaultValueCode =
+              serializedParameter.defaultValueCode;
         }
       }
     }
@@ -1562,6 +1719,7 @@
       }
       parameterElement.hasImplicitType = serializedParameter.type == null;
     }
+    buildVariableInitializer(parameterElement, serializedParameter.initializer);
     switch (serializedParameter.kind) {
       case UnlinkedParamKind.named:
         parameterElement.parameterKind = ParameterKind.NAMED;
@@ -1573,6 +1731,10 @@
         parameterElement.parameterKind = ParameterKind.REQUIRED;
         break;
     }
+    if (serializedParameter.visibleOffset != 0) {
+      parameterElement.setVisibleRange(
+          serializedParameter.visibleOffset, serializedParameter.visibleLength);
+    }
     return parameterElement;
   }
 
@@ -1745,11 +1907,27 @@
     element.const3 = serializedVariable.isConst;
     element.final2 = serializedVariable.isFinal;
     element.hasImplicitType = serializedVariable.type == null;
+    buildVariableInitializer(element, serializedVariable.initializer);
     buildDocumentation(element, serializedVariable.documentationComment);
     buildAnnotations(element, serializedVariable.annotations);
   }
 
   /**
+   * If the given [serializedInitializer] is not `null`, create the
+   * corresponding [FunctionElementImpl] and set it for the [variable].
+   */
+  void buildVariableInitializer(
+      VariableElementImpl variable, UnlinkedExecutable serializedInitializer) {
+    if (serializedInitializer == null) {
+      return null;
+    }
+    FunctionElementImpl initializerElement =
+        buildLocalFunction(serializedInitializer);
+    initializerElement.synthetic = true;
+    variable.initializer = initializerElement;
+  }
+
+  /**
    * Finish creating a [TypeParameterElement] by deserializing its bound.
    */
   void finishTypeParameter(UnlinkedTypeParam serializedTypeParameter,
@@ -1878,6 +2056,9 @@
       } else if (name == 'void') {
         type = VoidTypeImpl.instance;
         element = type.element;
+      } else if (name == '*bottom*') {
+        type = BottomTypeImpl.instance;
+        element = null;
       } else {
         List<String> locationComponents;
         if (enclosingInfo != null && enclosingInfo.element is ClassElement) {
@@ -1892,6 +2073,9 @@
         }
         ElementLocation location =
             new ElementLocationImpl.con3(locationComponents);
+        if (enclosingInfo != null) {
+          numTypeParameters += enclosingInfo.numTypeParameters;
+        }
         switch (linkedReference.kind) {
           case ReferenceKind.classOrEnum:
             element = new ClassElementHandle(summaryResynthesizer, location);
@@ -1900,7 +2084,6 @@
             assert(location.components.length == 4);
             element =
                 new ConstructorElementHandle(summaryResynthesizer, location);
-            numTypeParameters = enclosingInfo.numTypeParameters;
             break;
           case ReferenceKind.length:
             element = _buildStringLengthPropertyAccessorElement();
@@ -1926,6 +2109,28 @@
             element = new FunctionTypeAliasElementHandle(
                 summaryResynthesizer, location);
             break;
+          case ReferenceKind.variable:
+            Element enclosingElement = enclosingInfo.element;
+            if (enclosingElement is ExecutableElement) {
+              element = new _DeferredLocalVariableElement(
+                  enclosingElement, linkedReference.localIndex);
+            } else {
+              throw new StateError('Unexpected element enclosing variable:'
+                  ' ${enclosingElement.runtimeType}');
+            }
+            break;
+          case ReferenceKind.function:
+            Element enclosingElement = enclosingInfo.element;
+            if (enclosingElement is VariableElement) {
+              element = new _DeferredInitializerElement(enclosingElement);
+            } else if (enclosingElement is ExecutableElement) {
+              element = new _DeferredLocalFunctionElement(
+                  enclosingElement, linkedReference.localIndex);
+            } else {
+              throw new StateError('Unexpected element enclosing function:'
+                  ' ${enclosingElement.runtimeType}');
+            }
+            break;
           case ReferenceKind.prefix:
           case ReferenceKind.unresolved:
             break;
@@ -2138,7 +2343,7 @@
     if (specialType != null) {
       type = specialType;
     } else {
-      type = _buildType((_) => DynamicTypeImpl.instance, null);
+      type = _buildType((_) => DynamicTypeImpl.instance, const []);
     }
   }
 
@@ -2181,36 +2386,56 @@
    */
   DartType _buildType(
       DartType getTypeArgument(int i), List<int> implicitFunctionTypeIndices) {
-    List<DartType> typeArguments = const <DartType>[];
-    if (numTypeParameters != 0) {
-      typeArguments = <DartType>[];
-      for (int i = 0; i < numTypeParameters; i++) {
-        typeArguments.add(getTypeArgument(i));
-      }
-    }
     ElementHandle element = this.element; // To allow type promotion
     if (element is ClassElementHandle) {
-      return new InterfaceTypeImpl.elementWithNameAndArgs(
-          element, name, typeArguments);
+      return new InterfaceTypeImpl.elementWithNameAndArgs(element, name,
+          _buildTypeArguments(numTypeParameters, getTypeArgument));
     } else if (element is FunctionTypeAliasElementHandle) {
       return new FunctionTypeImpl.elementWithNameAndArgs(
-          element, name, typeArguments, typeArguments.isNotEmpty);
+          element,
+          name,
+          _buildTypeArguments(numTypeParameters, getTypeArgument),
+          numTypeParameters != 0);
     } else if (element is FunctionTypedElement) {
-      FunctionTypedElementComputer computer =
-          implicitFunctionTypeIndices != null
-              ? () {
-                  FunctionTypedElement element = this.element;
-                  for (int index in implicitFunctionTypeIndices) {
-                    element = element.parameters[index].type.element;
-                  }
-                  return element;
-                }
-              : () => this.element;
+      int numTypeArguments;
+      FunctionTypedElementComputer computer;
+      if (implicitFunctionTypeIndices.isNotEmpty) {
+        numTypeArguments = numTypeParameters;
+        computer = () {
+          FunctionTypedElement element = this.element;
+          for (int index in implicitFunctionTypeIndices) {
+            element = element.parameters[index].type.element;
+          }
+          return element;
+        };
+      } else {
+        // For a type that refers to a generic executable, the type arguments are
+        // not supposed to include the arguments to the executable itself.
+        numTypeArguments = enclosing == null ? 0 : enclosing.numTypeParameters;
+        computer = () => this.element;
+      }
       // TODO(paulberry): Is it a bug that we have to pass `false` for
       // isInstantiated?
-      return new DeferredFunctionTypeImpl(computer, null, typeArguments, false);
+      return new DeferredFunctionTypeImpl(computer, null,
+          _buildTypeArguments(numTypeArguments, getTypeArgument), false);
     } else {
       return null;
     }
   }
+
+  /**
+   * Build a list of type arguments having length [numTypeArguments] where each
+   * type argument is obtained by calling [getTypeArgument].
+   */
+  List<DartType> _buildTypeArguments(
+      int numTypeArguments, DartType getTypeArgument(int i)) {
+    List<DartType> typeArguments = const <DartType>[];
+    if (numTypeArguments != 0) {
+      typeArguments = <DartType>[];
+      for (int i = 0; i < numTypeArguments; i++) {
+        typeArguments.add(getTypeArgument(i));
+      }
+    }
+    return typeArguments;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index a3d915b..cd9ff61 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -93,8 +93,9 @@
     Expression target = access.target;
     if (target is Identifier) {
       EntityRefBuilder targetRef = serializeIdentifier(target);
-      return new EntityRefBuilder(reference: visitor.serializeReference(
-          targetRef.reference, access.propertyName.name));
+      return new EntityRefBuilder(
+          reference: visitor.serializeReference(
+              targetRef.reference, access.propertyName.name));
     } else {
       // TODO(scheglov) should we handle other targets in malformed constants?
       throw new StateError('Unexpected target type: ${target.runtimeType}');
@@ -193,6 +194,12 @@
       <UnlinkedExportNonPublicBuilder>[];
 
   /**
+   * List of objects which should be written to
+   * [UnlinkedExecutable.localLabels].
+   */
+  List<UnlinkedLabelBuilder> labels = <UnlinkedLabelBuilder>[];
+
+  /**
    * List of objects which should be written to [UnlinkedUnit.parts].
    */
   final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];
@@ -402,6 +409,8 @@
     if (combinator is ShowCombinator) {
       b.shows =
           combinator.shownNames.map((SimpleIdentifier id) => id.name).toList();
+      b.offset = combinator.offset;
+      b.end = combinator.end;
     } else if (combinator is HideCombinator) {
       b.hides =
           combinator.hiddenNames.map((SimpleIdentifier id) => id.name).toList();
@@ -475,7 +484,8 @@
    * [UnlinkedExecutable].
    */
   UnlinkedExecutableBuilder serializeExecutable(
-      SimpleIdentifier name,
+      String name,
+      int nameOffset,
       bool isGetter,
       bool isSetter,
       TypeName returnType,
@@ -491,7 +501,7 @@
     _TypeParameterScope typeParameterScope = new _TypeParameterScope();
     scopes.add(typeParameterScope);
     UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
-    String nameString = name.name;
+    String nameString = name;
     if (isGetter) {
       b.kind = UnlinkedExecutableKind.getter;
     } else if (isSetter) {
@@ -502,7 +512,7 @@
     }
     b.isAbstract = body is EmptyFunctionBody;
     b.name = nameString;
-    b.nameOffset = name.offset;
+    b.nameOffset = nameOffset;
     b.typeParameters =
         serializeTypeParameters(typeParameters, typeParameterScope);
     if (!isTopLevel) {
@@ -537,7 +547,12 @@
     return b;
   }
 
-  void serializeFunctionBody(UnlinkedExecutableBuilder b, FunctionBody body) {
+  /**
+   * Record local functions and variables into the given executable. The given
+   * [body] is usually an actual [FunctionBody], but may be an [Expression]
+   * when we process a synthetic variable initializer function.
+   */
+  void serializeFunctionBody(UnlinkedExecutableBuilder b, AstNode body) {
     if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
       for (UnlinkedParamBuilder parameter in b.parameters) {
         parameter.visibleOffset = body.offset;
@@ -545,13 +560,17 @@
       }
     }
     List<UnlinkedExecutableBuilder> oldExecutables = executables;
+    List<UnlinkedLabelBuilder> oldLabels = labels;
     List<UnlinkedVariableBuilder> oldVariables = variables;
     executables = <UnlinkedExecutableBuilder>[];
+    labels = <UnlinkedLabelBuilder>[];
     variables = <UnlinkedVariableBuilder>[];
     body.accept(this);
     b.localFunctions = executables;
+    b.localLabels = labels;
     b.localVariables = variables;
     executables = oldExecutables;
+    labels = oldLabels;
     variables = oldVariables;
   }
 
@@ -571,6 +590,22 @@
   }
 
   /**
+   * If the given [expression] is not `null`, serialize it as an
+   * [UnlinkedExecutableBuilder], otherwise return `null`.
+   */
+  UnlinkedExecutableBuilder serializeInitializerFunction(
+      Expression expression) {
+    if (expression == null) {
+      return null;
+    }
+    UnlinkedExecutableBuilder initializer =
+        new UnlinkedExecutableBuilder(nameOffset: expression.offset);
+    serializeFunctionBody(initializer, expression);
+    initializer.inferredReturnTypeSlot = assignTypeSlot();
+    return initializer;
+  }
+
+  /**
    * Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or
    * [SimpleFormalParameter] into an [UnlinkedParam].
    */
@@ -754,6 +789,7 @@
       }
       b.visibleOffset = enclosingBlock?.offset;
       b.visibleLength = enclosingBlock?.length;
+      b.initializer = serializeInitializerFunction(variable.initializer);
       this.variables.add(b);
     }
   }
@@ -806,6 +842,8 @@
     if (node.name != null) {
       b.name = node.name.name;
       b.nameOffset = node.name.offset;
+      b.periodOffset = node.period.offset;
+      b.nameEnd = node.name.end;
     } else {
       b.nameOffset = node.returnType.offset;
     }
@@ -853,7 +891,9 @@
     UnlinkedParamBuilder b = node.parameter.accept(this);
     if (node.defaultValue != null) {
       b.defaultValue = serializeConstExpr(node.defaultValue);
+      b.defaultValueCode = node.defaultValue.toSource();
     }
+    b.initializer = serializeInitializerFunction(node.defaultValue);
     return b;
   }
 
@@ -906,7 +946,8 @@
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     executables.add(serializeExecutable(
-        node.name,
+        node.name.name,
+        node.name.offset,
         node.isGetter,
         node.isSetter,
         node.returnType,
@@ -921,6 +962,26 @@
   }
 
   @override
+  void visitFunctionExpression(FunctionExpression node) {
+    if (node.parent is! FunctionDeclaration) {
+      executables.add(serializeExecutable(
+          null,
+          node.offset,
+          false,
+          false,
+          null,
+          node.parameters,
+          node.body,
+          false,
+          false,
+          null,
+          null,
+          node.typeParameters,
+          false));
+    }
+  }
+
+  @override
   void visitFunctionTypeAlias(FunctionTypeAlias node) {
     int oldScopesLength = scopes.length;
     _TypeParameterScope typeParameterScope = new _TypeParameterScope();
@@ -974,6 +1035,17 @@
   }
 
   @override
+  void visitLabel(Label node) {
+    AstNode parent = node.parent;
+    labels.add(new UnlinkedLabelBuilder(
+        name: node.label.name,
+        nameOffset: node.offset,
+        isOnSwitchMember: parent is SwitchMember,
+        isOnSwitchStatement:
+            parent is LabeledStatement && parent.statement is SwitchStatement));
+  }
+
+  @override
   void visitLibraryDirective(LibraryDirective node) {
     libraryName =
         node.name.components.map((SimpleIdentifier id) => id.name).join('.');
@@ -987,7 +1059,8 @@
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
     executables.add(serializeExecutable(
-        node.name,
+        node.name.name,
+        node.name.offset,
         node.isGetter,
         node.isSetter,
         node.returnType,
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index b631287..afd3ab1 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -26,8 +26,8 @@
     LibraryElement lib, TypeProvider typeProvider, bool strongMode) {
   var serializer = new _LibrarySerializer(lib, typeProvider, strongMode);
   LinkedLibraryBuilder linked = serializer.serializeLibrary();
-  return new LibrarySerializationResult(
-      linked, serializer.unlinkedUnits, serializer.unitUris);
+  return new LibrarySerializationResult(linked, serializer.unlinkedUnits,
+      serializer.unitUris, serializer.unitSources);
 }
 
 ReferenceKind _getReferenceKind(Element element) {
@@ -38,7 +38,10 @@
   } else if (element is ConstructorElement) {
     return ReferenceKind.constructor;
   } else if (element is FunctionElement) {
-    return ReferenceKind.topLevelFunction;
+    if (element.enclosingElement is CompilationUnitElement) {
+      return ReferenceKind.topLevelFunction;
+    }
+    return ReferenceKind.function;
   } else if (element is FunctionTypeAliasElement) {
     return ReferenceKind.typedef;
   } else if (element is PropertyAccessorElement) {
@@ -48,6 +51,16 @@
     return ReferenceKind.topLevelPropertyAccessor;
   } else if (element is MethodElement) {
     return ReferenceKind.method;
+  } else if (element is TopLevelVariableElement) {
+    // Summaries don't need to distinguish between references to a variable and
+    // references to its getter.
+    return ReferenceKind.topLevelPropertyAccessor;
+  } else if (element is LocalVariableElement) {
+    return ReferenceKind.variable;
+  } else if (element is FieldElement) {
+    // Summaries don't need to distinguish between references to a field and
+    // references to its getter.
+    return ReferenceKind.propertyAccessor;
   } else {
     throw new Exception('Unexpected element kind: ${element.runtimeType}');
   }
@@ -82,7 +95,14 @@
    */
   final List<String> unitUris;
 
-  LibrarySerializationResult(this.linked, this.unlinkedUnits, this.unitUris);
+  /**
+   * Source object corresponding to each compilation unit appearing in the
+   * library.
+   */
+  final List<Source> unitSources;
+
+  LibrarySerializationResult(
+      this.linked, this.unlinkedUnits, this.unitUris, this.unitSources);
 }
 
 /**
@@ -117,9 +137,9 @@
    */
   final UnlinkedUnitBuilder unlinkedUnit = new UnlinkedUnitBuilder();
 
-/**
- * Absolute URI of the compilation unit.
- */
+  /**
+   * Absolute URI of the compilation unit.
+   */
   String unitUri;
 
   /**
@@ -158,10 +178,22 @@
    */
   int unresolvedReferenceIndex = null;
 
+  /**
+   * Index into the "references table" representing the "bottom" type, if such
+   * an index exists.  `null` if no such entry has been made in the references
+   * table yet.
+   */
+  int bottomReferenceIndex = null;
+
   _CompilationUnitSerializer(
       this.librarySerializer, this.compilationUnit, this.unitNum);
 
   /**
+   * Source object for the compilation unit.
+   */
+  Source get unitSource => compilationUnit.source;
+
+  /**
    * Add all classes, enums, typedefs, executables, and top level variables
    * from the given compilation unit [element] to the compilation unit summary.
    * [unitNum] indicates the ordinal position of this compilation unit in the
@@ -354,6 +386,23 @@
   }
 
   /**
+   * Return the index of the entry in the references table
+   * ([LinkedLibrary.references]) used for the "bottom" type.  A new entry is
+   * added to the table if necessary to satisfy the request.
+   */
+  int serializeBottomReference() {
+    if (bottomReferenceIndex == null) {
+      // References to the "bottom" type are always implicit, since there is no
+      // way to explicitly refer to the "bottom" type.  Therefore they should
+      // be stored only in the linked references table.
+      bottomReferenceIndex = linkedReferences.length;
+      linkedReferences.add(new LinkedReferenceBuilder(
+          name: '*bottom*', kind: ReferenceKind.classOrEnum));
+    }
+    return bottomReferenceIndex;
+  }
+
+  /**
    * Serialize the given [classElement], creating an [UnlinkedClass].
    */
   UnlinkedClassBuilder serializeClass(ClassElement classElement) {
@@ -456,6 +505,8 @@
     UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
     if (combinator is ShowElementCombinator) {
       b.shows = combinator.shownNames;
+      b.offset = combinator.offset;
+      b.end = combinator.end;
     } else if (combinator is HideElementCombinator) {
       b.hides = combinator.hiddenNames;
     }
@@ -519,7 +570,12 @@
     UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
     b.name = executableElement.name;
     b.nameOffset = executableElement.nameOffset;
-    if (executableElement is! ConstructorElement) {
+    if (executableElement is ConstructorElement) {
+      if (executableElement.name.isNotEmpty) {
+        b.nameEnd = executableElement.nameEnd;
+        b.periodOffset = executableElement.periodOffset;
+      }
+    } else {
       if (!executableElement.hasImplicitReturnType) {
         b.returnType = serializeTypeRef(
             executableElement.type.returnType, executableElement);
@@ -598,6 +654,7 @@
     }
     b.localFunctions =
         executableElement.functions.map(serializeExecutable).toList();
+    b.localLabels = executableElement.labels.map(serializeLabel).toList();
     b.localVariables =
         executableElement.localVariables.map(serializeVariable).toList();
     return b;
@@ -652,6 +709,18 @@
   }
 
   /**
+   * Serialize the given [label], creating an [UnlinkedLabelBuilder].
+   */
+  UnlinkedLabelBuilder serializeLabel(LabelElementImpl label) {
+    UnlinkedLabelBuilder b = new UnlinkedLabelBuilder();
+    b.name = label.name;
+    b.nameOffset = label.nameOffset;
+    b.isOnSwitchMember = label.isOnSwitchMember;
+    b.isOnSwitchStatement = label.isOnSwitchStatement;
+    return b;
+  }
+
+  /**
    * Serialize the given [parameter] into an [UnlinkedParam].
    */
   UnlinkedParamBuilder serializeParam(ParameterElement parameter,
@@ -683,7 +752,7 @@
         b.inferredTypeSlot = storeInferredType(type, context);
       }
     } else {
-      if (type is FunctionType) {
+      if (type is FunctionType && type.element.isSynthetic) {
         b.isFunctionTyped = true;
         b.type = serializeTypeRef(type.returnType, parameter);
         b.parameters = type.parameters
@@ -698,8 +767,13 @@
       Expression initializer = constParameter.constantInitializer;
       if (initializer != null) {
         b.defaultValue = serializeConstExpr(initializer);
+        b.defaultValueCode = parameter.defaultValueCode;
       }
     }
+    // TODO(scheglov) VariableMember.initializer is not implemented
+    if (parameter is! VariableMember && parameter.initializer != null) {
+      b.initializer = serializeExecutable(parameter.initializer);
+    }
     {
       SourceRange visibleRange = parameter.visibleRange;
       if (visibleRange != null) {
@@ -728,6 +802,13 @@
     Element element = type.element;
     LibraryElement dependentLibrary = element?.library;
     if (dependentLibrary == null) {
+      if (type.isBottom) {
+        // References to the "bottom" type are always implicit, since there is
+        // no way to explicitly refer to the "bottom" type.  Therefore they
+        // should always be linked.
+        assert(linked);
+        return serializeBottomReference();
+      }
       assert(type.isDynamic || type.isVoid);
       if (type is UndefinedTypeImpl) {
         return serializeUnresolvedReference();
@@ -865,8 +946,8 @@
     // the element model.  For the moment we use a name that can't possibly
     // ever exist.
     if (unresolvedReferenceIndex == null) {
-      return serializeUnlinkedReference(
-          '*unresolved*', ReferenceKind.unresolved);
+      unresolvedReferenceIndex =
+          serializeUnlinkedReference('*unresolved*', ReferenceKind.unresolved);
     }
     return unresolvedReferenceIndex;
   }
@@ -913,21 +994,24 @@
         b.visibleLength = visibleRange.length;
       }
     }
+    // TODO(scheglov) VariableMember.initializer is not implemented
+    if (variable is! VariableMember && variable.initializer != null) {
+      b.initializer = serializeExecutable(variable.initializer);
+    }
     return b;
   }
 
   /**
    * Create a slot id for the given [type] (which is an inferred type).  If
-   * strong mode is enabled and [type] is not `dynamic`, it is stored in
-   * [linkedTypes] so that once the compilation unit has been fully visited, it
-   * will be serialized into [LinkedUnit.types].
+   * [type] is not `dynamic`, it is stored in [linkedTypes] so that once the
+   * compilation unit has been fully visited, it will be serialized into
+   * [LinkedUnit.types].
    *
    * [context] is the element within which the slot id will appear; this is
    * used to serialize type parameters.
    */
   int storeInferredType(DartType type, Element context) {
-    return storeLinkedType(
-        librarySerializer.strongMode && !type.isDynamic ? type : null, context);
+    return storeLinkedType(type.isDynamic ? null : type, context);
   }
 
   /**
@@ -950,23 +1034,17 @@
 
   int _getElementReferenceId(Element element, {bool linked: false}) {
     return referenceMap.putIfAbsent(element, () {
-      LibraryElement dependentLibrary;
+      LibraryElement dependentLibrary = librarySerializer.libraryElement;
+      int unit = 0;
+      Element enclosingElement;
       if (element != null) {
-        Element enclosingElement = element.enclosingElement;
+        enclosingElement = element.enclosingElement;
         if (enclosingElement is CompilationUnitElement) {
           dependentLibrary = enclosingElement.library;
+          unit = dependentLibrary.units.indexOf(enclosingElement);
+          assert(unit != -1);
         }
       }
-      int unit;
-      if (dependentLibrary == null) {
-        unit = 0;
-        dependentLibrary = librarySerializer.libraryElement;
-      } else {
-        CompilationUnitElement unitElement =
-            element.getAncestor((Element e) => e is CompilationUnitElement);
-        unit = dependentLibrary.units.indexOf(unitElement);
-        assert(unit != -1);
-      }
       ReferenceKind kind = _getReferenceKind(element);
       String name = element == null ? 'void' : element.name;
       int index;
@@ -974,11 +1052,31 @@
       if (linked) {
         linkedReference =
             new LinkedReferenceBuilder(kind: kind, unit: unit, name: name);
-        Element enclosing = element?.enclosingElement;
-        if (enclosing is ClassElement) {
+        if (enclosingElement != null &&
+            enclosingElement is! CompilationUnitElement) {
           linkedReference.containingReference =
-              _getElementReferenceId(enclosing, linked: linked);
-          linkedReference.numTypeParameters = enclosing.typeParameters.length;
+              _getElementReferenceId(enclosingElement, linked: linked);
+          if (enclosingElement is ClassElement) {
+            // Nothing to do.
+          } else if (enclosingElement is ExecutableElement) {
+            if (element is FunctionElement) {
+              assert(enclosingElement.functions.contains(element));
+              linkedReference.localIndex =
+                  enclosingElement.functions.indexOf(element);
+            } else if (element is LocalVariableElement) {
+              assert(enclosingElement.localVariables.contains(element));
+              linkedReference.localIndex =
+                  enclosingElement.localVariables.indexOf(element);
+            } else {
+              throw new StateError(
+                  'Unexpected enclosed element type: ${element.runtimeType}');
+            }
+          } else if (enclosingElement is VariableElement) {
+            assert(identical(enclosingElement.initializer, element));
+          } else {
+            throw new StateError(
+                'Unexpected enclosing element type: ${enclosingElement.runtimeType}');
+          }
         }
         index = linkedReferences.length;
         linkedReferences.add(linkedReference);
@@ -1231,6 +1329,13 @@
   }
 
   /**
+   * Retrieve a list of the Sources for the compilation units in the library.
+   */
+  List<String> get unitSources => compilationUnitSerializers
+      .map((_CompilationUnitSerializer s) => s.unitSource)
+      .toList();
+
+  /**
    * Retrieve a list of the URIs for the compilation units in the library.
    */
   List<String> get unitUris => compilationUnitSerializers
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 2108b74..ad422ca 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/context/cache.dart' show CacheEntry;
 import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -23,7 +24,7 @@
 
 class SdkSummaryResultProvider implements SummaryResultProvider {
   final InternalAnalysisContext context;
-  final SdkBundle bundle;
+  final PackageBundle bundle;
   final SummaryTypeProvider typeProvider = new SummaryTypeProvider();
 
   @override
@@ -49,7 +50,6 @@
     if (target.source == null || !target.source.isInSystemLibrary) {
       return false;
     }
-//    print('SummarySdkAnalysisContext: $result of $target');
     // Constant expressions are always resolved in summaries.
     if (result == CONSTANT_EXPRESSION_RESOLVED &&
         target is ConstantEvaluationTarget) {
@@ -89,6 +89,21 @@
 //        throw new UnimplementedError('$result of $target');
       }
     }
+    if (target is LibrarySpecificUnit) {
+      if (target.library == null || !target.library.isInSystemLibrary) {
+        return false;
+      }
+      if (result == COMPILATION_UNIT_ELEMENT) {
+        String libraryUri = target.library.uri.toString();
+        String unitUri = target.unit.uri.toString();
+        CompilationUnitElement unit = resynthesizer.getElement(
+            new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
+        if (unit != null) {
+          entry.setValue(result, unit, TargetedResult.EMPTY_LIST);
+          return true;
+        }
+      }
+    }
     return false;
   }
 
@@ -120,7 +135,7 @@
  * The implementation of [SummaryResynthesizer] for Dart SDK.
  */
 class SdkSummaryResynthesizer extends SummaryResynthesizer {
-  final SdkBundle bundle;
+  final PackageBundle bundle;
   final Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
   final Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{};
 
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index b492bb2..d21914c 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -271,13 +271,6 @@
     new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
 
 /**
- * The [Element]s defined in a [LibrarySpecificUnit].
- */
-final ListResultDescriptor<Element> DEFINED_ELEMENTS =
-    new ListResultDescriptor<Element>('DEFINED_ELEMENTS', null,
-        cachingPolicy: ELEMENT_CACHING_POLICY);
-
-/**
  * The sources representing the export closure of a library.
  * The [Source]s include only library sources, not their units.
  *
@@ -877,13 +870,24 @@
     Source source = getRequiredSource();
     CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
     //
+    // Try to get the existing CompilationUnitElement.
+    //
+    CompilationUnitElement element;
+    {
+      InternalAnalysisContext internalContext =
+          context as InternalAnalysisContext;
+      AnalysisCache analysisCache = internalContext.analysisCache;
+      CacheEntry cacheEntry = internalContext.getCacheEntry(target);
+      element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
+      if (element == null &&
+          internalContext.aboutToComputeResult(
+              cacheEntry, COMPILATION_UNIT_ELEMENT)) {
+        element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
+      }
+    }
+    //
     // Build or reuse CompilationUnitElement.
     //
-//    unit = AstCloner.clone(unit);
-    AnalysisCache analysisCache =
-        (context as InternalAnalysisContext).analysisCache;
-    CompilationUnitElement element =
-        analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
     if (element == null) {
       CompilationUnitBuilder builder = new CompilationUnitBuilder();
       element = builder.buildCompilationUnit(
@@ -1168,8 +1172,8 @@
     //
     // Compute export namespace.
     //
-    ExportNamespaceBuilder builder = new ExportNamespaceBuilder();
-    Namespace namespace = builder.build(library);
+    NamespaceBuilder builder = new NamespaceBuilder();
+    Namespace namespace = builder.createExportNamespaceForLibrary(library);
     library.exportNamespace = namespace;
     //
     // Update entry point.
@@ -1356,22 +1360,41 @@
       InternalAnalysisContext internalContext = context;
       owningContext = internalContext.getContextFor(librarySource);
     }
-    LibraryElementImpl libraryElement =
-        new LibraryElementImpl.forNode(owningContext, libraryNameNode);
-    libraryElement.definingCompilationUnit = definingCompilationUnitElement;
-    libraryElement.entryPoint = entryPoint;
-    libraryElement.parts = sourcedCompilationUnits;
-    for (Directive directive in directivesToResolve) {
-      directive.element = libraryElement;
+    //
+    // Try to get the existing LibraryElement.
+    //
+    LibraryElementImpl libraryElement;
+    {
+      InternalAnalysisContext internalContext =
+          context as InternalAnalysisContext;
+      AnalysisCache analysisCache = internalContext.analysisCache;
+      CacheEntry cacheEntry = internalContext.getCacheEntry(target);
+      libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1);
+      if (libraryElement == null &&
+          internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT1)) {
+        libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1);
+      }
     }
-    BuildLibraryElementUtils.patchTopLevelAccessors(libraryElement);
-    // set the library documentation to the docs associated with the first
-    // directive in the compilation unit.
-    if (definingCompilationUnit.directives.isNotEmpty) {
-      setElementDocumentationComment(
-          libraryElement, definingCompilationUnit.directives.first);
+    //
+    // Create a new LibraryElement.
+    //
+    if (libraryElement == null) {
+      libraryElement =
+          new LibraryElementImpl.forNode(owningContext, libraryNameNode);
+      libraryElement.definingCompilationUnit = definingCompilationUnitElement;
+      libraryElement.entryPoint = entryPoint;
+      libraryElement.parts = sourcedCompilationUnits;
+      for (Directive directive in directivesToResolve) {
+        directive.element = libraryElement;
+      }
+      BuildLibraryElementUtils.patchTopLevelAccessors(libraryElement);
+      // set the library documentation to the docs associated with the first
+      // directive in the compilation unit.
+      if (definingCompilationUnit.directives.isNotEmpty) {
+        setElementDocumentationComment(
+            libraryElement, definingCompilationUnit.directives.first);
+      }
     }
-
     //
     // Record outputs.
     //
@@ -1465,7 +1488,8 @@
   @override
   void internalPerform() {
     LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
-    library.publicNamespace = new PublicNamespaceBuilder().build(library);
+    NamespaceBuilder builder = new NamespaceBuilder();
+    library.publicNamespace = builder.createPublicNamespaceForLibrary(library);
     outputs[LIBRARY_ELEMENT3] = library;
   }
 
@@ -1578,7 +1602,11 @@
   @override
   void internalPerform() {
     LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
-    LibraryElement asyncLibrary = getRequiredInput(ASYNC_INPUT);
+    LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
+    if (asyncLibrary == null) {
+      asyncLibrary =
+          (context as AnalysisContextImpl).createMockAsyncLib(coreLibrary);
+    }
     Namespace coreNamespace = coreLibrary.publicNamespace;
     Namespace asyncNamespace = asyncLibrary.publicNamespace;
     //
@@ -1600,6 +1628,9 @@
     SourceFactory sourceFactory = contextTarget.context.sourceFactory;
     Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
     Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+    if (asyncSource == null) {
+      return <String, TaskInput>{CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource)};
+    }
     return <String, TaskInput>{
       CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource),
       ASYNC_INPUT: LIBRARY_ELEMENT3.of(asyncSource)
@@ -2224,6 +2255,16 @@
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
       createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
 
+  /**
+   * The name of the [LINE_INFO_INPUT] input.
+   */
+  static const String LINE_INFO_INPUT = 'LINE_INFO_INPUT';
+
+  /**
+   * The name of the [PARSED_UNIT_INPUT] input.
+   */
+  static const String PARSED_UNIT_INPUT = 'PARSED_UNIT_INPUT';
+
   // Prefix for comments ignoring error codes.
   static const String _normalizedIgnorePrefix = '//#ignore:';
 
@@ -2274,14 +2315,9 @@
     // Sort errors.
     errors.sort((AnalysisError e1, AnalysisError e2) => e1.offset - e2.offset);
 
-    Source source = target;
-    String contents = context.getContents(source).data;
-    Scanner scanner = new Scanner(source, new CharSequenceReader(contents),
-        AnalysisErrorListener.NULL_LISTENER);
-
-    // Scan.
-    Token token = scanner.tokenize();
-    LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+    CompilationUnit cu = getRequiredInput(PARSED_UNIT_INPUT);
+    Token token = cu.beginToken;
+    LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT);
 
     int errorIndex = 0;
 
@@ -2344,6 +2380,8 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     Source source = target;
     Map<String, TaskInput> inputs = <String, TaskInput>{};
+    inputs[LINE_INFO_INPUT] = LINE_INFO.of(source);
+    inputs[PARSED_UNIT_INPUT] = PARSED_UNIT.of(source);
     EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
     // for Source
     for (ResultDescriptor result in enginePlugin.dartErrorsForSource) {
@@ -2438,109 +2476,6 @@
 }
 
 /**
- * The helper for building the export [Namespace] of a [LibraryElement].
- */
-class ExportNamespaceBuilder {
-  /**
-   * Build the export [Namespace] of the given [LibraryElement].
-   */
-  Namespace build(LibraryElement library) {
-    return new Namespace(
-        _createExportMapping(library, new HashSet<LibraryElement>()));
-  }
-
-  /**
-   * Create a mapping table representing the export namespace of the given
-   * [library].
-   *
-   * The given [visitedElements] a set of libraries that do not need to be
-   * visited when processing the export directives of the given library because
-   * all of the names defined by them will be added by another library.
-   */
-  HashMap<String, Element> _createExportMapping(
-      LibraryElement library, HashSet<LibraryElement> visitedElements) {
-    visitedElements.add(library);
-    try {
-      HashMap<String, Element> definedNames = new HashMap<String, Element>();
-      // Add names of the export directives.
-      for (ExportElement element in library.exports) {
-        LibraryElement exportedLibrary = element.exportedLibrary;
-        if (exportedLibrary != null &&
-            !visitedElements.contains(exportedLibrary)) {
-          //
-          // The exported library will be null if the URI does not reference a
-          // valid library.
-          //
-          HashMap<String, Element> exportedNames =
-              _createExportMapping(exportedLibrary, visitedElements);
-          exportedNames = _applyCombinators(exportedNames, element.combinators);
-          definedNames.addAll(exportedNames);
-        }
-      }
-      // Add names of the public namespace.
-      {
-        Namespace publicNamespace = library.publicNamespace;
-        if (publicNamespace != null) {
-          definedNames.addAll(publicNamespace.definedNames);
-        }
-      }
-      return definedNames;
-    } finally {
-      visitedElements.remove(library);
-    }
-  }
-
-  /**
-   * Apply the given [combinators] to all of the names in [definedNames].
-   */
-  static HashMap<String, Element> _applyCombinators(
-      HashMap<String, Element> definedNames,
-      List<NamespaceCombinator> combinators) {
-    for (NamespaceCombinator combinator in combinators) {
-      if (combinator is HideElementCombinator) {
-        _hide(definedNames, combinator.hiddenNames);
-      } else if (combinator is ShowElementCombinator) {
-        definedNames = _show(definedNames, combinator.shownNames);
-      }
-    }
-    return definedNames;
-  }
-
-  /**
-   * Hide all of the [hiddenNames] by removing them from the given
-   * [definedNames].
-   */
-  static void _hide(
-      HashMap<String, Element> definedNames, List<String> hiddenNames) {
-    for (String name in hiddenNames) {
-      definedNames.remove(name);
-      definedNames.remove('$name=');
-    }
-  }
-
-  /**
-   * Show only the given [shownNames] by removing all other names from the given
-   * [definedNames].
-   */
-  static HashMap<String, Element> _show(
-      HashMap<String, Element> definedNames, List<String> shownNames) {
-    HashMap<String, Element> newNames = new HashMap<String, Element>();
-    for (String name in shownNames) {
-      Element element = definedNames[name];
-      if (element != null) {
-        newNames[name] = element;
-      }
-      String setterName = '$name=';
-      element = definedNames[setterName];
-      if (element != null) {
-        newNames[setterName] = element;
-      }
-    }
-    return newNames;
-  }
-}
-
-/**
  * A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
  */
 class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
@@ -2618,7 +2553,7 @@
       'GatherUsedLocalElementsTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[DEFINED_ELEMENTS, USED_LOCAL_ELEMENTS]);
+      <ResultDescriptor>[USED_LOCAL_ELEMENTS]);
 
   GatherUsedLocalElementsTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -2633,7 +2568,7 @@
     CompilationUnitElement unitElement = unit.element;
     LibraryElement libraryElement = unitElement.library;
     //
-    // Prepare defined and used local elements.
+    // Prepare used local elements.
     //
     GatherUsedLocalElementsVisitor visitor =
         new GatherUsedLocalElementsVisitor(libraryElement);
@@ -2641,7 +2576,6 @@
     //
     // Record outputs.
     //
-    outputs[DEFINED_ELEMENTS] = visitor.definedElements;
     outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
   }
 
@@ -2675,11 +2609,6 @@
   static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
 
   /**
-   * The name of a list of [DEFINED_ELEMENTS] for each library unit input.
-   */
-  static const String DEFINED_ELEMENTS_INPUT = 'DEFINED_ELEMENTS';
-
-  /**
    * The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
    */
   static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
@@ -2725,8 +2654,6 @@
     CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
     List<UsedImportedElements> usedImportedElementsList =
         getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
-    List<List<Element>> definedElementsList =
-        getRequiredInput(DEFINED_ELEMENTS_INPUT);
     List<UsedLocalElements> usedLocalElementsList =
         getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
     CompilationUnitElement unitElement = unit.element;
@@ -2751,11 +2678,7 @@
           new UsedLocalElements.merge(usedLocalElementsList);
       UnusedLocalElementsVerifier visitor =
           new UnusedLocalElementsVerifier(errorListener, usedElements);
-      for (List<Element> definedElements in definedElementsList) {
-        for (Element element in definedElements) {
-          element.accept(visitor);
-        }
-      }
+      unitElement.accept(visitor);
     }
     // Dart2js analysis.
     if (analysisOptions.dart2jsHint) {
@@ -2787,8 +2710,6 @@
     Source libSource = unit.library;
     return <String, TaskInput>{
       RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
-      DEFINED_ELEMENTS_INPUT:
-          LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(DEFINED_ELEMENTS),
       USED_LOCAL_ELEMENTS_INPUT:
           LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_LOCAL_ELEMENTS),
       USED_IMPORTED_ELEMENTS_INPUT:
@@ -3968,45 +3889,6 @@
 }
 
 /**
- * The helper for building the public [Namespace] of a [LibraryElement].
- */
-class PublicNamespaceBuilder {
-  final HashMap<String, Element> definedNames = new HashMap<String, Element>();
-
-  /**
-   * Build a public [Namespace] of the given [library].
-   */
-  Namespace build(LibraryElement library) {
-    definedNames.clear();
-    _addPublicNames(library.definingCompilationUnit);
-    library.parts.forEach(_addPublicNames);
-    return new Namespace(definedNames);
-  }
-
-  /**
-   * Add the given [element] if it has a publicly visible name.
-   */
-  void _addIfPublic(Element element) {
-    String name = element.name;
-    if (name != null && !Scope.isPrivateName(name)) {
-      definedNames[name] = element;
-    }
-  }
-
-  /**
-   * Add all of the public top-level names that are defined in the given
-   * [compilationUnit].
-   */
-  void _addPublicNames(CompilationUnitElement compilationUnit) {
-    compilationUnit.accessors.forEach(_addIfPublic);
-    compilationUnit.enums.forEach(_addIfPublic);
-    compilationUnit.functions.forEach(_addIfPublic);
-    compilationUnit.functionTypeAliases.forEach(_addIfPublic);
-    compilationUnit.types.forEach(_addIfPublic);
-  }
-}
-
-/**
  * A task that ensures that [LIBRARY_ELEMENT2] is ready for the target library
  * source and its import/export closure.
  */
@@ -5113,9 +4995,11 @@
     //
     TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    if (context.analysisOptions.strongMode) {
+    AnalysisOptionsImpl options = context.analysisOptions;
+    if (options.strongMode) {
       unit.accept(new CodeChecker(
-          typeProvider, new StrongTypeSystemImpl(), errorListener));
+          typeProvider, new StrongTypeSystemImpl(), errorListener,
+          hints: options.strongModeHints));
     }
     //
     // Record outputs.
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index b391517..8f0c9de 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/type_system.dart';
@@ -565,7 +566,7 @@
   }
 
   StaticInfo _checkAssignment(Expression expr, DartType toT) {
-    final fromT = expr.staticType ?? DynamicTypeImpl.instance;
+    final fromT = _getStaticType(expr);
     final Coercion c = _coerceTo(fromT, toT);
     if (c is Identity) return null;
     if (c is CoercionError) return new StaticTypeError(rules, expr, toT);
@@ -770,7 +771,63 @@
   }
 
   DartType _getStaticType(Expression expr) {
-    return expr.staticType ?? DynamicTypeImpl.instance;
+    DartType t = expr.staticType ?? DynamicTypeImpl.instance;
+
+    // Remove fuzzy arrow if possible.
+    if (t is FunctionType && StaticInfo.isKnownFunction(expr)) {
+      t = _removeFuzz(t);
+    }
+
+    return t;
+  }
+
+  /// Remove "fuzzy arrow" in this function type.
+  ///
+  /// Normally we treat dynamically typed parameters as bottom for function
+  /// types. This allows type tests such as `if (f is SingleArgFunction)`.
+  /// It also requires a dynamic check on the parameter type to call these
+  /// functions.
+  ///
+  /// When we convert to a strict arrow, dynamically typed parameters become
+  /// top. This is safe to do for known functions, like top-level or local
+  /// functions and static methods. Those functions must already be essentially
+  /// treating dynamic as top.
+  ///
+  /// Only the outer-most arrow can be strict. Any others must be fuzzy, because
+  /// we don't know what function value will be passed there.
+  // TODO(jmesserly): should we use a real "fuzzyArrow" bit on the function
+  // type? That would allow us to implement this in the subtype relation.
+  // TODO(jmesserly): we'll need to factor this differently if we want to
+  // move CodeChecker's functionality into existing analyzer. Likely we can
+  // let the Expression have a strict arrow, then in places were we do
+  // inference, convert back to a fuzzy arrow.
+  FunctionType _removeFuzz(FunctionType t) {
+    bool foundFuzz = false;
+    List<ParameterElement> parameters = <ParameterElement>[];
+    for (ParameterElement p in t.parameters) {
+      ParameterElement newP = _removeParameterFuzz(p);
+      parameters.add(newP);
+      if (p != newP) foundFuzz = true;
+    }
+    if (!foundFuzz) {
+      return t;
+    }
+
+    FunctionElementImpl function = new FunctionElementImpl("", -1);
+    function.synthetic = true;
+    function.returnType = t.returnType;
+    function.shareTypeParameters(t.typeFormals);
+    function.shareParameters(parameters);
+    return function.type = new FunctionTypeImpl(function);
+  }
+
+  /// Removes fuzzy arrow, see [_removeFuzz].
+  ParameterElement _removeParameterFuzz(ParameterElement p) {
+    if (p.type.isDynamic) {
+      return new ParameterElementImpl.synthetic(
+          p.name, typeProvider.objectType, p.parameterKind);
+    }
+    return p;
   }
 
   /// Given an expression, return its type assuming it is
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index c3a5839..6169815 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -138,16 +138,7 @@
       }
     }
 
-    Element element = null;
-    if (expression is PropertyAccess) {
-      element = expression.propertyName.staticElement;
-    } else if (expression is Identifier) {
-      element = expression.staticElement;
-    }
-    // First class functions and static methods, where we know the original
-    // declaration, will have an exact type, so we know a downcast will fail.
-    if (element is FunctionElement ||
-        element is MethodElement && element.isStatic) {
+    if (StaticInfo.isKnownFunction(expression)) {
       return new StaticTypeError(rules, expression, toT);
     }
 
@@ -551,6 +542,19 @@
   // TODO(jmesserly): review the usage of error codes. We probably want our own,
   // as well as some DDC specific [ErrorType]s.
   ErrorCode toErrorCode();
+
+  static bool isKnownFunction(Expression expression) {
+    Element element = null;
+    if (expression is PropertyAccess) {
+      element = expression.propertyName.staticElement;
+    } else if (expression is Identifier) {
+      element = expression.staticElement;
+    }
+    // First class functions and static methods, where we know the original
+    // declaration, will have an exact type, so we know a downcast will fail.
+    return element is FunctionElement ||
+        element is MethodElement && element.isStatic;
+  }
 }
 
 class StaticTypeError extends StaticError {
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 58e095b..8144f17 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -171,6 +171,17 @@
   bool get handlesDependencyCycles => false;
 
   /**
+   * Return the value of the input with the given [name], or `null` if the input
+   * value is not defined.
+   */
+  Object getOptionalInput(String name) {
+    if (inputs == null || !inputs.containsKey(name)) {
+      return null;
+    }
+    return inputs[name];
+  }
+
+  /**
    * Return the value of the input with the given [name]. Throw an exception if
    * the input value is not defined.
    */
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index c376533..bb328c2 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -7,6 +7,7 @@
   sdk: '>=1.12.0 <2.0.0'
 dependencies:
   args: '>=0.12.1 <0.14.0'
+  crypto: ^0.9.0
   glob: ^1.0.3
   html: ^0.12.0
   package_config: ^0.1.1
diff --git a/pkg/analyzer/test/enum_test.dart b/pkg/analyzer/test/enum_test.dart
index a61765d..0ba5a98 100644
--- a/pkg/analyzer/test/enum_test.dart
+++ b/pkg/analyzer/test/enum_test.dart
@@ -69,7 +69,8 @@
   }
 
   void test_Modifier() {
-    new EnumTester<Modifier>()
+    new EnumTester<Modifier>(
+        ignoreGetters: ["persistedValues", "transientValues"])
       ..check_getters()
       ..check_explicit_values();
   }
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 3eb5cd0..5d74e2c 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -176,6 +176,31 @@
     expect(source.uri.toString(), "dart:core");
   }
 
+  void test_fromFile_library_firstExact() {
+    DirectoryBasedDartSdk sdk = _createDartSdk();
+    JavaFile dirHtml = new JavaFile.relative(sdk.libraryDirectory, "html");
+    JavaFile dirDartium = new JavaFile.relative(dirHtml, "dartium");
+    JavaFile file = new JavaFile.relative(dirDartium, "html_dartium.dart");
+    expect(file.isFile(), isTrue);
+    Source source = sdk.fromFileUri(file.toURI());
+    expect(source, isNotNull);
+    expect(source.isInSystemLibrary, isTrue);
+    expect(source.uri.toString(), "dart:html");
+  }
+
+  void test_fromFile_library_html_common_dart2js() {
+    DirectoryBasedDartSdk sdk = _createDartSdk();
+    JavaFile dirHtml = new JavaFile.relative(sdk.libraryDirectory, "html");
+    JavaFile dirCommon = new JavaFile.relative(dirHtml, "html_common");
+    JavaFile file =
+        new JavaFile.relative(dirCommon, "html_common_dart2js.dart");
+    expect(file.isFile(), isTrue);
+    Source source = sdk.fromFileUri(file.toURI());
+    expect(source, isNotNull);
+    expect(source.isInSystemLibrary, isTrue);
+    expect(source.uri.toString(), "dart:html_common/html_common_dart2js.dart");
+  }
+
   void test_fromFile_part() {
     DirectoryBasedDartSdk sdk = _createDartSdk();
     Source source = sdk.fromFileUri(new JavaFile.relative(
@@ -275,11 +300,19 @@
    * resulting [ElementHolder].
    */
   ElementHolder buildElementsForText(String code) {
-    compilationUnit = ParserTestCase.parseCompilationUnit(code);
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = new ElementBuilder(holder, compilationUnitElement);
-    compilationUnit.accept(builder);
-    return holder;
+    TestLogger logger = new TestLogger();
+    AnalysisEngine.instance.logger = logger;
+    try {
+      compilationUnit = ParserTestCase.parseCompilationUnit(code);
+      ElementHolder holder = new ElementHolder();
+      ElementBuilder builder =
+          new ElementBuilder(holder, compilationUnitElement);
+      compilationUnit.accept(builder);
+      return holder;
+    } finally {
+      expect(logger.log, hasLength(0));
+      AnalysisEngine.instance.logger = Logger.NULL;
+    }
   }
 
   /**
@@ -587,6 +620,38 @@
     expect(type.isSynthetic, isFalse);
   }
 
+  void test_visitClassDeclaration_invalidFunctionInAnnotation_class() {
+    // https://github.com/dart-lang/sdk/issues/25696
+    String code = r'''
+class A {
+  const A({f});
+}
+
+@A(f: () {})
+class C {}
+''';
+    buildElementsForText(code);
+  }
+
+  void test_visitClassDeclaration_invalidFunctionInAnnotation_method() {
+    String code = r'''
+class A {
+  const A({f});
+}
+
+class C {
+  @A(f: () {})
+  void m() {}
+}
+''';
+    ElementHolder holder = buildElementsForText(code);
+    ClassElement elementC = holder.types[1];
+    expect(elementC, isNotNull);
+    MethodElement methodM = elementC.methods[0];
+    expect(methodM, isNotNull);
+    expect(methodM.functions, isEmpty);
+  }
+
   void test_visitClassDeclaration_minimal() {
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = _makeBuilder(holder);
@@ -986,6 +1051,9 @@
     expect(parameters, hasLength(1));
     ParameterElement parameter = parameters[0];
     expect(parameter.hasImplicitType, isTrue);
+    expect(parameter.initializer, isNotNull);
+    expect(parameter.initializer.type, isNotNull);
+    expect(parameter.initializer.hasImplicitReturnType, isTrue);
     expect(parameter.isConst, isFalse);
     expect(parameter.isDeprecated, isFalse);
     expect(parameter.isFinal, isFalse);
@@ -1012,6 +1080,9 @@
     expect(parameters, hasLength(1));
     ParameterElement parameter = parameters[0];
     expect(parameter.hasImplicitType, isFalse);
+    expect(parameter.initializer, isNotNull);
+    expect(parameter.initializer.type, isNotNull);
+    expect(parameter.initializer.hasImplicitReturnType, isTrue);
     expect(parameter.isConst, isFalse);
     expect(parameter.isDeprecated, isFalse);
     expect(parameter.isFinal, isFalse);
@@ -1931,6 +2002,7 @@
     FunctionElement initializer = parameter.initializer;
     expect(initializer, isNotNull);
     expect(initializer.isSynthetic, isTrue);
+    expect(initializer.hasImplicitReturnType, isTrue);
   }
 
   void test_visitSimpleFormalParameter_noType() {
@@ -2165,6 +2237,7 @@
     expect(fieldElement, isNotNull);
     FunctionElement initializerElement = fieldElement.initializer;
     expect(initializerElement, isNotNull);
+    expect(initializerElement.hasImplicitReturnType, isTrue);
     List<FunctionElement> functionElements = initializerElement.functions;
     expect(functionElements, hasLength(1));
     List<LocalVariableElement> variableElements =
@@ -2217,6 +2290,8 @@
     TopLevelVariableElement variable = variables[0];
     expect(variable, new isInstanceOf<ConstTopLevelVariableElementImpl>());
     expect(variable.initializer, isNotNull);
+    expect(variable.initializer.type, isNotNull);
+    expect(variable.initializer.hasImplicitReturnType, isTrue);
     expect(variable.name, variableName);
     expect(variable.hasImplicitType, isTrue);
     expect(variable.isConst, isTrue);
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 9c4f87c..7c0c15a 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -1462,6 +1462,23 @@
     verify([source]);
   }
 
+  void test_constWithNonConst_with() {
+    Source source = addSource(r'''
+class B {
+  const B();
+}
+class C = B with M;
+class M {}
+const x = const C();
+main() {
+  print(x);
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.CONST_WITH_NON_CONST]);
+    verify([source]);
+  }
+
   void test_constWithNonConstantArgument_annotation() {
     Source source = addSource(r'''
 class A {
@@ -1669,24 +1686,6 @@
     verify([librarySource, sourceA, sourceB]);
   }
 
-  void test_duplicateDefinition_inPart() {
-    Source librarySource = addNamedSource(
-        "/lib.dart",
-        r'''
-library test;
-part 'a.dart';
-class A {}''');
-    Source sourceA = addNamedSource(
-        "/a.dart",
-        r'''
-part of test;
-class A {}''');
-    computeLibrarySourceErrors(librarySource);
-    assertErrors(sourceA, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
-    assertNoErrors(librarySource);
-    verify([librarySource, sourceA]);
-  }
-
   void test_duplicateDefinition_catch() {
     Source source = addSource(r'''
 main() {
@@ -1730,6 +1729,24 @@
     verify([source]);
   }
 
+  void test_duplicateDefinition_inPart() {
+    Source librarySource = addNamedSource(
+        "/lib.dart",
+        r'''
+library test;
+part 'a.dart';
+class A {}''');
+    Source sourceA = addNamedSource(
+        "/a.dart",
+        r'''
+part of test;
+class A {}''');
+    computeLibrarySourceErrors(librarySource);
+    assertErrors(sourceA, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    assertNoErrors(librarySource);
+    verify([librarySource, sourceA]);
+  }
+
   void test_duplicateDefinition_locals_inCase() {
     Source source = addSource(r'''
 main() {
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 8d6bf51..0f1112d 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -314,6 +314,19 @@
     // no other validations than built into DeclarationResolver
   }
 
+  void test_visitMethodDeclaration_unaryMinus() {
+    String code = r'''
+class C {
+  C operator -() => null;
+  C operator -(C other) => null;
+}
+''';
+    CompilationUnit unit = resolveSource(code);
+    // re-resolve
+    _cloneResolveUnit(unit);
+    // no other validations than built into DeclarationResolver
+  }
+
   void test_visitMethodDeclaration_getter_duplicate() {
     String code = r'''
 class C {
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 5c52f17..80e4264 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -3501,11 +3501,7 @@
     }
     _checkCacheEntries(cache);
 
-    try {
-      assertSameResolution(unit, fullNewUnit);
-    } on IncrementalResolutionMismatch catch (mismatch) {
-      fail(mismatch.message);
-    }
+    assertSameResolution(unit, fullNewUnit);
     // errors
     List<AnalysisError> newFullErrors =
         analysisContext.getErrors(source).errors;
@@ -4849,11 +4845,44 @@
     }
   }
 
-  void _assertCacheResults({bool expectCachePostConstantsValid: true}) {
+  void test_updateFunctionToForLoop() {
+    _resolveUnit(r'''
+class PlayDrag {
+  final List<num> times = new List<num>();
+
+  PlayDrag.start() {}
+
+  void update(num pos) {
+    fo (int i = times.length - 2; i >= 0; i--) {}
+  }
+}
+''');
+
+    _updateAndValidate(
+        r'''
+class PlayDrag {
+  final List<num> times = new List<num>();
+
+  PlayDrag.start() {}
+
+  void update(num pos) {
+    for (int i = times.length - 2; i >= 0; i--) {}
+  }
+}
+''',
+        expectLibraryUnchanged: false);
+  }
+
+  void _assertCacheResults(
+      {bool expectLibraryUnchanged: true,
+      bool expectCachePostConstantsValid: true}) {
     _assertCacheSourceResult(TOKEN_STREAM);
     _assertCacheSourceResult(SCAN_ERRORS);
     _assertCacheSourceResult(PARSED_UNIT);
     _assertCacheSourceResult(PARSE_ERRORS);
+    if (!expectLibraryUnchanged) {
+      return;
+    }
     _assertCacheSourceResult(LIBRARY_ELEMENT1);
     _assertCacheSourceResult(LIBRARY_ELEMENT2);
     _assertCacheSourceResult(LIBRARY_ELEMENT3);
@@ -4943,6 +4972,7 @@
 
   void _updateAndValidate(String newCode,
       {bool expectedSuccess: true,
+      bool expectLibraryUnchanged: true,
       bool expectCachePostConstantsValid: true,
       bool compareWithFull: true,
       bool runTasksBeforeIncremental: true}) {
@@ -4955,7 +4985,7 @@
     _resetWithIncremental(true);
     analysisContext2.setContents(source, newCode);
     CompilationUnit newUnit = resolveCompilationUnit(source, oldLibrary);
-    expect(logger.hasError, isFalse);
+    logger.expectNoErrors();
     List<AnalysisError> newErrors = analysisContext.computeErrors(source);
     LineInfo newLineInfo = analysisContext.getLineInfo(source);
     // check for expected failure
@@ -4966,6 +4996,7 @@
     // The cache must still have enough results to make the incremental
     // resolution useful.
     _assertCacheResults(
+        expectLibraryUnchanged: expectLibraryUnchanged,
         expectCachePostConstantsValid: expectCachePostConstantsValid);
     // The existing CompilationUnit[Element] should be updated.
     expect(newUnit, same(oldUnit));
@@ -5255,7 +5286,14 @@
 }
 
 class _TestLogger implements logging.Logger {
-  bool hasError = false;
+  Object lastException;
+  Object lastStackTrace;
+
+  void expectNoErrors() {
+    if (lastException != null) {
+      fail("logged an exception:\n$lastException\n$lastStackTrace\n");
+    }
+  }
 
   @override
   void enter(String name) {}
@@ -5268,7 +5306,8 @@
 
   @override
   void logException(Object exception, [Object stackTrace]) {
-    hasError = true;
+    lastException = exception;
+    lastStackTrace = stackTrace;
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 72186b4..710be9b 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -1510,6 +1510,49 @@
         reason: 'parser recovers what it can');
   }
 
+  void test_method_invalidTypeParameterExtends() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25739.
+
+    // TODO(jmesserly): ideally we'd be better at parser recovery here.
+    enableGenericMethods = true;
+    MethodDeclaration method = parse3(
+        "parseClassMember",
+        <Object>["C"],
+        "f<E>(E extends num p);",
+        [
+          ParserErrorCode.MISSING_IDENTIFIER, // `extends` is a keyword
+          ParserErrorCode.EXPECTED_TOKEN, // comma
+          ParserErrorCode.EXPECTED_TOKEN, // close paren
+          ParserErrorCode.MISSING_FUNCTION_BODY
+        ]);
+    expect(method.parameters.toString(), '(E, extends)',
+        reason: 'parser recovers what it can');
+  }
+
+  void test_method_invalidTypeParameterExtendsComment() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25739.
+
+    // TODO(jmesserly): ideally we'd be better at parser recovery here.
+    // Also, this behavior is slightly different from how we would parse a
+    // normal generic method, because we "discover" the comment at a different
+    // point in the parser. This has a slight effect on the AST that results
+    // from error recovery.
+    enableGenericMethodComments = true;
+    MethodDeclaration method = parse3(
+        "parseClassMember",
+        <Object>["C"],
+        "f/*<E>*/(dynamic/*=E extends num*/p);",
+        [
+          ParserErrorCode.MISSING_IDENTIFIER, // `extends` is a keyword
+          ParserErrorCode.EXPECTED_TOKEN, // comma
+          ParserErrorCode.MISSING_IDENTIFIER, // `extends` is a keyword
+          ParserErrorCode.EXPECTED_TOKEN, // close paren
+          ParserErrorCode.MISSING_FUNCTION_BODY
+        ]);
+    expect(method.parameters.toString(), '(E extends, extends)',
+        reason: 'parser recovers what it can');
+  }
+
   void test_method_invalidTypeParameters() {
     // TODO(jmesserly): ideally we'd be better at parser recovery here.
     // It doesn't try to advance past the invalid token `!` to find the
@@ -1904,6 +1947,16 @@
         [ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP]);
   }
 
+  void test_redirectingConstructorWithBody_named() {
+    parse3("parseClassMember", <Object>["C"], "C.x() : this() {}",
+        [ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY]);
+  }
+
+  void test_redirectingConstructorWithBody_unnamed() {
+    parse3("parseClassMember", <Object>["C"], "C() : this.x() {}",
+        [ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY]);
+  }
+
   void test_redirectionInNonFactoryConstructor() {
     parse3("parseClassMember", <Object>["C"], "C() = D;",
         [ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR]);
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 4210fef..339d4d1 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -33,7 +33,6 @@
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:unittest/unittest.dart';
 
 import '../reflective_tests.dart';
@@ -220,6 +219,7 @@
       }
       FunctionElementImpl thenOnValue = ElementFactory.functionElement3(
           'onValue', futureThenR, [futureElement.typeParameters[0]], null);
+      thenOnValue.synthetic = true;
 
       DartType futureRType = futureElement.type.substitute4([futureThenR.type]);
       MethodElementImpl thenMethod = ElementFactory
@@ -256,12 +256,13 @@
       ];
       DartType returnType = streamSubscriptionElement.type
           .substitute4(streamElement.type.typeArguments);
-      List<DartType> parameterTypes = <DartType>[
-        ElementFactory
-            .functionElement3('onData', VoidTypeImpl.instance.element,
-                <TypeDefiningElement>[streamElement.typeParameters[0]], null)
-            .type,
-      ];
+      FunctionElementImpl listenOnData = ElementFactory.functionElement3(
+          'onData',
+          VoidTypeImpl.instance.element,
+          <TypeDefiningElement>[streamElement.typeParameters[0]],
+          null);
+      listenOnData.synthetic = true;
+      List<DartType> parameterTypes = <DartType>[listenOnData.type,];
       // TODO(brianwilkerson) This is missing the optional parameters.
       MethodElementImpl listenMethod =
           ElementFactory.methodElement('listen', returnType, parameterTypes);
@@ -426,8 +427,10 @@
     // core library so public and export namespaces are the same.
     //
     for (LibraryElementImpl library in elementMap.values) {
-      library.exportNamespace =
-          library.publicNamespace = new PublicNamespaceBuilder().build(library);
+      Namespace namespace =
+          new NamespaceBuilder().createPublicNamespaceForLibrary(library);
+      library.exportNamespace = namespace;
+      library.publicNamespace = namespace;
     }
     context.recordLibraryElements(elementMap);
     // Create the synthetic element for `loadLibrary`.
@@ -1489,8 +1492,8 @@
     //   break loop;
     // }
     String label = "loop";
-    LabelElementImpl labelElement =
-        new LabelElementImpl(AstFactory.identifier3(label), false, false);
+    LabelElementImpl labelElement = new LabelElementImpl.forNode(
+        AstFactory.identifier3(label), false, false);
     BreakStatement breakStatement = AstFactory.breakStatement2(label);
     Expression condition = AstFactory.booleanLiteral(true);
     WhileStatement whileStatement =
@@ -1579,8 +1582,8 @@
     //   continue loop;
     // }
     String label = "loop";
-    LabelElementImpl labelElement =
-        new LabelElementImpl(AstFactory.identifier3(label), false, false);
+    LabelElementImpl labelElement = new LabelElementImpl.forNode(
+        AstFactory.identifier3(label), false, false);
     ContinueStatement continueStatement = AstFactory.continueStatement(label);
     Expression condition = AstFactory.booleanLiteral(true);
     WhileStatement whileStatement =
@@ -2383,9 +2386,7 @@
   }
   return null;
 }''');
-    SimpleIdentifier y = _findIdentifier('y = ');
-    expect(y.staticType.toString(), 'dynamic');
-    expect(y.propagatedType.toString(), 'List<dynamic>');
+    _expectIdentifierType('y = ', 'dynamic', 'List<dynamic>');
   }
 }
 
@@ -10146,11 +10147,7 @@
 }
 ''';
     _resolveTestUnit(code);
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.isDynamic, isTrue);
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'dynamic', isNull);
   }
 
   void test_FunctionExpressionInvocation_curried() {
@@ -10162,11 +10159,7 @@
 }
 ''';
     _resolveTestUnit(code);
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'int');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'int', isNull);
   }
 
   void test_FunctionExpressionInvocation_expression() {
@@ -10176,11 +10169,7 @@
 }
 ''';
     _resolveTestUnit(code);
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'int');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'int', isNull);
   }
 
   void test_MethodInvocation_nameType_localVariable() {
@@ -10193,9 +10182,7 @@
 """;
     _resolveTestUnit(code);
     // "foo" should be resolved to the "Foo" type
-    SimpleIdentifier identifier = _findIdentifier("foo();");
-    DartType type = identifier.staticType;
-    expect(type, new isInstanceOf<FunctionType>());
+    _expectIdentifierType("foo();", new isInstanceOf<FunctionType>());
   }
 
   void test_MethodInvocation_nameType_parameter_FunctionTypeAlias() {
@@ -10207,9 +10194,7 @@
 """;
     _resolveTestUnit(code);
     // "foo" should be resolved to the "Foo" type
-    SimpleIdentifier identifier = _findIdentifier("foo();");
-    DartType type = identifier.staticType;
-    expect(type, new isInstanceOf<FunctionType>());
+    _expectIdentifierType("foo();", new isInstanceOf<FunctionType>());
   }
 
   void test_MethodInvocation_nameType_parameter_propagatedType() {
@@ -10222,13 +10207,8 @@
 }
 """;
     _resolveTestUnit(code);
-    SimpleIdentifier identifier = _findIdentifier("p()");
-    expect(identifier.staticType, DynamicTypeImpl.instance);
-    {
-      FunctionType type = identifier.propagatedType;
-      expect(type, isNotNull);
-      expect(type.name, 'Foo');
-    }
+    _expectIdentifierType("p()", DynamicTypeImpl.instance,
+        predicate((type) => type.name == 'Foo'));
   }
 
   void test_staticMethods_classTypeParameters() {
@@ -10241,15 +10221,7 @@
 }
 ''';
     _resolveTestUnit(code);
-    SimpleIdentifier identifier = _findIdentifier('m);');
-    FunctionTypeImpl type = identifier.staticType;
-    expect(type.toString(), '() → void');
-    expect(type.typeParameters, isEmpty,
-        reason: 'static methods should not have type parameters');
-    expect(type.typeArguments, isEmpty,
-        reason: 'static methods should not have type arguments');
-    expect(type.typeFormals, isEmpty,
-        reason: 'this static method is not generic');
+    _expectFunctionType('m);', '() → void');
   }
 
   void test_staticMethods_classTypeParameters_genericMethod() {
@@ -10271,16 +10243,11 @@
     // C - m
     TypeParameterType typeS;
     {
-      SimpleIdentifier identifier = _findIdentifier('m);');
-      FunctionTypeImpl type = identifier.staticType;
-      expect(type.toString(), '<S>(S) → void');
-      expect(type.typeParameters, isEmpty,
-          reason: 'static methods should not have type parameters');
-      expect(type.typeArguments, isEmpty,
-          reason: 'static methods should not have type arguments');
-      expect(type.typeFormals.toString(), '[S]');
-      typeS = type.typeFormals[0].type;
+      _expectFunctionType('m);', '<S>(S) → void',
+          elementTypeParams: '[S]', typeFormals: '[S]');
 
+      FunctionTypeImpl type = _findIdentifier('m);').staticType;
+      typeS = type.typeFormals[0].type;
       type = type.instantiate([DynamicTypeImpl.instance]);
       expect(type.toString(), '(dynamic) → void');
       expect(type.typeParameters.toString(), '[S]');
@@ -10289,13 +10256,13 @@
     }
     // C - m - f
     {
-      SimpleIdentifier identifier = _findIdentifier('f);');
-      FunctionTypeImpl type = identifier.staticType;
-      expect(type.toString(), '<U>(S, U) → void');
-      expect(type.typeParameters.toString(), '[S]');
-      expect(type.typeArguments.toString(), '[S]');
-      expect(type.typeFormals.toString(), '[U]');
+      _expectFunctionType('f);', '<U>(S, U) → void',
+          elementTypeParams: '[U]',
+          typeParams: '[S]',
+          typeArgs: '[S]',
+          typeFormals: '[U]');
 
+      FunctionTypeImpl type = _findIdentifier('f);').staticType;
       type = type.instantiate([DynamicTypeImpl.instance]);
       expect(type.toString(), '(S, dynamic) → void');
       expect(type.typeParameters.toString(), '[S, U]');
@@ -13364,20 +13331,13 @@
   var paramTearOffInst = pf/*<int>*/;
 }
 ''');
-    expect(_findIdentifier('methodTearOffInst').staticType.toString(),
-        "(int) → int");
-    expect(_findIdentifier('staticTearOffInst').staticType.toString(),
-        "(int) → int");
-    expect(_findIdentifier('staticFieldTearOffInst').staticType.toString(),
-        "(int) → int");
-    expect(_findIdentifier('topFunTearOffInst').staticType.toString(),
-        "(int) → int");
-    expect(_findIdentifier('topFieldTearOffInst').staticType.toString(),
-        "(int) → int");
-    expect(_findIdentifier('localTearOffInst').staticType.toString(),
-        "(int) → int");
-    expect(_findIdentifier('paramTearOffInst').staticType.toString(),
-        "(int) → int");
+    _expectIdentifierType('methodTearOffInst', "(int) → int");
+    _expectIdentifierType('staticTearOffInst', "(int) → int");
+    _expectIdentifierType('staticFieldTearOffInst', "(int) → int");
+    _expectIdentifierType('topFunTearOffInst', "(int) → int");
+    _expectIdentifierType('topFieldTearOffInst', "(int) → int");
+    _expectIdentifierType('localTearOffInst', "(int) → int");
+    _expectIdentifierType('paramTearOffInst', "(int) → int");
   }
 
   void setUp() {
@@ -13395,12 +13355,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'int');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'int', isNull);
   }
 
   void test_dynamicObjectMethod_toString() {
@@ -13411,47 +13366,34 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'String');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'String', isNull);
   }
 
   void test_genericFunction() {
     _resolveTestUnit(r'/*=T*/ f/*<T>*/(/*=T*/ x) => null;');
+    _expectFunctionType('f', '<T>(T) → T',
+        elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = _findIdentifier('f');
     FunctionElementImpl e = f.staticElement;
-    expect(e.typeParameters.toString(), '[T]');
-    expect(e.type.typeFormals.toString(), '[T]');
-    expect(e.type.typeParameters.toString(), '[]');
-    expect(e.type.toString(), '<T>(T) → T');
-
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), '(String) → String');
   }
 
   void test_genericFunction_bounds() {
     _resolveTestUnit(r'/*=T*/ f/*<T extends num>*/(/*=T*/ x) => null;');
-    SimpleIdentifier f = _findIdentifier('f');
-    FunctionElementImpl e = f.staticElement;
-    expect(e.typeParameters.toString(), '[T extends num]');
-    expect(e.type.typeFormals.toString(), '[T extends num]');
-    expect(e.type.typeParameters.toString(), '[]');
-    expect(e.type.toString(), '<T extends num>(T) → T');
+    _expectFunctionType('f', '<T extends num>(T) → T',
+        elementTypeParams: '[T extends num]', typeFormals: '[T extends num]');
   }
 
   void test_genericFunction_parameter() {
     _resolveTestUnit(r'''
 void g(/*=T*/ f/*<T>*/(/*=T*/ x)) {}
 ''');
+    _expectFunctionType('f', '<T>(T) → T',
+        elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = _findIdentifier('f');
     ParameterElementImpl e = f.staticElement;
     FunctionType type = e.type;
-    expect(e.typeParameters.toString(), '[T]');
-    expect(type.typeFormals.toString(), '[T]');
-    expect(type.toString(), '<T>(T) → T');
     FunctionType ft = type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), '(String) → String');
   }
@@ -13462,14 +13404,10 @@
   static /*=T*/ f/*<T>*/(/*=T*/ x) => null;
 }
 ''');
+    _expectFunctionType('f', '<T>(T) → T',
+        elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f = _findIdentifier('f');
     MethodElementImpl e = f.staticElement;
-    expect(e.typeParameters.toString(), '[T]');
-    expect(e.type.typeFormals.toString(), '[T]');
-    expect(e.type.typeParameters.toString(), '[]');
-    expect(e.type.typeArguments.toString(), '[]');
-    expect(e.type.toString(), '<T>(T) → T');
-
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), '(String) → String');
   }
@@ -13507,46 +13445,18 @@
 ''';
     _resolveTestUnit(code);
 
-    {
+    checkBody(String className) {
       List<Statement> statements =
-          AstFinder.getStatementsInMethod(testUnit, "C", "g");
+          AstFinder.getStatementsInMethod(testUnit, className, "g");
 
-      ExpressionStatement exps0 = statements[1];
-      ExpressionStatement exps1 = statements[2];
-      ExpressionStatement exps2 = statements[3];
-      ExpressionStatement exps3 = statements[4];
-      ExpressionStatement exps4 = statements[5];
-      Expression exp0 = exps0.expression;
-      Expression exp1 = exps1.expression;
-      Expression exp2 = exps2.expression;
-      Expression exp3 = exps3.expression;
-      Expression exp4 = exps4.expression;
-      expect(exp0.staticType, typeProvider.dynamicType);
-      expect(exp1.staticType, typeProvider.dynamicType);
-      expect(exp2.staticType, typeProvider.dynamicType);
-      expect(exp3.staticType, typeProvider.dynamicType);
-      expect(exp4.staticType, typeProvider.dynamicType);
+      for (int i = 1; i <= 5; i++) {
+        Expression exp = (statements[i] as ExpressionStatement).expression;
+        expect(exp.staticType, typeProvider.dynamicType);
+      }
     }
-    {
-      List<Statement> statements =
-          AstFinder.getStatementsInMethod(testUnit, "D", "g");
 
-      ExpressionStatement exps0 = statements[1];
-      ExpressionStatement exps1 = statements[2];
-      ExpressionStatement exps2 = statements[3];
-      ExpressionStatement exps3 = statements[4];
-      ExpressionStatement exps4 = statements[5];
-      Expression exp0 = exps0.expression;
-      Expression exp1 = exps1.expression;
-      Expression exp2 = exps2.expression;
-      Expression exp3 = exps3.expression;
-      Expression exp4 = exps4.expression;
-      expect(exp0.staticType, typeProvider.dynamicType);
-      expect(exp1.staticType, typeProvider.dynamicType);
-      expect(exp2.staticType, typeProvider.dynamicType);
-      expect(exp3.staticType, typeProvider.dynamicType);
-      expect(exp4.staticType, typeProvider.dynamicType);
-    }
+    checkBody("C");
+    checkBody("D");
   }
 
   void test_genericMethod() {
@@ -13558,14 +13468,11 @@
   C<String> cOfString;
 }
 ''');
-    SimpleIdentifier f = _findIdentifier('f');
-    MethodElementImpl e = f.staticElement;
-    expect(e.typeParameters.toString(), '[T]');
-    expect(e.type.typeFormals.toString(), '[T]');
-    expect(e.type.typeParameters.toString(), '[E]');
-    expect(e.type.typeArguments.toString(), '[E]');
-    expect(e.type.toString(), '<T>(E) → List<T>');
-
+    _expectFunctionType('f', '<T>(E) → List<T>',
+        elementTypeParams: '[T]',
+        typeParams: '[E]',
+        typeArgs: '[E]',
+        typeFormals: '[T]');
     SimpleIdentifier c = _findIdentifier('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
     expect(ft.toString(), '<T>(String) → List<T>');
@@ -13618,14 +13525,14 @@
   var paramCall = (pf)/*<int>*/(3);
 }
 ''');
-    expect(_findIdentifier('methodCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFunCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('localCall').staticType.toString(), "int");
-    expect(_findIdentifier('paramCall').staticType.toString(), "int");
-    expect(_findIdentifier('lambdaCall').staticType.toString(), "int");
+    _expectIdentifierType('methodCall', "int");
+    _expectIdentifierType('staticCall', "int");
+    _expectIdentifierType('staticFieldCall', "int");
+    _expectIdentifierType('topFunCall', "int");
+    _expectIdentifierType('topFieldCall', "int");
+    _expectIdentifierType('localCall', "int");
+    _expectIdentifierType('paramCall', "int");
+    _expectIdentifierType('lambdaCall', "int");
   }
 
   void test_genericMethod_functionExpressionInvocation_inferred() {
@@ -13652,14 +13559,14 @@
   var paramCall = (pf)(3);
 }
 ''');
-    expect(_findIdentifier('methodCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFunCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('localCall').staticType.toString(), "int");
-    expect(_findIdentifier('paramCall').staticType.toString(), "int");
-    expect(_findIdentifier('lambdaCall').staticType.toString(), "int");
+    _expectIdentifierType('methodCall', "int");
+    _expectIdentifierType('staticCall', "int");
+    _expectIdentifierType('staticFieldCall', "int");
+    _expectIdentifierType('topFunCall', "int");
+    _expectIdentifierType('topFieldCall', "int");
+    _expectIdentifierType('localCall', "int");
+    _expectIdentifierType('paramCall', "int");
+    _expectIdentifierType('lambdaCall', "int");
   }
 
   void test_genericMethod_functionInvocation_explicit() {
@@ -13684,13 +13591,13 @@
   var paramCall = pf/*<int>*/(3);
 }
 ''');
-    expect(_findIdentifier('methodCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFunCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('localCall').staticType.toString(), "int");
-    expect(_findIdentifier('paramCall').staticType.toString(), "int");
+    _expectIdentifierType('methodCall', "int");
+    _expectIdentifierType('staticCall', "int");
+    _expectIdentifierType('staticFieldCall', "int");
+    _expectIdentifierType('topFunCall', "int");
+    _expectIdentifierType('topFieldCall', "int");
+    _expectIdentifierType('localCall', "int");
+    _expectIdentifierType('paramCall', "int");
   }
 
   void test_genericMethod_functionInvocation_inferred() {
@@ -13715,13 +13622,13 @@
   var paramCall = pf(3);
 }
 ''');
-    expect(_findIdentifier('methodCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticCall').staticType.toString(), "int");
-    expect(_findIdentifier('staticFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFunCall').staticType.toString(), "int");
-    expect(_findIdentifier('topFieldCall').staticType.toString(), "int");
-    expect(_findIdentifier('localCall').staticType.toString(), "int");
-    expect(_findIdentifier('paramCall').staticType.toString(), "int");
+    _expectIdentifierType('methodCall', "int");
+    _expectIdentifierType('staticCall', "int");
+    _expectIdentifierType('staticFieldCall', "int");
+    _expectIdentifierType('topFunCall', "int");
+    _expectIdentifierType('topFieldCall', "int");
+    _expectIdentifierType('localCall', "int");
+    _expectIdentifierType('paramCall', "int");
   }
 
   void test_genericMethod_functionTypedParameter() {
@@ -13733,13 +13640,11 @@
   C<String> cOfString;
 }
 ''');
-    SimpleIdentifier f = _findIdentifier('f');
-    MethodElementImpl e = f.staticElement;
-    expect(e.typeParameters.toString(), '[T]');
-    expect(e.type.typeFormals.toString(), '[T]');
-    expect(e.type.typeParameters.toString(), '[E]');
-    expect(e.type.typeArguments.toString(), '[E]');
-    expect(e.type.toString(), '<T>((E) → T) → List<T>');
+    _expectFunctionType('f', '<T>((E) → T) → List<T>',
+        elementTypeParams: '[T]',
+        typeParams: '[E]',
+        typeArgs: '[E]',
+        typeFormals: '[T]');
 
     SimpleIdentifier c = _findIdentifier('cOfString');
     FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
@@ -13761,17 +13666,13 @@
   list.map((e) => e);
   list.map((e) => 3);
 }''');
+    _expectIdentifierType('map((e) => e);', '<T>((dynamic) → T) → T', isNull);
+    _expectIdentifierType('map((e) => 3);', '<T>((dynamic) → T) → T', isNull);
 
-    SimpleIdentifier map1 = _findIdentifier('map((e) => e);');
-    MethodInvocation m1 = map1.parent;
+    MethodInvocation m1 = _findIdentifier('map((e) => e);').parent;
     expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
-    expect(map1.staticType.toString(), '<T>((dynamic) → T) → T');
-    expect(map1.propagatedType, isNull);
-    SimpleIdentifier map2 = _findIdentifier('map((e) => 3);');
-    MethodInvocation m2 = map2.parent;
+    MethodInvocation m2 = _findIdentifier('map((e) => 3);').parent;
     expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int');
-    expect(map2.staticType.toString(), '<T>((dynamic) → T) → T');
-    expect(map2.propagatedType, isNull);
   }
 
   void test_genericMethod_max_doubleDouble() {
@@ -13782,12 +13683,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'double');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'double', isNull);
   }
 
   void test_genericMethod_max_doubleDouble_prefixed() {
@@ -13798,12 +13694,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'double');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'double', isNull);
   }
 
   void test_genericMethod_max_doubleInt() {
@@ -13814,12 +13705,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'num');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'num', isNull);
   }
 
   void test_genericMethod_max_intDouble() {
@@ -13830,12 +13716,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'num');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'num', isNull);
   }
 
   void test_genericMethod_max_intInt() {
@@ -13846,12 +13727,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'int');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'int', isNull);
   }
 
   void test_genericMethod_nestedBound() {
@@ -13881,8 +13757,7 @@
     FunctionType ft = f.staticInvokeType;
     expect('${ft.typeArguments}/${ft.typeParameters}', '[S, int]/[T, S]');
 
-    SimpleIdentifier f2 = _findIdentifier('f;');
-    expect(f2.staticType.toString(), '<S₀>(S₀) → S');
+    _expectIdentifierType('f;', '<S₀>(S₀) → S');
   }
 
   void test_genericMethod_nestedFunctions() {
@@ -13892,10 +13767,8 @@
   return null;
 }
 ''');
-    SimpleIdentifier g = _findIdentifier('f');
-    expect(g.staticType.toString(), '<S>(S) → S');
-    SimpleIdentifier f = _findIdentifier('g');
-    expect(f.staticType.toString(), '<S>(S) → dynamic');
+    _expectIdentifierType('f', '<S>(S) → S');
+    _expectIdentifierType('g', '<S>(S) → dynamic');
   }
 
   void test_genericMethod_override() {
@@ -13907,13 +13780,11 @@
   /*=T*/ f/*<T>*/(/*=T*/ x) => null; // from D
 }
 ''');
+    _expectFunctionType('f/*<T>*/(/*=T*/ x) => null; // from D', '<T>(T) → T',
+        elementTypeParams: '[T]', typeFormals: '[T]');
     SimpleIdentifier f =
         _findIdentifier('f/*<T>*/(/*=T*/ x) => null; // from D');
     MethodElementImpl e = f.staticElement;
-    expect(e.typeParameters.toString(), '[T]');
-    expect(e.type.typeFormals.toString(), '[T]');
-    expect(e.type.toString(), '<T>(T) → T');
-
     FunctionType ft = e.type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), '(String) → String');
   }
@@ -14015,9 +13886,7 @@
   }
   return null;
 }''');
-    SimpleIdentifier y = _findIdentifier('y = ');
-    expect(y.staticType.toString(), 'List<C>');
-    expect(y.propagatedType, isNull);
+    _expectIdentifierType('y = ', 'List<C>', isNull);
   }
 
   void test_genericMethod_tearoff() {
@@ -14042,18 +13911,13 @@
   var paramTearOff = pf;
 }
 ''');
-    expect(
-        _findIdentifier('methodTearOff').staticType.toString(), "<T>(int) → T");
-    expect(
-        _findIdentifier('staticTearOff').staticType.toString(), "<T>(T) → T");
-    expect(_findIdentifier('staticFieldTearOff').staticType.toString(),
-        "<T>(T) → T");
-    expect(
-        _findIdentifier('topFunTearOff').staticType.toString(), "<T>(T) → T");
-    expect(
-        _findIdentifier('topFieldTearOff').staticType.toString(), "<T>(T) → T");
-    expect(_findIdentifier('localTearOff').staticType.toString(), "<T>(T) → T");
-    expect(_findIdentifier('paramTearOff').staticType.toString(), "<T>(T) → T");
+    _expectIdentifierType('methodTearOff', "<T>(int) → T");
+    _expectIdentifierType('staticTearOff', "<T>(T) → T");
+    _expectIdentifierType('staticFieldTearOff', "<T>(T) → T");
+    _expectIdentifierType('topFunTearOff', "<T>(T) → T");
+    _expectIdentifierType('topFieldTearOff', "<T>(T) → T");
+    _expectIdentifierType('localTearOff', "<T>(T) → T");
+    _expectIdentifierType('paramTearOff', "<T>(T) → T");
   }
 
   void test_genericMethod_then() {
@@ -14066,13 +13930,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-
-    expect(declaration.initializer.staticType.toString(), "Future<String>");
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'Future<String>', isNull);
   }
 
   void test_genericMethod_then_prefixed() {
@@ -14085,13 +13943,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-
-    expect(declaration.initializer.staticType.toString(), "Future<String>");
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'Future<String>', isNull);
   }
 
   void test_genericMethod_then_propagatedType() {
@@ -14105,9 +13957,7 @@
 ''';
     // This should produce no hints or warnings.
     _resolveTestUnit(code);
-    VariableDeclaration foo = _findIdentifier('foo').parent;
-    expect(foo.initializer.staticType.toString(), "Future<String>");
-    expect(foo.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'Future<String>', isNull);
   }
 
   void test_setterWithDynamicTypeIsError() {
@@ -14190,12 +14040,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'int');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'int', isNull);
   }
 
   void test_ternaryOperator_null_right() {
@@ -14205,12 +14050,7 @@
 }
 ''';
     _resolveTestUnit(code);
-
-    SimpleIdentifier identifier = _findIdentifier('foo');
-    VariableDeclaration declaration =
-        identifier.getAncestor((node) => node is VariableDeclaration);
-    expect(declaration.initializer.staticType.name, 'int');
-    expect(declaration.initializer.propagatedType, isNull);
+    _expectInitializerType('foo', 'int', isNull);
   }
 }
 
@@ -17120,6 +16960,81 @@
   Source testSource;
   CompilationUnit testUnit;
 
+  /**
+   * Looks up the identifier with [name] and validates that its type type
+   * stringifies to [type] and that its generics match the given stringified
+   * output.
+   */
+  _expectFunctionType(String name, String type,
+      {String elementTypeParams: '[]',
+      String typeParams: '[]',
+      String typeArgs: '[]',
+      String typeFormals: '[]'}) {
+    SimpleIdentifier identifier = _findIdentifier(name);
+    // Element is either ExecutableElement or ParameterElement.
+    var element = identifier.staticElement;
+    FunctionTypeImpl functionType = identifier.staticType;
+    expect(functionType.toString(), type);
+    expect(element.typeParameters.toString(), elementTypeParams);
+    expect(functionType.typeParameters.toString(), typeParams);
+    expect(functionType.typeArguments.toString(), typeArgs);
+    expect(functionType.typeFormals.toString(), typeFormals);
+  }
+
+  /**
+   * Looks up the identifier with [name] and validates its static [type].
+   *
+   * If [type] is a string, validates that the identifier's static type
+   * stringifies to that text. Otherwise, [type] is used directly a [Matcher]
+   * to match the type.
+   *
+   * If [propagatedType] is given, also validate's the identifier's propagated
+   * type.
+   */
+  void _expectIdentifierType(String name, type, [propagatedType]) {
+    SimpleIdentifier identifier = _findIdentifier(name);
+    _expectType(identifier.staticType, type);
+    if (propagatedType != null) {
+      _expectType(identifier.propagatedType, propagatedType);
+    }
+  }
+
+  /**
+   * Looks up the initializer for the declaration containing [identifier] and
+   * validates its static [type].
+   *
+   * If [type] is a string, validates that the identifier's static type
+   * stringifies to that text. Otherwise, [type] is used directly a [Matcher]
+   * to match the type.
+   *
+   * If [propagatedType] is given, also validate's the identifier's propagated
+   * type.
+   */
+  void _expectInitializerType(String name, type, [propagatedType]) {
+    SimpleIdentifier identifier = _findIdentifier(name);
+    VariableDeclaration declaration =
+        identifier.getAncestor((node) => node is VariableDeclaration);
+    Expression initializer = declaration.initializer;
+    _expectType(initializer.staticType, type);
+    if (propagatedType != null) {
+      _expectType(initializer.propagatedType, propagatedType);
+    }
+  }
+
+  /**
+   * Validates that [type] matches [expected].
+   *
+   * If [expected] is a string, validates that the type stringifies to that
+   * text. Otherwise, [expected] is used directly a [Matcher] to match the type.
+   */
+  _expectType(DartType type, expected) {
+    if (expected is String) {
+      expect(type.toString(), expected);
+    } else {
+      expect(type, expected);
+    }
+  }
+
   SimpleIdentifier _findIdentifier(String search) {
     SimpleIdentifier identifier = EngineTestCase.findNode(
         testUnit, testCode, search, (node) => node is SimpleIdentifier);
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 5f5d0ef..137deb5 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -703,6 +703,16 @@
     verify([source]);
   }
 
+  void test_nonBoolCondition_for() {
+    Source source = addSource(r'''
+f() {
+  for (;3;) {}
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+    verify([source]);
+  }
+
   void test_nonBoolCondition_if() {
     Source source = addSource(r'''
 f() {
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index f9bca44..20d1a82 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -467,6 +467,27 @@
         [intType]);
   }
 
+  void test_returnTypeFromContext() {
+    // <T>() -> T
+    var t = TypeBuilder.variable('T');
+    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    expect(_inferCall(f, [], stringType), [stringType]);
+  }
+
+  void test_returnTypeWithBoundFromContext() {
+    // <T extends num>() -> T
+    var t = TypeBuilder.variable('T', bound: numType);
+    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    expect(_inferCall(f, [], doubleType), [doubleType]);
+  }
+
+  void test_returnTypeWithBoundFromInvalidContext() {
+    // <T extends num>() -> T
+    var t = TypeBuilder.variable('T', bound: numType);
+    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    expect(_inferCall(f, [], stringType), [numType]);
+  }
+
   void test_unifyParametersToFunctionParam() {
     // <T>(f(T t), g(T t)) -> T
     var t = TypeBuilder.variable('T');
@@ -498,9 +519,10 @@
     expect(_inferCall(f, []), [numType]);
   }
 
-  List<DartType> _inferCall(FunctionTypeImpl ft, List<DartType> arguments) {
-    FunctionType inferred = typeSystem.inferCallFromArguments(
-        typeProvider, ft, ft.parameters.map((p) => p.type).toList(), arguments);
+  List<DartType> _inferCall(FunctionTypeImpl ft, List<DartType> arguments,
+      [DartType returnType]) {
+    FunctionType inferred = typeSystem.inferGenericFunctionCall(typeProvider,
+        ft, ft.parameters.map((p) => p.type).toList(), arguments, returnType);
     return inferred.typeArguments;
   }
 }
@@ -1314,7 +1336,7 @@
     if (returns == null) {
       returns = voidType;
     }
-    
+
     return ElementFactory
         .functionElement8(required, returns, optional: optional, named: named)
         .type;
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index f2a2a9e..f6f898a 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -1194,6 +1194,10 @@
   static void _assertEqualTokens(AstNode cloneNode, AstNode originalNode) {
     Token clone = cloneNode.beginToken;
     Token original = originalNode.beginToken;
+    if (original is! CommentToken) {
+      _assertHasPrevious(original);
+      _assertHasPrevious(clone);
+    }
     Token stopOriginalToken = originalNode.endToken.next;
     Token skipCloneComment = null;
     Token skipOriginalComment = null;
@@ -1231,6 +1235,26 @@
       }
     }
   }
+
+  /**
+   * Assert that the [token] has `previous` set, and if it `EOF`, then it
+   * points itself.
+   */
+  static void _assertHasPrevious(Token token) {
+    expect(token, isNotNull);
+    if (token.type == TokenType.EOF) {
+      return;
+    }
+    while (token != null) {
+      Token previous = token.previous;
+      expect(previous, isNotNull);
+      if (token.type == TokenType.EOF) {
+        expect(previous, same(token));
+        break;
+      }
+      token = previous;
+    }
+  }
 }
 
 @reflectiveTest
@@ -3727,10 +3751,14 @@
   void test_variableDeclarationList() {
     VariableDeclarationList node = AstFactory.variableDeclarationList(
         null, AstFactory.typeName4("T"), [AstFactory.variableDeclaration("a")]);
+    node.documentationComment =
+        Comment.createEndOfLineComment(EMPTY_TOKEN_LIST);
+    node.metadata.add(AstFactory.annotation(AstFactory.identifier3("a")));
     _assertReplace(
         node, new Getter_NodeReplacerTest_test_variableDeclarationList());
     _assertReplace(
         node, new ListGetter_NodeReplacerTest_test_variableDeclarationList(0));
+    _testAnnotatedNode(node);
   }
 
   void test_variableDeclarationStatement() {
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 9bf1b79..7d85c4f 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -13,6 +13,55 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 
+const _MockSdkLibrary _LIB_ASYNC = const _MockSdkLibrary(
+    'dart:async',
+    '/lib/async/async.dart',
+    '''
+library dart.async;
+
+import 'dart:math';
+
+part 'stream.dart';
+
+class Future<T> {
+  factory Future(computation()) => null;
+  factory Future.delayed(Duration duration, [T computation()]) => null;
+  factory Future.value([T value]) => null;
+
+  static Future<List/*<T>*/> wait/*<T>*/(
+      Iterable<Future/*<T>*/> futures) => null;
+  Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
+}
+''',
+    const <String, String>{
+      '/lib/async/stream.dart': r'''
+part of dart.async;
+class Stream<T> {}
+abstract class StreamTransformer<S, T> {}
+'''
+    });
+
+const _MockSdkLibrary _LIB_COLLECTION = const _MockSdkLibrary(
+    'dart:collection',
+    '/lib/collection/collection.dart',
+    '''
+library dart.collection;
+
+abstract class HashMap<K, V> implements Map<K, V> {}
+''');
+
+const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary(
+    'dart:convert',
+    '/lib/convert/convert.dart',
+    '''
+library dart.convert;
+
+import 'dart:async';
+
+abstract class Converter<S, T> implements StreamTransformer {}
+class JsonDecoder extends Converter<String, Object> {}
+''');
+
 const _MockSdkLibrary _LIB_CORE = const _MockSdkLibrary(
     'dart:core',
     '/lib/core/core.dart',
@@ -36,7 +85,8 @@
   int compareTo(T other);
 }
 
-abstract class String implements Comparable<String> {
+abstract class Pattern {}
+abstract class String implements Comparable<String>, Pattern {
   external factory String.fromCharCodes(Iterable<int> charCodes,
                                         [int start = 0, int end]);
   String operator +(String other) => null;
@@ -47,6 +97,9 @@
   String toUpperCase();
   List<int> get codeUnits;
 }
+abstract class RegExp implements Pattern {
+  external factory RegExp(String source);
+}
 
 class bool extends Object {}
 abstract class num implements Comparable<num> {
@@ -104,6 +157,8 @@
 
 abstract class Map<K, V> extends Object {
   Iterable<K> get keys;
+  V operator [](K key);
+  void operator []=(K key, V value);
 }
 
 external bool identical(Object a, Object b);
@@ -116,55 +171,6 @@
 const Object override = const _Override();
 ''');
 
-const _MockSdkLibrary _LIB_ASYNC = const _MockSdkLibrary(
-    'dart:async',
-    '/lib/async/async.dart',
-    '''
-library dart.async;
-
-import 'dart:math';
-
-part 'stream.dart';
-
-class Future<T> {
-  factory Future(computation()) => null;
-  factory Future.delayed(Duration duration, [T computation()]) => null;
-  factory Future.value([T value]) => null;
-
-  static Future<List/*<T>*/> wait/*<T>*/(
-      Iterable<Future/*<T>*/> futures) => null;
-  Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
-}
-''',
-    const <String, String>{
-      '/lib/async/stream.dart': r'''
-part of dart.async;
-class Stream<T> {}
-abstract class StreamTransformer<S, T> {}
-'''
-    });
-
-const _MockSdkLibrary _LIB_COLLECTION = const _MockSdkLibrary(
-    'dart:collection',
-    '/lib/collection/collection.dart',
-    '''
-library dart.collection;
-
-abstract class HashMap<K, V> implements Map<K, V> {}
-''');
-
-const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary(
-    'dart:convert',
-    '/lib/convert/convert.dart',
-    '''
-library dart.convert;
-
-import 'dart:async';
-
-abstract class Converter<S, T> implements StreamTransformer {}
-class JsonDecoder extends Converter<String, Object> {}
-''');
-
 const _MockSdkLibrary _LIB_FOREIGN_HELPER = const _MockSdkLibrary(
     'dart:_foreign_helper',
     '/lib/_foreign_helper/_foreign_helper.dart',
@@ -176,6 +182,14 @@
 {}
 ''');
 
+const _MockSdkLibrary _LIB_HTML = const _MockSdkLibrary(
+    'dart:html',
+    '/lib/html/dartium/html_dartium.dart',
+    '''
+library dart.html;
+class HtmlElement {}
+''');
+
 const _MockSdkLibrary _LIB_MATH = const _MockSdkLibrary(
     'dart:math',
     '/lib/math/math.dart',
@@ -199,14 +213,6 @@
 }
 ''');
 
-const _MockSdkLibrary _LIB_HTML = const _MockSdkLibrary(
-    'dart:html',
-    '/lib/html/dartium/html_dartium.dart',
-    '''
-library dart.html;
-class HtmlElement {}
-''');
-
 const List<SdkLibrary> _LIBRARIES = const [
   _LIB_CORE,
   _LIB_ASYNC,
@@ -218,16 +224,37 @@
 ];
 
 class MockSdk implements DartSdk {
+  static const Map<String, String> FULL_URI_MAP = const {
+    "dart:core": "/lib/core/core.dart",
+    "dart:html": "/lib/html/dartium/html_dartium.dart",
+    "dart:async": "/lib/async/async.dart",
+    "dart:async/stream.dart": "/lib/async/stream.dart",
+    "dart:collection": "/lib/collection/collection.dart",
+    "dart:convert": "/lib/convert/convert.dart",
+    "dart:_foreign_helper": "/lib/_foreign_helper/_foreign_helper.dart",
+    "dart:math": "/lib/math/math.dart"
+  };
+
+  static const Map<String, String> NO_ASYNC_URI_MAP = const {
+    "dart:core": "/lib/core/core.dart",
+  };
+
   final resource.MemoryResourceProvider provider =
       new resource.MemoryResourceProvider();
 
+  final Map<String, String> uriMap;
+
   /**
    * The [AnalysisContextImpl] which is used for all of the sources.
    */
   AnalysisContextImpl _analysisContext;
 
+  @override
+  final List<SdkLibrary> sdkLibraries;
+
   MockSdk({bool dartAsync: true})
-      : sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE] {
+      : sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
+        uriMap = dartAsync ? FULL_URI_MAP : NO_ASYNC_URI_MAP {
     for (_MockSdkLibrary library in sdkLibraries) {
       provider.newFile(library.path, library.content);
       library.parts.forEach((String path, String content) {
@@ -247,9 +274,6 @@
   }
 
   @override
-  final List<SdkLibrary> sdkLibraries;
-
-  @override
   String get sdkVersion => throw new UnimplementedError();
 
   @override
@@ -299,18 +323,7 @@
 
   @override
   Source mapDartUri(String dartUri) {
-    const Map<String, String> uriToPath = const {
-      "dart:core": "/lib/core/core.dart",
-      "dart:html": "/lib/html/dartium/html_dartium.dart",
-      "dart:async": "/lib/async/async.dart",
-      "dart:async/stream.dart": "/lib/async/stream.dart",
-      "dart:collection": "/lib/collection/collection.dart",
-      "dart:convert": "/lib/convert/convert.dart",
-      "dart:_foreign_helper": "/lib/_foreign_helper/_foreign_helper.dart",
-      "dart:math": "/lib/math/math.dart"
-    };
-
-    String path = uriToPath[dartUri];
+    String path = uriMap[dartUri];
     if (path != null) {
       resource.File file = provider.getResource(path);
       Uri uri = new Uri(scheme: 'dart', path: dartUri.substring(5));
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index 3f6d653..8b1e4dd 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -13,11 +13,13 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/constant.dart' show DartObject;
 import 'package:analyzer/src/generated/element_handle.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart'
     show Namespace, TypeProvider;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
@@ -51,6 +53,17 @@
     otherLibrarySources.add(addNamedSource(filePath, contents));
   }
 
+  /**
+   * Verify that the given prefix is safe to elide from a resynthesized AST.
+   */
+  void checkElidablePrefix(SimpleIdentifier prefix) {
+    if (prefix.staticElement is! PrefixElement &&
+        prefix.staticElement is! ClassElement) {
+      fail('Prefix of type ${prefix.staticElement.runtimeType}'
+          ' should not have been elided');
+    }
+  }
+
   void checkLibrary(String text,
       {bool allowErrors: false, bool dumpSummaries: false}) {
     Source source = addSource(text);
@@ -135,10 +148,6 @@
     if (original is! LocalElement && resynthesized is! LocalElement) {
       return;
     }
-    // TODO(scheglov) add support for parameters
-    if (original is ParameterElement && resynthesized is ParameterElement) {
-      return;
-    }
     if (original is LocalElement && resynthesized is LocalElement) {
       expect(resynthesized.visibleRange, original.visibleRange);
     } else {
@@ -351,9 +360,27 @@
         expect(r.name, o.name, reason: desc);
         compareElements(r.staticElement, o.staticElement, desc);
       } else if (o is PrefixedIdentifier && r is SimpleIdentifier) {
-        // We often don't resynthesize prefixed identifiers.
-        // We use simple identifiers with correct elements.
-        compareConstAsts(r, o.identifier, desc);
+        // We don't resynthesize prefixed identifiers when the prefix refers to
+        // a PrefixElement or a ClassElement.  We use simple identifiers with
+        // correct elements.
+        if (o.prefix.staticElement is PrefixElement ||
+            o.prefix.staticElement is ClassElement) {
+          compareConstAsts(r, o.identifier, desc);
+        } else {
+          fail('Prefix of type ${o.prefix.staticElement.runtimeType} should not'
+              ' have been elided');
+        }
+      } else if (o is PropertyAccess &&
+          o.target is PrefixedIdentifier &&
+          r is PrefixedIdentifier) {
+        // We don't resynthesize prefixed identifiers when the prefix refers to
+        // a PrefixElement or a ClassElement.  Which means that if the original
+        // expression was e.g. `prefix.topLevelVariableName.length`, it will get
+        // resynthesized as `topLevelVariableName.length`
+        PrefixedIdentifier oTarget = o.target;
+        checkElidablePrefix(oTarget.prefix);
+        compareConstAsts(
+            r, AstFactory.identifier(oTarget.identifier, o.propertyName), desc);
       } else if (o is PrefixedIdentifier && r is PrefixedIdentifier) {
         compareConstAsts(r.prefix, o.prefix, desc);
         compareConstAsts(r.identifier, o.identifier, desc);
@@ -362,9 +389,15 @@
         expect(r.propertyName.name, o.propertyName.name, reason: desc);
         compareElements(
             r.propertyName.staticElement, o.propertyName.staticElement, desc);
-      } else if (o is PropertyAccess && r is SimpleIdentifier) {
-        // We don't resynthesize property access.
-        // We use simple identifiers with correct elements.
+      } else if (o is PropertyAccess &&
+          o.target is PrefixedIdentifier &&
+          r is SimpleIdentifier) {
+        // We don't resynthesize property access when it takes the form
+        // `prefixName.className.staticMember`.  We just resynthesize a
+        // SimpleIdentifier correctly resolved to the static member.
+        PrefixedIdentifier oTarget = o.target;
+        checkElidablePrefix(oTarget.prefix);
+        checkElidablePrefix(oTarget.identifier);
         compareConstAsts(r, o.propertyName, desc);
       } else if (o is NullLiteral) {
         expect(r, new isInstanceOf<NullLiteral>(), reason: desc);
@@ -495,6 +528,60 @@
           original.redirectedConstructor, '$desc redirectedConstructor');
     }
     checkPossibleMember(resynthesized, original, desc);
+    expect(resynthesized.nameEnd, original.nameEnd, reason: desc);
+    expect(resynthesized.periodOffset, original.periodOffset, reason: desc);
+  }
+
+  void compareConstValues(
+      DartObject resynthesized, DartObject original, String desc) {
+    if (original == null) {
+      expect(resynthesized, isNull, reason: desc);
+    } else {
+      expect(resynthesized, isNotNull, reason: desc);
+      compareTypes(resynthesized.type, original.type, desc);
+      expect(resynthesized.hasKnownValue, original.hasKnownValue, reason: desc);
+      if (original.isNull) {
+        expect(resynthesized.isNull, isTrue, reason: desc);
+      } else if (original.toBoolValue() != null) {
+        expect(resynthesized.toBoolValue(), original.toBoolValue(),
+            reason: desc);
+      } else if (original.toIntValue() != null) {
+        expect(resynthesized.toIntValue(), original.toIntValue(), reason: desc);
+      } else if (original.toDoubleValue() != null) {
+        expect(resynthesized.toDoubleValue(), original.toDoubleValue(),
+            reason: desc);
+      } else if (original.toListValue() != null) {
+        List<DartObject> resynthesizedList = resynthesized.toListValue();
+        List<DartObject> originalList = original.toListValue();
+        expect(resynthesizedList, hasLength(originalList.length));
+        for (int i = 0; i < originalList.length; i++) {
+          compareConstValues(resynthesizedList[i], originalList[i], desc);
+        }
+      } else if (original.toMapValue() != null) {
+        Map<DartObject, DartObject> resynthesizedMap =
+            resynthesized.toMapValue();
+        Map<DartObject, DartObject> originalMap = original.toMapValue();
+        expect(resynthesizedMap, hasLength(originalMap.length));
+        List<DartObject> resynthesizedKeys = resynthesizedMap.keys.toList();
+        List<DartObject> originalKeys = originalMap.keys.toList();
+        for (int i = 0; i < originalKeys.length; i++) {
+          DartObject resynthesizedKey = resynthesizedKeys[i];
+          DartObject originalKey = originalKeys[i];
+          compareConstValues(resynthesizedKey, originalKey, desc);
+          DartObject resynthesizedValue = resynthesizedMap[resynthesizedKey];
+          DartObject originalValue = originalMap[originalKey];
+          compareConstValues(resynthesizedValue, originalValue, desc);
+        }
+      } else if (original.toStringValue() != null) {
+        expect(resynthesized.toStringValue(), original.toStringValue(),
+            reason: desc);
+      } else if (original.toSymbolValue() != null) {
+        expect(resynthesized.toSymbolValue(), original.toSymbolValue(),
+            reason: desc);
+      } else if (original.toTypeValue() != null) {
+        fail('Not implemented');
+      }
+    }
   }
 
   void compareElementAnnotations(ElementAnnotationImpl resynthesized,
@@ -534,12 +621,19 @@
     compareMetadata(resynthesized.metadata, original.metadata, desc);
     // Modifiers are a pain to test via handles.  So just test them via the
     // actual element.
-    for (Modifier modifier in Modifier.values) {
+    for (Modifier modifier in Modifier.persistedValues) {
       bool got = rImpl.hasModifier(modifier);
       bool want = oImpl.hasModifier(modifier);
       expect(got, want,
           reason: 'Mismatch in $desc.$modifier: got $got, want $want');
     }
+    for (Modifier modifier in Modifier.transientValues) {
+      bool got = rImpl.hasModifier(modifier);
+      bool want = false;
+      expect(got, false,
+          reason: 'Mismatch in $desc.$modifier: got $got, want $want');
+    }
+
     // Validate members.
     if (oImpl is Member) {
       expect(rImpl, new isInstanceOf<Member>(), reason: desc);
@@ -551,13 +645,8 @@
   void compareExecutableElements(ExecutableElement resynthesized,
       ExecutableElement original, String desc) {
     compareElements(resynthesized, original, desc);
-    expect(resynthesized.parameters.length, original.parameters.length);
-    for (int i = 0; i < resynthesized.parameters.length; i++) {
-      compareParameterElements(
-          resynthesized.parameters[i],
-          original.parameters[i],
-          '$desc parameter ${original.parameters[i].name}');
-    }
+    compareParameterElementLists(
+        resynthesized.parameters, original.parameters, desc);
     compareTypes(
         resynthesized.returnType, original.returnType, '$desc return type');
     compareTypes(resynthesized.type, original.type, desc);
@@ -578,6 +667,15 @@
       }
     }
     if (original is! Member) {
+      List<LabelElement> rLabels = resynthesized.labels;
+      List<LabelElement> oLabels = original.labels;
+      expect(rLabels, hasLength(oLabels.length));
+      for (int i = 0; i < oLabels.length; i++) {
+        compareLabelElements(
+            rLabels[i], oLabels[i], '$desc label ${oLabels[i].name}');
+      }
+    }
+    if (original is! Member) {
       List<LocalVariableElement> rVariables = resynthesized.localVariables;
       List<LocalVariableElement> oVariables = original.localVariables;
       expect(rVariables, hasLength(oVariables.length));
@@ -607,6 +705,10 @@
 
   void compareFunctionElements(
       FunctionElement resynthesized, FunctionElement original, String desc) {
+    if (original == null && resynthesized == null) {
+      return;
+    }
+    expect(resynthesized, isNotNull, reason: desc);
     compareExecutableElements(resynthesized, original, desc);
     checkPossibleLocalElements(resynthesized, original);
   }
@@ -616,13 +718,8 @@
       FunctionTypeAliasElementImpl original,
       String desc) {
     compareElements(resynthesized, original, desc);
-    expect(resynthesized.parameters.length, original.parameters.length);
-    for (int i = 0; i < resynthesized.parameters.length; i++) {
-      compareParameterElements(
-          resynthesized.parameters[i],
-          original.parameters[i],
-          '$desc parameter ${original.parameters[i].name}');
-    }
+    compareParameterElementLists(
+        resynthesized.parameters, original.parameters, desc);
     compareTypes(
         resynthesized.returnType, original.returnType, '$desc return type');
     compareTypes(resynthesized.type, original.type, desc);
@@ -654,6 +751,15 @@
     }
   }
 
+  void compareLabelElements(
+      LabelElementImpl resynthesized, LabelElementImpl original, String desc) {
+    expect(resynthesized.isOnSwitchMember, original.isOnSwitchMember,
+        reason: desc);
+    expect(resynthesized.isOnSwitchStatement, original.isOnSwitchStatement,
+        reason: desc);
+    compareElements(resynthesized, original, desc);
+  }
+
   void compareMetadata(List<ElementAnnotation> resynthesized,
       List<ElementAnnotation> original, String desc) {
     expect(resynthesized, hasLength(original.length), reason: desc);
@@ -675,6 +781,8 @@
     if (original is ShowElementCombinatorImpl &&
         resynthesized is ShowElementCombinatorImpl) {
       expect(resynthesized.shownNames, original.shownNames);
+      expect(resynthesized.offset, original.offset);
+      expect(resynthesized.end, original.end);
     } else if (original is HideElementCombinatorImpl &&
         resynthesized is HideElementCombinatorImpl) {
       expect(resynthesized.hiddenNames, original.hiddenNames);
@@ -699,16 +807,24 @@
     }
   }
 
+  void compareParameterElementLists(
+      List<ParameterElement> resynthesizedParameters,
+      List<ParameterElement> originalParameters,
+      String desc) {
+    expect(resynthesizedParameters.length, originalParameters.length);
+    for (int i = 0; i < resynthesizedParameters.length; i++) {
+      compareParameterElements(
+          resynthesizedParameters[i],
+          originalParameters[i],
+          '$desc parameter ${originalParameters[i].name}');
+    }
+  }
+
   void compareParameterElements(
       ParameterElement resynthesized, ParameterElement original, String desc) {
     compareVariableElements(resynthesized, original, desc);
-    expect(resynthesized.parameters.length, original.parameters.length);
-    for (int i = 0; i < resynthesized.parameters.length; i++) {
-      compareParameterElements(
-          resynthesized.parameters[i],
-          original.parameters[i],
-          '$desc parameter ${original.parameters[i].name}');
-    }
+    compareParameterElementLists(
+        resynthesized.parameters, original.parameters, desc);
     expect(resynthesized.parameterKind, original.parameterKind);
     expect(resynthesized.isInitializingFormal, original.isInitializingFormal,
         reason: desc);
@@ -724,6 +840,13 @@
             resynthesized.field, original.field, '$desc field');
       }
     }
+    expect(resynthesized.defaultValueCode, original.defaultValueCode,
+        reason: desc);
+    ParameterElementImpl resynthesizedActual =
+        getActualElement(resynthesized, desc);
+    ParameterElementImpl originalActual = getActualElement(original, desc);
+    compareFunctionElements(
+        resynthesizedActual.initializer, originalActual.initializer, desc);
   }
 
   void comparePrefixElements(PrefixElementImpl resynthesized,
@@ -845,6 +968,8 @@
       // TODO(scheglov) In the strong mode constant variable like
       //  `var V = new Unresolved()` gets `UndefinedTypeImpl`, and it gets
       // `DynamicTypeImpl` in the spec mode.
+    } else if (resynthesized is BottomTypeImpl && original is BottomTypeImpl) {
+      expect(resynthesized, same(original));
     } else if (resynthesized.runtimeType != original.runtimeType) {
       fail('Type mismatch: expected ${original.runtimeType},'
           ' got ${resynthesized.runtimeType} ($desc)');
@@ -865,16 +990,24 @@
       VariableElement resynthesized, VariableElement original, String desc) {
     compareElements(resynthesized, original, desc);
     compareTypes(resynthesized.type, original.type, desc);
+    VariableElementImpl resynthesizedActual =
+        getActualElement(resynthesized, desc);
     VariableElementImpl originalActual = getActualElement(original, desc);
+    compareFunctionElements(
+        resynthesizedActual.initializer, originalActual.initializer, desc);
     if (originalActual is ConstVariableElement) {
-      VariableElementImpl resynthesizedActual =
-          getActualElement(resynthesized, desc);
-      Expression initializer = resynthesizedActual.constantInitializer;
-      if (constantInitializersAreInvalid) {
-        _assertUnresolvedIdentifier(initializer, desc);
+      Element oEnclosing = original.enclosingElement;
+      if (oEnclosing is ClassElement && oEnclosing.isEnum) {
+        compareConstValues(
+            resynthesized.constantValue, original.constantValue, desc);
       } else {
-        compareConstAsts(initializer, originalActual.constantInitializer,
-            '$desc initializer');
+        Expression initializer = resynthesizedActual.constantInitializer;
+        if (constantInitializersAreInvalid) {
+          _assertUnresolvedIdentifier(initializer, desc);
+        } else {
+          compareConstAsts(initializer, originalActual.constantInitializer,
+              '$desc initializer');
+        }
       }
     }
     checkPossibleMember(resynthesized, original, desc);
@@ -1315,6 +1448,15 @@
     checkLibrary('class C {} class D {}');
   }
 
+  test_closure_executable_with_return_type_from_closure() {
+    checkLibrary('''
+f() {
+  print(() {});
+  print(() => () => 0);
+}
+''');
+  }
+
   test_const_invalid_field_const() {
     constantInitializersAreInvalid = true;
     checkLibrary(
@@ -2391,6 +2533,13 @@
     checkLibrary('enum E1 { v1 } enum E2 { v2 }');
   }
 
+  test_executable_parameter_type_typedef() {
+    checkLibrary(r'''
+typedef F(int p);
+main(F f) {}
+''');
+  }
+
   test_export_class() {
     addLibrarySource('/a.dart', 'class C {}');
     checkLibrary('export "a.dart";');
@@ -2764,6 +2913,100 @@
     checkLibrary('import "a.dart"; import "b.dart"; C c; D d;');
   }
 
+  test_inferred_function_type_for_variable_in_generic_function() {
+    // In the code below, `x` has an inferred type of `() => int`, with 2
+    // (unused) type parameters from the enclosing top level function.
+    checkLibrary('''
+f<U, V>() {
+  var x = () => 0;
+}
+''');
+  }
+
+  test_inferred_function_type_in_generic_class_constructor() {
+    // In the code below, `() => () => 0` has an inferred return type of
+    // `() => int`, with 2 (unused) type parameters from the enclosing class.
+    checkLibrary('''
+class C<U, V> {
+  final x;
+  C() : x = (() => () => 0);
+}
+''');
+  }
+
+  test_inferred_function_type_in_generic_class_getter() {
+    // In the code below, `() => () => 0` has an inferred return type of
+    // `() => int`, with 2 (unused) type parameters from the enclosing class.
+    checkLibrary('''
+class C<U, V> {
+  get x => () => () => 0;
+}
+''');
+  }
+
+  test_inferred_function_type_in_generic_class_in_generic_method() {
+    // In the code below, `() => () => 0` has an inferred return type of
+    // `() => int`, with 3 (unused) type parameters from the enclosing class
+    // and method.
+    checkLibrary('''
+class C<T> {
+  f<U, V>() {
+    print(() => () => 0);
+  }
+}
+''');
+  }
+
+  test_inferred_function_type_in_generic_class_setter() {
+    // In the code below, `() => () => 0` has an inferred return type of
+    // `() => int`, with 2 (unused) type parameters from the enclosing class.
+    checkLibrary('''
+class C<U, V> {
+  void set x(value) {
+    print(() => () => 0);
+  }
+}
+''');
+  }
+
+  test_inferred_function_type_in_generic_closure() {
+    if (!options.strongMode) {
+      // The test below uses generic comment syntax because proper generic
+      // method syntax doesn't support generic closures.  So it can only run in
+      // strong mode.
+      // TODO(paulberry): once proper generic method syntax supports generic
+      // closures, rewrite the test below without using generic comment syntax,
+      // and remove this hack.  See dartbug.com/25819
+      return;
+    }
+    // In the code below, `<U, V>() => () => 0` has an inferred return type of
+    // `() => int`, with 3 (unused) type parameters.
+    checkLibrary('''
+f<T>() {
+  print(/*<U, V>*/() => () => 0);
+}
+''');
+  }
+
+  test_inferred_generic_function_type_in_generic_closure() {
+    if (!options.strongMode) {
+      // The test below uses generic comment syntax because proper generic
+      // method syntax doesn't support generic closures.  So it can only run in
+      // strong mode.
+      // TODO(paulberry): once proper generic method syntax supports generic
+      // closures, rewrite the test below without using generic comment syntax,
+      // and remove this hack.  See dartbug.com/25819
+      return;
+    }
+    // In the code below, `<U, V>() => <W, X, Y, Z>() => 0` has an inferred
+    // return type of `() => int`, with 7 (unused) type parameters.
+    checkLibrary('''
+f<T>() {
+  print(/*<U, V>*/() => /*<W, X, Y, Z>*/() => 0);
+}
+''');
+  }
+
   test_inferred_type_is_typedef() {
     checkLibrary('typedef int F(String s);'
         ' class C extends D { var v; }'
@@ -2798,6 +3041,27 @@
         ' abstract class D { void set f(int g(String s)); }');
   }
 
+  test_initializer_executable_with_return_type_from_closure() {
+    checkLibrary('var v = () => 0;');
+  }
+
+  test_initializer_executable_with_return_type_from_closure_field() {
+    checkLibrary('''
+class C {
+  var v = () => 0;
+}
+''');
+  }
+
+  test_initializer_executable_with_return_type_from_closure_local() {
+    checkLibrary('''
+void f() {
+  int u = 0;
+  var v = () => 0;
+}
+''');
+  }
+
   test_library() {
     checkLibrary('');
   }
@@ -2858,6 +3122,46 @@
 ''');
   }
 
+  test_localLabels_inConstructor() {
+    checkLibrary(r'''
+class C {
+  C() {
+    aaa: while (true) {}
+    bbb: switch (42) {
+      ccc: case 0:
+        break;
+    }
+  }
+}
+''');
+  }
+
+  test_localLabels_inMethod() {
+    checkLibrary(r'''
+class C {
+  m() {
+    aaa: while (true) {}
+    bbb: switch (42) {
+      ccc: case 0:
+        break;
+    }
+  }
+}
+''');
+  }
+
+  test_localLabels_inTopLevelFunction() {
+    checkLibrary(r'''
+main() {
+  aaa: while (true) {}
+  bbb: switch (42) {
+    ccc: case 0:
+      break;
+  }
+}
+''');
+  }
+
   test_localVariables_inConstructor() {
     checkLibrary(r'''
 class C {
@@ -3289,6 +3593,15 @@
     checkLibrary('library my.lib; part "a.dart"; part "b.dart";');
   }
 
+  test_propagated_type_refers_to_closure() {
+    checkLibrary('''
+void f() {
+  var x = () => 0;
+  var y = x;
+}
+''');
+  }
+
   test_setter_documented() {
     checkLibrary('''
 // Extra comment so doc comment offset != 0
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 5e2f084..6356d47 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -314,9 +314,9 @@
   }
 
   /**
-   * Test an inferred type.  If strong mode is disabled, verify that the given
-   * [slotId] exists and has no associated type.  Otherwise, behave as in
-   * [checkLinkedTypeSlot].
+   * Test an inferred type.  If [onlyInStrongMode] is `true` (the default) and
+   * strong mode is disabled, verify that the given [slotId] exists and has no
+   * associated type.  Otherwise, behave as in [checkLinkedTypeSlot].
    */
   void checkInferredTypeSlot(
       int slotId, String absoluteUri, String relativeUri, String expectedName,
@@ -325,8 +325,9 @@
       int expectedTargetUnit: 0,
       LinkedUnit linkedSourceUnit,
       UnlinkedUnit unlinkedSourceUnit,
-      int numTypeParameters: 0}) {
-    if (strongMode) {
+      int numTypeParameters: 0,
+      bool onlyInStrongMode: true}) {
+    if (strongMode || !onlyInStrongMode) {
       checkLinkedTypeSlot(slotId, absoluteUri, relativeUri, expectedName,
           allowTypeArguments: allowTypeParameters,
           expectedKind: expectedKind,
@@ -479,7 +480,8 @@
       LinkedUnit linkedSourceUnit,
       UnlinkedUnit unlinkedSourceUnit,
       int numTypeParameters: 0,
-      bool checkAstDerivedDataOverride: false}) {
+      bool checkAstDerivedDataOverride: false,
+      int localIndex: 0}) {
     linkedSourceUnit ??= definingUnit;
     unlinkedSourceUnit ??= unlinkedUnits[0];
     LinkedReference referenceResolution =
@@ -525,6 +527,7 @@
     expect(referenceResolution.kind, expectedKind);
     expect(referenceResolution.unit, expectedTargetUnit);
     expect(referenceResolution.numTypeParameters, numTypeParameters);
+    expect(referenceResolution.localIndex, localIndex);
     return reference;
   }
 
@@ -584,15 +587,8 @@
     } else if (prefixExpectations != null) {
       for (_PrefixExpectation expectation in prefixExpectations) {
         expect(reference.prefixReference, isNot(0));
-        reference = checkReferenceIndex(
-            reference.prefixReference,
-            expectation.inLibraryDefiningUnit
-                ? null
-                : expectation.absoluteUri ?? absoluteUri,
-            expectation.inLibraryDefiningUnit
-                ? null
-                : expectation.relativeUri ?? relativeUri,
-            expectation.name,
+        reference = checkReferenceIndex(reference.prefixReference,
+            expectation.absoluteUri, expectation.relativeUri, expectation.name,
             expectedKind: expectation.kind,
             checkAstDerivedDataOverride: checkAstDerivedDataOverride,
             expectedTargetUnit: expectedTargetUnit,
@@ -782,8 +778,8 @@
    * executable with the given [executableName].
    */
   UnlinkedExecutable serializeExecutableText(String text,
-      [String executableName = 'f']) {
-    serializeLibraryText(text);
+      {String executableName: 'f', bool allowErrors: false}) {
+    serializeLibraryText(text, allowErrors: allowErrors);
     return findExecutable(executableName, failIfAbsent: true);
   }
 
@@ -838,6 +834,20 @@
     return findVariable(variableName, failIfAbsent: true);
   }
 
+  test_bottom_reference_shared() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // The synthetic executables for both `x` and `y` have type `() => `Bottom`.
+    // Verify that they both use the same reference to `Bottom`.
+    serializeLibraryText('int x = null; int y = null;');
+    EntityRef xInitializerReturnType =
+        getTypeRefForSlot(findVariable('x').initializer.inferredReturnTypeSlot);
+    EntityRef yInitializerReturnType =
+        getTypeRefForSlot(findVariable('y').initializer.inferredReturnTypeSlot);
+    expect(xInitializerReturnType.reference, yInitializerReturnType.reference);
+  }
+
   test_cascaded_export_hide_hide() {
     addNamedSource('/lib1.dart', 'export "lib2.dart" hide C hide B, C;');
     addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
@@ -1317,6 +1327,86 @@
     expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
   }
 
+  test_closure_executable_with_bottom_return_type() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('f() { print((() => null)()); }');
+    expect(executable.localFunctions, hasLength(1));
+    expect(executable.localFunctions[0].returnType, isNull);
+    if (strongMode) {
+      // Strong mode infers a type for the closure of `() => dynamic`, so the
+      // inferred return type slot should be empty.
+      expect(
+          getTypeRefForSlot(
+              executable.localFunctions[0].inferredReturnTypeSlot),
+          isNull);
+    } else {
+      // Spec mode infers a type for the closure of `() => Bottom`.
+      checkInferredTypeSlot(executable.localFunctions[0].inferredReturnTypeSlot,
+          null, null, '*bottom*',
+          onlyInStrongMode: false);
+    }
+  }
+
+  test_closure_executable_with_imported_return_type() {
+    addNamedSource('/a.dart', 'class C { D d; } class D {}');
+    // The closure has type `() => D`; `D` is defined in a library that is
+    // imported.
+    UnlinkedExecutable executable = serializeExecutableText(
+        'import "a.dart"; f() { print((() => new C().d)()); }');
+    expect(executable.localFunctions, hasLength(1));
+    expect(executable.localFunctions[0].returnType, isNull);
+    checkInferredTypeSlot(executable.localFunctions[0].inferredReturnTypeSlot,
+        absUri('/a.dart'), 'a.dart', 'D',
+        onlyInStrongMode: false);
+    checkHasDependency(absUri('/a.dart'), 'a.dart', fullyLinked: false);
+  }
+
+  test_closure_executable_with_return_type_from_closure() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // The closure has type `() => () => int`, where the `() => int` part refers
+    // to the nested closure.
+    UnlinkedExecutable executable = serializeExecutableText('''
+f() {
+  print(() {}); // force the closure below to have index 1
+  print(() => () => 0);
+}
+''');
+    expect(executable.localFunctions, hasLength(2));
+    EntityRef closureType =
+        getTypeRefForSlot(executable.localFunctions[1].inferredReturnTypeSlot);
+    checkLinkedTypeRef(closureType, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int outerClosureIndex =
+        definingUnit.references[closureType.reference].containingReference;
+    checkReferenceIndex(outerClosureIndex, null, null, '',
+        expectedKind: ReferenceKind.function, localIndex: 1);
+    int topLevelFunctionIndex =
+        definingUnit.references[outerClosureIndex].containingReference;
+    checkReferenceIndex(topLevelFunctionIndex, null, null, 'f',
+        expectedKind: ReferenceKind.topLevelFunction);
+    expect(
+        definingUnit.references[topLevelFunctionIndex].containingReference, 0);
+  }
+
+  test_closure_executable_with_unimported_return_type() {
+    addNamedSource('/a.dart', 'import "b.dart"; class C { D d; }');
+    addNamedSource('/b.dart', 'class D {}');
+    // The closure has type `() => D`; `D` is defined in a library that is not
+    // imported.
+    UnlinkedExecutable executable = serializeExecutableText(
+        'import "a.dart"; f() { print((() => new C().d)()); }');
+    expect(executable.localFunctions, hasLength(1));
+    expect(executable.localFunctions[0].returnType, isNull);
+    checkInferredTypeSlot(executable.localFunctions[0].inferredReturnTypeSlot,
+        absUri('/b.dart'), 'b.dart', 'D',
+        onlyInStrongMode: false);
+    if (!skipFullyLinkedData) {
+      checkHasDependency(absUri('/b.dart'), 'b.dart', fullyLinked: true);
+    }
+  }
+
   test_constExpr_binary_add() {
     UnlinkedVariable variable = serializeVariableText('const v = 1 + 2;');
     _assertUnlinkedConst(variable.constExpr, operators: [
@@ -1706,8 +1796,7 @@
                   absoluteUri: absUri('/a.dart'),
                   relativeUri: 'a.dart',
                   numTypeParameters: 2),
-              new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                  inLibraryDefiningUnit: true)
+              new _PrefixExpectation(ReferenceKind.prefix, 'p')
             ],
             allowTypeParameters: true);
         checkTypeRef(r.typeArguments[0], 'dart:core', 'dart:core', 'int');
@@ -1793,8 +1882,7 @@
             numTypeParameters: 2,
             allowTypeParameters: true,
             prefixExpectations: [
-              new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                  inLibraryDefiningUnit: true)
+              new _PrefixExpectation(ReferenceKind.prefix, 'p')
             ]);
         checkTypeRef(r.typeArguments[0], 'dart:core', 'dart:core', 'int');
         checkTypeRef(r.typeArguments[1], 'dart:core', 'dart:core', 'String');
@@ -1873,8 +1961,7 @@
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -1964,8 +2051,7 @@
       (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'C',
               expectedKind: ReferenceKind.classOrEnum,
               prefixExpectations: [
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2038,8 +2124,7 @@
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2063,8 +2148,7 @@
               checkAstDerivedDataOverride: true,
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.unresolved, 'C'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2125,8 +2209,7 @@
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2209,8 +2292,7 @@
                 new _PrefixExpectation(
                     ReferenceKind.topLevelPropertyAccessor, 'a',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2579,8 +2661,7 @@
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p'),
               ])
     ]);
   }
@@ -2665,8 +2746,7 @@
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2736,8 +2816,7 @@
       (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'f',
               expectedKind: ReferenceKind.topLevelFunction,
               prefixExpectations: [
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true)
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
               ])
     ]);
   }
@@ -2852,8 +2931,7 @@
               prefixExpectations: [
                 new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
                     absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
-                new _PrefixExpectation(ReferenceKind.prefix, 'p',
-                    inLibraryDefiningUnit: true),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p'),
               ])
     ]);
   }
@@ -2925,6 +3003,8 @@
     expect(executable.returnType, isNull);
     expect(executable.isExternal, isFalse);
     expect(executable.nameOffset, text.indexOf('C();'));
+    expect(executable.periodOffset, 0);
+    expect(executable.nameEnd, 0);
     expect(executable.isRedirectedConstructor, isFalse);
     expect(executable.redirectedConstructor, isNull);
     expect(executable.redirectedConstructorName, isEmpty);
@@ -3208,6 +3288,7 @@
     UnlinkedParam param = executable.parameters[0];
     expect(param.isFunctionTyped, isTrue);
     expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.defaultValueCode, 'foo');
     _assertUnlinkedConst(param.defaultValue, operators: [
       UnlinkedConstOperation.pushReference
     ], referenceValidators: [
@@ -3241,6 +3322,7 @@
     UnlinkedParam parameter = executable.parameters[0];
     expect(parameter.kind, UnlinkedParamKind.named);
     expect(parameter.defaultValue, isNull);
+    expect(parameter.defaultValueCode, isEmpty);
   }
 
   test_constructor_initializing_formal_named_withDefault() {
@@ -3249,6 +3331,8 @@
             .executables);
     UnlinkedParam parameter = executable.parameters[0];
     expect(parameter.kind, UnlinkedParamKind.named);
+    expect(parameter.initializer, isNotNull);
+    expect(parameter.defaultValueCode, '42');
     _assertUnlinkedConst(parameter.defaultValue,
         operators: [UnlinkedConstOperation.pushInt], ints: [42]);
   }
@@ -3268,6 +3352,7 @@
     UnlinkedParam parameter = executable.parameters[0];
     expect(parameter.kind, UnlinkedParamKind.positional);
     expect(parameter.defaultValue, isNull);
+    expect(parameter.defaultValueCode, isEmpty);
   }
 
   test_constructor_initializing_formal_positional_withDefault() {
@@ -3277,6 +3362,8 @@
                 .executables);
     UnlinkedParam parameter = executable.parameters[0];
     expect(parameter.kind, UnlinkedParamKind.positional);
+    expect(parameter.initializer, isNotNull);
+    expect(parameter.defaultValueCode, '42');
     _assertUnlinkedConst(parameter.defaultValue,
         operators: [UnlinkedConstOperation.pushInt], ints: [42]);
   }
@@ -3308,6 +3395,7 @@
 }''').executables);
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.defaultValueCode, '42');
     _assertUnlinkedConst(param.defaultValue,
         operators: [UnlinkedConstOperation.pushInt], ints: [42]);
   }
@@ -3318,6 +3406,8 @@
         executables: serializeClassText(text).executables);
     expect(executable.name, 'foo');
     expect(executable.nameOffset, text.indexOf('foo'));
+    expect(executable.periodOffset, text.indexOf('.foo'));
+    expect(executable.nameEnd, text.indexOf('()'));
   }
 
   test_constructor_non_const() {
@@ -3961,7 +4051,7 @@
   }
 
   test_executable_function_private() {
-    serializeExecutableText('_f() {}', '_f');
+    serializeExecutableText('_f() {}', executableName: '_f');
     expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
   }
 
@@ -3987,7 +4077,7 @@
   }
 
   test_executable_getter_private() {
-    serializeExecutableText('int get _f => 1;', '_f');
+    serializeExecutableText('int get _f => 1;', executableName: '_f');
     expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
   }
 
@@ -4025,6 +4115,91 @@
     }
   }
 
+  test_executable_localLabels_inMethod() {
+    String code = r'''
+class C {
+  m() {
+    aaa: while (true) {}
+    bbb: while (true) {}
+  }
+}
+''';
+    UnlinkedExecutable executable =
+        findExecutable('m', executables: serializeClassText(code).executables);
+    List<UnlinkedLabel> labels = executable.localLabels;
+    expect(labels, hasLength(2));
+    {
+      UnlinkedLabel aaa = labels.singleWhere((l) => l.name == 'aaa');
+      expect(aaa, isNotNull);
+      expect(aaa.isOnSwitchMember, isFalse);
+      expect(aaa.isOnSwitchStatement, isFalse);
+    }
+    {
+      UnlinkedLabel bbb = labels.singleWhere((l) => l.name == 'bbb');
+      expect(bbb, isNotNull);
+      expect(bbb.isOnSwitchMember, isFalse);
+      expect(bbb.isOnSwitchStatement, isFalse);
+    }
+  }
+
+  test_executable_localLabels_inTopLevelFunction() {
+    String code = r'''
+f() {
+  aaa: while (true) {}
+  bbb: switch (42) {
+    ccc: case 0:
+      break;
+  }
+}
+''';
+    UnlinkedExecutable executable = serializeExecutableText(code);
+    List<UnlinkedLabel> labels = executable.localLabels;
+    expect(labels, hasLength(3));
+    {
+      UnlinkedLabel aaa = labels.singleWhere((l) => l.name == 'aaa');
+      expect(aaa, isNotNull);
+      expect(aaa.isOnSwitchMember, isFalse);
+      expect(aaa.isOnSwitchStatement, isFalse);
+    }
+    {
+      UnlinkedLabel bbb = labels.singleWhere((l) => l.name == 'bbb');
+      expect(bbb, isNotNull);
+      expect(bbb.isOnSwitchMember, isFalse);
+      expect(bbb.isOnSwitchStatement, isTrue);
+    }
+    {
+      UnlinkedLabel ccc = labels.singleWhere((l) => l.name == 'ccc');
+      expect(ccc, isNotNull);
+      expect(ccc.isOnSwitchMember, isTrue);
+      expect(ccc.isOnSwitchStatement, isFalse);
+    }
+  }
+
+  test_executable_localLabels_inTopLevelGetter() {
+    String code = r'''
+get g {
+  aaa: while (true) {}
+  bbb: while (true) {}
+}
+''';
+    UnlinkedExecutable executable =
+        serializeExecutableText(code, executableName: 'g');
+    List<UnlinkedLabel> labels = executable.localLabels;
+    expect(labels, hasLength(2));
+    {
+      UnlinkedLabel aaa = labels.singleWhere((l) => l.name == 'aaa');
+      expect(aaa, isNotNull);
+      expect(aaa.isOnSwitchMember, isFalse);
+      expect(aaa.isOnSwitchStatement, isFalse);
+    }
+    {
+      UnlinkedLabel bbb = labels.singleWhere((l) => l.name == 'bbb');
+      expect(bbb, isNotNull);
+      expect(bbb.isOnSwitchMember, isFalse);
+      expect(bbb.isOnSwitchStatement, isFalse);
+    }
+  }
+
   test_executable_localVariables_empty() {
     UnlinkedExecutable executable = serializeExecutableText(r'''
 f() {
@@ -4167,7 +4342,8 @@
   f() {}
 } // 2
 ''';
-    UnlinkedExecutable executable = serializeExecutableText(code, 'g');
+    UnlinkedExecutable executable =
+        serializeExecutableText(code, executableName: 'g');
     {
       List<UnlinkedExecutable> functions = executable.localFunctions;
       expect(functions, hasLength(1));
@@ -4397,7 +4573,7 @@
   test_executable_param_function_typed_return_type_implicit() {
     if (!checkAstDerivedData) {
       // TODO(paulberry): this test fails when building the summary from the
-      // element model because the elment model doesn't record whether a
+      // element model because the element model doesn't record whether a
       // function-typed parameter's return type is implicit.
       return;
     }
@@ -4418,6 +4594,8 @@
 ''');
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.initializer, isNotNull);
+    expect(param.defaultValueCode, 'foo');
     _assertUnlinkedConst(param.defaultValue, operators: [
       UnlinkedConstOperation.pushReference
     ], referenceValidators: [
@@ -4430,13 +4608,17 @@
     UnlinkedExecutable executable = serializeExecutableText('f({x}) {}');
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.named);
+    expect(param.initializer, isNull);
     expect(param.defaultValue, isNull);
+    expect(param.defaultValueCode, isEmpty);
   }
 
   test_executable_param_kind_named_withDefault() {
     UnlinkedExecutable executable = serializeExecutableText('f({x: 42}) {}');
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.named);
+    expect(param.initializer, isNotNull);
+    expect(param.defaultValueCode, '42');
     _assertUnlinkedConst(param.defaultValue,
         operators: [UnlinkedConstOperation.pushInt], ints: [42]);
   }
@@ -4445,13 +4627,17 @@
     UnlinkedExecutable executable = serializeExecutableText('f([x]) {}');
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.initializer, isNull);
     expect(param.defaultValue, isNull);
+    expect(param.defaultValueCode, isEmpty);
   }
 
   test_executable_param_kind_positional_withDefault() {
     UnlinkedExecutable executable = serializeExecutableText('f([x = 42]) {}');
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.positional);
+    expect(param.initializer, isNotNull);
+    expect(param.defaultValueCode, '42');
     _assertUnlinkedConst(param.defaultValue,
         operators: [UnlinkedConstOperation.pushInt], ints: [42]);
   }
@@ -4460,7 +4646,9 @@
     UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
     UnlinkedParam param = executable.parameters[0];
     expect(param.kind, UnlinkedParamKind.required);
+    expect(param.initializer, isNull);
     expect(param.defaultValue, isNull);
+    expect(param.defaultValueCode, isEmpty);
   }
 
   test_executable_param_name() {
@@ -4504,6 +4692,16 @@
     expect(executable.parameters[0].type, isNull);
   }
 
+  test_executable_param_type_typedef() {
+    UnlinkedExecutable executable = serializeExecutableText(r'''
+typedef MyFunction(int p);
+f(MyFunction myFunction) {}
+''');
+    expect(executable.parameters[0].isFunctionTyped, isFalse);
+    checkTypeRef(executable.parameters[0].type, null, null, 'MyFunction',
+        expectedKind: ReferenceKind.typedef);
+  }
+
   test_executable_return_type() {
     UnlinkedExecutable executable = serializeExecutableText('int f() => 1;');
     checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
@@ -4521,7 +4719,8 @@
 
   test_executable_setter() {
     String text = 'void set f(value) {}';
-    UnlinkedExecutable executable = serializeExecutableText(text, 'f=');
+    UnlinkedExecutable executable =
+        serializeExecutableText(text, executableName: 'f=');
     expect(executable.kind, UnlinkedExecutableKind.setter);
     expect(executable.returnType, isNotNull);
     expect(executable.isExternal, isFalse);
@@ -4535,25 +4734,27 @@
   }
 
   test_executable_setter_external() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('external void set f(value);', 'f=');
+    UnlinkedExecutable executable = serializeExecutableText(
+        'external void set f(value);',
+        executableName: 'f=');
     expect(executable.isExternal, isTrue);
   }
 
   test_executable_setter_implicit_return() {
     UnlinkedExecutable executable =
-        serializeExecutableText('set f(value) {}', 'f=');
+        serializeExecutableText('set f(value) {}', executableName: 'f=');
     expect(executable.returnType, isNull);
   }
 
   test_executable_setter_private() {
-    serializeExecutableText('void set _f(value) {}', '_f=');
+    serializeExecutableText('void set _f(value) {}', executableName: '_f=');
     expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
   }
 
   test_executable_setter_type() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('void set f(int value) {}', 'f=');
+    UnlinkedExecutable executable = serializeExecutableText(
+        'void set f(int value) {}',
+        executableName: 'f=');
     checkVoidTypeRef(executable.returnType);
     expect(executable.parameters, hasLength(1));
     expect(executable.parameters[0].name, 'value');
@@ -4688,6 +4889,9 @@
         'Future');
     expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
         'Stream');
+    expect(
+        unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset, 0);
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end, 0);
     expect(linked.exportNames, isNotEmpty);
   }
 
@@ -4780,7 +4984,8 @@
   }
 
   test_export_show_order() {
-    serializeLibraryText('export "dart:async" show Future, Stream;');
+    String libraryText = 'export "dart:async" show Future, Stream;';
+    serializeLibraryText(libraryText);
     expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
     expect(
         unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
@@ -4792,6 +4997,10 @@
         'Future');
     expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
         'Stream');
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset,
+        libraryText.indexOf('show'));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end,
+        libraryText.indexOf(';'));
   }
 
   test_export_typedef() {
@@ -5126,6 +5335,8 @@
     expect(unlinkedUnits[0].imports[0].combinators[0].hides, hasLength(2));
     expect(unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
     expect(unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
+    expect(unlinkedUnits[0].imports[0].combinators[0].offset, 0);
+    expect(unlinkedUnits[0].imports[0].combinators[0].end, 0);
   }
 
   test_import_implicit() {
@@ -5318,6 +5529,10 @@
     expect(unlinkedUnits[0].imports[0].combinators[0].hides, isEmpty);
     expect(unlinkedUnits[0].imports[0].combinators[0].shows[0], 'Future');
     expect(unlinkedUnits[0].imports[0].combinators[0].shows[1], 'Stream');
+    expect(unlinkedUnits[0].imports[0].combinators[0].offset,
+        libraryText.indexOf('show'));
+    expect(unlinkedUnits[0].imports[0].combinators[0].end,
+        libraryText.indexOf('; Future'));
   }
 
   test_import_uri() {
@@ -5369,7 +5584,7 @@
     expect(linkedReference.dependency, 0);
     expect(linkedReference.kind, ReferenceKind.method);
     expect(linkedReference.name, 'f');
-    expect(linkedReference.numTypeParameters, 2);
+    expect(linkedReference.numTypeParameters, 0);
     expect(linkedReference.unit, 0);
     expect(linkedReference.containingReference, isNot(0));
     expect(linkedReference.containingReference, lessThan(type.reference));
@@ -5466,6 +5681,142 @@
     checkReferenceIndex(linkedReference.containingReference, null, null, 'D');
   }
 
+  test_initializer_executable_with_bottom_return_type() {
+    // The synthetic executable for `v` has type `() => Bottom`.
+    UnlinkedVariable variable = serializeVariableText('int v = null;');
+    expect(variable.initializer.returnType, isNull);
+    checkInferredTypeSlot(
+        variable.initializer.inferredReturnTypeSlot, null, null, '*bottom*',
+        onlyInStrongMode: false);
+  }
+
+  test_initializer_executable_with_imported_return_type() {
+    addNamedSource('/a.dart', 'class C { D d; } class D {}');
+    // The synthetic executable for `v` has type `() => D`; `D` is defined in
+    // a library that is imported.  Note: `v` is mis-typed as `int` to prevent
+    // type propagation, which would complicate the test.
+    UnlinkedVariable variable = serializeVariableText(
+        'import "a.dart"; int v = new C().d;',
+        allowErrors: true);
+    expect(variable.initializer.returnType, isNull);
+    checkInferredTypeSlot(variable.initializer.inferredReturnTypeSlot,
+        absUri('/a.dart'), 'a.dart', 'D',
+        onlyInStrongMode: false);
+    checkHasDependency(absUri('/a.dart'), 'a.dart', fullyLinked: false);
+  }
+
+  test_initializer_executable_with_return_type_from_closure() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // The synthetic executable for `v` has type `() => () => int`, where the
+    // `() => int` part refers to the closure declared inside the initializer
+    // for v.  Note: `v` is mis-typed as `int` to prevent type propagation,
+    // which would complicate the test.
+    UnlinkedVariable variable =
+        serializeVariableText('int v = () => 0;', allowErrors: true);
+    EntityRef closureType =
+        getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
+    checkLinkedTypeRef(closureType, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int initializerIndex =
+        definingUnit.references[closureType.reference].containingReference;
+    checkReferenceIndex(initializerIndex, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int variableIndex =
+        definingUnit.references[initializerIndex].containingReference;
+    checkReferenceIndex(variableIndex, null, null, 'v',
+        expectedKind: ReferenceKind.topLevelPropertyAccessor);
+    expect(definingUnit.references[variableIndex].containingReference, 0);
+  }
+
+  test_initializer_executable_with_return_type_from_closure_field() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // The synthetic executable for `v` has type `() => () => int`, where the
+    // `() => int` part refers to the closure declared inside the initializer
+    // for v.  Note: `v` is mis-typed as `int` to prevent type propagation,
+    // which would complicate the test.
+    UnlinkedClass cls = serializeClassText(
+        '''
+class C {
+  int v = () => 0;
+}
+''',
+        allowErrors: true);
+    UnlinkedVariable variable = cls.fields[0];
+    EntityRef closureType =
+        getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
+    checkLinkedTypeRef(closureType, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int initializerIndex =
+        definingUnit.references[closureType.reference].containingReference;
+    checkReferenceIndex(initializerIndex, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int variableIndex =
+        definingUnit.references[initializerIndex].containingReference;
+    checkReferenceIndex(variableIndex, null, null, 'v',
+        expectedKind: ReferenceKind.propertyAccessor);
+    int classIndex = definingUnit.references[variableIndex].containingReference;
+    checkReferenceIndex(classIndex, null, null, 'C');
+    expect(definingUnit.references[classIndex].containingReference, 0);
+  }
+
+  test_initializer_executable_with_return_type_from_closure_local() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // The synthetic executable for `v` has type `() => () => int`, where the
+    // `() => int` part refers to the closure declared inside the initializer
+    // for v.  Note: `v` is mis-typed as `int` to prevent type propagation,
+    // which would complicate the test.
+    UnlinkedExecutable executable = serializeExecutableText(
+        '''
+void f() {
+  int u = 0; // force the variable below to have index 1
+  int v = () => 0;
+}''',
+        allowErrors: true);
+    UnlinkedVariable variable = executable.localVariables[1];
+    EntityRef closureType =
+        getTypeRefForSlot(variable.initializer.inferredReturnTypeSlot);
+    checkLinkedTypeRef(closureType, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int initializerIndex =
+        definingUnit.references[closureType.reference].containingReference;
+    checkReferenceIndex(initializerIndex, null, null, '',
+        expectedKind: ReferenceKind.function);
+    int variableIndex =
+        definingUnit.references[initializerIndex].containingReference;
+    checkReferenceIndex(variableIndex, null, null, 'v',
+        expectedKind: ReferenceKind.variable, localIndex: 1);
+    int topLevelFunctionIndex =
+        definingUnit.references[variableIndex].containingReference;
+    checkReferenceIndex(topLevelFunctionIndex, null, null, 'f',
+        expectedKind: ReferenceKind.topLevelFunction);
+    expect(
+        definingUnit.references[topLevelFunctionIndex].containingReference, 0);
+  }
+
+  test_initializer_executable_with_unimported_return_type() {
+    addNamedSource('/a.dart', 'import "b.dart"; class C { D d; }');
+    addNamedSource('/b.dart', 'class D {}');
+    // The synthetic executable for `v` has type `() => D`; `D` is defined in
+    // a library that is not imported.  Note: `v` is mis-typed as `int` to
+    // prevent type propagation, which would complicate the test.
+    UnlinkedVariable variable = serializeVariableText(
+        'import "a.dart"; int v = new C().d;',
+        allowErrors: true);
+    expect(variable.initializer.returnType, isNull);
+    checkInferredTypeSlot(variable.initializer.inferredReturnTypeSlot,
+        absUri('/b.dart'), 'b.dart', 'D',
+        onlyInStrongMode: false);
+    if (!skipFullyLinkedData) {
+      checkHasDependency(absUri('/b.dart'), 'b.dart', fullyLinked: true);
+    }
+  }
+
   test_invalid_prefix_dynamic() {
     if (checkAstDerivedData) {
       // TODO(paulberry): get this to work properly.
@@ -5744,9 +6095,10 @@
   }
 
   test_metadata_functionDeclaration_setter() {
-    checkAnnotationA(
-        serializeExecutableText('const a = null; @a set f(value) {}', 'f=')
-            .annotations);
+    checkAnnotationA(serializeExecutableText(
+            'const a = null; @a set f(value) {}',
+            executableName: 'f=')
+        .annotations);
   }
 
   test_metadata_functionTypeAlias() {
@@ -6098,7 +6450,8 @@
  * Docs
  */
 void set f(value) {}''';
-    UnlinkedExecutable executable = serializeExecutableText(text, 'f=');
+    UnlinkedExecutable executable =
+        serializeExecutableText(text, executableName: 'f=');
     expect(executable.documentationComment, isNotNull);
     checkDocumentationComment(executable.documentationComment, text);
   }
@@ -6153,12 +6506,13 @@
 
   test_setter_inferred_type_top_level_implicit_param() {
     UnlinkedExecutable f =
-        serializeExecutableText('void set f(value) {}', 'f=');
+        serializeExecutableText('void set f(value) {}', executableName: 'f=');
     expect(f.parameters[0].inferredTypeSlot, 0);
   }
 
   test_setter_inferred_type_top_level_implicit_return() {
-    UnlinkedExecutable f = serializeExecutableText('set f(int value) {}', 'f=');
+    UnlinkedExecutable f =
+        serializeExecutableText('set f(int value) {}', executableName: 'f=');
     expect(f.inferredReturnTypeSlot, 0);
   }
 
@@ -6630,6 +6984,15 @@
         unlinkedSourceUnit: unlinkedUnits[1]);
   }
 
+  test_unresolved_reference_shared() {
+    // Both `x` and `y` use unresolved identifier `C` as their type.  Verify
+    // that they both use the same unresolved reference.
+    serializeLibraryText('C x; C y;', allowErrors: true);
+    EntityRef xType = findVariable('x').type;
+    EntityRef yType = findVariable('y').type;
+    expect(xType.reference, yType.reference);
+  }
+
   test_variable() {
     String text = 'int i;';
     UnlinkedVariable v = serializeVariableText(text, variableName: 'i');
@@ -6697,6 +7060,61 @@
     expect(v.inferredTypeSlot, 0);
   }
 
+  test_variable_initializer_literal() {
+    UnlinkedVariable variable = serializeVariableText('var v = 42;');
+    UnlinkedExecutable initializer = variable.initializer;
+    expect(initializer, isNotNull);
+    expect(initializer.nameOffset, 8);
+    expect(initializer.name, isEmpty);
+    expect(initializer.localFunctions, isEmpty);
+    expect(initializer.localVariables, isEmpty);
+  }
+
+  test_variable_initializer_noInitializer() {
+    UnlinkedVariable variable = serializeVariableText('var v;');
+    expect(variable.initializer, isNull);
+  }
+
+  test_variable_initializer_withLocals() {
+    String text =
+        'var v = <dynamic, dynamic>{"1": () { f1() {} var v1; }, '
+        '"2": () { f2() {} var v2; }};';
+    UnlinkedVariable variable = serializeVariableText(text);
+    UnlinkedExecutable initializer = variable.initializer;
+    expect(initializer, isNotNull);
+    expect(initializer.nameOffset, text.indexOf('<dynamic, dynamic>{"1'));
+    expect(initializer.name, isEmpty);
+    expect(initializer.localFunctions, hasLength(2));
+    // closure: () { f1() {} var v1; }
+    {
+      UnlinkedExecutable closure = initializer.localFunctions[0];
+      expect(closure.nameOffset, text.indexOf('() { f1()'));
+      expect(closure.name, isEmpty);
+      // closure - f1
+      expect(closure.localFunctions, hasLength(1));
+      expect(closure.localFunctions[0].name, 'f1');
+      expect(closure.localFunctions[0].nameOffset, text.indexOf('f1()'));
+      // closure - v1
+      expect(closure.localVariables, hasLength(1));
+      expect(closure.localVariables[0].name, 'v1');
+      expect(closure.localVariables[0].nameOffset, text.indexOf('v1;'));
+    }
+    // closure: () { f2() {} var v2; }
+    {
+      UnlinkedExecutable closure = initializer.localFunctions[1];
+      expect(closure.nameOffset, text.indexOf('() { f2()'));
+      expect(closure.name, isEmpty);
+      // closure - f1
+      expect(closure.localFunctions, hasLength(1));
+      expect(closure.localFunctions[0].name, 'f2');
+      expect(closure.localFunctions[0].nameOffset, text.indexOf('f2()'));
+      // closure - v1
+      expect(closure.localVariables, hasLength(1));
+      expect(closure.localVariables[0].name, 'v2');
+      expect(closure.localVariables[0].nameOffset, text.indexOf('v2;'));
+    }
+  }
+
   test_variable_name() {
     UnlinkedVariable variable =
         serializeVariableText('int i;', variableName: 'i');
@@ -6901,14 +7319,10 @@
 class _PrefixExpectation {
   final ReferenceKind kind;
   final String name;
-  final bool inLibraryDefiningUnit;
   final String absoluteUri;
   final String relativeUri;
   final int numTypeParameters;
 
   _PrefixExpectation(this.kind, this.name,
-      {this.inLibraryDefiningUnit: false,
-      this.absoluteUri,
-      this.relativeUri,
-      this.numTypeParameters: 0});
+      {this.absoluteUri, this.relativeUri, this.numTypeParameters: 0});
 }
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 21c2fd3..9bf0050 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -1145,6 +1145,33 @@
         outputs[CONSTANT_DEPENDENCIES].toSet(), [x, constructorForD].toSet());
   }
 
+  test_annotation_with_nonConstArg() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+class A {
+  const A(x);
+}
+class C {
+  @A(const [(_) => null])
+  String s;
+}
+''');
+    // First compute the resolved unit for the source.
+    LibrarySpecificUnit librarySpecificUnit =
+        new LibrarySpecificUnit(source, source);
+    computeResult(librarySpecificUnit, RESOLVED_UNIT1);
+    CompilationUnit unit = outputs[RESOLVED_UNIT1];
+    // Find the annotation on the field.
+    ClassDeclaration classC = unit.declarations[1];
+    Annotation annotation = classC.members[0].metadata[0];
+    // Now compute the dependencies for the annotation, and check that it is
+    // the right size.
+    computeResult(annotation.elementAnnotation, CONSTANT_DEPENDENCIES,
+        matcher: isComputeConstantDependenciesTask);
+    expect(outputs[CONSTANT_DEPENDENCIES], hasLength(1));
+  }
+
   test_annotation_without_args() {
     Source source = newSource(
         '/test.dart',
@@ -2240,8 +2267,6 @@
 
 @reflectiveTest
 class GatherUsedLocalElementsTaskTest extends _AbstractDartTaskTest {
-  List<Element> definedElements;
-  Set<String> definedElementNames;
   UsedLocalElements usedElements;
   Set<String> usedElementNames;
 
@@ -2306,7 +2331,6 @@
 }''');
     _computeUsedElements(source);
     // validate
-    expect(definedElementNames, unorderedEquals(['main', 'v1', 'v2']));
     expect(usedElementNames, unorderedEquals(['v2']));
   }
 
@@ -2326,30 +2350,14 @@
 ''');
     _computeUsedElements(source);
     // validate
-    expect(definedElementNames,
-        unorderedEquals(['A', '_m1', '_m2', 'main', 'a', 'p']));
     expect(usedElementNames, unorderedEquals(['A', 'a', 'p', '_m2']));
     expect(usedElements.members, unorderedEquals(['_m2', '_m3']));
   }
 
-  test_perform_unresolvedImportWithPrefix() {
-    Source source = newSource(
-        '/test.dart',
-        r'''
-import 'x' as p;
-''');
-    _computeUsedElements(source);
-    // validate
-    expect(definedElementNames, isEmpty);
-    expect(usedElementNames, isEmpty);
-  }
-
   void _computeUsedElements(Source source) {
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
     computeResult(target, USED_LOCAL_ELEMENTS,
         matcher: isGatherUsedLocalElementsTask);
-    definedElements = outputs[DEFINED_ELEMENTS];
-    definedElementNames = definedElements.map((e) => e.name).toSet();
     usedElements = outputs[USED_LOCAL_ELEMENTS];
     usedElementNames = usedElements.elements.map((e) => e.name).toSet();
   }
@@ -4069,8 +4077,6 @@
    */
   void expectMutated(FunctionBody body, VariableElement variable,
       bool mutatedInClosure, bool mutatedInScope) {
-    expect(variable.isPotentiallyMutatedInClosure, mutatedInClosure);
-    expect(variable.isPotentiallyMutatedInScope, mutatedInScope);
     expect(body.isPotentiallyMutatedInClosure(variable), mutatedInClosure);
     expect(body.isPotentiallyMutatedInScope(variable), mutatedInScope);
   }
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index cc7047e..a87577c 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -33,10 +33,10 @@
           // because we're using the spec's LUB on function types, which isn't
           // sound.
           SplayTreeMap([int compare(K key1, K key2),
-                        bool isValidKey(potentialKey)]) {
+                        bool isValidKey(potentialKey)])
             : _comparator = (compare == null) ? Comparable.compare : compare,
-              _validKey = (isValidKey != null) ? isValidKey : ((v) => true);
-             _Predicate<Object> v = /*warning:DOWN_CAST_COMPOSITE*/(isValidKey != null)
+              _validKey = (isValidKey != null) ? isValidKey : ((v) => true) {
+            _Predicate<Object> v = /*warning:DOWN_CAST_COMPOSITE*/(isValidKey != null)
                                     ? isValidKey : (/*info:INFERRED_TYPE_CLOSURE*/(_) => true);
 
             v = (isValidKey != null)
@@ -59,7 +59,7 @@
   test('if/for/do/while statements use boolean conversion', () {
     checkFile('''
       main() {
-        dynamic d = 42;
+        dynamic dyn = 42;
         Object obj = 42;
         int i = 42;
         bool b = false;
@@ -133,12 +133,12 @@
           (/*info:DYNAMIC_INVOKE*/g.call(32.0));
           (/*info:DYNAMIC_INVOKE*/g.col(42.0));
           (/*info:DYNAMIC_INVOKE*/g.foo(42.0));
-          (/*info:DYNAMIC_INVOKE*/g.x);
+          (/*info:DYNAMIC_INVOKE*/g./*info:UNDEFINED_GETTER*/x);
           A f = new B();
           f.call(32.0);
           (/*info:DYNAMIC_INVOKE*/f.col(42.0));
           (/*info:DYNAMIC_INVOKE*/f.foo(42.0));
-          (/*info:DYNAMIC_INVOKE*/f.x);
+          (/*info:DYNAMIC_INVOKE*/f./*warning:UNDEFINED_GETTER*/x);
         }
       }
     ''');
@@ -203,7 +203,7 @@
         (/*info:DYNAMIC_INVOKE*/b2("hello"));
 
         dynamic a1 = new B();
-        (/*info:DYNAMIC_INVOKE*/a1.x);
+        (/*info:DYNAMIC_INVOKE*/a1./*info:UNDEFINED_GETTER*/x);
         a1.toString();
         (/*info:DYNAMIC_INVOKE*/a1.toString(42));
         var toStringClosure = a1.toString;
@@ -263,7 +263,7 @@
   test('Unbound variable', () {
     checkFile('''
       void main() {
-         dynamic y = /*pass should be severe:STATIC_TYPE_ERROR*/unboundVariable;
+         dynamic y = /*warning:UNDEFINED_IDENTIFIER should be error*/unboundVariable;
       }
    ''');
   });
@@ -271,7 +271,7 @@
   test('Unbound type name', () {
     checkFile('''
       void main() {
-         /*pass should be severe:STATIC_TYPE_ERROR*/AToB y;
+         /*warning:UNDEFINED_CLASS should be error*/AToB y;
       }
    ''');
   });
@@ -556,12 +556,11 @@
       typedef A Right(dynamic x);         // Right branch
       typedef A Bottom(A x);              // Bottom of the lattice
 
-      dynamic left(A x) => x;
-      A bot(A x) => x;
-      dynamic top(dynamic x) => x;
-      A right(dynamic x) => /*info:DYNAMIC_CAST*/x;
-
       void main() {
+        Top top;
+        Left left;
+        Right right;
+        Bottom bot;
         {
           Top f;
           f = top;
@@ -571,29 +570,106 @@
         }
         {
           Left f;
-          f = /*severe:STATIC_TYPE_ERROR*/top;
+          f = /*warning:DOWN_CAST_COMPOSITE*/top;
           f = left;
-          f = /*severe:STATIC_TYPE_ERROR*/right;
+          f = /*warning:DOWN_CAST_COMPOSITE*/right;
           f = bot;
         }
         {
           Right f;
-          f = /*severe:STATIC_TYPE_ERROR*/top;
-          f = /*severe:STATIC_TYPE_ERROR*/left;
+          f = /*warning:DOWN_CAST_COMPOSITE*/top;
+          f = /*warning:DOWN_CAST_COMPOSITE*/left;
           f = right;
           f = bot;
         }
         {
           Bottom f;
-          f = /*severe:STATIC_TYPE_ERROR*/top;
-          f = /*severe:STATIC_TYPE_ERROR*/left;
-          f = /*severe:STATIC_TYPE_ERROR*/right;
+          f = /*warning:DOWN_CAST_COMPOSITE*/top;
+          f = /*warning:DOWN_CAST_COMPOSITE*/left;
+          f = /*warning:DOWN_CAST_COMPOSITE*/right;
           f = bot;
         }
       }
    ''');
     });
 
+    test('dynamic - known functions', () {
+
+      // Our lattice should look like this:
+      //
+      //
+      //           Bot -> Top
+      //          /        \
+      //      A -> Top    Bot -> A
+      //       /     \      /
+      // Top -> Top   A -> A
+      //         \      /
+      //         Top -> A
+      //
+      checkFile('''
+        class A {}
+
+        typedef dynamic BotTop(dynamic x);
+        typedef dynamic ATop(A x);
+        typedef A BotA(dynamic x);
+        typedef A AA(A x);
+        typedef A TopA(Object x);
+        typedef dynamic TopTop(Object x);
+
+        dynamic aTop(A x) => x;
+        A aa(A x) => x;
+        dynamic topTop(dynamic x) => x;
+        A topA(dynamic x) => /*info:DYNAMIC_CAST*/x;
+
+        void main() {
+          BotTop botTop;
+          BotA botA;
+          {
+            BotTop f;
+            f = topTop;
+            f = aTop;
+            f = topA;
+            f = aa;
+          }
+          {
+            ATop f;
+            f = topTop;
+            f = aTop;
+            f = topA;
+            f = aa;
+          }
+          {
+            BotA f;
+            f = /*severe:STATIC_TYPE_ERROR*/topTop;
+            f = /*severe:STATIC_TYPE_ERROR*/aTop;
+            f = topA;
+            f = aa;
+          }
+          {
+            AA f;
+            f = /*severe:STATIC_TYPE_ERROR*/topTop;
+            f = /*severe:STATIC_TYPE_ERROR*/aTop;
+            f = topA;
+            f = aa;
+          }
+          {
+            TopTop f;
+            f = topTop;
+            f = /*severe:STATIC_TYPE_ERROR*/aTop;
+            f = topA;
+            f = /*severe:STATIC_TYPE_ERROR*/aa;
+          }
+          {
+            TopA f;
+            f = /*severe:STATIC_TYPE_ERROR*/topTop;
+            f = /*severe:STATIC_TYPE_ERROR*/aTop;
+            f = topA;
+            f = /*severe:STATIC_TYPE_ERROR*/aa;
+          }
+        }
+     ''');
+    });
+
     test('function literal variance', () {
       checkFile('''
 
@@ -1010,7 +1086,7 @@
          o = /*severe:STATIC_TYPE_ERROR*/ro;
          o = /*severe:STATIC_TYPE_ERROR*/rn;
          o = oo;
-         o = /*severe:STATIC_TYPE_ERROR*/nn
+         o = /*severe:STATIC_TYPE_ERROR*/nn;
          o = /*severe:STATIC_TYPE_ERROR*/nnn;
 
          n = /*severe:STATIC_TYPE_ERROR*/r;
@@ -1386,7 +1462,7 @@
     checkFile(r'''
         class Animal {
           Animal();
-          factory Animal.cat() => return new Cat();
+          factory Animal.cat() => new Cat();
         }
 
         class Cat extends Animal {}
@@ -1656,21 +1732,22 @@
           /*=T*/ bar/*<T>*/({/*=T*/ x, /*=T*/ y}) => x;
 
           main() {
-            // resolving thses shouldn't crash.
-            foo(1, 2, 3);
-            String x = foo('1', '2', '3');
-            foo(1);
-            String x = foo('1');
-            x = /*severe:STATIC_TYPE_ERROR*/foo(1, 2, 3);
-            x = /*severe:STATIC_TYPE_ERROR*/foo(1);
+            String x;
+            // resolving these shouldn't crash.
+            foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/(1, 2, 3);
+            x = foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/('1', '2', '3');
+            foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/(1);
+            x = foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/('1');
+            x = /*info:DYNAMIC_CAST*/foo/*warning:EXTRA_POSITIONAL_ARGUMENTS*/(1, 2, 3);
+            x = /*info:DYNAMIC_CAST*/foo/*warning:NOT_ENOUGH_REQUIRED_ARGUMENTS*/(1);
 
             // named arguments
-            bar(y: 1, x: 2, z: 3);
-            String x = bar(z: '1', x: '2', y: '3');
+            bar(y: 1, x: 2, /*warning:UNDEFINED_NAMED_PARAMETER*/z: 3);
+            x = bar(/*warning:UNDEFINED_NAMED_PARAMETER*/z: '1', x: '2', y: '3');
             bar(y: 1);
-            x = bar(x: '1', z: 42);
-            x = /*severe:STATIC_TYPE_ERROR*/bar(y: 1, x: 2, z: 3);
-            x = /*severe:STATIC_TYPE_ERROR*/bar(x: 1);
+            x = bar(x: '1', /*warning:UNDEFINED_NAMED_PARAMETER*/z: 42);
+            x = /*info:DYNAMIC_CAST*/bar(y: 1, x: 2, /*warning:UNDEFINED_NAMED_PARAMETER*/z: 3);
+            x = /*info:DYNAMIC_CAST*/bar(x: 1);
           }
       ''');
   });
@@ -1708,6 +1785,7 @@
       test() {
         A a = new A();
         var c = foo();
+        dynamic d;
 
         ~a;
         (/*info:DYNAMIC_INVOKE*/~d);
@@ -1889,7 +1967,7 @@
             a[/*severe:STATIC_TYPE_ERROR*/z] += d;
             a[b] += /*info:DYNAMIC_CAST*/c;
             a[b] += /*severe:STATIC_TYPE_ERROR*/z;
-            (/*info:DYNAMIC_INVOKE*/(/*info:DYNAMIC_INVOKE*/c[b]) += d);
+            /*info:DYNAMIC_INVOKE,info:DYNAMIC_INVOKE*/c[b] += d;
           }
        ''');
   });
@@ -1948,6 +2026,7 @@
     addFile('''library lib1;''', name: '/lib1.dart');
     checkFile(r'''
         import 'lib1.dart' deferred as lib1;
+        import 'dart:async' show Future;
         main() {
           Future f = lib1.loadLibrary();
         }''');
@@ -1964,11 +2043,11 @@
             }
 
             class T1 extends Base {
-              /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/B get f => null;
+              /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_FIELD_OVERRIDE*/B get f => null;
             }
 
             class T2 extends Base {
-              /*severe:INVALID_FIELD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/set f(B b) => null;
+              /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_FIELD_OVERRIDE*/set f(B b) => null;
             }
 
             class T3 extends Base {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 2e7981e..ba964d8 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -261,6 +261,7 @@
         name: '/c.dart');
     addFile(
         '''
+          library e;
           import 'a.dart';
           part 'e2.dart';
 
@@ -281,6 +282,7 @@
         name: '/f.dart');
     addFile(
         '''
+          part of e;
           class F {
             static final f1 = 1;
             final f2 = 1;
@@ -334,17 +336,17 @@
         class B extends A { B(ignore); }
         var a = new A();
         // Note: it doesn't matter that some of these refer to 'x'.
-        var b = new B(x);       // allocations
-        var c1 = [x];           // list literals
+        var b = new B(/*warning:UNDEFINED_IDENTIFIER*/x);  // allocations
+        var c1 = [/*warning:UNDEFINED_IDENTIFIER*/x];      // list literals
         var c2 = const [];
-        var d = {'a': 'b'};     // map literals
+        var d = <dynamic, dynamic>{'a': 'b'};     // map literals
         var e = new A()..x = 3; // cascades
         var f = 2 + 3;          // binary expressions are OK if the left operand
                                 // is from a library in a different strongest
                                 // conected component.
         var g = -3;
         var h = new A() + 3;
-        var i = - new A();
+        var i = /*warning:UNDEFINED_OPERATOR*/- new A();
         var j = null as B;
 
         test1() {
@@ -365,9 +367,9 @@
           g = 1;
           g = /*severe:STATIC_TYPE_ERROR*/false;
           h = /*severe:STATIC_TYPE_ERROR*/false;
-          h = new B();
+          h = new B('b');
           i = false;
-          j = new B();
+          j = new B('b');
           j = /*severe:STATIC_TYPE_ERROR*/false;
           j = /*severe:STATIC_TYPE_ERROR*/[];
         }
@@ -683,12 +685,12 @@
     test('5', () {
       checkFile('''
         abstract class I<E> {
-          String m(a, String f(v, T e));
+          String m(a, String f(v, E e));
         }
 
         abstract class A<E> implements I<E> {
           const A();
-          String m(a, String f(v, T e));
+          String m(a, String f(v, E e));
         }
 
         abstract class M {
@@ -699,7 +701,7 @@
           const B();
           int get y => 0;
 
-          m(a, f(v, T e)) {}
+          m(a, f(v, E e)) {}
         }
 
         foo () {
@@ -728,7 +730,7 @@
         }
         foo () {
           int y = new C().x;
-          String y = /*severe:STATIC_TYPE_ERROR*/new C().x;
+          String z = /*severe:STATIC_TYPE_ERROR*/new C().x;
         }
     ''');
   });
@@ -987,7 +989,7 @@
         const a1 = 3;
         const a2 = 4;
         class A {
-          a3;
+          static const a3 = null;
         }
       ''',
         name: '/a.dart');
@@ -1203,7 +1205,7 @@
 
 abstract class C {
   static AsserterBuilder<List<Asserter<DartType>>, DartType> assertBOf;
-  static AsserterBuilder<List<Asserter<DartType>>, DartType> get assertCOf;
+  static AsserterBuilder<List<Asserter<DartType>>, DartType> get assertCOf => null;
 
   AsserterBuilder<List<Asserter<DartType>>, DartType> assertAOf;
   AsserterBuilder<List<Asserter<DartType>>, DartType> get assertDOf;
@@ -1230,7 +1232,7 @@
 }
 
 AsserterBuilder<List<Asserter<DartType>>, DartType> assertBOf;
-AsserterBuilder<List<Asserter<DartType>>, DartType> get assertCOf;
+AsserterBuilder<List<Asserter<DartType>>, DartType> get assertCOf => null;
 
 main() {
   AsserterBuilder<List<Asserter<DartType>>, DartType> assertAOf;
@@ -1255,11 +1257,11 @@
   group('downwards inference on function arguments', () {
     test('infer downwards', () {
       checkFile('''
-      void f0(List<int> a) {};
-      void f1({List<int> a}) {};
-      void f2(Iterable<int> a) {};
-      void f3(Iterable<Iterable<int>> a) {};
-      void f4({Iterable<Iterable<int>> a}) {};
+      void f0(List<int> a) {}
+      void f1({List<int> a}) {}
+      void f2(Iterable<int> a) {}
+      void f3(Iterable<Iterable<int>> a) {}
+      void f4({Iterable<Iterable<int>> a}) {}
       void main() {
         f0(/*info:INFERRED_TYPE_LITERAL*/[]);
         f0(/*info:INFERRED_TYPE_LITERAL*/[3]);
@@ -1294,19 +1296,19 @@
     test('infer downwards', () {
       checkFile('''
       class F0 {
-        F0(List<int> a) {};
+        F0(List<int> a) {}
       }
       class F1 {
-        F1({List<int> a}) {};
+        F1({List<int> a}) {}
       }
       class F2 {
-        F2(Iterable<int> a) {};
+        F2(Iterable<int> a) {}
       }
       class F3 {
-        F3(Iterable<Iterable<int>> a) {};
+        F3(Iterable<Iterable<int>> a) {}
       }
       class F4 {
-        F4({Iterable<Iterable<int>> a}) {};
+        F4({Iterable<Iterable<int>> a}) {}
       }
       void main() {
         new F0(/*info:INFERRED_TYPE_LITERAL*/[]);
@@ -1345,19 +1347,19 @@
     test('infer downwards', () {
       checkFile('''
       class F0<T> {
-        F0(List<T> a) {};
+        F0(List<T> a) {}
       }
       class F1<T> {
-        F1({List<T> a}) {};
+        F1({List<T> a}) {}
       }
       class F2<T> {
-        F2(Iterable<T> a) {};
+        F2(Iterable<T> a) {}
       }
       class F3<T> {
-        F3(Iterable<Iterable<T>> a) {};
+        F3(Iterable<Iterable<T>> a) {}
       }
       class F4<T> {
-        F4({Iterable<Iterable<T>> a}) {};
+        F4({Iterable<Iterable<T>> a}) {}
       }
       void main() {
         new F0<int>(/*info:INFERRED_TYPE_LITERAL*/[]);
@@ -1406,7 +1408,7 @@
     test('infer downwards', () {
       checkFile('''
       void foo([Map<int, String> m1 = /*info:INFERRED_TYPE_LITERAL*/const {1: "hello"},
-        Map<int, String> m1 = /*info:INFERRED_TYPE_LITERAL*/const {(/*severe:STATIC_TYPE_ERROR*/"hello"): "world"}]) {
+        Map<int, String> m2 = /*info:INFERRED_TYPE_LITERAL*/const {(/*severe:STATIC_TYPE_ERROR*/"hello"): "world"}]) {
       }
       void main() {
         {
@@ -1530,7 +1532,7 @@
           x = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x+1;
           var y = int2String;
           y = /*info:INFERRED_TYPE_CLOSURE, severe:STATIC_TYPE_ERROR*//*<T>*/(x) => x;
-          y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => /*info:DYNAMIC_CAST, info:DYNAMIC_INVOKE*/x.substring(3);
+          y = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => /*info:DYNAMIC_INVOKE, info:DYNAMIC_CAST*/x.substring(3);
           var z = string2String;
           z = /*info:INFERRED_TYPE_CLOSURE*//*<T>*/(x) => x.substring(3);
         }
@@ -1571,28 +1573,30 @@
       void f([List<int> l = /*info:INFERRED_TYPE_LITERAL*/const [1]]) {}
       // We do this inference in an early task but don't preserve the infos.
       Function2<List<int>, String> g = /*pass should be info:INFERRED_TYPE_CLOSURE*/([llll = /*info:INFERRED_TYPE_LITERAL*/const [1]]) => "hello";
-''');
+    ''');
   });
 
   test('downwards inference async/await', () {
     checkFile('''
       import 'dart:async';
       Future<int> test() async {
-        List<int> l0 = /*warning:DOWN_CAST_COMPOSITE should be pass*/await /*pass should be info:INFERRED_TYPE_LITERAL*/[3];
-        List<int> l1 = await /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[3]);
-        ''');
+        dynamic d;
+        List<int> l0 = /*warning:DOWN_CAST_COMPOSITE should be pass*/await /*pass should be info:INFERRED_TYPE_LITERAL*/[d];
+        List<int> l1 = await /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d]);
+      }
+    ''');
   });
 
   test('downwards inference foreach', () {
     checkFile('''
       import 'dart:async';
-      void main() {
+      Future main() async {
         for(int x in /*info:INFERRED_TYPE_LITERAL*/[1, 2, 3]) {
         }
         await for(int x in /*info:INFERRED_TYPE_ALLOCATION*/new Stream()) {
         }
       }
-        ''');
+    ''');
   });
 
   test('downwards inference yield/yield*', () {
@@ -1691,7 +1695,7 @@
           Iterable<Future<int>> list = <int>[1, 2, 3].map(make);
           Future<List<int>> results = Future.wait(list);
           Future<String> results2 = results.then((List<int> list)
-            => list.fold('', (String x, int y) => x + y.toString()));
+            => list.fold('', /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y.toString()));
         }
     ''');
     });
@@ -1826,7 +1830,7 @@
   /*severe:INVALID_METHOD_OVERRIDE*/m(x) => x;
 }
 main() {
-  int y = /*info:DYNAMIC_CAST*/new D().m/*<int>*/(42);
+  int y = /*info:DYNAMIC_CAST*/new D()./*warning:WRONG_NUMBER_OF_TYPE_ARGUMENTS*/m/*<int>*/(42);
   print(y);
 }
     ''');
@@ -1834,7 +1838,7 @@
 
     test('correctly recognize generic upper bound', () {
       // Regression test for https://github.com/dart-lang/sdk/issues/25740.
-      checkFile('''
+      checkFile(r'''
 class Foo<T extends Pattern> {
   void method/*<U extends T>*/(dynamic/*=U*/ u) {}
 }
@@ -1849,11 +1853,52 @@
 }
       ''');
     });
+
+    test('basic downwards inference', () {
+      checkFile(r'''
+/*=T*/ f/*<S, T>*/(/*=S*/ s) => null;
+main() {
+  String x = f(42);
+  String y = (f)(42);
+}
+      ''');
+    });
+
+    test('downwards inference affects arguments', () {
+      checkFile(r'''
+/*=T*/ f/*<T>*/(List/*<T>*/ s) => null;
+main() {
+  String x = f(/*info:INFERRED_TYPE_LITERAL*/['hi']);
+  String y = f(/*info:INFERRED_TYPE_LITERAL*/[/*severe:STATIC_TYPE_ERROR*/42]);
+}
+      ''');
+    });
+
+    test('downwards inference fold', () {
+      // Regression from https://github.com/dart-lang/sdk/issues/25491
+      // The first example works now, but the latter requires a full solution to
+      // https://github.com/dart-lang/sdk/issues/25490
+      checkFile(r'''
+void main() {
+  List<int> o;
+  int y = o.fold(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y);
+  var z = o.fold(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => /*info:DYNAMIC_INVOKE*/x + y);
+  y = /*info:DYNAMIC_CAST*/z;
+}
+void functionExpressionInvocation() {
+  List<int> o;
+  int y = (o.fold)(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => x + y);
+  var z = (o.fold)(0, /*info:INFERRED_TYPE_CLOSURE*/(x, y) => /*info:DYNAMIC_INVOKE*/x + y);
+  y = /*info:DYNAMIC_CAST*/z;
+}
+      ''');
+    });
+
   });
 
   // Regression test for https://github.com/dart-lang/dev_compiler/issues/47
   test('null literal should not infer as bottom', () {
-    checkFile('''
+    checkFile(r'''
       var h = null;
       void foo(int f(Object _)) {}
 
@@ -1874,4 +1919,45 @@
   ''');
   });
 
+  test('list literals', () {
+    checkFile(r'''
+test1() {
+  var x = [1, 2, 3];
+  x.add(/*severe:STATIC_TYPE_ERROR*/'hi');
+  x.add(/*severe:STATIC_TYPE_ERROR*/4.0);
+  x.add(4);
+  List<num> y = x;
+}
+test2() {
+  var x = [1, 2.0, 3];
+  x.add(/*severe:STATIC_TYPE_ERROR*/'hi');
+  x.add(4.0);
+  List<int> y = /*info:ASSIGNMENT_CAST*/x;
+}
+    ''');
+  });
+
+  test('map literals', () {
+    checkFile(r'''
+test1() {
+  var x = { 1: 'x', 2: 'y' };
+  x[3] = 'z';
+  x[/*severe:STATIC_TYPE_ERROR*/'hi'] = 'w';
+  x[/*severe:STATIC_TYPE_ERROR*/4.0] = 'u';
+  x[3] = /*severe:STATIC_TYPE_ERROR*/42;
+  Map<num, String> y = x;
+}
+
+test2() {
+  var x = { 1: 'x', 2: 'y', 3.0: new RegExp('.') };
+  x[3] = 'z';
+  x[/*severe:STATIC_TYPE_ERROR*/'hi'] = 'w';
+  x[4.0] = 'u';
+  x[3] = /*severe:STATIC_TYPE_ERROR*/42;
+  Pattern p = null;
+  x[2] = p;
+  Map<int, String> y = /*info:ASSIGNMENT_CAST*/x;
+}
+    ''');
+  });
 }
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index e858a37..19ed5b3 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -15,8 +15,6 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:logging/logging.dart';
 import 'package:source_span/source_span.dart';
 import 'package:unittest/unittest.dart';
@@ -64,7 +62,7 @@
   // Enable task model strong mode
   var context = AnalysisEngine.instance.createAnalysisContext();
   context.analysisOptions.strongMode = true;
-  context.analysisOptions.strongModeHints = true;
+  (context.analysisOptions as AnalysisOptionsImpl).strongModeHints = true;
   context.sourceFactory =
       new SourceFactory([new DartUriResolver(new MockSdk()), uriResolver]);
 
@@ -73,13 +71,10 @@
   var initialLibrary = context.resolveCompilationUnit2(mainSource, mainSource);
 
   var collector = new _ErrorCollector();
-  var checker = new CodeChecker(
-      context.typeProvider, new StrongTypeSystemImpl(), collector,
-      hints: true);
 
   // Extract expectations from the comments in the test files, and
   // check that all errors we emit are included in the expected map.
-  var allLibraries = reachableLibraries(initialLibrary.element.library);
+  var allLibraries = _reachableLibraries(initialLibrary.element.library);
   for (var lib in allLibraries) {
     for (var unit in lib.units) {
       var errors = <AnalysisError>[];
@@ -90,9 +85,10 @@
 
       var librarySource = context.getLibrariesContaining(source).single;
       var resolved = context.resolveCompilationUnit2(source, librarySource);
-      errors.addAll(context.getErrors(source).errors.where((error) =>
-          error.errorCode.name.startsWith('STRONG_MODE_INFERRED_TYPE')));
-      checker.visitCompilationUnit(resolved);
+      errors.addAll(context.getErrors(source).errors.where((e) =>
+          e.errorCode != HintCode.UNUSED_LOCAL_VARIABLE &&
+          // TODO(jmesserly): these are usually intentional dynamic calls.
+          e.errorCode.name != 'UNDEFINED_METHOD'));
 
       _expectErrors(resolved, errors);
     }
@@ -105,11 +101,11 @@
   check();
 }
 
-SourceSpanWithContext createSpanHelper(
+SourceSpanWithContext _createSpanHelper(
     LineInfo lineInfo, int start, Source source, String content,
     {int end}) {
-  var startLoc = locationForOffset(lineInfo, source.uri, start);
-  var endLoc = locationForOffset(lineInfo, source.uri, end ?? start);
+  var startLoc = _locationForOffset(lineInfo, source.uri, start);
+  var endLoc = _locationForOffset(lineInfo, source.uri, end ?? start);
 
   var lineStart = startLoc.offset - startLoc.column;
   // Find the end of the line. This is not exposed directly on LineInfo, but
@@ -123,7 +119,7 @@
 
   if (end == null) {
     end = lineEnd;
-    endLoc = locationForOffset(lineInfo, source.uri, lineEnd);
+    endLoc = _locationForOffset(lineInfo, source.uri, lineEnd);
   }
 
   var text = content.substring(start, end);
@@ -131,19 +127,17 @@
   return new SourceSpanWithContext(startLoc, endLoc, text, lineText);
 }
 
-String errorCodeName(ErrorCode errorCode) {
+String _errorCodeName(ErrorCode errorCode) {
   var name = errorCode.name;
   final prefix = 'STRONG_MODE_';
   if (name.startsWith(prefix)) {
     return name.substring(prefix.length);
   } else {
-    // TODO(jmesserly): this is for backwards compat, but not sure it's very
-    // useful to log this.
-    return 'AnalyzerMessage';
+    return name;
   }
 }
 
-initStrongModeTests() {
+void initStrongModeTests() {
   setUp(() {
     AnalysisEngine.instance.processRequiredPlugins();
     files = new MemoryResourceProvider();
@@ -157,15 +151,14 @@
   });
 }
 
-// TODO(jmesserly): can we reuse the same mock SDK as Analyzer tests?
-SourceLocation locationForOffset(LineInfo lineInfo, Uri uri, int offset) {
+SourceLocation _locationForOffset(LineInfo lineInfo, Uri uri, int offset) {
   var loc = lineInfo.getLocation(offset);
   return new SourceLocation(offset,
       sourceUrl: uri, line: loc.lineNumber - 1, column: loc.columnNumber - 1);
 }
 
 /// Returns all libraries transitively imported or exported from [start].
-List<LibraryElement> reachableLibraries(LibraryElement start) {
+List<LibraryElement> _reachableLibraries(LibraryElement start) {
   var results = <LibraryElement>[];
   var seen = new Set();
   void find(LibraryElement lib) {
@@ -190,6 +183,26 @@
 void _expectErrors(CompilationUnit unit, List<AnalysisError> actualErrors) {
   var expectedErrors = _findExpectedErrors(unit.beginToken);
 
+  // Sort both lists: by offset, then level, then name.
+  actualErrors.sort((x, y) {
+    int delta = x.offset.compareTo(y.offset);
+    if (delta != 0) return delta;
+
+    delta = x.errorCode.errorSeverity.compareTo(y.errorCode.errorSeverity);
+    if (delta != 0) return delta;
+
+    return _errorCodeName(x.errorCode).compareTo(_errorCodeName(y.errorCode));
+  });
+  expectedErrors.sort((x, y) {
+    int delta = x.offset.compareTo(y.offset);
+    if (delta != 0) return delta;
+
+    delta = x.level.compareTo(y.level);
+    if (delta != 0) return delta;
+
+    return x.typeName.compareTo(y.typeName);
+  });
+
   // Categorize the differences, if any.
   var unreported = <_ErrorExpectation>[];
   var different = <_ErrorExpectation, AnalysisError>{};
@@ -198,7 +211,7 @@
     AnalysisError actual = expected._removeMatchingActual(actualErrors);
     if (actual != null) {
       if (_actualErrorLevel(actual) != expected.level ||
-          errorCodeName(actual.errorCode) != expected.typeName) {
+          _errorCodeName(actual.errorCode) != expected.typeName) {
         different[expected] = actual;
       }
     } else {
@@ -223,9 +236,11 @@
       if (c.type == TokenType.MULTI_LINE_COMMENT) {
         String value = c.lexeme.substring(2, c.lexeme.length - 2);
         if (value.contains(':')) {
-          var offset = c.end;
-          if (c.next?.type == TokenType.GENERIC_METHOD_TYPE_LIST) {
-            offset += 2;
+          int offset = t.offset;
+          Token previous = t.previous;
+          while (previous != null && previous.offset > c.offset) {
+            offset = previous.offset;
+            previous = previous.previous;
           }
           for (var expectCode in value.split(',')) {
             var expected = _ErrorExpectation.parse(offset, expectCode);
@@ -252,20 +267,20 @@
   String formatActualError(AnalysisError error) {
     int offset = error.offset;
     int length = error.length;
-    var span = createSpanHelper(
+    var span = _createSpanHelper(
         unit.lineInfo, offset, unit.element.source, sourceCode,
         end: offset + length);
     var levelName = _actualErrorLevel(error).name.toLowerCase();
-    return '@$offset $levelName: [${errorCodeName(error.errorCode)}]\n' +
+    return '@$offset $levelName:${_errorCodeName(error.errorCode)}\n' +
         span.message(error.message);
   }
 
   String formatExpectedError(_ErrorExpectation error) {
     int offset = error.offset;
-    var span = createSpanHelper(
+    var span = _createSpanHelper(
         unit.lineInfo, offset, unit.element.source, sourceCode);
     var levelName = error.level.toString().toLowerCase();
-    return '@$offset $levelName: [${error.typeName}]\n' + span.message('');
+    return '@$offset $levelName:${error.typeName}\n' + span.message('');
   }
 
   var message = new StringBuffer();
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index 8e6c5fc..176f7c6 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -1,3 +1,4 @@
+import 'dart:convert';
 import 'dart:io';
 
 import 'package:analyzer/dart/element/element.dart';
@@ -8,6 +9,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:crypto/crypto.dart';
 import 'package:path/path.dart';
 
 main(List<String> args) {
@@ -73,6 +75,7 @@
   final List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
   final List<String> unlinkedUnitUris = <String>[];
   final List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+  final List<String> unlinkedUnitHashes = <String>[];
 
   _Builder(this.sdkPath, this.outputDirectoryPath, this.strongMode);
 
@@ -92,20 +95,28 @@
     context.analysisOptions = new AnalysisOptionsImpl()
       ..strongMode = strongMode;
     //
+    // Prepare 'dart:' URIs to serialize.
+    //
+    Set<String> uriSet =
+        sdk.sdkLibraries.map((SdkLibrary library) => library.shortName).toSet();
+    uriSet.add('dart:html/nativewrappers.dart');
+    uriSet.add('dart:html_common/html_common_dart2js.dart');
+    //
     // Serialize each SDK library.
     //
-    for (SdkLibrary lib in sdk.sdkLibraries) {
-      Source libSource = sdk.mapDartUri(lib.shortName);
+    for (String uri in uriSet) {
+      Source libSource = sdk.mapDartUri(uri);
       _serializeLibrary(libSource);
     }
     //
     // Write the whole SDK bundle.
     //
-    SdkBundleBuilder sdkBundle = new SdkBundleBuilder(
+    PackageBundleBuilder sdkBundle = new PackageBundleBuilder(
         linkedLibraryUris: linkedLibraryUris,
         linkedLibraries: linkedLibraries,
         unlinkedUnitUris: unlinkedUnitUris,
-        unlinkedUnits: unlinkedUnits);
+        unlinkedUnits: unlinkedUnits,
+        unlinkedUnitHashes: unlinkedUnitHashes);
     String outputFilePath =
         join(outputDirectoryPath, strongMode ? 'strong.sum' : 'spec.sum');
     File file = new File(outputFilePath);
@@ -117,6 +128,15 @@
   }
 
   /**
+   * Compute a hash of the given file contents.
+   */
+  String _hash(String contents) {
+    MD5 md5 = new MD5();
+    md5.add(UTF8.encode(contents));
+    return CryptoUtils.bytesToHex(md5.close());
+  }
+
+  /**
    * Serialize the library with the given [source] and all its direct or
    * indirect imports and exports.
    */
@@ -141,5 +161,8 @@
     linkedLibraries.add(libraryResult.linked);
     unlinkedUnitUris.addAll(libraryResult.unitUris);
     unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+    for (Source source in libraryResult.unitSources) {
+      unlinkedUnitHashes.add(_hash(source.contents.data));
+    }
   }
 }
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index ba4a49e..9d5fcb6 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -62,6 +62,8 @@
   return codeGenerator._outBuffer.toString();
 });
 
+typedef String _StringToString(String s);
+
 class _CodeGenerator {
   /**
    * Buffer in which generated code is accumulated.
@@ -341,6 +343,7 @@
     out();
     out("import 'flat_buffers.dart' as fb;");
     out("import 'idl.dart' as idl;");
+    out("import 'dart:convert' as convert;");
     out();
     for (idlModel.EnumDeclaration enm in _idl.enums.values) {
       _generateEnumReader(enm);
@@ -631,6 +634,45 @@
     String mixinName = '_${name}Mixin';
     out('abstract class $mixinName implements ${idlPrefix(name)} {');
     indent(() {
+      // Write toJson().
+      out('@override');
+      out('Map<String, Object> toJson() {');
+      indent(() {
+        out('Map<String, Object> _result = <String, Object>{};');
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          String condition;
+          if (field.type.isList) {
+            condition = '${field.name}.isNotEmpty';
+          } else {
+            condition = '${field.name} != ${defaultValue(field.type, false)}';
+          }
+          _StringToString convertItem;
+          if (_idl.classes.containsKey(field.type.typeName)) {
+            convertItem = (String name) => '$name.toJson()';
+          } else if (_idl.enums.containsKey(field.type.typeName)) {
+            // TODO(paulberry): it would be better to generate a const list of
+            // strings so that we don't have to do this kludge.
+            convertItem = (String name) => "$name.toString().split('.')[1]";
+          } else if (field.type.typeName == 'double') {
+            convertItem =
+                (String name) => '$name.isFinite ? $name : $name.toString()';
+          }
+          String convertField;
+          if (convertItem == null) {
+            convertField = field.name;
+          } else if (field.type.isList) {
+            convertField = '${field.name}.map((_value) =>'
+                ' ${convertItem('_value')}).toList()';
+          } else {
+            convertField = convertItem(field.name);
+          }
+          String storeField = '_result[${quoted(field.name)}] = $convertField';
+          out('if ($condition) $storeField;');
+        }
+        out('return _result;');
+      });
+      out('}');
+      out();
       // Write toMap().
       out('@override');
       out('Map<String, Object> toMap() => {');
@@ -641,6 +683,10 @@
         }
       });
       out('};');
+      out();
+      // Write toString().
+      out('@override');
+      out('String toString() => convert.JSON.encode(toJson());');
     });
     out('}');
   }
diff --git a/pkg/analyzer/tool/summary/stats.dart b/pkg/analyzer/tool/summary/stats.dart
index da524a0..b8f5dd7 100644
--- a/pkg/analyzer/tool/summary/stats.dart
+++ b/pkg/analyzer/tool/summary/stats.dart
@@ -24,8 +24,8 @@
   String inputFilePath = args[0];
 
   // Read the input.
-  SdkBundle bundle =
-      new SdkBundle.fromBuffer(new File(inputFilePath).readAsBytesSync());
+  PackageBundle bundle =
+      new PackageBundle.fromBuffer(new File(inputFilePath).readAsBytesSync());
 
   // Compute and output stats.
   Stats stats = new Stats();
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index 1f14eda..d77151b 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -76,8 +76,6 @@
   DART_ERRORS [shape=box]
   DART_SCRIPTS -> ScanDartTask
   DART_SCRIPTS [shape=box]
-  DEFINED_ELEMENTS -> GenerateHintsTask
-  DEFINED_ELEMENTS [shape=box]
   DartErrorsTask -> DART_ERRORS
   EXPLICITLY_IMPORTED_LIBRARIES [shape=box]
   EXPORTED_LIBRARIES -> BuildDirectiveElementsTask
@@ -90,7 +88,6 @@
   EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT11
   EvaluateUnitConstantsTask -> RESOLVED_UNIT11
   GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
-  GatherUsedLocalElementsTask -> DEFINED_ELEMENTS
   GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
   GenerateHintsTask -> HINTS
   GenerateLintsTask -> LINTS
@@ -166,6 +163,7 @@
   LIBRARY_SPECIFIC_UNITS [shape=box]
   LIBRARY_UNIT_ERRORS -> dartErrorsForUnit
   LIBRARY_UNIT_ERRORS [shape=box]
+  LINE_INFO -> DartErrorsTask
   LINE_INFO -> ParseDartTask
   LINE_INFO [shape=box]
   LINTS -> LibraryUnitErrorsTask
@@ -175,6 +173,7 @@
   MODIFICATION_TIME -> ParseDartTask
   MODIFICATION_TIME [shape=box]
   PARSED_UNIT -> BuildCompilationUnitElementTask
+  PARSED_UNIT -> DartErrorsTask
   PARSED_UNIT [shape=box]
   PARSE_ERRORS -> dartErrorsForSource
   PARSE_ERRORS [shape=box]
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 75cbe52..56eaa2f 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -224,35 +224,8 @@
     formatter.formatErrors(errorInfos);
   }
 
-  /// Check various configuration options to get a desired severity for this
-  /// [error] (or `null` if it's to be suppressed).
-  ProcessedSeverity _processError(AnalysisError error) {
-    ErrorSeverity severity = computeSeverity(error, options, context);
-    bool isOverridden = false;
-
-    // First check for a filter.
-    if (severity == null) {
-      // Null severity means the error has been explicitly ignored.
-      return null;
-    } else {
-      isOverridden = true;
-    }
-
-    // If not overridden, some "natural" severities get globally filtered.
-    if (!isOverridden) {
-      // Check for global hint filtering.
-      if (severity == ErrorSeverity.INFO && options.disableHints) {
-        return null;
-      }
-
-      // Skip TODOs.
-      if (severity == ErrorType.TODO) {
-        return null;
-      }
-    }
-
-    return new ProcessedSeverity(severity, isOverridden);
-  }
+  ProcessedSeverity _processError(AnalysisError error) =>
+      processError(error, options, context);
 
   LibraryElement _resolveLibrary() {
     return _resolveLibraryTag.makeCurrentWhile(() {
@@ -303,6 +276,37 @@
     // Not found.
     return null;
   }
+
+  /// Check various configuration options to get a desired severity for this
+  /// [error] (or `null` if it's to be suppressed).
+  static ProcessedSeverity processError(AnalysisError error,
+      CommandLineOptions options, AnalysisContext context) {
+    ErrorSeverity severity = computeSeverity(error, options, context);
+    bool isOverridden = false;
+
+    // First check for a filter.
+    if (severity == null) {
+      // Null severity means the error has been explicitly ignored.
+      return null;
+    } else {
+      isOverridden = true;
+    }
+
+    // If not overridden, some "natural" severities get globally filtered.
+    if (!isOverridden) {
+      // Check for global hint filtering.
+      if (severity == ErrorSeverity.INFO && options.disableHints) {
+        return null;
+      }
+
+      // Skip TODOs.
+      if (severity == ErrorType.TODO) {
+        return null;
+      }
+    }
+
+    return new ProcessedSeverity(severity, isOverridden);
+  }
 }
 
 /// This [Logger] prints out information comments to [outSink] and error messages
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 3de4b4d..85c53ee 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -34,6 +34,7 @@
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer_cli/src/analyzer_impl.dart';
 import 'package:analyzer_cli/src/options.dart';
+import 'package:analyzer_cli/src/package_analyzer.dart';
 import 'package:analyzer_cli/src/perf_report.dart';
 import 'package:analyzer_cli/starter.dart';
 import 'package:linter/src/plugin/linter_plugin.dart';
@@ -113,7 +114,13 @@
     _setupEnv(options);
 
     // Do analysis.
-    if (_isBatch) {
+    if (options.packageMode) {
+      ErrorSeverity severity = _analyzePackage(options);
+      // In case of error propagate exit code.
+      if (severity == ErrorSeverity.ERROR) {
+        exitCode = severity.ordinal;
+      }
+    } else if (_isBatch) {
       _BatchRunner.runAsBatch(args, (List<String> args) {
         CommandLineOptions options = CommandLineOptions.parse(args);
         return _analyzeAll(options);
@@ -215,6 +222,13 @@
     return allResult;
   }
 
+  /// Perform package analysis according to the given [options].
+  ErrorSeverity _analyzePackage(CommandLineOptions options) {
+    return _analyzeAllTag.makeCurrentWhile(() {
+      return new PackageAnalyzer(options).analyze();
+    });
+  }
+
   /// Determine whether the context created during a previous call to
   /// [_analyzeAll] can be re-used in order to analyze using [options].
   bool _canContextBeReused(CommandLineOptions options) {
@@ -461,6 +475,7 @@
 
     // Create a context.
     AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    _context = context;
 
     // Choose a package resolution policy and a diet parsing policy based on
     // the command-line options.
@@ -471,34 +486,10 @@
 
     context.sourceFactory = sourceFactory;
 
-    Map<String, String> definedVariables = options.definedVariables;
-    if (!definedVariables.isEmpty) {
-      DeclaredVariables declaredVariables = context.declaredVariables;
-      definedVariables.forEach((String variableName, String value) {
-        declaredVariables.define(variableName, value);
-      });
-    }
-
-    if (options.log) {
-      AnalysisEngine.instance.logger = new StdLogger();
-    }
-
-    // Set context options.
-    AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
-    contextOptions.hint = !options.disableHints;
-    contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
-    contextOptions.enableSuperMixins = options.enableSuperMixins;
-    contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy;
-    contextOptions.generateImplicitErrors = options.showPackageWarnings;
-    contextOptions.generateSdkErrors = options.showSdkWarnings;
-    contextOptions.lint = options.lints;
-    contextOptions.strongMode = options.strongMode;
-    context.analysisOptions = contextOptions;
-    sourceFactory.dartSdk.context.analysisOptions = contextOptions;
-    _context = context;
-
-    // Process analysis options file (and notify all interested parties).
-    _processAnalysisOptions(options, context);
+    setAnalysisContextOptions(_context, options,
+        (AnalysisOptionsImpl contextOptions) {
+      contextOptions.analyzeFunctionBodiesPredicate = dietParsingPolicy;
+    });
   }
 
   /// Return discovered packagespec, or `null` if none is found.
@@ -515,22 +506,6 @@
     return null;
   }
 
-  fileSystem.File _getOptionsFile(CommandLineOptions options) {
-    fileSystem.File file;
-    String filePath = options.analysisOptionsFile;
-    if (filePath != null) {
-      file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
-      if (!file.exists) {
-        printAndFail('Options file not found: $filePath',
-            exitCode: ErrorSeverity.ERROR.ordinal);
-      }
-    } else {
-      filePath = AnalysisEngine.ANALYSIS_OPTIONS_FILE;
-      file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
-    }
-    return file;
-  }
-
   Map<String, List<fileSystem.Folder>> _getPackageMap(Packages packages) {
     if (packages == null) {
       return null;
@@ -546,34 +521,6 @@
     return folderMap;
   }
 
-  void _processAnalysisOptions(
-      CommandLineOptions options, AnalysisContext context) {
-    fileSystem.File file = _getOptionsFile(options);
-    List<OptionsProcessor> optionsProcessors =
-        AnalysisEngine.instance.optionsPlugin.optionsProcessors;
-    try {
-      AnalysisOptionsProvider analysisOptionsProvider =
-          new AnalysisOptionsProvider();
-      Map<String, YamlNode> optionMap =
-          analysisOptionsProvider.getOptionsFromFile(file);
-      optionsProcessors.forEach(
-          (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
-
-      // Fill in lint rule defaults in case lints are enabled and rules are
-      // not specified in an options file.
-      if (options.lints && !containsLintRuleEntry(optionMap)) {
-        setLints(context, linterPlugin.contributedRules);
-      }
-
-      // Ask engine to further process options.
-      if (optionMap != null) {
-        configureContextOptions(context, optionMap);
-      }
-    } on Exception catch (e) {
-      optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
-    }
-  }
-
   void _processPlugins() {
     List<Plugin> plugins = <Plugin>[];
     plugins.addAll(AnalysisEngine.instance.requiredPlugins);
@@ -611,6 +558,41 @@
     _isBatch = options.shouldBatch;
   }
 
+  static void setAnalysisContextOptions(
+      AnalysisContext context,
+      CommandLineOptions options,
+      void configureContextOptions(AnalysisOptionsImpl contextOptions)) {
+    Map<String, String> definedVariables = options.definedVariables;
+    if (!definedVariables.isEmpty) {
+      DeclaredVariables declaredVariables = context.declaredVariables;
+      definedVariables.forEach((String variableName, String value) {
+        declaredVariables.define(variableName, value);
+      });
+    }
+
+    if (options.log) {
+      AnalysisEngine.instance.logger = new StdLogger();
+    }
+
+    // Prepare context options.
+    AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
+    contextOptions.hint = !options.disableHints;
+    contextOptions.enableStrictCallChecks = options.enableStrictCallChecks;
+    contextOptions.enableSuperMixins = options.enableSuperMixins;
+    contextOptions.generateImplicitErrors = options.showPackageWarnings;
+    contextOptions.generateSdkErrors = options.showSdkWarnings;
+    contextOptions.lint = options.lints;
+    contextOptions.strongMode = options.strongMode;
+    configureContextOptions(contextOptions);
+
+    // Set context options.
+    context.analysisOptions = contextOptions;
+    context.sourceFactory.dartSdk.context.analysisOptions = contextOptions;
+
+    // Process analysis options file (and notify all interested parties).
+    _processAnalysisOptions(context, options);
+  }
+
   /// Perform a deep comparison of two string maps.
   static bool _equalMaps(Map<String, String> m1, Map<String, String> m2) {
     if (m1.length != m2.length) {
@@ -624,9 +606,53 @@
     return true;
   }
 
+  static fileSystem.File _getOptionsFile(CommandLineOptions options) {
+    fileSystem.File file;
+    String filePath = options.analysisOptionsFile;
+    if (filePath != null) {
+      file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
+      if (!file.exists) {
+        printAndFail('Options file not found: $filePath',
+            exitCode: ErrorSeverity.ERROR.ordinal);
+      }
+    } else {
+      filePath = AnalysisEngine.ANALYSIS_OPTIONS_FILE;
+      file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
+    }
+    return file;
+  }
+
   /// Convert [sourcePath] into an absolute path.
   static String _normalizeSourcePath(String sourcePath) =>
       path.normalize(new File(sourcePath).absolute.path);
+
+  static void _processAnalysisOptions(
+      AnalysisContext context, CommandLineOptions options) {
+    fileSystem.File file = _getOptionsFile(options);
+    List<OptionsProcessor> optionsProcessors =
+        AnalysisEngine.instance.optionsPlugin.optionsProcessors;
+    try {
+      AnalysisOptionsProvider analysisOptionsProvider =
+          new AnalysisOptionsProvider();
+      Map<String, YamlNode> optionMap =
+          analysisOptionsProvider.getOptionsFromFile(file);
+      optionsProcessors.forEach(
+          (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
+
+      // Fill in lint rule defaults in case lints are enabled and rules are
+      // not specified in an options file.
+      if (options.lints && !containsLintRuleEntry(optionMap)) {
+        setLints(context, linterPlugin.contributedRules);
+      }
+
+      // Ask engine to further process options.
+      if (optionMap != null) {
+        configureContextOptions(context, optionMap);
+      }
+    } on Exception catch (e) {
+      optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
+    }
+  }
 }
 
 /// Provides a framework to read command line options from stdin and feed them
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 2bc48b9..732fc63 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -74,6 +74,21 @@
   /// Whether to use machine format for error display
   final bool machineFormat;
 
+  /// Whether to use the whole package analysis mode.
+  final bool packageMode;
+
+  /// The path of the root folder of the package to analyze.
+  final String packageModePath;
+
+  /// The name of the package being analyzed.
+  final String packageName;
+
+  /// Mapping of package names to package summary file paths.
+  final Map<String, String> packageSummaryInputs;
+
+  /// The path to find the package summary.
+  final String packageSummaryOutput;
+
   /// The path to the package root
   final String packageRootPath;
 
@@ -106,7 +121,7 @@
   CommandLineOptions._fromArgs(
       ArgResults args, Map<String, String> definedVariables)
       : dartSdkPath = args['dart-sdk'],
-        this.definedVariables = definedVariables,
+        definedVariables = definedVariables,
         analysisOptionsFile = args['options'],
         disableHints = args['no-hints'],
         displayVersion = args['version'],
@@ -119,6 +134,11 @@
         lints = args['lints'],
         log = args['log'],
         machineFormat = args['machine'] || args['format'] == 'machine',
+        packageMode = args['package-mode'],
+        packageModePath = args['package-mode-path'],
+        packageName = args['package-name'],
+        packageSummaryInputs = _parsePackageSummaryInputs(args),
+        packageSummaryOutput = args['package-summary-output'],
         packageConfigPath = args['packages'],
         packageRootPath = args['package-root'],
         perfReport = args['x-perf-report'],
@@ -267,6 +287,33 @@
           allowMultiple: true,
           splitCommas: false)
       //
+      // Package analysis mode and summary.
+      //
+      ..addFlag('package-mode',
+          help: 'Enable the whole package analysis mode. '
+              'Exactly one input path must be specified, which must be a path '
+              'to the folder with a Pub package.',
+          defaultsTo: false,
+          negatable: false,
+          hide: true)
+      ..addOption('package-mode-path',
+          help: 'The path of the root folder of the package to analyze.',
+          hide: true)
+      ..addOption('package-name',
+          help: 'The name of the package to analyze, as it is used by clients.',
+          hide: true)
+      ..addOption('package-summary-input',
+          help: '--package-summary-input=packageName,/path/to/package.sum '
+              'specifies the summary file that contains information about '
+              'every library of the specified package.',
+          allowMultiple: true,
+          splitCommas: false,
+          hide: true)
+      ..addOption('package-summary-output',
+          help: 'Specifies the path to the file where the summary information '
+              'about the package should be written to.',
+          hide: true)
+      //
       // Hidden flags.
       //
       ..addFlag('enable-async',
@@ -352,6 +399,27 @@
     }
   }
 
+  /// Parse the `--package-summary-input` arguments into a Map of package
+  /// names to summary paths.
+  static Map<String, String> _parsePackageSummaryInputs(ArgResults args) {
+    Map<String, String> result = <String, String>{};
+    List<String> argList = args['package-summary-input'];
+    for (String arg in argList) {
+      int index = arg.indexOf(',');
+      if (index == -1) {
+        errorSink.writeln(
+            'The syntax is --package-summary-input=packageName,/path/to/pkg.sum');
+        errorSink.writeln('No comma found in: $arg');
+        exitHandler(15);
+        return null; // Only reachable in testing.
+      }
+      String packageName = arg.substring(0, index);
+      String summaryPath = arg.substring(index + 1);
+      result[packageName] = summaryPath;
+    }
+    return result;
+  }
+
   static _showUsage(parser) {
     errorSink
         .writeln('Usage: $_binaryName [options...] <libraries to analyze...>');
@@ -409,7 +477,8 @@
       String defaultsTo,
       void callback(value),
       bool allowMultiple: false,
-      bool splitCommas}) {
+      bool splitCommas,
+      bool hide: false}) {
     _knownFlags.add(name);
     _parser.addOption(name,
         abbr: abbr,
@@ -419,7 +488,8 @@
         defaultsTo: defaultsTo,
         callback: callback,
         allowMultiple: allowMultiple,
-        splitCommas: splitCommas);
+        splitCommas: splitCommas,
+        hide: hide);
   }
 
   /// Generates a string displaying usage information for the defined options.
diff --git a/pkg/analyzer_cli/lib/src/package_analyzer.dart b/pkg/analyzer_cli/lib/src/package_analyzer.dart
new file mode 100644
index 0000000..0bad260
--- /dev/null
+++ b/pkg/analyzer_cli/lib/src/package_analyzer.dart
@@ -0,0 +1,427 @@
+// 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_cli.src.package_analyzer;
+
+import 'dart:convert';
+import 'dart:core' hide Resource;
+import 'dart:io' as io;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/sdk_io.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/resynthesize.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:analyzer_cli/src/analyzer_impl.dart';
+import 'package:analyzer_cli/src/driver.dart';
+import 'package:analyzer_cli/src/error_formatter.dart';
+import 'package:analyzer_cli/src/options.dart';
+import 'package:crypto/crypto.dart';
+import 'package:path/path.dart' as pathos;
+
+/**
+ * If [uri] has the `package` scheme in form of `package:pkg/file.dart`,
+ * return the `pkg` name.  Otherwise return `null`.
+ */
+String getPackageName(Uri uri) {
+  if (uri.scheme != 'package') {
+    return null;
+  }
+  String path = uri.path;
+  int index = path.indexOf('/');
+  if (index == -1) {
+    return null;
+  }
+  return path.substring(0, index);
+}
+
+/**
+ * A concrete resynthesizer that serves summaries from given file paths.
+ */
+class FileBasedSummaryResynthesizer extends SummaryResynthesizer {
+  final Map<String, UnlinkedUnit> unlinkedMap = <String, UnlinkedUnit>{};
+  final Map<String, LinkedLibrary> linkedMap = <String, LinkedLibrary>{};
+
+  FileBasedSummaryResynthesizer(
+      SummaryResynthesizer parent,
+      AnalysisContext context,
+      TypeProvider typeProvider,
+      SourceFactory sourceFactory,
+      bool strongMode,
+      List<String> summaryPaths)
+      : super(parent, context, typeProvider, sourceFactory, strongMode) {
+    summaryPaths.forEach(_fillMaps);
+  }
+
+  @override
+  LinkedLibrary getLinkedSummary(String uri) {
+    return linkedMap[uri];
+  }
+
+  @override
+  UnlinkedUnit getUnlinkedSummary(String uri) {
+    return unlinkedMap[uri];
+  }
+
+  @override
+  bool hasLibrarySummary(String uri) {
+    return linkedMap.containsKey(uri);
+  }
+
+  void _fillMaps(String path) {
+    io.File file = new io.File(path);
+    List<int> buffer = file.readAsBytesSync();
+    PackageBundle bundle = new PackageBundle.fromBuffer(buffer);
+    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
+      unlinkedMap[bundle.unlinkedUnitUris[i]] = bundle.unlinkedUnits[i];
+    }
+    for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
+      linkedMap[bundle.linkedLibraryUris[i]] = bundle.linkedLibraries[i];
+    }
+  }
+}
+
+/**
+ * The [ResultProvider] that provides results from input package summaries.
+ */
+class InputPackagesResultProvider extends ResultProvider {
+  final InternalAnalysisContext context;
+  final Map<String, String> packageSummaryInputs;
+
+  FileBasedSummaryResynthesizer resynthesizer;
+  SummaryResultProvider sdkProvider;
+
+  InputPackagesResultProvider(this.context, this.packageSummaryInputs) {
+    InternalAnalysisContext sdkContext = context.sourceFactory.dartSdk.context;
+    sdkProvider = sdkContext.resultProvider;
+    // Set the type provider to prevent the context from computing it.
+    context.typeProvider = sdkContext.typeProvider;
+    // Create a chained resynthesizer.
+    resynthesizer = new FileBasedSummaryResynthesizer(
+        sdkProvider.resynthesizer,
+        context,
+        context.typeProvider,
+        context.sourceFactory,
+        context.analysisOptions.strongMode,
+        packageSummaryInputs.values.toList());
+  }
+
+  bool compute(CacheEntry entry, ResultDescriptor result) {
+    if (sdkProvider.compute(entry, result)) {
+      return true;
+    }
+    AnalysisTarget target = entry.target;
+    // Only library results are supported for now.
+    if (target is Source) {
+      Uri uri = target.uri;
+      // We know how to server results to input packages.
+      String sourcePackageName = getPackageName(uri);
+      if (!packageSummaryInputs.containsKey(sourcePackageName)) {
+        return false;
+      }
+      // Provide known results.
+      String uriString = uri.toString();
+      if (result == LIBRARY_ELEMENT1 ||
+          result == LIBRARY_ELEMENT2 ||
+          result == LIBRARY_ELEMENT3 ||
+          result == LIBRARY_ELEMENT4 ||
+          result == LIBRARY_ELEMENT5 ||
+          result == LIBRARY_ELEMENT6 ||
+          result == LIBRARY_ELEMENT7 ||
+          result == LIBRARY_ELEMENT8 ||
+          result == LIBRARY_ELEMENT ||
+          false) {
+        LibraryElement libraryElement =
+            resynthesizer.getLibraryElement(uriString);
+        entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
+        return true;
+      } else if (result == READY_LIBRARY_ELEMENT2 ||
+          result == READY_LIBRARY_ELEMENT5 ||
+          result == READY_LIBRARY_ELEMENT6) {
+        entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+        return true;
+      } else if (result == SOURCE_KIND) {
+        if (resynthesizer.linkedMap.containsKey(uriString)) {
+          entry.setValue(result, SourceKind.LIBRARY, TargetedResult.EMPTY_LIST);
+          return true;
+        }
+        if (resynthesizer.unlinkedMap.containsKey(uriString)) {
+          entry.setValue(result, SourceKind.PART, TargetedResult.EMPTY_LIST);
+          return true;
+        }
+        return false;
+      }
+    }
+    return false;
+  }
+}
+
+/**
+ * The [UriResolver] that knows about sources that are parts of packages which
+ * are served from their summaries.
+ */
+class InSummaryPackageUriResolver extends UriResolver {
+  final Map<String, String> packageSummaryInputs;
+
+  InSummaryPackageUriResolver(this.packageSummaryInputs);
+
+  @override
+  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
+    actualUri ??= uri;
+    String packageName = getPackageName(actualUri);
+    if (packageSummaryInputs.containsKey(packageName)) {
+      return new InSummarySource(actualUri);
+    }
+    return null;
+  }
+}
+
+/**
+ * A placeholder of a source that is part of a package whose analysis results
+ * are served from its summary.  This source uses its URI as [fullName] and has
+ * empty contents.
+ */
+class InSummarySource extends Source {
+  final Uri uri;
+
+  InSummarySource(this.uri);
+
+  @override
+  TimestampedData<String> get contents => new TimestampedData<String>(0, '');
+
+  @override
+  String get encoding => uri.toString();
+
+  @override
+  String get fullName => encoding;
+
+  @override
+  bool get isInSystemLibrary => false;
+
+  @override
+  int get modificationStamp => 0;
+
+  @override
+  String get shortName => pathos.basename(fullName);
+
+  @override
+  UriKind get uriKind => UriKind.PACKAGE_URI;
+
+  @override
+  bool exists() => true;
+
+  @override
+  Uri resolveRelativeUri(Uri relativeUri) {
+    Uri baseUri = uri;
+    return baseUri.resolveUri(relativeUri);
+  }
+
+  @override
+  String toString() => uri.toString();
+}
+
+/**
+ * The hermetic whole package analyzer.
+ */
+class PackageAnalyzer {
+  final CommandLineOptions options;
+
+  String packagePath;
+  String packageLibPath;
+
+  final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
+  InternalAnalysisContext context;
+  final List<Source> explicitSources = <Source>[];
+
+  final List<String> linkedLibraryUris = <String>[];
+  final List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
+  final List<String> unlinkedUnitUris = <String>[];
+  final List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+  final List<String> unlinkedUnitHashes = <String>[];
+
+  PackageAnalyzer(this.options);
+
+  /**
+   * Perform package analysis according to the given [options].
+   */
+  ErrorSeverity analyze() {
+    packagePath = options.packageModePath;
+    packageLibPath = resourceProvider.pathContext.join(packagePath, 'lib');
+    if (packageLibPath == null) {
+      errorSink.writeln('--package-mode-path must be set to the root '
+          'folder of the package to analyze.');
+      io.exitCode = ErrorSeverity.ERROR.ordinal;
+      return ErrorSeverity.ERROR;
+    }
+
+    // Write the progress message.
+    if (!options.machineFormat) {
+      outSink.writeln("Analyzing sources ${options.sourceFiles}...");
+    }
+
+    // Prepare the analysis context.
+    _createContext();
+
+    // Add sources.
+    ChangeSet changeSet = new ChangeSet();
+    for (String path in options.sourceFiles) {
+      if (AnalysisEngine.isDartFileName(path)) {
+        path = resourceProvider.pathContext.absolute(path);
+        File file = resourceProvider.getFile(path);
+        if (!file.exists) {
+          errorSink.writeln('File not found: $path');
+          io.exitCode = ErrorSeverity.ERROR.ordinal;
+          return ErrorSeverity.ERROR;
+        }
+        Source source = _createSourceInContext(file);
+        explicitSources.add(source);
+        changeSet.addedSource(source);
+      }
+    }
+    context.applyChanges(changeSet);
+
+    // Perform full analysis.
+    while (true) {
+      AnalysisResult analysisResult = context.performAnalysisTask();
+      if (!analysisResult.hasMoreWork) {
+        break;
+      }
+    }
+
+    // Write summary for Dart libraries.
+    if (options.packageSummaryOutput != null) {
+      for (Source source in context.librarySources) {
+        if (pathos.isWithin(packageLibPath, source.fullName)) {
+          LibraryElement libraryElement = context.getLibraryElement(source);
+          if (libraryElement != null) {
+            _serializeSingleLibrary(libraryElement);
+          }
+        }
+      }
+      // Write the whole package bundle.
+      PackageBundleBuilder sdkBundle = new PackageBundleBuilder(
+          linkedLibraryUris: linkedLibraryUris,
+          linkedLibraries: linkedLibraries,
+          unlinkedUnitUris: unlinkedUnitUris,
+          unlinkedUnits: unlinkedUnits,
+          unlinkedUnitHashes: unlinkedUnitHashes);
+      io.File file = new io.File(options.packageSummaryOutput);
+      file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
+    }
+
+    // Process errors.
+    _printErrors();
+    return _computeMaxSeverity();
+  }
+
+  ErrorSeverity _computeMaxSeverity() {
+    ErrorSeverity maxSeverity = ErrorSeverity.NONE;
+    for (Source source in explicitSources) {
+      AnalysisErrorInfo errorInfo = context.getErrors(source);
+      for (AnalysisError error in errorInfo.errors) {
+        ProcessedSeverity processedSeverity =
+            AnalyzerImpl.processError(error, options, context);
+        if (processedSeverity != null) {
+          maxSeverity = maxSeverity.max(processedSeverity.severity);
+        }
+      }
+    }
+    return maxSeverity;
+  }
+
+  void _createContext() {
+    DirectoryBasedDartSdk sdk = DirectoryBasedDartSdk.defaultSdk;
+    sdk.useSummary = true;
+
+    // Create the context.
+    context = AnalysisEngine.instance.createAnalysisContext();
+    context.typeProvider = sdk.context.typeProvider;
+    context.sourceFactory = new SourceFactory(<UriResolver>[
+      new DartUriResolver(sdk),
+      new InSummaryPackageUriResolver(options.packageSummaryInputs),
+      new PackageMapUriResolver(resourceProvider, <String, List<Folder>>{
+        options.packageName: <Folder>[
+          resourceProvider.getFolder(packageLibPath)
+        ],
+      }),
+      new FileUriResolver()
+    ]);
+
+    // Set context options.
+    Driver.setAnalysisContextOptions(
+        context, options, (AnalysisOptionsImpl contextOptions) {});
+
+    // Set the result provider.
+    context.resultProvider =
+        new InputPackagesResultProvider(context, options.packageSummaryInputs);
+  }
+
+  /**
+   * Create and return a source representing the given [file].
+   */
+  Source _createSourceInContext(File file) {
+    Source source = file.createSource();
+    if (context == null) {
+      return source;
+    }
+    Uri uri = context.sourceFactory.restoreUri(source);
+    return file.createSource(uri);
+  }
+
+  /**
+   * Compute a hash of the given file contents.
+   */
+  String _hash(String contents) {
+    MD5 md5 = new MD5();
+    md5.add(UTF8.encode(contents));
+    return CryptoUtils.bytesToHex(md5.close());
+  }
+
+  /**
+   * Print errors for all explicit sources.
+   */
+  void _printErrors() {
+    StringSink sink = options.machineFormat ? errorSink : outSink;
+    ErrorFormatter formatter = new ErrorFormatter(
+        sink,
+        options,
+        (AnalysisError error) =>
+            AnalyzerImpl.processError(error, options, context));
+    for (Source source in explicitSources) {
+      AnalysisErrorInfo errorInfo = context.getErrors(source);
+      formatter.formatErrors([errorInfo]);
+    }
+  }
+
+  /**
+   * Serialize the library with the given [element].
+   */
+  void _serializeSingleLibrary(LibraryElement element) {
+    String uri = element.source.uri.toString();
+    LibrarySerializationResult libraryResult =
+        serializeLibrary(element, context.typeProvider, options.strongMode);
+    linkedLibraryUris.add(uri);
+    linkedLibraries.add(libraryResult.linked);
+    unlinkedUnitUris.addAll(libraryResult.unitUris);
+    unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+    for (Source source in libraryResult.unitSources) {
+      unlinkedUnitHashes.add(_hash(source.contents.data));
+    }
+  }
+}
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index 0fe04f6..6e59161 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -14,5 +14,6 @@
   plugin: ^0.1.0
   yaml: ^2.1.2
 dev_dependencies:
+  test_reflective_loader: '>=0.0.3 <0.1.0'
   typed_mock: '>=0.0.4 <1.0.0'
   unittest: '>=0.9.0 <0.12.0'
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 900747b..1c6aa76 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -4,8 +4,12 @@
 
 library analyzer_cli.test.options;
 
+import 'dart:io';
+
+import 'package:analyzer_cli/src/driver.dart';
 import 'package:analyzer_cli/src/options.dart';
 import 'package:args/args.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:unittest/unittest.dart';
 
 main() {
@@ -26,7 +30,9 @@
         expect(options.ignoreUnrecognizedFlags, isFalse);
         expect(options.log, isFalse);
         expect(options.machineFormat, isFalse);
+        expect(options.packageMode, isFalse);
         expect(options.packageRootPath, isNull);
+        expect(options.packageSummaryInputs, isEmpty);
         expect(options.shouldBatch, isFalse);
         expect(options.showPackageWarnings, isFalse);
         expect(options.showSdkWarnings, isFalse);
@@ -165,8 +171,8 @@
       });
 
       test('strong mode', () {
-        CommandLineOptions options = CommandLineOptions
-            .parse(['--strong', 'foo.dart']);
+        CommandLineOptions options =
+            CommandLineOptions.parse(['--strong', 'foo.dart']);
         expect(options.strongMode, isTrue);
       });
 
@@ -187,4 +193,85 @@
       });
     });
   });
+  defineReflectiveTests(CommandLineOptionsTest);
+}
+
+@reflectiveTest
+class AbstractStatusTest {
+  int lastExitHandlerCode;
+  StringBuffer outStringBuffer = new StringBuffer();
+  StringBuffer errorStringBuffer = new StringBuffer();
+
+  StringSink savedOutSink, savedErrorSink;
+  int savedExitCode;
+  ExitHandler savedExitHandler;
+
+  setUp() {
+    savedOutSink = outSink;
+    savedErrorSink = errorSink;
+    savedExitHandler = exitHandler;
+    savedExitCode = exitCode;
+    exitHandler = (int code) {
+      lastExitHandlerCode = code;
+    };
+    outSink = outStringBuffer;
+    errorSink = errorStringBuffer;
+  }
+
+  tearDown() {
+    outSink = savedOutSink;
+    errorSink = savedErrorSink;
+    exitCode = savedExitCode;
+    exitHandler = savedExitHandler;
+  }
+}
+
+@reflectiveTest
+class CommandLineOptionsTest extends AbstractStatusTest {
+  CommandLineOptions options;
+
+  test_packageMode() {
+    _parse(['--package-mode', '/path/to/pkg']);
+    expect(options.packageMode, isTrue);
+    print(options.packageSummaryInputs);
+  }
+
+  test_packageSummaryInput() {
+    _parse([
+      '--package-mode',
+      '--package-summary-input=aaa,/path/to/aaa.sum',
+      '--package-summary-input=long.package.bbb,/path/to/bbb.sum',
+      '/path/to/pkg'
+    ]);
+    expect(options.packageMode, isTrue);
+    Map<String, String> map = options.packageSummaryInputs;
+    expect(map, hasLength(2));
+    expect(map, containsPair('aaa', '/path/to/aaa.sum'));
+    expect(map, containsPair('long.package.bbb', '/path/to/bbb.sum'));
+  }
+
+  test_packageSummaryInput_noComma() {
+    _parse([
+      '--package-mode',
+      '--package-summary-input=noCommaInMapping',
+      '/path/to/pkg'
+    ]);
+    expect(lastExitHandlerCode, 15);
+    expect(errorStringBuffer.toString(), contains('--package-summary-input'));
+    expect(errorStringBuffer.toString(), contains('noCommaInMapping'));
+  }
+
+  test_packageSummaryOutput() {
+    _parse([
+      '--package-mode',
+      '--package-summary-output=/path/to/output.sum',
+      '/path/to/pkg'
+    ]);
+    expect(options.packageMode, isTrue);
+    expect(options.packageSummaryOutput, '/path/to/output.sum');
+  }
+
+  void _parse(List<String> args) {
+    options = CommandLineOptions.parse(args);
+  }
 }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index e6b4f4c..3df2ba4 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1797,9 +1797,8 @@
 
         bool sameToken(Token token, Token sought) {
           if (token == sought) return true;
-          if (token.stringValue == '>>' ||
-              token.stringValue == '>>>') {
-            // `>>` and `>>>` are converted to `>` in the parser when needed.
+          if (token.stringValue == '>>') {
+            // `>>` is converted to `>` in the parser when needed.
             return sought.stringValue == '>' &&
                 token.charOffset <= sought.charOffset &&
                 sought.charOffset < token.charEnd;
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
index 28ea3d5..d6096af 100644
--- a/pkg/compiler/lib/src/cps_ir/inline.dart
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -18,6 +18,7 @@
     FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
+import 'package:js_ast/js_ast.dart' as js;
 
 /// Inlining stack entries.
 ///
@@ -259,8 +260,32 @@
       --size;
     }
   }
+
+  processForeignCode(ForeignCode node) {
+    // Count the number of nodes in the JS fragment, and discount the size
+    // originally added by LetPrim.
+    JsSizeVisitor visitor = new JsSizeVisitor();
+    node.codeTemplate.ast.accept(visitor);
+    size += visitor.size - 1;
+  }
 }
 
+class JsSizeVisitor extends js.BaseVisitor {
+  int size = 0;
+
+  visitNode(js.Node node) {
+    ++size;
+    return super.visitNode(node);
+  }
+
+  visitInterpolatedExpression(js.InterpolatedExpression node) {
+    // Suppress call to visitNode.  Placeholders should not be counted, because
+    // the argument has already been counted, and will in most cases be inserted
+    // directly in the placeholder.
+  }
+}
+
+
 class InliningVisitor extends TrampolineRecursiveVisitor {
   final Inliner _inliner;
 
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index 337ff32..2b248fe 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -25,7 +25,7 @@
 export 'inline.dart' show Inliner;
 export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
 export 'loop_invariant_branch.dart' show LoopInvariantBranchMotion;
-export 'duplicate_branch.dart' show PathBasedOptimizer;
+export 'path_based_optimizer.dart' show PathBasedOptimizer;
 export 'use_field_initializers.dart' show UseFieldInitializers;
 export 'parent_visitor.dart' show ParentVisitor;
 
diff --git a/pkg/compiler/lib/src/cps_ir/duplicate_branch.dart b/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
similarity index 98%
rename from pkg/compiler/lib/src/cps_ir/duplicate_branch.dart
rename to pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
index 26244a4..6f9fac5 100644
--- a/pkg/compiler/lib/src/cps_ir/duplicate_branch.dart
+++ b/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2016, 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 dart2js.cps_ir.duplicate_branch; // FIXME: Rename file.
+library dart2js.cps_ir.path_based_optimizer;
 
 import 'cps_ir_nodes.dart';
 import 'optimizers.dart';
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index a9a99fa..00cbfb1 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -44,7 +44,10 @@
   final ConstantSystem constantSystem;
   final types.DartTypes dartTypes;
   final AbstractConstantValue anything;
+  final AbstractConstantValue nothing = new AbstractConstantValue.nothing();
   final AbstractConstantValue nullValue;
+  final AbstractConstantValue trueValue;
+  final AbstractConstantValue falseValue;
 
   ConstantPropagationLattice(CpsFunctionCompiler functionCompiler)
     : typeSystem = functionCompiler.typeSystem,
@@ -53,9 +56,11 @@
       anything = new AbstractConstantValue.nonConstant(
           functionCompiler.typeSystem.dynamicType),
       nullValue = new AbstractConstantValue.constantValue(
-          new NullConstantValue(), new TypeMask.empty());
-
-  final AbstractConstantValue nothing = new AbstractConstantValue.nothing();
+          new NullConstantValue(), new TypeMask.empty()),
+      trueValue = new AbstractConstantValue.constantValue(
+          new TrueConstantValue(), functionCompiler.typeSystem.boolType),
+      falseValue = new AbstractConstantValue.constantValue(
+          new FalseConstantValue(), functionCompiler.typeSystem.boolType);
 
   AbstractConstantValue constant(ConstantValue value, [TypeMask type]) {
     if (type == null) type = typeSystem.getTypeOf(value);
@@ -559,21 +564,41 @@
 
   AbstractConstantValue lessSpecial(AbstractConstantValue left,
                                     AbstractConstantValue right) {
+    if (isDefinitelyUint(left) && right.isZeroOrNegativeConstant) {
+      return falseValue; // "uint < 0" is false.
+    } else if (left.isNegativeConstant && isDefinitelyUint(right)) {
+      return trueValue; // "-1 < uint" is true.
+    }
     return foldBinary(constantSystem.less, left, right);
   }
 
   AbstractConstantValue lessEqualSpecial(AbstractConstantValue left,
                                          AbstractConstantValue right) {
+    if (isDefinitelyUint(left) && right.isNegativeConstant) {
+      return falseValue; // "uint <= -1" is false.
+    } else if (left.isZeroOrNegativeConstant && isDefinitelyUint(right)) {
+      return trueValue; // "0 <= uint" is true.
+    }
     return foldBinary(constantSystem.lessEqual, left, right);
   }
 
   AbstractConstantValue greaterSpecial(AbstractConstantValue left,
                                        AbstractConstantValue right) {
+    if (left.isZeroOrNegativeConstant && isDefinitelyUint(right)) {
+      return falseValue; // "0 > uint" is false
+    } else if (isDefinitelyUint(left) && right.isNegativeConstant) {
+      return trueValue; // "uint > -1" is true
+    }
     return foldBinary(constantSystem.greater, left, right);
   }
 
   AbstractConstantValue greaterEqualSpecial(AbstractConstantValue left,
                                             AbstractConstantValue right) {
+    if (left.isNegativeConstant && isDefinitelyUint(right)) {
+      return falseValue; // "-1 >= uint" is false
+    } else if (isDefinitelyUint(left) && right.isZeroOrNegativeConstant) {
+      return trueValue; // "uint >= 0" is true
+    }
     return foldBinary(constantSystem.greaterEqual, left, right);
   }
 
@@ -1245,6 +1270,22 @@
       return cps;
     }
 
+    Selector renameToOptimizedSelector(String name) {
+      return new Selector.call(
+          new Name(name, backend.helpers.interceptorsLibrary),
+          node.selector.callStructure);
+    }
+
+    /// Replaces the call with a call to [name] with the same inputs.
+    InvokeMethod makeRenamedInvoke(String name) {
+      return new InvokeMethod(node.receiver.definition,
+          renameToOptimizedSelector(name),
+          node.mask,
+          node.arguments.map((ref) => ref.definition).toList(),
+          sourceInformation: node.sourceInformation,
+          callingConvention: node.callingConvention);
+    }
+
     TypeMask successType =
         typeSystem.receiverTypeFor(node.selector, node.dartReceiver.type);
 
@@ -1301,10 +1342,20 @@
           // Try to insert a shift-right operator. JavaScript's right shift is
           // consistent with Dart's only for left operands in the unsigned
           // 32-bit range.
-          if (opname == '>>' &&
-              lattice.isDefinitelyUint32(left, allowNull: true) &&
-              lattice.isDefinitelyIntInRange(right, min: 0, max: 31)) {
-            return makeBinary(BuiltinOperator.NumShr, guard: checkIsNumber);
+          if (opname == '>>') {
+            if (lattice.isDefinitelyUint32(left, allowNull: true) &&
+                lattice.isDefinitelyIntInRange(right, min: 0, max: 31)) {
+              return makeBinary(BuiltinOperator.NumShr, guard: checkIsNumber);
+            } else if (lattice.isDefinitelyUint(left) &&
+                       lattice.isDefinitelyUint(right)) {
+              return makeRenamedInvoke('_shrBothPositive');
+            } else if (lattice.isDefinitelyUint(left) &&
+                       lattice.isDefinitelyNum(right)) {
+              return makeRenamedInvoke('_shrReceiverPositive');
+            } else if (lattice.isDefinitelyNum(left) &&
+                       lattice.isDefinitelyUint(right)) {
+              return makeRenamedInvoke('_shrOtherPositive');
+            }
           }
           // Try to use remainder for '%'. Both operands must be non-negative
           // and the divisor must be non-zero.
@@ -3299,6 +3350,17 @@
   bool get isNullConstant => kind == CONSTANT && constant.isNull;
   bool get isTrueConstant => kind == CONSTANT && constant.isTrue;
   bool get isFalseConstant => kind == CONSTANT && constant.isFalse;
+  bool get isZeroConstant => kind == CONSTANT && constant.isZero;
+  bool get isZeroOrNegativeConstant {
+    if (kind != CONSTANT || !constant.isNum) return false;
+    PrimitiveConstantValue value = constant;
+    return value.primitiveValue <= 0;
+  }
+  bool get isNegativeConstant {
+    if (kind != CONSTANT || !constant.isNum) return false;
+    PrimitiveConstantValue value = constant;
+    return value.primitiveValue < 0;
+  }
 
   bool get isNullable => kind != NOTHING && type.isNullable;
   bool get isDefinitelyNotNull => kind == NOTHING || !type.isNullable;
diff --git a/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart b/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
index 2aa258a..13d4c95 100644
--- a/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
@@ -17,18 +17,107 @@
     "Const constructor or factory can't have a body.",
     howToFix: "Remove the 'const' keyword or the body.",
     examples: const [
-      r'''
+      r"""
          class C {
            const C() {}
          }
 
-         main() => new C();''',
-      r'''
+         main() => new C();""",
+      r"""
          class C {
            const factory C() {}
          }
 
-         main() => new C();''',
+         main() => new C();""",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.EXTRANEOUS_MODIFIER: const MessageTemplate(
+    MessageKind.EXTRANEOUS_MODIFIER,
+    "Can't have modifier '#{modifier}' here.",
+    howToFix: "Try removing '#{modifier}'.",
+    examples: const [
+      "var String foo; main(){}",
+      "var set foo; main(){}",
+      "var final foo; main(){}",
+      "var var foo; main(){}",
+      "var const foo; main(){}",
+      "var abstract foo; main(){}",
+      "var static foo; main(){}",
+      "var external foo; main(){}",
+      "get var foo; main(){}",
+      "set var foo; main(){}",
+      "final var foo; main(){}",
+      "var var foo; main(){}",
+      "const var foo; main(){}",
+      "abstract var foo; main(){}",
+      "static var foo; main(){}",
+      "external var foo; main(){}",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.EXTRANEOUS_MODIFIER_REPLACE: const MessageTemplate(
+    MessageKind.EXTRANEOUS_MODIFIER_REPLACE,
+    "Can't have modifier '#{modifier}' here.",
+    howToFix: "Try replacing modifier '#{modifier}' with 'var', 'final', or a type.",
+    examples: const [
+      "set foo; main(){}",
+      "abstract foo; main(){}",
+      "static foo; main(){}",
+      "external foo; main(){}",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE: const MessageTemplate(
+    MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE,
+    "Constructors can't have a return type",
+    howToFix: "Try removing the return type.",
+    examples: const [
+      "class A { int A() {} } main() { new A(); }",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.MISSING_EXPRESSION_IN_THROW: const MessageTemplate(
+    MessageKind.MISSING_EXPRESSION_IN_THROW,
+    "Missing expression after 'throw'.",
+    howToFix: "Did you mean 'rethrow'?",
+    examples: const [
+      "main() { throw; }",
+      "main() { try { throw 0; } catch(e) { throw; } }",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.RETHROW_OUTSIDE_CATCH: const MessageTemplate(
+    MessageKind.RETHROW_OUTSIDE_CATCH,
+    "Rethrow must be inside of catch clause",
+    howToFix: "Try moving the expression into a catch clause, or using a 'throw' expression.",
+    examples: const [
+      "main() { rethrow; }",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.RETURN_IN_GENERATIVE_CONSTRUCTOR: const MessageTemplate(
+    MessageKind.RETURN_IN_GENERATIVE_CONSTRUCTOR,
+    "Constructors can't return values.",
+    howToFix: "Try removing the return statement or using a factory constructor.",
+    examples: const [
+      r"""
+        class C {
+          C() {
+            return 1;
+          }
+        }
+
+        main() => new C();""",
+    ]
+  ),  // Generated. Don't edit.
+  MessageKind.RETURN_IN_GENERATOR: const MessageTemplate(
+    MessageKind.RETURN_IN_GENERATOR,
+    "Can't return a value from a generator function (using the '#{modifier}' modifier).",
+    howToFix: "Try removing the value, replacing 'return' with 'yield' or changing the method body modifier",
+    examples: const [
+      r"""
+        foo() async* { return 0; }
+        main() => foo();
+        """,
+      r"""
+        foo() sync* { return 0; }
+        main() => foo();
+        """,
     ]
   ),  // Generated. Don't edit.
 };
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 2679c75..84e9cc2 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -136,7 +136,7 @@
   CANNOT_RESOLVE_IN_INITIALIZER,
   CANNOT_RESOLVE_SETTER,
   CANNOT_RESOLVE_TYPE,
-  CANNOT_RETURN_FROM_CONSTRUCTOR,
+  RETURN_IN_GENERATIVE_CONSTRUCTOR,
   CLASS_NAME_EXPECTED,
   COMPILER_CRASHED,
   COMPLEX_RETURNING_NSM,
@@ -428,7 +428,7 @@
   THIS_IS_THE_METHOD,
   THIS_IS_THE_PART_OF_TAG,
   THIS_PROPERTY,
-  THROW_WITHOUT_EXPRESSION,
+  RETHROW_OUTSIDE_CATCH,
   TOP_LEVEL_VARIABLE_DECLARED_STATIC,
   TYPE_ARGUMENT_COUNT_MISMATCH,
   TYPE_VARIABLE_IN_CONSTANT,
@@ -453,7 +453,7 @@
   UNSUPPORTED_EQ_EQ_EQ,
   UNSUPPORTED_LITERAL_SYMBOL,
   UNSUPPORTED_PREFIX_PLUS,
-  UNSUPPORTED_THROW_WITHOUT_EXP,
+  MISSING_EXPRESSION_IN_THROW,
   UNTERMINATED_COMMENT,
   UNTERMINATED_STRING,
   UNTERMINATED_TOKEN,
@@ -476,7 +476,7 @@
 // TODO(johnnniwinther): For Infos, consider adding a reference to the
 // error/warning/hint that they belong to.
 class MessageTemplate {
-  final dynamic/*MessageKind | SharedMessageKind*/ kind;
+  final MessageKind kind;
 
   /// Should describe what is wrong and why.
   final String template;
@@ -1149,11 +1149,6 @@
         const MessageTemplate(MessageKind.OPTIONAL_PARAMETER_IN_CATCH,
           "Cannot use optional parameters in catch."),
 
-      MessageKind.THROW_WITHOUT_EXPRESSION:
-        const MessageTemplate(MessageKind.THROW_WITHOUT_EXPRESSION,
-          "Cannot use re-throw outside of catch block "
-          "(expression expected after 'throw')."),
-
       MessageKind.UNBOUND_LABEL:
         const MessageTemplate(MessageKind.UNBOUND_LABEL,
           "Cannot resolve label '#{labelName}'."),
@@ -1847,23 +1842,6 @@
         const MessageTemplate(MessageKind.OPERATOR_NAMED_PARAMETERS,
           "Operator '#{operatorName}' cannot have named parameters."),
 
-      MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE:
-        const MessageTemplate(MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE,
-          "Cannot have return type for constructor."),
-
-      MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR:
-        const MessageTemplate(MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR,
-          "Constructors can't return values.",
-          howToFix: "Remove the return statement or use a factory constructor.",
-          examples: const ["""
-class C {
-  C() {
-    return 1;
-  }
-}
-
-main() => new C();"""]),
-
       MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER:
         const MessageTemplate(MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER,
           "Cannot have final modifier on method."),
@@ -2414,11 +2392,6 @@
               "main() => +2;  // No longer a valid way to write '2'"
           ]),
 
-      MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP:
-        const MessageTemplate(MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP,
-          "No expression after 'throw'. "
-          "Did you mean 'rethrow'?"),
-
       MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX:
         const MessageTemplate(MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX,
           "'typedef' not allowed here. ",
@@ -2594,42 +2567,6 @@
           // Don't know how to fix since the underlying error is unknown.
           howToFix: DONT_KNOW_HOW_TO_FIX),
 
-      MessageKind.EXTRANEOUS_MODIFIER:
-        const MessageTemplate(MessageKind.EXTRANEOUS_MODIFIER,
-          "Can't have modifier '#{modifier}' here.",
-          howToFix: "Try removing '#{modifier}'.",
-          examples: const [
-              "var String foo; main(){}",
-              // "var get foo; main(){}",
-              "var set foo; main(){}",
-              "var final foo; main(){}",
-              "var var foo; main(){}",
-              "var const foo; main(){}",
-              "var abstract foo; main(){}",
-              "var static foo; main(){}",
-              "var external foo; main(){}",
-              "get var foo; main(){}",
-              "set var foo; main(){}",
-              "final var foo; main(){}",
-              "var var foo; main(){}",
-              "const var foo; main(){}",
-              "abstract var foo; main(){}",
-              "static var foo; main(){}",
-              "external var foo; main(){}"]),
-
-      MessageKind.EXTRANEOUS_MODIFIER_REPLACE:
-        const MessageTemplate(MessageKind.EXTRANEOUS_MODIFIER_REPLACE,
-          "Can't have modifier '#{modifier}' here.",
-          howToFix:
-            "Try replacing modifier '#{modifier}' with 'var', 'final', "
-            "or a type.",
-          examples: const [
-              // "get foo; main(){}",
-              "set foo; main(){}",
-              "abstract foo; main(){}",
-              "static foo; main(){}",
-              "external foo; main(){}"]),
-
       MessageKind.ABSTRACT_CLASS_INSTANTIATION:
         const MessageTemplate(MessageKind.ABSTRACT_CLASS_INSTANTIATION,
           "Can't instantiate abstract class.",
@@ -3354,23 +3291,6 @@
  var yield;
 }"""]),
 
-      MessageKind.RETURN_IN_GENERATOR:
-        const MessageTemplate(MessageKind.RETURN_IN_GENERATOR,
-          "'return' with a value is not allowed in a method body using the "
-          "'#{modifier}' modifier.",
-          howToFix: "Try removing the value, replacing 'return' with 'yield' "
-                    "or changing the method body modifier.",
-          examples: const [
-"""
-foo() async* { return 0; }
-main() => foo();
-""",
-
-"""
-foo() sync* { return 0; }
-main() => foo();
-"""]),
-
       MessageKind.NATIVE_NOT_SUPPORTED:
         const MessageTemplate(MessageKind.NATIVE_NOT_SUPPORTED,
           "'native' modifier is not supported.",
@@ -3706,7 +3626,7 @@
     assert(() { computeMessage(); return true; });
   }
 
-  dynamic/*MessageKind | SharedMessageKind*/ get kind => template.kind;
+  MessageKind get kind => template.kind;
 
   String computeMessage() {
     if (message == null) {
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index 3a3e91b..b5f1db2 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -450,7 +450,7 @@
     pushNode(new Rethrow(throwToken, endToken));
     if (identical(throwToken.stringValue, 'throw')) {
       reporter.reportErrorMessage(
-          throwToken, MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP);
+          throwToken, MessageKind.MISSING_EXPRESSION_IN_THROW);
     }
   }
 
diff --git a/pkg/compiler/lib/src/parser/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
index f2e0577..42e432b 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -780,10 +780,6 @@
         token = new SymbolToken(GT_INFO, token.charOffset);
         token.next = new SymbolToken(GT_INFO, token.charOffset + 1);
         token.next.next = next;
-      } else if (identical(token.stringValue, '>>>')) {
-        token = new SymbolToken(GT_INFO, token.charOffset);
-        token.next = new SymbolToken(GT_GT_INFO, token.charOffset + 1);
-        token.next.next = next;
       }
       endStuff(count, begin, token);
       return expect('>', token);
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index da82058..fb5a6f8 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -665,8 +665,7 @@
       if (identical(string, '!') ||
           identical(string, '&&') || identical(string, '||') ||
           identical(string, 'is') || identical(string, 'as') ||
-          identical(string, '?') || identical(string, '??') ||
-          identical(string, '>>>')) {
+          identical(string, '?') || identical(string, '??')) {
         return null;
       }
       String op = source;
@@ -3658,9 +3657,9 @@
   }
 
   ResolutionResult visitRethrow(Rethrow node) {
-    if (!inCatchBlock) {
+    if (!inCatchBlock && node.throwToken.stringValue == 'rethrow') {
       reporter.reportErrorMessage(
-          node, MessageKind.THROW_WITHOUT_EXPRESSION);
+          node, MessageKind.RETHROW_OUTSIDE_CATCH);
     }
     return const NoneResult();
   }
@@ -3674,7 +3673,7 @@
         // Specification 13.12.)
         reporter.reportErrorMessage(
             expression,
-            MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR);
+            MessageKind.RETURN_IN_GENERATIVE_CONSTRUCTOR);
       } else if (!node.isArrowBody && currentAsyncMarker.isYielding) {
         reporter.reportErrorMessage(
             node,
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 07cf4e6..c31ee4a 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -16,6 +16,7 @@
     show Compiler;
 import '../constants/constructors.dart';
 import '../constants/expressions.dart';
+import '../core_types.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../elements/modelx.dart' show
@@ -853,7 +854,7 @@
   bool get hasLocalScopeMembers => _unsupported('hasLocalScopeMembers');
 
   @override
-  bool implementsFunction(Compiler compiler) {
+  bool implementsFunction(CoreClasses coreClasses) {
     return _unsupported('implementsFunction');
   }
 
@@ -1572,4 +1573,4 @@
   Element lookupLocalMember(String memberName) {
     return _unsupported('lookupLocalMember');
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/dart_messages/bin/publish.dart b/pkg/dart_messages/bin/publish.dart
index 4b497b8..d6e3f87 100644
--- a/pkg/dart_messages/bin/publish.dart
+++ b/pkg/dart_messages/bin/publish.dart
@@ -112,17 +112,25 @@
     }
     if (message.examples != null) {
       out.writeln(",\n    examples: const [");
+
+      String escapeExampleContent(String content) {
+        if (content.contains("\n") || content.contains('"')) {
+          return 'r"""\n$content"""';
+        } else if (content.contains("\\")) {
+          return 'r"$content"';
+        }
+        return '"$content"';
+      }
       for (var example in message.examples) {
         if (example is String) {
-          out.writeln("      r'''");
-          out.write(example);
-          out.write("'''");
+          out.write("      ");
+          out.write(escapeExampleContent(example));
         } else if (example is Map) {
           out.writeln("      const {");
           example.forEach((String fileName, String content) {
-            out.writeln("      '$fileName': r'''");
-            out.write(content);
-            out.writeln("''',");
+            out.writeln("      '$fileName': ");
+            out.write(escapeExampleContent(content));
+            out.writeln(",");
           });
           out.write("      }");
         }
@@ -147,9 +155,12 @@
     }
   }
   int seenHoles = 0;
-  return template.replaceAllMapped(new RegExp(r"#\w+"), (Match match) {
+  return template.replaceAllMapped(new RegExp(r"#\w+|#{\w+}"), (Match match) {
     if (holeMap != null) {
-      String holeName = match[0].substring(1);
+      String matchedString = match[0];
+      String holeName = matchedString.startsWith("#{")
+          ? matchedString.substring(2, matchedString.length - 1)
+          : matchedString.substring(1);
       int index = holeMap[holeName];
       if (index == null) {
         throw "Couldn't find hole-position for $holeName $holeMap";
diff --git a/pkg/dart_messages/lib/generated/shared_messages.json b/pkg/dart_messages/lib/generated/shared_messages.json
index 8b20467..a40bc3f 100644
--- a/pkg/dart_messages/lib/generated/shared_messages.json
+++ b/pkg/dart_messages/lib/generated/shared_messages.json
@@ -1 +1,315 @@
-{"exampleMessage":{"id":"use an Id generated by bin/message_id.dart","subId":0,"category":"AnalysisOptionsError","template":"#use #named #arguments","templateHoleOrder":["arguments","named","use"],"howToFix":"an explanation on how to fix things","options":null,"usedBy":[],"examples":["      Some multiline example;\n      That generates the bug.",{"fileA.dart":"        or a map from file to content.\n        again multiline","fileB.dart":"        with possibly multiple files.\n        muliline too"}]},"CONST_CONSTRUCTOR_OR_FACTORY_WITH_BODY":{"id":"LGJGHW","subId":0,"category":"ParserError","template":"Const constructor or factory can't have a body.","templateHoleOrder":null,"howToFix":"Remove the 'const' keyword or the body.","options":null,"usedBy":["Platform.dart2js"],"examples":["         class C {\n           const C() {}\n         }\n\n         main() => new C();","         class C {\n           const factory C() {}\n         }\n\n         main() => new C();"]},"CONST_CONSTRUCTOR_WITH_BODY":{"id":"LGJGHW","subId":1,"category":"ParserError","template":"Const constructor can't have a body.","templateHoleOrder":null,"howToFix":"Try removing the 'const' keyword or the body.","options":null,"usedBy":["Platform.analyzer"],"examples":["         class C {\n           const C() {}\n         }\n\n         main() => new C();"]},"CONST_FACTORY":{"id":"LGJGHW","subId":2,"category":"ParserError","template":"Only redirecting factory constructors can be declared to be 'const'.","templateHoleOrder":null,"howToFix":"Try removing the 'const' keyword or replacing the body with '=' followed by a valid target","options":null,"usedBy":["Platform.analyzer"],"examples":["         class C {\n           const factory C() {}\n         }\n\n         main() => new C();"]}}
\ No newline at end of file
+{
+  "exampleMessage": {
+    "id": "use an Id generated by bin/message_id.dart",
+    "subId": 0,
+    "category": "AnalysisOptionsError",
+    "template": "#use #named #arguments",
+    "templateHoleOrder": [
+      "arguments",
+      "named",
+      "use"
+    ],
+    "howToFix": "an explanation on how to fix things",
+    "options": null,
+    "usedBy": [],
+    "examples": [
+      "      Some multiline example;\n      That generates the bug.",
+      {
+        "fileA.dart": "        or a map from file to content.\n        again multiline",
+        "fileB.dart": "        with possibly multiple files.\n        muliline too"
+      }
+    ]
+  },
+  "CONST_CONSTRUCTOR_OR_FACTORY_WITH_BODY": {
+    "id": "LGJGHW",
+    "subId": 0,
+    "category": "ParserError",
+    "template": "Const constructor or factory can't have a body.",
+    "templateHoleOrder": null,
+    "howToFix": "Remove the 'const' keyword or the body.",
+    "options": null,
+    "usedBy": [
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "         class C {\n           const C() {}\n         }\n\n         main() => new C();",
+      "         class C {\n           const factory C() {}\n         }\n\n         main() => new C();"
+    ]
+  },
+  "CONST_CONSTRUCTOR_WITH_BODY": {
+    "id": "LGJGHW",
+    "subId": 1,
+    "category": "ParserError",
+    "template": "Const constructor can't have a body.",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the 'const' keyword or the body.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "         class C {\n           const C() {}\n         }\n\n         main() => new C();"
+    ]
+  },
+  "CONST_FACTORY": {
+    "id": "LGJGHW",
+    "subId": 2,
+    "category": "ParserError",
+    "template": "Only redirecting factory constructors can be declared to be 'const'.",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the 'const' keyword or replacing the body with '=' followed by a valid target.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "         class C {\n           const factory C() {}\n         }\n\n         main() => new C();"
+    ]
+  },
+  "EXTRANEOUS_MODIFIER": {
+    "id": "GRKIQE",
+    "subId": 0,
+    "category": "ParserError",
+    "template": "Can't have modifier '#{modifier}' here.",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing '#{modifier}'.",
+    "options": null,
+    "usedBy": [
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "var String foo; main(){}",
+      "var set foo; main(){}",
+      "var final foo; main(){}",
+      "var var foo; main(){}",
+      "var const foo; main(){}",
+      "var abstract foo; main(){}",
+      "var static foo; main(){}",
+      "var external foo; main(){}",
+      "get var foo; main(){}",
+      "set var foo; main(){}",
+      "final var foo; main(){}",
+      "var var foo; main(){}",
+      "const var foo; main(){}",
+      "abstract var foo; main(){}",
+      "static var foo; main(){}",
+      "external var foo; main(){}"
+    ]
+  },
+  "EXTRANEOUS_MODIFIER_REPLACE": {
+    "id": "GRKIQE",
+    "subId": 1,
+    "category": "ParserError",
+    "template": "Can't have modifier '#{modifier}' here.",
+    "templateHoleOrder": null,
+    "howToFix": "Try replacing modifier '#{modifier}' with 'var', 'final', or a type.",
+    "options": null,
+    "usedBy": [
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "set foo; main(){}",
+      "abstract foo; main(){}",
+      "static foo; main(){}",
+      "external foo; main(){}"
+    ]
+  },
+  "CONST_CLASS": {
+    "id": "GRKIQE",
+    "subId": 2,
+    "category": "ParserError",
+    "template": "Classes can't be declared to be 'const'",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the 'const' keyword or moving to the class' constructor(s).",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "        const class C {}\n\n        main() => new C();\n        "
+    ]
+  },
+  "CONST_METHOD": {
+    "id": "GRKIQE",
+    "subId": 3,
+    "category": "ParserError",
+    "template": "Getters, setters and methods can't be declared to be 'const'",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the 'const' keyword.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "const int foo() => 499; main() {}",
+      "const int get foo => 499; main() {}",
+      "const set foo(v) => 499; main() {}",
+      "class A { const int foo() => 499; } main() { new A(); }",
+      "class A { const int get foo => 499; } main() { new A(); }",
+      "class A { const set foo(v) => 499; } main() { new A(); }"
+    ]
+  },
+  "CONST_ENUM": {
+    "id": "GRKIQE",
+    "subId": 4,
+    "category": "ParserError",
+    "template": "Enums can't be declared to be 'const'",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the 'const' keyword.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "const enum Foo { x } main() {}"
+    ]
+  },
+  "CONST_TYPEDEF": {
+    "id": "GRKIQE",
+    "subId": 5,
+    "category": "ParserError",
+    "template": "Type aliases can't be declared to be 'const'",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the 'const' keyword.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "const typedef void Foo(); main() {}"
+    ]
+  },
+  "CONST_AND_FINAL": {
+    "id": "GRKIQE",
+    "subId": 6,
+    "category": "ParserError",
+    "template": "Members can't be declared to be both 'const' and 'final'",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing either the 'const' or 'final' keyword.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "final const int x = 499; main() {}",
+      "const final int x = 499; main() {}",
+      "class A { static final const int x = 499; } main() {}",
+      "class A { static const final int x = 499; } main() {}"
+    ]
+  },
+  "CONST_AND_VAR": {
+    "id": "GRKIQE",
+    "subId": 7,
+    "category": "ParserError",
+    "template": "Members can't be declared to be both 'const' and 'var'",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing either the 'const' or 'var' keyword.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "var const x = 499; main() {}",
+      "const var x = 499; main() {}",
+      "class A { var const x = 499; } main() {}",
+      "class A { const var x = 499; } main() {}"
+    ]
+  },
+  "CLASS_IN_CLASS": {
+    "id": "DOTHQH",
+    "subId": 0,
+    "category": "ParserError",
+    "template": "Classes can't be declared inside other classes.",
+    "templateHoleOrder": null,
+    "howToFix": "Try moving the class to the top-level.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer"
+    ],
+    "examples": [
+      "class A { class B {} } main() { new A(); }"
+    ]
+  },
+  "CONSTRUCTOR_WITH_RETURN_TYPE": {
+    "id": "VOJBWY",
+    "subId": 0,
+    "category": "ParserError",
+    "template": "Constructors can't have a return type",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the return type.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer",
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "class A { int A() {} } main() { new A(); }"
+    ]
+  },
+  "MISSING_EXPRESSION_IN_THROW": {
+    "id": "FTGGMJ",
+    "subId": 0,
+    "category": "ParserError",
+    "template": "Missing expression after 'throw'.",
+    "templateHoleOrder": null,
+    "howToFix": "Did you mean 'rethrow'?",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer",
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "main() { throw; }",
+      "main() { try { throw 0; } catch(e) { throw; } }"
+    ]
+  },
+  "RETHROW_OUTSIDE_CATCH": {
+    "id": "MWETLC",
+    "subId": 0,
+    "category": "CompileTimeError",
+    "template": "Rethrow must be inside of catch clause",
+    "templateHoleOrder": null,
+    "howToFix": "Try moving the expression into a catch clause, or using a 'throw' expression.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer",
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "main() { rethrow; }"
+    ]
+  },
+  "RETURN_IN_GENERATIVE_CONSTRUCTOR": {
+    "id": "UOTDQH",
+    "subId": 0,
+    "category": "CompileTimeError",
+    "template": "Constructors can't return values.",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the return statement or using a factory constructor.",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer",
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "        class C {\n          C() {\n            return 1;\n          }\n        }\n\n        main() => new C();"
+    ]
+  },
+  "RETURN_IN_GENERATOR": {
+    "id": "JRUTUQ",
+    "subId": 0,
+    "category": "CompileTimeError",
+    "template": "Can't return a value from a generator function (using the '#{modifier}' modifier).",
+    "templateHoleOrder": null,
+    "howToFix": "Try removing the value, replacing 'return' with 'yield' or changing the method body modifier",
+    "options": null,
+    "usedBy": [
+      "Platform.analyzer",
+      "Platform.dart2js"
+    ],
+    "examples": [
+      "        foo() async* { return 0; }\n        main() => foo();\n        ",
+      "        foo() sync* { return 0; }\n        main() => foo();\n        "
+    ]
+  }
+}
\ No newline at end of file
diff --git a/pkg/dart_messages/lib/shared_messages.dart b/pkg/dart_messages/lib/shared_messages.dart
index 32d7935..ece8895 100644
--- a/pkg/dart_messages/lib/shared_messages.dart
+++ b/pkg/dart_messages/lib/shared_messages.dart
@@ -75,20 +75,40 @@
 
   static final parserError = new Category("ParserError");
 
+  static final compileTimeError = new Category("CompileTimeError");
+
   final String name;
 
   Category(this.name);
 }
 
-enum Platform {
-  dart2js, analyzer,
-}
+enum Platform { dart2js, analyzer, }
 const dart2js = Platform.dart2js;
 const analyzer = Platform.analyzer;
 
 class Message {
+  /// Generic id for this message.
+  ///
+  /// This id should be shared by all errors that fall into the same category.
+  /// In particular, we want errors of the same category to share the same
+  /// explanation page, and want to disable warnings of the same category
+  /// with just one line.
   final String id;
+
+  /// The sub-id of the error.
+  ///
+  /// This id just needs to be unique within the same [id].
   final int subId;
+
+  /// The error sub-id of which this message is a specialization.
+  ///
+  /// For example, "Const is not allowed on getters" may be a specialization of
+  /// "The 'const' keyword is not allowed here".
+  ///
+  /// Examples of the specialized message, should trigger for the more generic
+  /// message, when the platform doesn't support the more specialized message.
+  final int specializationOf;
+
   final Category category;
   final String template;
   // The analyzer fills holes positionally (and not named). The following field
@@ -107,6 +127,7 @@
   Message(
       {this.id,
       this.subId: 0,
+      this.specializationOf: -1,
       this.category,
       this.template,
       this.templateHoleOrder,
@@ -131,7 +152,7 @@
       'examples': message.examples,
     };
   });
-  return JSON.encode(jsonified);
+  return new JsonEncoder.withIndent('  ').convert(jsonified);
 }
 
 final Map<String, Message> MESSAGES = {
@@ -162,7 +183,9 @@
       category: Category.parserError,
       template: "Const constructor or factory can't have a body.",
       howToFix: "Remove the 'const' keyword or the body.",
-      usedBy: [dart2js],
+      usedBy: [
+        dart2js
+      ],
       examples: const [
         r"""
          class C {
@@ -181,10 +204,13 @@
   'CONST_CONSTRUCTOR_WITH_BODY': new Message(
       id: 'LGJGHW',
       subId: 1,
+      specializationOf: 0,
       category: Category.parserError,
       template: "Const constructor can't have a body.",
       howToFix: "Try removing the 'const' keyword or the body.",
-      usedBy: [analyzer],
+      usedBy: [
+        analyzer
+      ],
       examples: const [
         r"""
          class C {
@@ -197,12 +223,15 @@
   'CONST_FACTORY': new Message(
       id: 'LGJGHW',
       subId: 2,
+      specializationOf: 0,
       category: Category.parserError,
       template: "Only redirecting factory constructors can be declared to "
           "be 'const'.",
       howToFix: "Try removing the 'const' keyword or replacing the body with "
-          "'=' followed by a valid target",
-      usedBy: [analyzer],
+          "'=' followed by a valid target.",
+      usedBy: [
+        analyzer
+      ],
       examples: const [
         r"""
          class C {
@@ -211,4 +240,247 @@
 
          main() => new C();"""
       ]),
+
+  'EXTRANEOUS_MODIFIER': new Message(
+      id: 'GRKIQE',
+      subId: 0,
+      category: Category.parserError,
+      template: "Can't have modifier '#{modifier}' here.",
+      howToFix: "Try removing '#{modifier}'.",
+      usedBy: [
+        dart2js
+      ],
+      examples: const [
+        "var String foo; main(){}",
+        // "var get foo; main(){}",
+        "var set foo; main(){}",
+        "var final foo; main(){}",
+        "var var foo; main(){}",
+        "var const foo; main(){}",
+        "var abstract foo; main(){}",
+        "var static foo; main(){}",
+        "var external foo; main(){}",
+        "get var foo; main(){}",
+        "set var foo; main(){}",
+        "final var foo; main(){}",
+        "var var foo; main(){}",
+        "const var foo; main(){}",
+        "abstract var foo; main(){}",
+        "static var foo; main(){}",
+        "external var foo; main(){}"
+      ]),
+
+  'EXTRANEOUS_MODIFIER_REPLACE': new Message(
+      id: 'GRKIQE',
+      subId: 1,
+      category: Category.parserError,
+      template: "Can't have modifier '#{modifier}' here.",
+      howToFix: "Try replacing modifier '#{modifier}' with 'var', 'final', "
+          "or a type.",
+      usedBy: [
+        dart2js
+      ],
+      examples: const [
+        // "get foo; main(){}",
+        "set foo; main(){}",
+        "abstract foo; main(){}",
+        "static foo; main(){}",
+        "external foo; main(){}"
+      ]),
+
+  'CONST_CLASS': new Message(
+      id: 'GRKIQE',
+      subId: 2,
+      // The specialization could also be 1, but the example below triggers 0.
+      specializationOf: 0,
+      category: Category.parserError,
+      template: "Classes can't be declared to be 'const'",
+      howToFix: "Try removing the 'const' keyword or moving to the class'"
+          " constructor(s).",
+      usedBy: [
+        analyzer
+      ],
+      examples: const [
+        r"""
+        const class C {}
+
+        main() => new C();
+        """
+      ]),
+
+  'CONST_METHOD': new Message(
+      id: 'GRKIQE',
+      subId: 3,
+      // The specialization could also be 1, but the example below triggers 0.
+      specializationOf: 0,
+      category: Category.parserError,
+      template: "Getters, setters and methods can't be declared to be 'const'",
+      howToFix: "Try removing the 'const' keyword.",
+      usedBy: [
+        analyzer
+      ],
+      examples: const [
+        "const int foo() => 499; main() {}",
+        "const int get foo => 499; main() {}",
+        "const set foo(v) => 499; main() {}",
+        "class A { const int foo() => 499; } main() { new A(); }",
+        "class A { const int get foo => 499; } main() { new A(); }",
+        "class A { const set foo(v) => 499; } main() { new A(); }",
+      ]),
+
+  'CONST_ENUM': new Message(
+      id: 'GRKIQE',
+      subId: 4,
+      // The specialization could also be 1, but the example below triggers 0.
+      specializationOf: 0,
+      category: Category.parserError,
+      template: "Enums can't be declared to be 'const'",
+      howToFix: "Try removing the 'const' keyword.",
+      usedBy: [analyzer],
+      examples: const ["const enum Foo { x } main() {}",]),
+
+  'CONST_TYPEDEF': new Message(
+      id: 'GRKIQE',
+      subId: 5,
+      // The specialization could also be 1, but the example below triggers 0.
+      specializationOf: 0,
+      category: Category.parserError,
+      template: "Type aliases can't be declared to be 'const'",
+      howToFix: "Try removing the 'const' keyword.",
+      usedBy: [analyzer],
+      examples: const ["const typedef void Foo(); main() {}",]),
+
+  'CONST_AND_FINAL': new Message(
+      id: 'GRKIQE',
+      subId: 6,
+      // The specialization could also be 1, but the example below triggers 0.
+      specializationOf: 0,
+      category: Category.parserError,
+      template: "Members can't be declared to be both 'const' and 'final'",
+      howToFix: "Try removing either the 'const' or 'final' keyword.",
+      usedBy: [
+        analyzer
+      ],
+      examples: const [
+        "final const int x = 499; main() {}",
+        "const final int x = 499; main() {}",
+        "class A { static final const int x = 499; } main() {}",
+        "class A { static const final int x = 499; } main() {}",
+      ]),
+
+  'CONST_AND_VAR': new Message(
+      id: 'GRKIQE',
+      subId: 7,
+      // The specialization could also be 1, but the example below triggers 0.
+      specializationOf: 0,
+      category: Category.parserError,
+      template: "Members can't be declared to be both 'const' and 'var'",
+      howToFix: "Try removing either the 'const' or 'var' keyword.",
+      usedBy: [
+        analyzer
+      ],
+      examples: const [
+        "var const x = 499; main() {}",
+        "const var x = 499; main() {}",
+        "class A { var const x = 499; } main() {}",
+        "class A { const var x = 499; } main() {}",
+      ]),
+
+  'CLASS_IN_CLASS': new Message(
+      // Dart2js currently reports this as an EXTRANEOUS_MODIFIER error.
+      // TODO(floitsch): make dart2js use this error instead.
+      id: 'DOTHQH',
+      category: Category.parserError,
+      template: "Classes can't be declared inside other classes.",
+      howToFix: "Try moving the class to the top-level.",
+      usedBy: [analyzer],
+      examples: const ["class A { class B {} } main() { new A(); }",]),
+
+  'CONSTRUCTOR_WITH_RETURN_TYPE': new Message(
+      id: 'VOJBWY',
+      category: Category.parserError,
+      template: "Constructors can't have a return type",
+      howToFix: "Try removing the return type.",
+      usedBy: [analyzer, dart2js],
+      examples: const ["class A { int A() {} } main() { new A(); }",]),
+
+  'MISSING_EXPRESSION_IN_THROW': new Message(
+      id: 'FTGGMJ',
+      subId: 0,
+      category: Category.parserError,
+      template: "Missing expression after 'throw'.",
+      howToFix: "Did you mean 'rethrow'?",
+      usedBy: [
+        analyzer,
+        dart2js
+      ],
+      examples: const [
+        'main() { throw; }',
+        'main() { try { throw 0; } catch(e) { throw; } }'
+      ]),
+
+  /**
+   * 12.8.1 Rethrow: It is a compile-time error if an expression of the form
+   * <i>rethrow;</i> is not enclosed within a on-catch clause.
+   */
+  'RETHROW_OUTSIDE_CATCH': new Message(
+      id: 'MWETLC',
+      category: Category.compileTimeError,
+      template: 'Rethrow must be inside of catch clause',
+      howToFix: "Try moving the expression into a catch clause, or "
+          "using a 'throw' expression.",
+      usedBy: [analyzer, dart2js],
+      examples: const ["main() { rethrow; }"]),
+
+  /**
+   * 13.12 Return: It is a compile-time error if a return statement of the form
+   * <i>return e;</i> appears in a generative constructor.
+   */
+  'RETURN_IN_GENERATIVE_CONSTRUCTOR': new Message(
+      id: 'UOTDQH',
+      category: Category.compileTimeError,
+      template: "Constructors can't return values.",
+      howToFix:
+          "Try removing the return statement or using a factory constructor.",
+      usedBy: [
+        analyzer,
+        dart2js
+      ],
+      examples: const [
+        """
+        class C {
+          C() {
+            return 1;
+          }
+        }
+
+        main() => new C();"""
+      ]),
+
+  /**
+   * 13.12 Return: It is a compile-time error if a return statement of the form
+   * <i>return e;</i> appears in a generator function.
+   */
+  'RETURN_IN_GENERATOR': new Message(
+      id: 'JRUTUQ',
+      subId: 0,
+      category: Category.compileTimeError,
+      template: "Can't return a value from a generator function "
+          "(using the '#{modifier}' modifier).",
+      howToFix: "Try removing the value, replacing 'return' with 'yield' or"
+          " changing the method body modifier",
+      usedBy: [
+        analyzer,
+        dart2js
+      ],
+      examples: const [
+        """
+        foo() async* { return 0; }
+        main() => foo();
+        """,
+        """
+        foo() sync* { return 0; }
+        main() => foo();
+        """
+      ]),
 };
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
new file mode 100644
index 0000000..6c3009b
--- /dev/null
+++ b/pkg/meta/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.9.0
+* Introduce `@protected` annotation for methods that must only be called from
+instance methods of subclasses.
diff --git a/pkg/meta/LICENSE b/pkg/meta/LICENSE
new file mode 100644
index 0000000..82e9b52
--- /dev/null
+++ b/pkg/meta/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2016, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
new file mode 100644
index 0000000..a914ff6
--- /dev/null
+++ b/pkg/meta/lib/meta.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2016, 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.
+
+/// Constants for use in metadata annotations such as `@protected`.
+///
+/// See also `@deprecated` and `@override` in the `dart:core` library.
+///
+/// Annotations provide semantic information that tools can use to provide a
+/// better user experience. For example, an IDE might not autocomplete the name
+/// of a function that's been marked `@deprecated`, or it might display the
+/// function's name differently.
+///
+/// For information on installing and importing this library, see the
+/// [meta package on pub.dartlang.org] (http://pub.dartlang.org/packages/meta).
+/// For examples of using annotations, see
+/// [Metadata](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#metadata)
+/// in the language tour.
+library meta;
+
+/// Used to annotate an instance method `m` in a class `C`. Indicates that `m`
+/// should only be invoked from instance methods of `C` or classes that extend
+/// or mix in `C`, either directly or indirectly. Additionally indicates that
+/// `m` should only be invoked on `this`, whether explicitly or implicitly.
+///
+/// Tools, such as the analyzer, can provide feedback if an invocation of a
+/// method marked as being protected is used outside of an instance method
+/// defined on a class that extends or mixes in the class in which the protected
+/// method is defined, or that uses a receiver other than `this`.
+const _Protected protected = const _Protected();
+
+class _Protected {
+  const _Protected();
+}
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
new file mode 100644
index 0000000..4b20d9c
--- /dev/null
+++ b/pkg/meta/pubspec.yaml
@@ -0,0 +1,10 @@
+name: meta
+version: 0.9.0
+author: Dart Team <misc@dartlang.org>
+homepage: http://www.dartlang.org
+description: >
+ This library contains the definitions of annotations that provide additional
+ semantic information about the program being annotated. These annotations are
+ intended to be used by tools to provide a better user experience.
+environment:
+  sdk: '>=1.12.0 <2.0.0'
diff --git a/pkg/pkg.status b/pkg/pkg.status
index d6170c0..ef18a9b 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -14,7 +14,7 @@
 # Analyzer2dart is not maintained anymore.
 analyzer2dart/test/*: Skip
 
-[ $compiler == none && ($runtime == drt || $runtime == dartium || $runtime == ContentShellOnAndroid) ]
+[ $compiler == none && ($runtime == drt || $runtime == dartium) ]
 mutation_observer: Skip # Issue 21149
 unittest/*: Skip # Issue 21949
 lookup_map/*: SkipByDesign
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index cb4b63e..5d7b48e 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -752,6 +752,9 @@
         '<(resources_cc_file)',
         '<(observatory_assets_cc_file)',
       ],
+      'defines': [
+        'DART_PRECOMPILED_RUNTIME',
+      ],
       'conditions': [
         ['OS=="win"', {
           'link_settings': {
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 123f56f..51b1d56 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -109,10 +109,10 @@
   V(SecurityContext_Allocate, 1)                                               \
   V(SecurityContext_UsePrivateKeyBytes, 3)                                     \
   V(SecurityContext_SetAlpnProtocols, 3)                                       \
-  V(SecurityContext_SetClientAuthoritiesBytes, 2)                              \
-  V(SecurityContext_SetTrustedCertificatesBytes, 2)                            \
+  V(SecurityContext_SetClientAuthoritiesBytes, 3)                              \
+  V(SecurityContext_SetTrustedCertificatesBytes, 3)                            \
   V(SecurityContext_TrustBuiltinRoots, 1)                                      \
-  V(SecurityContext_UseCertificateChainBytes, 2)                               \
+  V(SecurityContext_UseCertificateChainBytes, 3)                               \
   V(ServerSocket_Accept, 2)                                                    \
   V(ServerSocket_CreateBindListen, 6)                                          \
   V(Socket_CreateConnect, 3)                                                   \
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index e5e60dc..4642486 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -411,8 +411,10 @@
 #ifndef DART_PRODUCT_BINARY
   Log::PrintErr("Full Application snapshots can only be be run with"
                 " dart_product\n");
-#endif
+  return false;
+#else
   return ProcessSnapshotOptionHelper(filename, &run_full_snapshot);
+#endif  // defined(DART_PRODUCT_BINARY)
 }
 
 
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index d7735af..f63d9d0 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -282,7 +282,9 @@
 
 
 static Dart_Handle WrappedX509Certificate(X509* certificate) {
-  if (certificate == NULL) return Dart_Null();
+  if (certificate == NULL) {
+    return Dart_Null();
+  }
   Dart_Handle x509_type =
       DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
   if (Dart_IsError(x509_type)) {
@@ -307,7 +309,9 @@
 
 
 int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) {
-  if (preverify_ok == 1) return 1;
+  if (preverify_ok == 1) {
+    return 1;
+  }
   Dart_Isolate isolate = Dart_CurrentIsolate();
   if (isolate == NULL) {
     FATAL("CertificateCallback called with no current isolate\n");
@@ -319,7 +323,9 @@
   SSLFilter* filter = static_cast<SSLFilter*>(
       SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
   Dart_Handle callback = filter->bad_certificate_callback();
-  if (Dart_IsNull(callback)) return 0;
+  if (Dart_IsNull(callback)) {
+    return 0;
+  }
   Dart_Handle args[1];
   args[0] = WrappedX509Certificate(certificate);
   if (Dart_IsError(args[0])) {
@@ -360,12 +366,12 @@
 }
 
 
-void CheckStatus(int status,
-                 const char* type,
-                 const char* message) {
+void CheckStatus(int status, const char* type, const char* message) {
   // TODO(24183): Take appropriate action on failed calls,
   // throw exception that includes all messages from the error stack.
-  if (status == 1) return;
+  if (status == 1) {
+    return;
+  }
   if (SSL_LOG_STATUS) {
     int error = ERR_get_error();
     Log::PrintErr("Failed: %s status %d", message, status);
@@ -556,25 +562,31 @@
 }
 
 
-void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
-    Dart_NativeArguments args) {
-  SSL_CTX* context = GetSecurityContext(args);
-
-  Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
+static const char* GetPasswordArgument(Dart_NativeArguments args,
+                                       intptr_t index) {
+  Dart_Handle password_object =
+      ThrowIfError(Dart_GetNativeArgument(args, index));
   const char* password = NULL;
   if (Dart_IsString(password_object)) {
     ThrowIfError(Dart_StringToCString(password_object, &password));
     if (strlen(password) > PEM_BUFSIZE - 1) {
       Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "SecurityContext.usePrivateKey password length is greater than"
-        " 1023 (PEM_BUFSIZE)"));
+        "Password length is greater than 1023 (PEM_BUFSIZE)"));
     }
   } else if (Dart_IsNull(password_object)) {
     password = "";
   } else {
     Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "SecurityContext.usePrivateKey password is not a String or null"));
+        "Password is not a String or null"));
   }
+  return password;
+}
+
+
+void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
+    Dart_NativeArguments args) {
+  SSL_CTX* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
 
   int status;
   {
@@ -590,7 +602,9 @@
 }
 
 
-static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context, BIO* bio) {
+static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context,
+                                             BIO* bio,
+                                             const char* password) {
   ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
   if (p12.get() == NULL) {
     return NULL;
@@ -599,22 +613,12 @@
   EVP_PKEY* key = NULL;
   X509 *cert = NULL;
   STACK_OF(X509) *ca_certs = NULL;
-  // There should be no private keys in this file, so we hardcode the password
-  // to "".
-  // TODO(zra): Allow passing a password anyway.
-  int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
   if (status == 0) {
     return status;
   }
 
   ScopedX509Stack cert_stack(ca_certs);
-
-  // There should be no private key.
-  if (key != NULL) {
-    X509_free(cert);
-    return 0;
-  }
-
   X509_STORE* store = SSL_CTX_get_cert_store(context);
   status = X509_STORE_add_cert(store, cert);
   if (status == 0) {
@@ -662,12 +666,14 @@
 }
 
 
-static int SetTrustedCertificatesBytes(SSL_CTX* context, BIO* bio) {
+static int SetTrustedCertificatesBytes(SSL_CTX* context,
+                                       BIO* bio,
+                                       const char* password) {
   int status = SetTrustedCertificatesBytesPEM(context, bio);
   if (TryPKCS12(status != 0)) {
     ERR_clear_error();
     BIO_reset(bio);
-    status = SetTrustedCertificatesBytesPKCS12(context, bio);
+    status = SetTrustedCertificatesBytesPKCS12(context, bio, password);
   } else if (status != 0) {
     // The PEM file was successfully parsed.
     ERR_clear_error();
@@ -679,10 +685,11 @@
 void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
     Dart_NativeArguments args) {
   SSL_CTX* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
   int status;
   {
     ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = SetTrustedCertificatesBytes(context, bio.bio());
+    status = SetTrustedCertificatesBytes(context, bio.bio(), password);
   }
   CheckStatus(status,
               "TlsException",
@@ -708,7 +715,9 @@
 }
 
 
-static int UseChainBytesPKCS12(SSL_CTX* context, BIO* bio) {
+static int UseChainBytesPKCS12(SSL_CTX* context,
+                               BIO* bio,
+                               const char* password) {
   ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
   if (p12.get() == NULL) {
     return NULL;
@@ -717,22 +726,13 @@
   EVP_PKEY* key = NULL;
   X509 *cert = NULL;
   STACK_OF(X509) *ca_certs = NULL;
-  // There should be no private keys in this file, so we hardcode the password
-  // to "".
-  // TODO(zra): Allow passing a password anyway.
-  int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
   if (status == 0) {
     return status;
   }
 
   ScopedX509 x509(cert);
   ScopedX509Stack certs(ca_certs);
-
-  // There should be no private key.
-  if (key != NULL) {
-    return 0;
-  }
-
   status = SSL_CTX_use_certificate(context, x509.get());
   if (ERR_peek_error() != 0) {
     // Key/certificate mismatch doesn't imply status is 0.
@@ -801,12 +801,12 @@
 }
 
 
-static int UseChainBytes(SSL_CTX* context, BIO* bio) {
+static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) {
   int status = UseChainBytesPEM(context, bio);
   if (TryPKCS12(status != 0)) {
     ERR_clear_error();
     BIO_reset(bio);
-    status = UseChainBytesPKCS12(context, bio);
+    status = UseChainBytesPKCS12(context, bio, password);
   } else if (status != 0) {
     // The PEM file was successfully read.
     ERR_clear_error();
@@ -818,10 +818,11 @@
 void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
     Dart_NativeArguments args) {
   SSL_CTX* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
   int status;
   {
     ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = UseChainBytes(context, bio.bio());
+    status = UseChainBytes(context, bio.bio(), password);
   }
   CheckStatus(status,
               "TlsException",
@@ -829,7 +830,8 @@
 }
 
 
-static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio) {
+static STACK_OF(X509_NAME)* GetCertificateNamesPKCS12(BIO* bio,
+                                                      const char* password) {
   ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
   if (p12.get() == NULL) {
     return NULL;
@@ -843,22 +845,13 @@
   EVP_PKEY* key = NULL;
   X509 *cert = NULL;
   STACK_OF(X509) *ca_certs = NULL;
-  // There should be no private keys in this file, so we hardcode the password
-  // to "".
-  // TODO(zra): Allow passing a password anyway.
-  int status = PKCS12_parse(p12.get(), "", &key, &cert, &ca_certs);
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
   if (status == 0) {
     return NULL;
   }
 
   ScopedX509 x509(cert);
   ScopedX509Stack certs(ca_certs);
-
-  // There should be no private key.
-  if (key != NULL) {
-    return NULL;
-  }
-
   X509_NAME* x509_name = X509_get_subject_name(x509.get());
   if (x509_name == NULL) {
     return NULL;
@@ -935,12 +928,13 @@
 }
 
 
-static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio) {
+static STACK_OF(X509_NAME)* GetCertificateNames(BIO* bio,
+                                                const char* password) {
   STACK_OF(X509_NAME)* result = GetCertificateNamesPEM(bio);
   if (TryPKCS12(result != NULL)) {
     ERR_clear_error();
     BIO_reset(bio);
-    result = GetCertificateNamesPKCS12(bio);
+    result = GetCertificateNamesPKCS12(bio, password);
   } else if (result != NULL) {
     // The PEM file was successfully parsed.
     ERR_clear_error();
@@ -952,11 +946,12 @@
 void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
     Dart_NativeArguments args) {
   SSL_CTX* context = GetSecurityContext(args);
+  const char* password = GetPasswordArgument(args, 2);
   STACK_OF(X509_NAME)* certificate_names;
 
   {
     ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    certificate_names = GetCertificateNames(bio.bio());
+    certificate_names = GetCertificateNames(bio.bio(), password);
   }
 
   if (certificate_names != NULL) {
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index b15d61a..ccfc1c1 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -147,38 +147,38 @@
   void usePrivateKeyBytes(List<int> keyBytes, {String password})
       native "SecurityContext_UsePrivateKeyBytes";
 
-  void setTrustedCertificates(String file) {
-    setTrustedCertificatesSync(file);
+  void setTrustedCertificates(String file, {String password}) {
+    setTrustedCertificatesSync(file, password: password);
   }
-  void setTrustedCertificatesSync(String file) {
+  void setTrustedCertificatesSync(String file, {String password}) {
     List<int> bytes = (new File(file)).readAsBytesSync();
-    setTrustedCertificatesBytes(bytes);
+    setTrustedCertificatesBytes(bytes, password: password);
   }
-  void setTrustedCertificatesBytes(List<int> certBytes)
+  void setTrustedCertificatesBytes(List<int> certBytes, {String password})
       native "SecurityContext_SetTrustedCertificatesBytes";
 
-  void useCertificateChain({String file, String directory}) {
+  void useCertificateChain({String file, String directory, String password}) {
     if (directory != null) {
       throw new UnsupportedError(
           "The directory argument to useCertificateChain is not supported.");
     }
-    useCertificateChainSync(file);
+    useCertificateChainSync(file, password: password);
   }
-  void useCertificateChainSync(String chainFile) {
+  void useCertificateChainSync(String chainFile, {String password}) {
     List<int> bytes = (new File(chainFile)).readAsBytesSync();
-    useCertificateChainBytes(bytes);
+    useCertificateChainBytes(bytes, password: password);
   }
-  void useCertificateChainBytes(List<int> chainBytes)
+  void useCertificateChainBytes(List<int> chainBytes, {String password})
       native "SecurityContext_UseCertificateChainBytes";
 
-  void setClientAuthorities(String file) {
-    setClientAuthoritiesSync(file);
+  void setClientAuthorities(String file, {String password}) {
+    setClientAuthoritiesSync(file, password: password);
   }
-  void setClientAuthoritiesSync(String file) {
+  void setClientAuthoritiesSync(String file, {String password}) {
     List<int> bytes = (new File(file)).readAsBytesSync();
-    setClientAuthoritiesBytes(bytes);
+    setClientAuthoritiesBytes(bytes, password: password);
   }
-  void setClientAuthoritiesBytes(List<int> authCertBytes)
+  void setClientAuthoritiesBytes(List<int> authCertBytes, {String password})
       native "SecurityContext_SetClientAuthoritiesBytes";
   void setAlpnProtocols(List<String> protocols, bool isServer) {
     Uint8List encodedProtocols =
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 6ff907c..2a9fc8f 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -62,13 +62,6 @@
   Builtin::SetNativeResolver(Builtin::kBuiltinLibrary);
   Builtin::SetNativeResolver(Builtin::kIOLibrary);
 
-  Dart_Handle result;
-
-  // Prepare for script loading by setting up the 'print' and 'timer'
-  // closures and setting up 'package root' for URI resolution.
-  result = DartUtils::PrepareForScriptLoading(true, false);
-  CHECK_RESULT(result);
-
   ASSERT(Dart_IsServiceIsolate(isolate));
   if (!VmService::Setup(DEFAULT_VM_SERVICE_SERVER_IP,
                         DEFAULT_VM_SERVICE_SERVER_PORT,
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index 915b5b4..f976190 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -95,7 +95,7 @@
       'target_name': 'libdart_precompiled_runtime',
       'type': 'static_library',
       'dependencies': [
-        'libdart_lib',
+        'libdart_lib_precompiled_runtime',
         'libdart_vm_precompiled_runtime',
         'libdouble_conversion',
         'generate_version_cc_file#host',
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index 39b4522..016a454 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -113,13 +113,26 @@
   factory _GrowableList.withData(_List data)
     native "GrowableList_allocate";
 
-  int get length native "GrowableList_getLength";
-
   int get _capacity native "GrowableList_getCapacity";
 
+  int get length native "GrowableList_getLength";
+
   void set length(int new_length) {
-    if (new_length > _capacity) {
-      _grow(new_length);
+    int new_capacity = (new_length == 0) ? _kDefaultCapacity : new_length;
+    if (new_capacity > _capacity) {
+      _grow(new_capacity);
+      _setLength(new_length);
+      return;
+    }
+    // We are shrinking. Pick the method which has fewer writes.
+    // In the shrink-to-fit path, we write |new_capacity + new_length| words
+    // (null init + copy).
+    // In the non-shrink-to-fit path, we write |length - new_length| words
+    // (null overwrite).
+    final bool shouldShrinkToFit =
+        (new_capacity + new_length) < (length - new_length);
+    if (shouldShrinkToFit) {
+      _shrink(new_capacity, new_length);
     } else {
       for (int i = new_length; i < length; i++) {
         this[i] = null;
@@ -217,14 +230,22 @@
     throw IterableElementError.tooMany();;
   }
 
-  void _grow(int new_length) {
-    var new_data = new _List(new_length);
+  void _grow(int new_capacity) {
+    var new_data = new _List(new_capacity);
     for (int i = 0; i < length; i++) {
       new_data[i] = this[i];
     }
     _setData(new_data);
   }
 
+  void _shrink(int new_capacity, int new_length) {
+    var new_data = new _List(new_capacity);
+    for (int i = 0; i < new_length; i++) {
+      new_data[i] = this[i];
+    }
+    _setData(new_data);
+  }
+
   // Iterable interface.
 
   void forEach(f(T element)) {
diff --git a/runtime/lib/identical.cc b/runtime/lib/identical.cc
index 4b24219..bbb47bd 100644
--- a/runtime/lib/identical.cc
+++ b/runtime/lib/identical.cc
@@ -5,7 +5,6 @@
 #include "vm/bootstrap_natives.h"
 
 #include "vm/object.h"
-#include "vm/report.h"
 
 namespace dart {
 
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index e2ded52..10b39ce 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -10,6 +10,7 @@
 #include "vm/compiler.h"
 #include "vm/dart_entry.h"
 #include "vm/exceptions.h"
+#include "vm/flags.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"
 #include "vm/port.h"
@@ -18,7 +19,7 @@
 
 namespace dart {
 
-DECLARE_FLAG(bool, lazy_dispatchers);
+#ifndef PRODUCT
 
 #define PROPAGATE_IF_MALFORMED(type)                                           \
   if (type.IsMalformed()) {                                                    \
@@ -2089,5 +2090,6 @@
   return Bool::Get(a.IsSubtypeOf(b, NULL, NULL, Heap::kNew)).raw();
 }
 
+#endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 95f2661..c34552d 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -10,7 +10,6 @@
 #include "vm/heap.h"
 #include "vm/native_entry.h"
 #include "vm/object.h"
-#include "vm/report.h"
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 3692d6a..3bf25b5 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -1810,7 +1810,7 @@
   Future smartNext() async {
     if (isolatePaused()) {
       var event = isolate.pauseEvent;
-      if (event.atAsyncJump) {
+      if (event.atAsyncSuspension) {
         return asyncNext();
       } else {
         return syncNext();
@@ -1823,11 +1823,10 @@
   Future asyncNext() async {
     if (isolatePaused()) {
       var event = isolate.pauseEvent;
-      if (event.asyncContinuation == null) {
+      if (!event.atAsyncSuspension) {
         console.print("No async continuation at this location");
       } else {
-        List<Future> asyncStepFutures = await isolate.asyncStepOver();
-        return asyncStepFutures[Isolate.kFirstResume];
+        return isolate.stepOverAsyncSuspension();
       }
     } else {
       console.print('The program is already running');
diff --git a/runtime/observatory/lib/src/elements/heap_profile.dart b/runtime/observatory/lib/src/elements/heap_profile.dart
index 731ff48..9e5b142 100644
--- a/runtime/observatory/lib/src/elements/heap_profile.dart
+++ b/runtime/observatory/lib/src/elements/heap_profile.dart
@@ -156,7 +156,6 @@
   static const _FREE_INDEX = 1;
   static const _EXTERNAL_INDEX = 2;
 
-  static const _LABEL_INDEX = 0;
   static const _VALUE_INDEX = 1;
 
   void _initPieChartData(List rows) {
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index b7a5462..fbecb10 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -8,7 +8,6 @@
 import 'dart:convert';
 import 'dart:html';
 import 'observatory_element.dart';
-import 'package:observatory/app.dart';
 import 'package:observatory/service_html.dart';
 import 'package:polymer/polymer.dart';
 
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index bd76e67..78b6765 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1577,92 +1577,12 @@
     return invokeRpc('resume', {'step': 'Over'});
   }
 
-  Future stepOut() {
-    return invokeRpc('resume', {'step': 'Out'});
+  Future stepOverAsyncSuspension() {
+    return invokeRpc('resume', {'step': 'OverAsyncSuspension'});
   }
 
-
-  static const int kFirstResume = 0;
-  static const int kSecondResume = 1;
-  /// result[kFirstResume] completes after the inital resume. The UI should
-  /// wait on this future because some other breakpoint may be hit before the
-  /// async continuation.
-  /// result[kSecondResume] completes after the second resume. Tests should
-  /// wait on this future to avoid confusing the pause event at the
-  /// state-machine switch with the pause event after the state-machine switch.
-  Future<List<Future>> asyncStepOver() async {
-    final Completer firstResume = new Completer();
-    final Completer secondResume = new Completer();
-    final List<Future> result = [firstResume.future, secondResume.future];
-    StreamSubscription subscription;
-
-    // Inner error handling function.
-    handleError(error) {
-      if (subscription != null) {
-        subscription.cancel();
-        subscription = null;
-      }
-      firstResume.completeError(error);
-      secondResume.completeError(error);
-    }
-
-    if ((pauseEvent == null) ||
-        (pauseEvent.kind != ServiceEvent.kPauseBreakpoint) ||
-        (pauseEvent.asyncContinuation == null)) {
-      handleError(new Exception("No async continuation available"));
-    } else {
-      Instance continuation = pauseEvent.asyncContinuation;
-      assert(continuation.isClosure);
-
-      // Add breakpoint at continuation.
-      Breakpoint continuationBpt;
-      try {
-        continuationBpt = await addBreakOnActivation(continuation);
-      } catch (e) {
-        handleError(e);
-        return result;
-      }
-
-      // Subscribe to the debugger event stream.
-      Stream stream;
-      try {
-        stream = await vm.getEventStream(VM.kDebugStream);
-      } catch (e) {
-        handleError(e);
-        return result;
-      }
-
-      Completer onResume = firstResume;
-      subscription = stream.listen((ServiceEvent event) async {
-        if ((event.kind == ServiceEvent.kPauseBreakpoint) &&
-            (event.breakpoint == continuationBpt)) {
-          // We are stopped before state-machine dispatch:
-          // 1) Remove the continuation breakpoint.
-          // 2) step over.
-          // reach user code.
-          await removeBreakpoint(continuationBpt);
-          onResume = secondResume;
-          stepOver().catchError(handleError);
-        } else if (event.kind == ServiceEvent.kResume) {
-          // We've resumed.
-          if (onResume == secondResume) {
-            // This is our second resume, cancel our subscription to the debug
-            // stream.
-            subscription.cancel();
-            subscription = null;
-          }
-          // Complete onResume and clear it.
-          if (onResume != null) {
-            onResume.complete(this);
-            onResume = null;
-          }
-        }
-      });
-
-      // Call resume, which will eventually cause us to hit continuationBpt.
-      resume().catchError(handleError);
-    }
-    return result;
+  Future stepOut() {
+    return invokeRpc('resume', {'step': 'Out'});
   }
 
   Future setName(String newName) {
@@ -1914,8 +1834,7 @@
   @observable Frame topFrame;
   @observable String extensionRPC;
   @observable Instance exception;
-  @observable Instance asyncContinuation;
-  @observable bool atAsyncJump;
+  @observable bool atAsyncSuspension;
   @observable ServiceObject inspectee;
   @observable ByteData data;
   @observable int count;
@@ -1964,12 +1883,7 @@
     if (map['exception'] != null) {
       exception = map['exception'];
     }
-    if (map['_asyncContinuation'] != null) {
-      asyncContinuation = map['_asyncContinuation'];
-      atAsyncJump = map['_atAsyncJump'];
-    } else {
-      atAsyncJump = false;
-    }
+    atAsyncSuspension = map['atAsyncSuspension'] != null;
     if (map['inspectee'] != null) {
       inspectee = map['inspectee'];
     }
@@ -2040,6 +1954,10 @@
   // The breakpoint has been assigned to a final source location.
   @observable bool resolved;
 
+  // The breakpoint was synthetically created as part of an
+  // 'OverAsyncContinuation' resume request.
+  @observable bool isSyntheticAsyncContinuation;
+
   void _update(ObservableMap map, bool mapIsRef) {
     _loaded = true;
     _upgradeCollection(map, owner);
@@ -2066,6 +1984,8 @@
       newScript._addBreakpoint(this);
     }
 
+    isSyntheticAsyncContinuation = map['isSyntheticAsyncContinuation'] != null;
+
     assert(resolved || location is UnresolvedSourceLocation);
   }
 
@@ -2081,7 +2001,11 @@
 
   String toString() {
     if (number != null) {
-      return 'Breakpoint ${number} at ${location})';
+      if (isSyntheticAsyncContinuation) {
+        return 'Synthetic Async Continuation Breakpoint ${number}';
+      } else {
+        return 'Breakpoint ${number} at ${location}';
+      }
     } else {
       return 'Uninitialized breakpoint';
     }
diff --git a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
index a51a2b3..b735254 100644
--- a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
+++ b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
@@ -5,10 +5,14 @@
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
 import 'test_helper.dart';
 import 'deferred_library.dart' deferred as deferredLib;
 import 'dart:async';
 
+const int LINE_A = 24;
+const int LINE_B = 26;
+
 int value = 0;
 
 int incValue(int amount) {
@@ -17,9 +21,9 @@
 }
 
 Future testMain() async {
-  incValue(incValue(1));  // line 20
+  incValue(incValue(1));  // line A.
 
-  incValue(incValue(1));  // line 22
+  incValue(incValue(1));  // line B.
 
   await deferredLib.loadLibrary();
   deferredLib.deferredTest();
@@ -35,17 +39,17 @@
     var script = rootLib.scripts[0];
 
     // Future breakpoint.
-    var futureBpt1 = await isolate.addBreakpoint(script, 20);
+    var futureBpt1 = await isolate.addBreakpoint(script, LINE_A);
     expect(futureBpt1.number, equals(1));
     expect(futureBpt1.resolved, isFalse);
-    expect(await futureBpt1.location.getLine(), equals(20));
+    expect(await futureBpt1.location.getLine(), equals(LINE_A));
     expect(await futureBpt1.location.getColumn(), equals(null));
 
     // Future breakpoint with specific column.
-    var futureBpt2 = await isolate.addBreakpoint(script, 20, 3);
+    var futureBpt2 = await isolate.addBreakpoint(script, LINE_A, 3);
     expect(futureBpt2.number, equals(2));
     expect(futureBpt2.resolved, isFalse);
-    expect(await futureBpt2.location.getLine(), equals(20));
+    expect(await futureBpt2.location.getLine(), equals(LINE_A));
     expect(await futureBpt2.location.getColumn(), equals(3));
 
     var stream = await isolate.vm.getEventStream(VM.kDebugStream);
@@ -67,10 +71,10 @@
     // After resolution the breakpoints have assigned line & column.
     expect(resolvedCount, equals(2));
     expect(futureBpt1.resolved, isTrue);
-    expect(await futureBpt1.location.getLine(), equals(20));
+    expect(await futureBpt1.location.getLine(), equals(LINE_A));
     expect(await futureBpt1.location.getColumn(), equals(12));
     expect(futureBpt2.resolved, isTrue);
-    expect(await futureBpt2.location.getLine(), equals(20));
+    expect(await futureBpt2.location.getLine(), equals(LINE_A));
     expect(await futureBpt2.location.getColumn(), equals(3));
 
     // The first breakpoint hits before value is modified.
@@ -176,19 +180,19 @@
     var script = isolate.rootLibrary.scripts[0];
     // Try all columns, including some columns that are too big.
     for (int col = 1; col <= 50; col++) {
-      var bpt = await isolate.addBreakpoint(script, 20, col);
+      var bpt = await isolate.addBreakpoint(script, LINE_A, col);
       expect(bpt.resolved, isTrue);
       int resolvedLine = await bpt.location.getLine();
       int resolvedCol = await bpt.location.getColumn();
       print('20:${col} -> ${resolvedLine}:${resolvedCol}');
       if (col <= 10) {
-        expect(resolvedLine, equals(20));
+        expect(resolvedLine, equals(LINE_A));
         expect(resolvedCol, equals(3));
       } else if (col <= 19) {
-        expect(resolvedLine, equals(20));
+        expect(resolvedLine, equals(LINE_A));
         expect(resolvedCol, equals(12));
       } else {
-        expect(resolvedLine, equals(22));
+        expect(resolvedLine, equals(LINE_B));
         expect(resolvedCol, equals(12));
       }
       expect((await isolate.removeBreakpoint(bpt)).type, equals('Success'));
diff --git a/runtime/observatory/tests/service/async_continuation_test.dart b/runtime/observatory/tests/service/async_continuation_test.dart
deleted file mode 100644
index dfbad2d..0000000
--- a/runtime/observatory/tests/service/async_continuation_test.dart
+++ /dev/null
@@ -1,95 +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.
-// VMOptions=--error_on_bad_type --error_on_bad_override --verbose-debug
-
-import 'dart:async';
-import 'dart:developer';
-import 'package:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
-import 'test_helper.dart';
-
-foo() {}
-
-doSync() {
-  foo();  // Line 15
-}
-
-doAsync() async {
-  foo();  // Line 19
-  await null;
-}
-
-doAsyncStar() async* {
-  foo();  // Line 24
-  yield null;
-}
-
-testeeDo() {
-  debugger();
-
-  doSync();
-
-  doAsync();
-
-  doAsyncStar().listen((_) => null);
-}
-
-test(Isolate isolate) async {
-  await isolate.rootLibrary.load();
-  var script = isolate.rootLibrary.scripts[0];
-
-  var bp1 = await isolate.addBreakpoint(script, 15);
-  expect(bp1, isNotNull);
-  expect(bp1 is Breakpoint, isTrue);
-
-  var bp2 = await isolate.addBreakpoint(script, 19);
-  expect(bp2, isNotNull);
-  expect(bp2 is Breakpoint, isTrue);
-
-  var bp3 = await isolate.addBreakpoint(script, 24);
-  expect(bp3, isNotNull);
-  expect(bp3 is Breakpoint, isTrue);
-
-  isolate.resume();
-
-  var bp1_hit = new Completer();
-  var bp2_hit = new Completer();
-  var bp3_hit = new Completer();
-
-  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
-  stream.listen((ServiceEvent event) async {
-    print("Event: $event");
-    if (event.kind == ServiceEvent.kPauseBreakpoint) {
-      var bp = event.breakpoint;
-      print('Hit $bp');
-      if (bp == bp1) {
-        await stoppedAtLine(15)(isolate);
-        print(event.asyncContinuation);
-        expect(event.asyncContinuation, equals(null));
-        isolate.resume();
-        bp1_hit.complete(null);
-      }
-      if (bp == bp2) {
-        await stoppedAtLine(19)(isolate);
-        print(event.asyncContinuation);
-        expect(event.asyncContinuation.isClosure, isTrue);
-        isolate.resume();
-        bp2_hit.complete(null);
-      }
-      if (bp == bp3) {
-        await stoppedAtLine(24)(isolate);
-        print(event.asyncContinuation);
-        expect(event.asyncContinuation.isClosure, isTrue);
-        isolate.resume();
-        bp3_hit.complete(null);
-      }
-    }
-  });
-
-  await bp1_hit.future;
-  await bp2_hit.future;
-  await bp3_hit.future;
-}
-
-main(args) => runIsolateTests(args, [test], testeeConcurrent: testeeDo);
diff --git a/runtime/observatory/tests/service/async_next_test.dart b/runtime/observatory/tests/service/async_next_test.dart
index dbdc19b..4fefcca 100644
--- a/runtime/observatory/tests/service/async_next_test.dart
+++ b/runtime/observatory/tests/service/async_next_test.dart
@@ -4,16 +4,21 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override  --verbose_debug
 
 import 'package:observatory/service_io.dart';
+import 'service_test_common.dart';
 import 'test_helper.dart';
 import 'dart:developer';
 
+const int LINE_A = 19;
+const int LINE_B = 20;
+const int LINE_C = 21;
+
 foo() async { }
 
 doAsync(stop) async {
   if (stop) debugger();
-  await foo(); // Line 14.
-  await foo(); // Line 15.
-  await foo(); // Line 16.
+  await foo(); // Line A.
+  await foo(); // Line B.
+  await foo(); // Line C.
   return null;
 }
 
@@ -26,19 +31,20 @@
 
 asyncNext(Isolate isolate) async {
   print('asyncNext');
-  List asyncStepFutures = await isolate.asyncStepOver();
-  return asyncStepFutures[Isolate.kSecondResume];
+  return asyncStepOver(isolate);
 }
 
 var tests = [
   hasStoppedAtBreakpoint,
-  stoppedAtLine(14),
+  stoppedAtLine(LINE_A),
+  stepOver, // foo()
   asyncNext,
   hasStoppedAtBreakpoint,
-  stoppedAtLine(15),
+  stoppedAtLine(LINE_B),
+  stepOver, // foo()
   asyncNext,
   hasStoppedAtBreakpoint,
-  stoppedAtLine(16),
+  stoppedAtLine(LINE_C),
   resumeIsolate,
 ];
 
diff --git a/runtime/observatory/tests/service/async_scope_test.dart b/runtime/observatory/tests/service/async_scope_test.dart
index a3f97cc..170a638 100644
--- a/runtime/observatory/tests/service/async_scope_test.dart
+++ b/runtime/observatory/tests/service/async_scope_test.dart
@@ -6,19 +6,23 @@
 import 'dart:developer';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
 import 'test_helper.dart';
 
+const int LINE_A = 19;
+const int LINE_B = 25;
+
 foo() {}
 
 doAsync(param1) async {
   var local1 = param1 + 1;
-  foo(); // Line 15
+  foo(); // Line A.
   await local1;
 }
 
 doAsyncStar(param2) async* {
   var local2 = param2 + 1;
-  foo(); // Line 21
+  foo(); // Line B.
   yield local2;
 }
 
@@ -53,17 +57,17 @@
 
 var tests = [
   hasStoppedAtBreakpoint, // debugger()
-  setBreakpointAtLine(15),
-  setBreakpointAtLine(21),
+  setBreakpointAtLine(LINE_A),
+  setBreakpointAtLine(LINE_B),
   resumeIsolate,
 
   hasStoppedAtBreakpoint,
-  stoppedAtLine(15),
+  stoppedAtLine(LINE_A),
   checkAsyncVarDescriptors,
   resumeIsolate,
 
   hasStoppedAtBreakpoint,
-  stoppedAtLine(21),
+  stoppedAtLine(LINE_B),
   checkAsyncStarVarDescriptors,
   resumeIsolate,
 ];
diff --git a/runtime/observatory/tests/service/break_on_function_test.dart b/runtime/observatory/tests/service/break_on_function_test.dart
index 1a0e0ee..e428b25 100644
--- a/runtime/observatory/tests/service/break_on_function_test.dart
+++ b/runtime/observatory/tests/service/break_on_function_test.dart
@@ -5,10 +5,13 @@
 
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
 import 'test_helper.dart';
 import 'dart:developer';
 
-testFunction(flag) {  // Line 11
+const int LINE_A = 14;
+
+testFunction(flag) {  // Line A.
   if (flag) {
     print("Yes");
   } else {
@@ -40,11 +43,11 @@
 resumeIsolate,
 
 hasStoppedAtBreakpoint,
-stoppedAtLine(11),
+stoppedAtLine(LINE_A),
 resumeIsolate,
 
 hasStoppedAtBreakpoint,
-stoppedAtLine(11),
+stoppedAtLine(LINE_A),
 resumeIsolate,
 
 ];
diff --git a/runtime/observatory/tests/service/capture_stdio_test.dart b/runtime/observatory/tests/service/capture_stdio_test.dart
index 56a1451..279d055 100644
--- a/runtime/observatory/tests/service/capture_stdio_test.dart
+++ b/runtime/observatory/tests/service/capture_stdio_test.dart
@@ -8,6 +8,7 @@
 import 'dart:io';
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
 import 'test_helper.dart';
 
 void test() {
diff --git a/runtime/observatory/tests/service/coverage_test.dart b/runtime/observatory/tests/service/coverage_test.dart
index 7a8ee93..1266500 100644
--- a/runtime/observatory/tests/service/coverage_test.dart
+++ b/runtime/observatory/tests/service/coverage_test.dart
@@ -6,13 +6,18 @@
 import 'package:observatory/service_io.dart';
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
+import 'service_test_common.dart';
 import 'dart:developer';
 
+const int LINE_A = 20;
+const int LINE_B = 38;
+const int LINE_C = 136;
+
 int globalVar = 100;
 
 class MyClass {
   static void myFunction(int value) {
-    if (value < 0) {
+    if (value < 0) {  // Line A.
       print("negative");
     } else {
       print("positive");
@@ -30,7 +35,7 @@
 }
 
 void testFunction() {
-  MyClass.otherFunction(-100);
+  MyClass.otherFunction(-100);  // Line B.
   MyClass.myFunction(10000);
 }
 
@@ -60,7 +65,10 @@
   expect(coverage['type'], equals('CodeCoverage'));
   expect(coverage['coverage'].length, equals(1));
   expect(coverage['coverage'][0]['hits'],
-         equals([15, 1, 16, 0, 18, 1, 20, 1]));
+         equals([LINE_A, 1,
+                 LINE_A + 1, 0,
+                 LINE_A + 3, 1,
+                 LINE_A + 5, 1]));
 
   // Class
   coverage = await isolate.invokeRpcNoUpgrade('_getCoverage',
@@ -68,8 +76,14 @@
   expect(coverage['type'], equals('CodeCoverage'));
   expect(coverage['coverage'].length, equals(1));
   expect(coverage['coverage'][0]['hits'],
-         equals([15, 1, 16, 0, 18, 1, 20, 1,
-                 24, 1, 25, 1, 27, 0, 13, 0]));
+         equals([LINE_A, 1,
+                 LINE_A + 1, 0,
+                 LINE_A + 3, 1,
+                 LINE_A + 5, 1,
+                 LINE_A + 9, 1,
+                 LINE_A + 10, 1,
+                 LINE_A + 12, 0,
+                 LINE_A - 2, 0]));
 
   // Library
   coverage = await isolate.invokeRpcNoUpgrade('_getCoverage',
@@ -77,10 +91,18 @@
   expect(coverage['type'], equals('CodeCoverage'));
   expect(coverage['coverage'].length, equals(4));
   expect(coverage['coverage'][0]['hits'],
-         equals([15, 1, 16, 0, 18, 1, 20, 1,
-                 24, 1, 25, 1, 27, 0, 13, 0]));
+         equals([LINE_A, 1,
+                 LINE_A + 1, 0,
+                 LINE_A + 3, 1,
+                 LINE_A + 5, 1,
+                 LINE_A + 9, 1,
+                 LINE_A + 10, 1,
+                 LINE_A + 12, 0,
+                 LINE_A - 2, 0]));
   expect(coverage['coverage'][1]['hits'],
-         equals([33, 1, 34, 1, 106, 2]));
+         equals([LINE_B, 1,
+                 LINE_B + 1, 1,
+                 LINE_C, 2]));
 
   // Script
   await cls.load();
@@ -89,10 +111,18 @@
   expect(coverage['type'], equals('CodeCoverage'));
   expect(coverage['coverage'].length, equals(4));
   expect(coverage['coverage'][0]['hits'],
-         equals([15, 1, 16, 0, 18, 1, 20, 1,
-                 24, 1, 25, 1, 27, 0, 13, 0]));
+         equals([LINE_A, 1,
+                 LINE_A + 1, 0,
+                 LINE_A + 3, 1,
+                 LINE_A + 5, 1,
+                 LINE_A + 9, 1,
+                 LINE_A + 10, 1,
+                 LINE_A + 12, 0,
+                 LINE_A - 2, 0]));
   expect(coverage['coverage'][1]['hits'],
-         equals([33, 1, 34, 1, 106, 2]));
+         equals([LINE_B, 1,
+                 LINE_B + 1, 1,
+                 LINE_C, 2]));
 
   // Isolate
   coverage = await isolate.invokeRpcNoUpgrade('_getCoverage', {});
@@ -103,6 +133,6 @@
 
 ];
 
-main(args) => runIsolateTests(args, tests,
+main(args) => runIsolateTests(args, tests,    // Line C.
                               testeeConcurrent: testFunction,
                               trace_service: true);
diff --git a/runtime/observatory/tests/service/debugger_location_test.dart b/runtime/observatory/tests/service/debugger_location_test.dart
index ab50f4d..53ed4fb 100644
--- a/runtime/observatory/tests/service/debugger_location_test.dart
+++ b/runtime/observatory/tests/service/debugger_location_test.dart
@@ -6,15 +6,20 @@
 import 'package:observatory/service_io.dart';
 import 'package:observatory/debugger.dart';
 import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
 import 'test_helper.dart';
 import 'dart:async';
 import 'dart:developer';
 
+const int LINE_A = 22;
+const int LINE_B = 112;
+const int LINE_C = 12;
+
 void testFunction() {
   int i = 0;
   while (i == 0) {
     debugger();
-    print('loop');
+    print('loop');  // Line A.
     print('loop');
   }
 }
@@ -59,7 +64,7 @@
   var debugger = await initDebugger(isolate);
   var loc = await DebuggerLocation.parse(debugger, '');
   expect(loc.valid, isTrue);
-  expect(loc.toString(), equals('debugger_location_test.dart:17:5'));
+  expect(loc.toString(), equals('debugger_location_test.dart:$LINE_A:5'));
 },
 
 // Parse line
@@ -236,22 +241,18 @@
       await DebuggerLocation.complete(debugger,
                                       'debugger_location_test.dart:11');
   expect(completions.toString(), equals(
-      '[debugger_location_test.dart:110 ,'
-      ' debugger_location_test.dart:110:,'
-      ' debugger_location_test.dart:111 ,'
-      ' debugger_location_test.dart:111:,'
-      ' debugger_location_test.dart:112 ,'
-      ' debugger_location_test.dart:112:,'
-      ' debugger_location_test.dart:115 ,'
-      ' debugger_location_test.dart:115:,'
-      ' debugger_location_test.dart:116 ,'
-      ' debugger_location_test.dart:116:,'
-      ' debugger_location_test.dart:117 ,'
-      ' debugger_location_test.dart:117:,'
-      ' debugger_location_test.dart:118 ,'
-      ' debugger_location_test.dart:118:,'
-      ' debugger_location_test.dart:119 ,'
-      ' debugger_location_test.dart:119:]'));
+      '[debugger_location_test.dart:${LINE_B + 0} ,'
+      ' debugger_location_test.dart:${LINE_B + 0}:,'
+      ' debugger_location_test.dart:${LINE_B + 1} ,'
+      ' debugger_location_test.dart:${LINE_B + 1}:,'
+      ' debugger_location_test.dart:${LINE_B + 2} ,'
+      ' debugger_location_test.dart:${LINE_B + 2}:,'
+      ' debugger_location_test.dart:${LINE_B + 3} ,'
+      ' debugger_location_test.dart:${LINE_B + 3}:,'
+      ' debugger_location_test.dart:${LINE_B + 4} ,'
+      ' debugger_location_test.dart:${LINE_B + 4}:,'
+      ' debugger_location_test.dart:${LINE_B + 5} ,'
+      ' debugger_location_test.dart:${LINE_B + 5}:]'));
 },
 
 // Complete script:line:col
@@ -259,27 +260,27 @@
   var debugger = await initDebugger(isolate);
   var completions =
       await DebuggerLocation.complete(debugger,
-                                      'debugger_location_test.dart:11:2');
+                                      'debugger_location_test.dart:$LINE_C:2');
   expect(completions.toString(), equals(
-      '[debugger_location_test.dart:11:2 ,'
-      ' debugger_location_test.dart:11:20 ,'
-      ' debugger_location_test.dart:11:21 ,'
-      ' debugger_location_test.dart:11:22 ,'
-      ' debugger_location_test.dart:11:23 ,'
-      ' debugger_location_test.dart:11:24 ]'));
+      '[debugger_location_test.dart:$LINE_C:2 ,'
+      ' debugger_location_test.dart:$LINE_C:20 ,'
+      ' debugger_location_test.dart:$LINE_C:21 ,'
+      ' debugger_location_test.dart:$LINE_C:22 ,'
+      ' debugger_location_test.dart:$LINE_C:23 ,'
+      ' debugger_location_test.dart:$LINE_C:24 ]'));
 },
 
 // Complete without the script name.
 (Isolate isolate) async {
   var debugger = await initDebugger(isolate);
-  var completions = await DebuggerLocation.complete(debugger, '11:2');
+  var completions = await DebuggerLocation.complete(debugger, '$LINE_C:2');
   expect(completions.toString(), equals(
-      '[debugger_location_test.dart:11:2 ,'
-      ' debugger_location_test.dart:11:20 ,'
-      ' debugger_location_test.dart:11:21 ,'
-      ' debugger_location_test.dart:11:22 ,'
-      ' debugger_location_test.dart:11:23 ,'
-      ' debugger_location_test.dart:11:24 ]'));
+      '[debugger_location_test.dart:$LINE_C:2 ,'
+      ' debugger_location_test.dart:$LINE_C:20 ,'
+      ' debugger_location_test.dart:$LINE_C:21 ,'
+      ' debugger_location_test.dart:$LINE_C:22 ,'
+      ' debugger_location_test.dart:$LINE_C:23 ,'
+      ' debugger_location_test.dart:$LINE_C:24 ]'));
 },
 
 ];