Version 1.15.0-dev.0.0

Merge commit '6a4903f20174697d732b6b6afbfd87c04fde47f8' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3fffad..7702384 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.15.0
+
+### Core library changes
+  * Added `Uri.queryParametersAll` to handle multiple query parameters with
+    the same name.
+
 ## 1.14.0
 
 ### Core library changes
@@ -10,8 +16,10 @@
 
 * `dart:core`
   * Added `current` getter to `StackTrace` class.
-  * Added `Uri.data` getter for `data:` URIs, and `UriData` class for the
-    return type.
+  * `Uri` class added support for data URIs
+      * Added two new constructors: `dataFromBytes` and `dataFromString`.
+      * Added a `data` getter for `data:` URIs with a new `UriData` class for
+      the return type.
   * Added `growable` parameter to `List.filled` constructor.
   * Added microsecond support to `DateTime`: `DateTime.microsecond`,
     `DateTime.microsecondsSinceEpoch`, and
@@ -23,14 +31,25 @@
     embedder for every generated random value.
 
 * `dart:io`
-  * `Platform` added an `isIOS` getter and `Platform.operatingSystem` may now
-    return `ios`.
-  * Added support for WebSocket compression as standardized in RFC 7692. By
-    default compression is turned on for all WebSocket connections. The
-    optionally named parameter `compression` on the methods `WebSocket.connect`,
-    `WebSocket.fromUpgradedSocket`, and `WebSocketTransformer.upgrade` and on
-    the `WebSocketTransformer` constructor is used to select the compression
-    options.
+  * `Platform` added a static `isIOS` getter and `Platform.operatingSystem` may
+    now return `ios`.
+  * `Platform` added a static `packageConfig` getter.
+  * Added support for WebSocket compression as standardized in RFC 7692.
+  * Compression is enabled by default for all WebSocket connections.
+      * The optionally named parameter `compression` on the methods
+      `WebSocket.connect`, `WebSocket.fromUpgradedSocket`, and
+      `WebSocketTransformer.upgrade` and  the `WebSocketTransformer`
+      constructor can be used to modify or disable compression using the new
+      `CompressionOptions` class.
+
+* `dart:isolate`
+  * Added **_experimental_** support for [Package Resolution Configuration].
+    * Added `packageConfig` and `packageRoot` instance getters to `Isolate`.
+    * Added a `resolvePackageUri` method to `Isolate`.
+    * Added named arguments `packageConfig` and `automaticPackageResolution` to
+    the `Isolate.spawnUri` constructor.
+
+[Package Resolution Configuration File]: https://github.com/dart-lang/dart_enhancement_proposals/blob/master/Accepted/0005%20-%20Package%20Specification/DEP-pkgspec.md
 
 ### Tool changes
 
diff --git a/DEPS b/DEPS
index fbe59dc..fdb11dc 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,7 @@
   "dart2js_info_rev" : "@0a221eaf16aec3879c45719de656680ccb80d8a1",
   "dartdoc_tag" : "@v0.8.5",
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
-  "dart_style_tag": "@0.2.2",
+  "dart_style_tag": "@0.2.4",
   "dev_compiler_rev": "@0.1.9",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
   "html_tag" : "@0.12.1+1",
@@ -86,7 +86,6 @@
   "test_tag": "@0.12.6+1",
   "test_reflective_loader_tag": "@0.0.3",
   "utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
-  "unittest_tag": "@0.11.6",
   "usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
   "watcher_tag": "@0.9.7",
   "when_tag": "@0.2.0+2",
@@ -256,8 +255,6 @@
   Var("dart_root") + "/third_party/pkg/test_reflective_loader":
       (Var("github_mirror") % "test_reflective_loader") +
       Var("test_reflective_loader_tag"),
-  Var("dart_root") + "/third_party/pkg/unittest":
-      (Var("github_mirror") % "test") + Var("unittest_tag"),
   Var("dart_root") + "/third_party/pkg/usage":
       (Var("github_mirror") % "usage") + Var("usage_rev"),
   Var("dart_root") + "/third_party/pkg/utf":
@@ -384,6 +381,22 @@
     ],
   },
   {
+    "name": "unittest",
+    # Unittest is an early version, 0.11.6, of the package "test"
+    # Do not use it in any new tests.
+    "pattern": ".",
+    "action": [
+      "download_from_google_storage",
+      "--no_auth",
+      "--no_resume",
+      "--bucket",
+      "dart-dependencies",
+      "--extract",
+      "-s",
+      Var('dart_root') + "/third_party/pkg/unittest.tar.gz.sha1",
+    ],
+  },
+  {
     "name": "7zip",
     "pattern": ".",
     "action": [
diff --git a/dart.gyp b/dart.gyp
index 3e73877..a0c5a85 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -25,7 +25,7 @@
       'type': 'none',
       'dependencies': [
         'runtime/dart-runtime.gyp:dart',
-        'runtime/dart-runtime.gyp:dart_precompiled',
+        'runtime/dart-runtime.gyp:dart_precompiled_runtime',
         'runtime/dart-runtime.gyp:dart_no_snapshot',
         'runtime/dart-runtime.gyp:run_vm_tests',
         'runtime/dart-runtime.gyp:process_test',
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index fb3a9e4..25a0c0d 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -1547,7 +1547,7 @@
 Any expression that appears within the initializer list of a constant constructor must be a potentially constant expression, or a compile-time error occurs. 
 
 \LMHash{}
-A {\em potentially constant expression} is an expression $e$ that would be a valid constant expression if all formal parameters of $e$'s immediately enclosing constant constructor were treated as compile-time constants that were guaranteed to evaluate to an integer, boolean or string value as required by their immediately enclosing superexpression.
+A {\em potentially constant expression} is an expression $e$ that would be a valid constant expression if all formal parameters of $e$'s immediately enclosing constant constructor were treated as compile-time constants that were guaranteed to evaluate to an integer, boolean or string value as required by their immediately enclosing superexpression, <em>and</em> where $e$ is also a valid expression if all the formal parameters are treated as non-constant variables.
 
 \commentary{
 Note that a parameter that is not used in a superexpression that is restricted to certain types can be a constant of any type. For example}
diff --git a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
index 2da3812..863ced0 100644
--- a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
@@ -61,7 +61,7 @@
       return Assist.EMPTY_LIST;
     }
     CompilationUnit unit =
-        analysisContext.resolveCompilationUnit2(source, libraries[0]);
+        analysisContext.getResolvedCompilationUnit2(source, libraries[0]);
     if (unit == null) {
       return Assist.EMPTY_LIST;
     }
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
index e8f7104..6ef1bed 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -44,7 +44,7 @@
       return Fix.EMPTY_LIST;
     }
     CompilationUnit unit =
-        analysisContext.resolveCompilationUnit2(source, libraries[0]);
+        analysisContext.getResolvedCompilationUnit2(source, libraries[0]);
     if (unit == null) {
       return Fix.EMPTY_LIST;
     }
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 45467ca..02c4f70 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -6,6 +6,7 @@
 
 import 'package:analysis_server/plugin/protocol/protocol.dart'
     show HoverInformation;
+import 'package:analysis_server/src/computer/computer_overrides.dart';
 import 'package:analysis_server/src/utilities/documentation.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/ast.dart';
@@ -69,7 +70,6 @@
             hover.containingLibraryPath = library.source.fullName;
           }
         }
-
         // documentation
         hover.dartdoc = _computeDocumentation(element);
       }
@@ -91,7 +91,23 @@
     if (element is ParameterElement) {
       element = element.enclosingElement;
     }
-    return removeDartDocDelimiters(element.documentationComment);
+    // The documentation of the element itself.
+    if (element.documentationComment != null) {
+      return removeDartDocDelimiters(element.documentationComment);
+    }
+    // Look for documentation comments of overridden members.
+    OverriddenElements overridden = findOverriddenElements(element);
+    for (Element superElement in []
+      ..addAll(overridden.superElements)
+      ..addAll(overridden.interfaceElements)) {
+      String rawDoc = superElement.documentationComment;
+      if (rawDoc != null) {
+        Element interfaceClass = superElement.enclosingElement;
+        return removeDartDocDelimiters(rawDoc) +
+            '\n\nCopied from `${interfaceClass.displayName}`.';
+      }
+    }
+    return null;
   }
 
   static _safeToString(obj) => obj != null ? obj.toString() : null;
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
index 4e2e00b..4eb93d1 100644
--- a/pkg/analysis_server/lib/src/computer/computer_overrides.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
@@ -5,15 +5,106 @@
 library computer.overrides;
 
 import 'package:analysis_server/src/collections.dart';
-import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analyzer/dart/element/element.dart' as engine;
-import 'package:analyzer/dart/element/type.dart' as engine;
+import 'package:analysis_server/src/protocol_server.dart' as proto;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/ast.dart';
 
 /**
+ * Return the elements that the given [element] overrides.
+ */
+OverriddenElements findOverriddenElements(Element element) {
+  if (element?.enclosingElement is ClassElement) {
+    return new _OverriddenElementsFinder(element).find();
+  }
+  return new OverriddenElements(element, <Element>[], <Element>[]);
+}
+
+/**
  * A computer for class member overrides in a Dart [CompilationUnit].
  */
 class DartUnitOverridesComputer {
+  final CompilationUnit _unit;
+  final List<proto.Override> _overrides = <proto.Override>[];
+
+  DartUnitOverridesComputer(this._unit);
+
+  /**
+   * Returns the computed occurrences, not `null`.
+   */
+  List<proto.Override> compute() {
+    for (CompilationUnitMember unitMember in _unit.declarations) {
+      if (unitMember is ClassDeclaration) {
+        for (ClassMember classMember in unitMember.members) {
+          if (classMember is MethodDeclaration) {
+            if (classMember.isStatic) {
+              continue;
+            }
+            _addOverride(classMember.name);
+          }
+          if (classMember is FieldDeclaration) {
+            if (classMember.isStatic) {
+              continue;
+            }
+            List<VariableDeclaration> fields = classMember.fields.variables;
+            for (VariableDeclaration field in fields) {
+              _addOverride(field.name);
+            }
+          }
+        }
+      }
+    }
+    return _overrides;
+  }
+
+  /**
+   * Add a new [Override] for the declaration with the given name [node].
+   */
+  void _addOverride(SimpleIdentifier node) {
+    Element element = node.staticElement;
+    OverriddenElements overridesResult =
+        new _OverriddenElementsFinder(element).find();
+    List<Element> superElements = overridesResult.superElements;
+    List<Element> interfaceElements = overridesResult.interfaceElements;
+    if (superElements.isNotEmpty || interfaceElements.isNotEmpty) {
+      proto.OverriddenMember superMember = superElements.isNotEmpty
+          ? proto.newOverriddenMember_fromEngine(superElements.first)
+          : null;
+      List<proto.OverriddenMember> interfaceMembers = interfaceElements
+          .map((member) => proto.newOverriddenMember_fromEngine(member))
+          .toList();
+      _overrides.add(new proto.Override(node.offset, node.length,
+          superclassMember: superMember,
+          interfaceMembers: nullIfEmpty(interfaceMembers)));
+    }
+  }
+}
+
+/**
+ * The container with elements that a class member overrides.
+ */
+class OverriddenElements {
+  /**
+   * The element that overrides other class members.
+   */
+  final Element element;
+
+  /**
+   * The elements that [element] overrides and which is defined in a class that
+   * is a superclass of the class that defines [element].
+   */
+  final List<Element> superElements;
+
+  /**
+   * The elements that [element] overrides and which is defined in a class that
+   * which is implemented by the class that defines [element].
+   */
+  final List<Element> interfaceElements;
+
+  OverriddenElements(this.element, this.superElements, this.interfaceElements);
+}
+
+class _OverriddenElementsFinder {
   static const List<ElementKind> FIELD_KINDS = const <ElementKind>[
     ElementKind.FIELD,
     ElementKind.GETTER,
@@ -34,138 +125,102 @@
     ElementKind.SETTER
   ];
 
-  final CompilationUnit _unit;
+  Element _seed;
+  LibraryElement _library;
+  ClassElement _class;
+  String _name;
+  List<ElementKind> _kinds;
 
-  final List<Override> _overrides = <Override>[];
-  engine.ClassElement _currentClass;
+  List<Element> _superElements = <Element>[];
+  List<Element> _interfaceElements = <Element>[];
+  Set<InterfaceType> _visited = new Set<InterfaceType>();
 
-  DartUnitOverridesComputer(this._unit);
-
-  /**
-   * Returns the computed occurrences, not `null`.
-   */
-  List<Override> compute() {
-    for (CompilationUnitMember unitMember in _unit.declarations) {
-      if (unitMember is ClassDeclaration) {
-        _currentClass = unitMember.element;
-        for (ClassMember classMember in unitMember.members) {
-          if (classMember is MethodDeclaration) {
-            if (classMember.isStatic) {
-              continue;
-            }
-            SimpleIdentifier nameNode = classMember.name;
-            List<ElementKind> kinds;
-            if (classMember.isGetter) {
-              kinds = GETTER_KINDS;
-            } else if (classMember.isSetter) {
-              kinds = SETTER_KINDS;
-            } else {
-              kinds = METHOD_KINDS;
-            }
-            _addOverride(
-                nameNode.offset, nameNode.length, nameNode.name, kinds);
-          }
-          if (classMember is FieldDeclaration) {
-            if (classMember.isStatic) {
-              continue;
-            }
-            List<VariableDeclaration> fields = classMember.fields.variables;
-            for (VariableDeclaration field in fields) {
-              SimpleIdentifier nameNode = field.name;
-              _addOverride(
-                  nameNode.offset, nameNode.length, nameNode.name, FIELD_KINDS);
-            }
-          }
-        }
-      }
+  _OverriddenElementsFinder(Element seed) {
+    _seed = seed;
+    _class = seed.enclosingElement;
+    _library = _class.library;
+    _name = seed.displayName;
+    if (seed is MethodElement) {
+      _kinds = METHOD_KINDS;
+    } else if (seed is PropertyAccessorElement) {
+      _kinds = seed.isGetter ? GETTER_KINDS : SETTER_KINDS;
+    } else {
+      _kinds = FIELD_KINDS;
     }
-    return _overrides;
   }
 
-  void _addInterfaceOverrides(
-      Set<engine.Element> elements,
-      String name,
-      List<ElementKind> kinds,
-      engine.InterfaceType type,
-      bool checkType,
-      Set<engine.InterfaceType> visited) {
+  /**
+   * Add the [OverriddenElements] for this element.
+   */
+  OverriddenElements find() {
+    _visited.clear();
+    _addSuperOverrides(_class.supertype);
+    _visited.clear();
+    _addInterfaceOverrides(_class.type, false);
+    _superElements.forEach(_interfaceElements.remove);
+    return new OverriddenElements(_seed, _superElements, _interfaceElements);
+  }
+
+  void _addInterfaceOverrides(InterfaceType type, bool checkType) {
     if (type == null) {
       return;
     }
-    if (!visited.add(type)) {
+    if (!_visited.add(type)) {
       return;
     }
-    // check type
+    // this type
     if (checkType) {
-      engine.Element element = _lookupMember(type.element, name, kinds);
-      if (element != null) {
-        elements.add(element);
-        return;
-      }
-    }
-    // check interfaces
-    for (engine.InterfaceType interfaceType in type.interfaces) {
-      _addInterfaceOverrides(
-          elements, name, kinds, interfaceType, true, visited);
-    }
-    // check super
-    _addInterfaceOverrides(
-        elements, name, kinds, type.superclass, checkType, visited);
-  }
-
-  void _addOverride(
-      int offset, int length, String name, List<ElementKind> kinds) {
-    // super
-    engine.Element superEngineElement;
-    {
-      engine.InterfaceType superType = _currentClass.supertype;
-      if (superType != null) {
-        superEngineElement = _lookupMember(superType.element, name, kinds);
+      Element element = _lookupMember(type.element);
+      if (element != null && !_interfaceElements.contains(element)) {
+        _interfaceElements.add(element);
       }
     }
     // interfaces
-    Set<engine.Element> interfaceEngineElements = new Set<engine.Element>();
-    _addInterfaceOverrides(interfaceEngineElements, name, kinds,
-        _currentClass.type, false, new Set<engine.InterfaceType>());
-    interfaceEngineElements.remove(superEngineElement);
-    // is there any override?
-    if (superEngineElement != null || interfaceEngineElements.isNotEmpty) {
-      OverriddenMember superMember = superEngineElement != null
-          ? newOverriddenMember_fromEngine(superEngineElement)
-          : null;
-      List<OverriddenMember> interfaceMembers = interfaceEngineElements
-          .map((member) => newOverriddenMember_fromEngine(member))
-          .toList();
-      _overrides.add(new Override(offset, length,
-          superclassMember: superMember,
-          interfaceMembers: nullIfEmpty(interfaceMembers)));
+    for (InterfaceType interfaceType in type.interfaces) {
+      _addInterfaceOverrides(interfaceType, true);
     }
+    // super
+    _addInterfaceOverrides(type.superclass, checkType);
   }
 
-  static engine.Element _lookupMember(
-      engine.ClassElement classElement, String name, List<ElementKind> kinds) {
+  void _addSuperOverrides(InterfaceType type) {
+    if (type == null) {
+      return;
+    }
+    if (!_visited.add(type)) {
+      return;
+    }
+    // this type
+    Element element = _lookupMember(type.element);
+    if (element != null && !_superElements.contains(element)) {
+      _superElements.add(element);
+    }
+    // super
+    _addSuperOverrides(type.superclass);
+  }
+
+  Element _lookupMember(ClassElement classElement) {
     if (classElement == null) {
       return null;
     }
-    engine.LibraryElement library = classElement.library;
-    engine.Element member;
+    Element member;
     // method
-    if (kinds.contains(ElementKind.METHOD)) {
-      member = classElement.lookUpMethod(name, library);
+    if (_kinds.contains(ElementKind.METHOD)) {
+      member = classElement.lookUpMethod(_name, _library);
       if (member != null) {
         return member;
       }
     }
     // getter
-    if (kinds.contains(ElementKind.GETTER)) {
-      member = classElement.lookUpGetter(name, library);
+    if (_kinds.contains(ElementKind.GETTER)) {
+      member = classElement.lookUpGetter(_name, _library);
       if (member != null) {
         return member;
       }
     }
     // setter
-    if (kinds.contains(ElementKind.SETTER)) {
-      member = classElement.lookUpSetter(name + '=', library);
+    if (_kinds.contains(ElementKind.SETTER)) {
+      member = classElement.lookUpSetter(_name + '=', _library);
       if (member != null) {
         return member;
       }
diff --git a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
index 5391d5e..42e7213 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
@@ -57,21 +57,23 @@
     if (element.isSynthetic || _isStatic(element)) {
       return;
     }
-    String name = element.displayName;
-    if (name != null && _hasOverride(name)) {
+    if (_hasOverride(element)) {
       _addImplementedMember(element);
     }
   }
 
-  bool _hasOverride(String name) {
+  bool _hasOverride(Element element) {
+    String name = element.displayName;
+    LibraryElement library = element.library;
     for (ClassElement subtype in subtypes) {
-      MethodElement method = subtype.getMethod(name);
-      if (method != null) {
-        return !method.isStatic;
+      ClassMemberElement subElement = subtype.getMethod(name);
+      if (subElement == null) {
+        subElement = subtype.getField(name);
       }
-      FieldElement field = subtype.getField(name);
-      if (field != null) {
-        return !field.isStatic;
+      if (subElement != null &&
+          !subElement.isStatic &&
+          subElement.isAccessibleIn(library)) {
+        return true;
       }
     }
     return false;
diff --git a/pkg/analysis_server/lib/src/search/type_hierarchy.dart b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
index 793e471..e723722 100644
--- a/pkg/analysis_server/lib/src/search/type_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
@@ -175,7 +175,7 @@
         result = clazz.getSetter(_pivotName);
       }
     }
-    if (result != null) {
+    if (result != null && result.isAccessibleIn(_pivotLibrary)) {
       return result;
     }
     // try to find in the class mixin
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 5833af4..664ab74 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -46,8 +46,9 @@
   // create logger
   if (spec == 'console') {
     logger = new StringSinkLogger(stdout);
-  }
-  if (spec.startsWith('file:')) {
+  } else if (spec == 'stderr') {
+    logger = new StringSinkLogger(stderr);
+  } else if (spec.startsWith('file:')) {
     String fileName = spec.substring('file:'.length);
     File file = new File(fileName);
     IOSink sink = file.openWrite();
@@ -485,7 +486,7 @@
         defaultsTo: false,
         negatable: false);
     parser.addOption(INCREMENTAL_RESOLUTION_LOG,
-        help: "the description of the incremental resolution log");
+        help: "set a destination for the incremental resolver's log");
     parser.addFlag(INCREMENTAL_RESOLUTION_VALIDATION,
         help: "enable validation of incremental resolution results (slow)",
         defaultsTo: false,
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index a683638..13714ae 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -1092,17 +1092,15 @@
     Block targetBlock;
     {
       Statement statement = node.getAncestor((n) => n is Statement);
-      prefix = utils.getNodePrefix(statement);
       if (statement is IfStatement && statement.thenStatement is Block) {
         targetBlock = statement.thenStatement;
-      }
-      if (statement is WhileStatement && statement.body is Block) {
+      } else if (statement is WhileStatement && statement.body is Block) {
         targetBlock = statement.body;
+      } else {
+        _coverageMarker();
+        return;
       }
-    }
-    if (targetBlock == null) {
-      _coverageMarker();
-      return;
+      prefix = utils.getNodePrefix(statement);
     }
     // prepare location
     int offset;
diff --git a/pkg/analysis_server/lib/src/services/correction/strings.dart b/pkg/analysis_server/lib/src/services/correction/strings.dart
index 1689c7c..4a0ff76 100644
--- a/pkg/analysis_server/lib/src/services/correction/strings.dart
+++ b/pkg/analysis_server/lib/src/services/correction/strings.dart
@@ -201,6 +201,10 @@
   return str == null || str.isEmpty;
 }
 
+bool isEOL(int c) {
+  return c == 0x0D || c == 0x0A;
+}
+
 bool isLetter(int c) {
   return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
 }
@@ -220,7 +224,7 @@
 }
 
 bool isWhitespace(int c) {
-  return isSpace(c) || c == 0x0D || c == 0x0A;
+  return isSpace(c) || isEOL(c);
 }
 
 String remove(String str, String remove) {
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 33a3105..63aefd9 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -396,17 +396,14 @@
  */
 Expression getNodeQualifier(SimpleIdentifier node) {
   AstNode parent = node.parent;
-  if (parent is PropertyAccess) {
-    PropertyAccess propertyAccess = parent;
-    if (identical(propertyAccess.propertyName, node)) {
-      return propertyAccess.target;
-    }
+  if (parent is MethodInvocation && identical(parent.methodName, node)) {
+    return parent.target;
   }
-  if (parent is PrefixedIdentifier) {
-    PrefixedIdentifier prefixed = parent;
-    if (identical(prefixed.identifier, node)) {
-      return prefixed.prefix;
-    }
+  if (parent is PropertyAccess && identical(parent.propertyName, node)) {
+    return parent.target;
+  }
+  if (parent is PrefixedIdentifier && identical(parent.identifier, node)) {
+    return parent.prefix;
   }
   return null;
 }
@@ -667,7 +664,8 @@
     AstNode enclosingNode = findNode(offset);
     Block enclosingBlock = enclosingNode.getAncestor((node) => node is Block);
     if (enclosingBlock != null) {
-      _CollectReferencedUnprefixedNames visitor = new _CollectReferencedUnprefixedNames();
+      _CollectReferencedUnprefixedNames visitor =
+          new _CollectReferencedUnprefixedNames();
       enclosingBlock.accept(visitor);
       return visitor.names;
     }
@@ -906,10 +904,14 @@
    * Returns a [SourceRange] that covers [range] and extends (if possible) to
    * cover whole lines.
    */
-  SourceRange getLinesRange(SourceRange range) {
+  SourceRange getLinesRange(SourceRange range,
+      {bool skipLeadingEmptyLines: false}) {
     // start
     int startOffset = range.offset;
     int startLineOffset = getLineContentStart(startOffset);
+    if (skipLeadingEmptyLines) {
+      startLineOffset = skipEmptyLinesLeft(startLineOffset);
+    }
     // end
     int endOffset = range.end;
     int afterEndLineOffset = getLineContentEnd(endOffset);
@@ -1224,6 +1226,27 @@
   }
 
   /**
+   * Skip spaces, tabs and EOLs on the left from [index].
+   *
+   * If [index] is the start of a method, then in the most cases return the end
+   * of the previous not-whitespace line.
+   */
+  int skipEmptyLinesLeft(int index) {
+    int lastLine = index;
+    while (index > 0) {
+      int c = _buffer.codeUnitAt(index - 1);
+      if (!isWhitespace(c)) {
+        return lastLine;
+      }
+      if (isEOL(c)) {
+        lastLine = index;
+      }
+      index--;
+    }
+    return 0;
+  }
+
+  /**
    * @return the [ImportElement] used to import given [Element] into [library].
    *         May be `null` if was not imported, i.e. declared in the same library.
    */
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 3b3c786..125c7ba 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -102,7 +102,7 @@
     }
   });
   // replace static field "qualifier" with invocation target
-  part._staticFieldOffsets.forEach((String className, List<int> offsets) {
+  part._implicitClassNameOffsets.forEach((String className, List<int> offsets) {
     for (int offset in offsets) {
 //      edits.add(newSourceEdit_range(range, className + '.'));
       edits.add(new SourceEdit(offset, 0, className + '.'));
@@ -263,7 +263,8 @@
     // delete method
     if (deleteSource && inlineAll) {
       SourceRange methodRange = rangeNode(_methodNode);
-      SourceRange linesRange = _methodUtils.getLinesRange(methodRange);
+      SourceRange linesRange =
+          _methodUtils.getLinesRange(methodRange, skipLeadingEmptyLines: true);
       doSourceChange_addElementEdit(
           change, _methodElement, newSourceEdit_range(linesRange, ''));
     }
@@ -682,9 +683,9 @@
   final List<int> _implicitThisOffsets = [];
 
   /**
-   * The offsets of the implicit class references in static field references.
+   * The offsets of the implicit class references in static member references.
    */
-  final Map<String, List<int>> _staticFieldOffsets = {};
+  final Map<String, List<int>> _implicitClassNameOffsets = {};
 
   _SourcePart(this._base, this._source, this._prefix);
 
@@ -692,6 +693,15 @@
     _explicitThisOffsets.add(offset - _base);
   }
 
+  void addImplicitClassNameOffset(String className, int offset) {
+    List<int> offsets = _implicitClassNameOffsets[className];
+    if (offsets == null) {
+      offsets = [];
+      _implicitClassNameOffsets[className] = offsets;
+    }
+    offsets.add(offset - _base);
+  }
+
   void addImplicitThisOffset(int offset) {
     _implicitThisOffsets.add(offset - _base);
   }
@@ -709,15 +719,6 @@
     }
   }
 
-  void addStaticFieldOffset(String className, int offset) {
-    List<int> offsets = _staticFieldOffsets[className];
-    if (offsets == null) {
-      offsets = [];
-      _staticFieldOffsets[className] = offsets;
-    }
-    offsets.add(offset - _base);
-  }
-
   void addVariable(VariableElement element, SourceRange range) {
     List<SourceRange> ranges = _variables[element];
     if (ranges == null) {
@@ -765,7 +766,7 @@
   visitSimpleIdentifier(SimpleIdentifier node) {
     SourceRange nodeRange = rangeNode(node);
     if (bodyRange.covers(nodeRange)) {
-      _addInstanceFieldQualifier(node);
+      _addMemberQualifier(node);
       _addParameter(node);
       _addVariable(node);
     }
@@ -779,19 +780,28 @@
     }
   }
 
-  void _addInstanceFieldQualifier(SimpleIdentifier node) {
-    PropertyAccessorElement accessor = getPropertyAccessorElement(node);
-    if (isFieldAccessorElement(accessor)) {
-      AstNode qualifier = getNodeQualifier(node);
-      if (qualifier == null) {
-        int offset = node.offset;
-        if (accessor.isStatic) {
-          String className = accessor.enclosingElement.displayName;
-          result.addStaticFieldOffset(className, offset);
-        } else {
-          result.addImplicitThisOffset(offset);
-        }
-      }
+  void _addMemberQualifier(SimpleIdentifier node) {
+    // should be unqualified
+    AstNode qualifier = getNodeQualifier(node);
+    if (qualifier != null) {
+      return;
+    }
+    // should be a method or field reference
+    Element element = node.staticElement;
+    if (!(element is MethodElement || element is PropertyAccessorElement)) {
+      return;
+    }
+    if (element.enclosingElement is! ClassElement) {
+      return;
+    }
+    // record the implicit static or instance reference
+    ExecutableElement member = element;
+    int offset = node.offset;
+    if (member.isStatic) {
+      String className = member.enclosingElement.displayName;
+      result.addImplicitClassNameOffset(className, offset);
+    } else {
+      result.addImplicitThisOffset(offset);
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index 7260013..b20d642 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -65,10 +65,10 @@
   int totalDocSpan = 0;
 
   void visit(Element element) {
-    SourceRange docRange = element.docRange;
-    if (docRange != null) {
+    String comment = element.documentationComment;
+    if (comment != null) {
       ++elementsWithDocs;
-      totalDocSpan += docRange.length;
+      totalDocSpan += comment.length;
     }
 
     Type type = element.runtimeType;
@@ -639,8 +639,16 @@
           Set<AnalysisTarget> countedTargets = new HashSet<AnalysisTarget>();
           Map<String, int> sourceTypeCounts = new HashMap<String, int>();
           Map<String, int> typeCounts = new HashMap<String, int>();
+          int explicitSourceCount = 0;
+          int explicitLineInfoCount = 0;
+          int explicitLineCount = 0;
+          int implicitSourceCount = 0;
+          int implicitLineInfoCount = 0;
+          int implicitLineCount = 0;
           analysisServer.folderMap
               .forEach((Folder folder, InternalAnalysisContext context) {
+            Set<Source> explicitSources = new HashSet<Source>();
+            Set<Source> implicitSources = new HashSet<Source>();
             AnalysisCache cache = context.analysisCache;
             MapIterator<AnalysisTarget, CacheEntry> iterator = cache.iterator();
             while (iterator.moveNext()) {
@@ -651,8 +659,10 @@
                   String sourceName;
                   if (AnalysisEngine.isDartFileName(name)) {
                     if (iterator.value.explicitlyAdded) {
+                      explicitSources.add(target);
                       sourceName = 'Dart file (explicit)';
                     } else {
+                      implicitSources.add(target);
                       sourceName = 'Dart file (implicit)';
                     }
                   } else if (AnalysisEngine.isHtmlFileName(name)) {
@@ -677,6 +687,26 @@
                 }
               }
             }
+
+            int lineCount(Set<Source> sources, bool explicit) {
+              return sources.fold(0, (int previousTotal, Source source) {
+                LineInfo lineInfo = context.getLineInfo(source);
+                if (lineInfo is LineInfoWithCount) {
+                  if (explicit) {
+                    explicitLineInfoCount++;
+                  } else {
+                    implicitLineInfoCount++;
+                  }
+                  return previousTotal + lineInfo.lineCount;
+                } else {
+                  return previousTotal;
+                }
+              });
+            }
+            explicitSourceCount += explicitSources.length;
+            explicitLineCount += lineCount(explicitSources, true);
+            implicitSourceCount += implicitSources.length;
+            implicitLineCount += lineCount(implicitSources, false);
           });
           List<String> sourceTypeNames = sourceTypeCounts.keys.toList();
           sourceTypeNames.sort();
@@ -697,6 +727,37 @@
                 classes: [null, "right"]);
           }
           buffer.write('</table>');
+
+          buffer.write('<p><b>Line counts</b></p>');
+          buffer.write(
+              '<table style="border-collapse: separate; border-spacing: 10px 5px;">');
+          _writeRow(buffer, ['Kind', 'Lines of Code', 'Source Counts'],
+              header: true);
+          _writeRow(buffer, [
+            'Explicit',
+            explicitLineCount.toString(),
+            '$explicitLineInfoCount / $explicitSourceCount'
+          ], classes: [
+            null,
+            "right"
+          ]);
+          _writeRow(buffer, [
+            'Implicit',
+            implicitLineCount.toString(),
+            '$implicitLineInfoCount / $implicitSourceCount'
+          ], classes: [
+            null,
+            "right"
+          ]);
+          _writeRow(buffer, [
+            'Total',
+            (explicitLineCount + implicitLineCount).toString(),
+            '${explicitLineInfoCount + implicitLineInfoCount} / ${explicitSourceCount + implicitSourceCount}'
+          ], classes: [
+            null,
+            "right"
+          ]);
+          buffer.write('</table>');
         }, (StringBuffer buffer) {
           //
           // Write task model timing information.
@@ -1293,9 +1354,16 @@
           buffer.write('<p><b>Error Processor count</b>: $processorCount</p>');
         });
 
-        _writeFiles(buffer, 'Priority Files', priorityNames);
-        _writeFiles(buffer, 'Explicitly Analyzed Files', explicitNames);
-        _writeFiles(buffer, 'Implicitly Analyzed Files', implicitNames);
+        _writeFiles(
+            buffer, 'Priority Files (${priorityNames.length})', priorityNames);
+        _writeFiles(
+            buffer,
+            'Explicitly Analyzed Files (${explicitNames.length})',
+            explicitNames);
+        _writeFiles(
+            buffer,
+            'Implicitly Analyzed Files (${implicitNames.length})',
+            implicitNames);
 
         buffer.write('<h3>Exceptions</h3>');
         if (exceptions.isEmpty) {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index cc1a4e4..672e9f2 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -96,6 +96,71 @@
     expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
   }
 
+  test_dartdoc_inherited_methodByMethod_fromInterface() async {
+    addTestFile('''
+class A {
+  /// my doc
+  m() {} // in A
+}
+
+class B implements A {
+  m() {} // in B
+}
+''');
+    HoverInformation hover = await prepareHover('m() {} // in B');
+    expect(hover.dartdoc, '''my doc\n\nCopied from `A`.''');
+  }
+
+  test_dartdoc_inherited_methodByMethod_fromSuper_direct() async {
+    addTestFile('''
+class A {
+  /// my doc
+  m() {} // in A
+}
+
+class B extends A {
+  m() {} // in B
+}
+''');
+    HoverInformation hover = await prepareHover('m() {} // in B');
+    expect(hover.dartdoc, '''my doc\n\nCopied from `A`.''');
+  }
+
+  test_dartdoc_inherited_methodByMethod_fromSuper_indirect() async {
+    addTestFile('''
+class A {
+  /// my doc
+  m() {}
+}
+class B extends A {
+  m() {}
+}
+class C extends B {
+  m() {} // in C
+}''');
+    HoverInformation hover = await prepareHover('m() {} // in C');
+    expect(hover.dartdoc, '''my doc\n\nCopied from `A`.''');
+  }
+
+  test_dartdoc_inherited_methodByMethod_preferSuper() async {
+    addTestFile('''
+class A {
+  /// my doc
+  m() {}
+}
+class B extends A {
+}
+class I {
+  // wrong doc
+  m() {}
+}
+class C extends B implements I {
+  m() {} // in C
+}''');
+    HoverInformation hover = await prepareHover('m() {} // in C');
+    expect(hover.dartdoc, '''my doc\n\nCopied from `A`.''');
+  }
+
   test_enum() async {
     addTestFile('''
 enum MyEnum {AAA, BBB, CCC}
diff --git a/pkg/analysis_server/test/analysis/notification_implemented_test.dart b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
index d5cde86..ab0e0c1 100644
--- a/pkg/analysis_server/test/analysis/notification_implemented_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
@@ -276,6 +276,38 @@
     assertHasImplementedMember('m() {} // A');
   }
 
+  test_method_withMethod_private_differentLib() async {
+    addFile(
+        '$testFolder/lib.dart',
+        r'''
+import 'test.dart';
+class B extends A {
+  void _m() {}
+}
+''');
+    addTestFile('''
+class A {
+  _m() {} // A
+}
+''');
+    await prepareImplementedElements();
+    assertNoImplementedMember('_m() {} // A');
+  }
+
+  test_method_withMethod_private_sameLibrary() async {
+    addTestFile('''
+class A {
+  _m() {} // A
+}
+class B extends A {
+  _m() {} // B
+}
+''');
+    await prepareImplementedElements();
+    assertHasImplementedMember('_m() {} // A');
+    assertNoImplementedMember('_m() {} // B');
+  }
+
   test_method_withMethod_wasAbstract() async {
     addTestFile('''
 abstract class A {
diff --git a/pkg/analysis_server/test/analysis/notification_overrides_test.dart b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
index ae7551e..61db513 100644
--- a/pkg/analysis_server/test/analysis/notification_overrides_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
@@ -229,6 +229,24 @@
     assertNoOverride('fff(x) {} // B');
   }
 
+  test_BAD_privateByPrivate_inDifferentLib() async {
+    addFile(
+        '$testFolder/lib.dart',
+        r'''
+class A {
+  void _m() {}
+}
+''');
+    addTestFile('''
+import 'lib.dart';
+class B extends A {
+  void _m() {} // in B
+}
+''');
+    await prepareOverrides();
+    assertNoOverride('_m() {} // in B');
+  }
+
   test_BAD_setterByGetter() async {
     addTestFile('''
 class A {
@@ -352,7 +370,7 @@
 ''');
     await prepareOverrides();
     assertHasOverride('m() {} // in C');
-    expect(override.interfaceMembers, hasLength(1));
+    expect(override.interfaceMembers, hasLength(2));
     assertHasInterfaceMember('m() {} // in B');
   }
 
@@ -514,6 +532,21 @@
     assertNoInterfaceMembers();
   }
 
+  test_super_method_privateByPrivate() async {
+    addTestFile('''
+class A {
+  _m() {} // in A
+}
+class B extends A {
+  _m() {} // in B
+}
+''');
+    await prepareOverrides();
+    assertHasOverride('_m() {} // in B');
+    assertHasSuperElement('_m() {} // in A');
+    assertNoInterfaceMembers();
+  }
+
   test_super_method_superTypeCycle() async {
     addTestFile('''
 class A extends B {
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 5c0616e..4faf108 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -32,7 +32,8 @@
     int c = search.codeUnitAt(length);
     if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
         c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
-        c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0))) {
+        c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0) ||
+        c == '_'.codeUnitAt(0))) {
       break;
     }
     length++;
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index f6eff47..c332aa9 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/services/lint.dart';
@@ -366,7 +367,8 @@
     // Sanity check embedder libs.
     var source = context.sourceFactory.forUri('dart:foobar');
     expect(source, isNotNull);
-    expect(source.fullName, '/my/proj/sdk_ext/entry.dart');
+    expect(source.fullName,
+        '/my/proj/sdk_ext/entry.dart'.replaceAll('/', JavaFile.separator));
   }
 
   test_embedder_packagespec() async {
@@ -403,7 +405,8 @@
     var context = contexts[0];
     var source = context.sourceFactory.forUri('dart:foobar');
     expect(source, isNotNull);
-    expect(source.fullName, equals('/my/proj/sdk_ext/entry.dart'));
+    expect(source.fullName,
+        '/my/proj/sdk_ext/entry.dart'.replaceAll('/', JavaFile.separator));
     // We can't find dart:core because we didn't list it in our
     // embedder_libs map.
     expect(context.sourceFactory.forUri('dart:core'), isNull);
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index f234463..e0a6867 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -71,14 +71,15 @@
       var request = new DiagnosticGetDiagnosticsParams().toRequest('0');
       var response = handler.handleRequest(request);
 
-      int fileCount = MockSdk.LIBRARIES.length + 1 /* test.dart */;
+      int fileCount = 1 /* test.dart */;
 
       var json = response.toJson()[Response.RESULT];
       expect(json['contexts'], hasLength(1));
       var context = json['contexts'][0];
       expect(context['name'], '/project');
       expect(context['explicitFileCount'], fileCount);
-      expect(context['implicitFileCount'], 0);
+      // dart:core dart:async dart:math dart:_internal
+      expect(context['implicitFileCount'], 4);
       expect(context['workItemQueueLength'], isNotNull);
     });
 
diff --git a/pkg/analysis_server/test/mock_sdk.dart b/pkg/analysis_server/test/mock_sdk.dart
index 1fbb426..c43ef63 100644
--- a/pkg/analysis_server/test/mock_sdk.dart
+++ b/pkg/analysis_server/test/mock_sdk.dart
@@ -222,12 +222,6 @@
       _analysisContext = new SdkAnalysisContext();
       SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
       _analysisContext.sourceFactory = factory;
-      ChangeSet changeSet = new ChangeSet();
-      for (String uri in uris) {
-        Source source = factory.forUri(uri);
-        changeSet.addedSource(source);
-      }
-      _analysisContext.applyChanges(changeSet);
     }
     return _analysisContext;
   }
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 1d6ddf9a..c8b62dd 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -186,8 +186,9 @@
 class C extends A {}
 ''');
     // configure roots
-    Request request = new AnalysisSetAnalysisRootsParams(
-        [projectPath, '/packages/pkgA'], []).toRequest('0');
+    Request request =
+        new AnalysisSetAnalysisRootsParams([projectPath, '/packages/pkgA'], [])
+            .toRequest('0');
     handleSuccessfulRequest(request);
     // test A type hierarchy
     List<TypeHierarchyItem> items = await _getTypeHierarchy('A {}');
@@ -699,6 +700,66 @@
         itemD.memberElement.location.offset, findOffset('test() {} // in D'));
   }
 
+  test_member_method_private_differentLib() async {
+    addFile(
+        '$testFolder/lib.dart',
+        r'''
+import 'test.dart';
+class A {
+  void _m() {}
+}
+class C extends B {
+  void _m() {}
+}
+''');
+    addTestFile('''
+import 'lib.dart';
+class B extends A {
+  _m() {} // in B
+}
+class D extends C {
+  _m() {} // in D
+}
+''');
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('_m() {} // in B');
+    var itemB = items[0];
+    var itemA = items[itemB.superclass];
+    var itemC = items[itemB.subclasses[0]];
+    var itemD = items[itemC.subclasses[0]];
+    expect(itemB.classElement.name, 'B');
+    expect(itemA.classElement.name, 'A');
+    expect(itemC.classElement.name, 'C');
+    expect(itemD.classElement.name, 'D');
+    expect(itemA.memberElement, isNull);
+    expect(itemC.memberElement, isNull);
+    expect(itemB.memberElement, isNotNull);
+    expect(itemD.memberElement, isNotNull);
+  }
+
+  test_member_method_private_sameLib() async {
+    addTestFile('''
+class A {
+  _m() {} // in A
+}
+class B extends A {
+  _m() {} // in B
+}
+class C extends B {
+  _m() {} // in C
+}
+''');
+    List<TypeHierarchyItem> items = await _getTypeHierarchy('_m() {} // in B');
+    var itemB = items[0];
+    var itemA = items[itemB.superclass];
+    var itemC = items[itemB.subclasses[0]];
+    expect(itemA.classElement.name, 'A');
+    expect(itemB.classElement.name, 'B');
+    expect(itemC.classElement.name, 'C');
+    expect(itemA.memberElement.location.offset, findOffset('_m() {} // in A'));
+    expect(itemB.memberElement.location.offset, findOffset('_m() {} // in B'));
+    expect(itemC.memberElement.location.offset, findOffset('_m() {} // in C'));
+  }
+
   test_member_ofMixin2_method() async {
     addTestFile('''
 class M1 {
@@ -963,8 +1024,9 @@
 
   test_superOnly_fileDoesNotExist() async {
     Request request = new SearchGetTypeHierarchyParams(
-        '/does/not/exist.dart', 0,
-        superOnly: true).toRequest(requestId);
+            '/does/not/exist.dart', 0,
+            superOnly: true)
+        .toRequest(requestId);
     Response response = await serverChannel.sendRequest(request);
     List<TypeHierarchyItem> items =
         new SearchGetTypeHierarchyResult.fromResponse(response).hierarchyItems;
@@ -973,7 +1035,8 @@
 
   Request _createGetTypeHierarchyRequest(String search, {bool superOnly}) {
     return new SearchGetTypeHierarchyParams(testFile, findOffset(search),
-        superOnly: superOnly).toRequest(requestId);
+            superOnly: superOnly)
+        .toRequest(requestId);
   }
 
   Future<List<TypeHierarchyItem>> _getTypeHierarchy(String search,
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index ed3d7d3..859f248 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -2379,6 +2379,15 @@
     await assertNoAssistAt('if (p', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE);
   }
 
+  test_introduceLocalTestedType_BAD_notStatement() async {
+    resolveTestUnit('''
+class C {
+  bool b;
+  C(v) : b = v is int;
+}''');
+    await assertNoAssistAt('is int', DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE);
+  }
+
   test_introduceLocalTestedType_OK_if_is() async {
     resolveTestUnit('''
 class MyTypeName {}
diff --git a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
index 8ff6c84..3433f1e 100644
--- a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
@@ -917,6 +917,81 @@
 ''');
   }
 
+  test_method_methodInstance() {
+    indexTestUnit(r'''
+class A {
+  ma() {}
+}
+class B extends A {
+  test() {
+    ma();
+    mb();
+  }
+  mb() {}
+}
+main(B b) {
+  b.test();
+}
+''');
+    _createRefactoring('test();');
+    // validate change
+    return _assertSuccessfulRefactoring(r'''
+class A {
+  ma() {}
+}
+class B extends A {
+  test() {
+    ma();
+    mb();
+  }
+  mb() {}
+}
+main(B b) {
+  b.ma();
+  b.mb();
+}
+''');
+  }
+
+  test_method_methodStatic() {
+    indexTestUnit(r'''
+class A {
+  static ma() {}
+}
+class B extends A {
+  static mb() {}
+  test() {
+    mb();
+    A.ma();
+    B.mb();
+  }
+}
+main(B b) {
+  b.test();
+}
+''');
+    _createRefactoring('test();');
+    // validate change
+    return _assertSuccessfulRefactoring(r'''
+class A {
+  static ma() {}
+}
+class B extends A {
+  static mb() {}
+  test() {
+    mb();
+    A.ma();
+    B.mb();
+  }
+}
+main(B b) {
+  B.mb();
+  A.ma();
+  B.mb();
+}
+''');
+  }
+
   test_method_singleStatement() {
     indexTestUnit(r'''
 class A {
@@ -973,7 +1048,7 @@
 ''');
   }
 
-  test_method_unqualifiedUnvocation() {
+  test_method_unqualifiedInvocation() {
     indexTestUnit(r'''
 class A {
   test(a, b) {
@@ -1198,6 +1273,36 @@
 ''');
   }
 
+  test_removeEmptyLinesBefore_method() {
+    indexTestUnit(r'''
+class A {
+  before() {
+  }
+
+
+  test() {
+    print(0);
+  }
+
+  foo() {
+    test();
+  }
+}
+''');
+    _createRefactoring('test() {');
+    // validate change
+    return _assertSuccessfulRefactoring(r'''
+class A {
+  before() {
+  }
+
+  foo() {
+    print(0);
+  }
+}
+''');
+  }
+
   test_setter_classMember_instance() {
     indexTestUnit(r'''
 class A {
@@ -1361,7 +1466,7 @@
 ''');
   }
 
-  test_singleExpression_wrapIntoParenthesized_bools() {
+  test_singleExpression_wrapIntoParenthesized_bool() {
     indexTestUnit(r'''
 test(bool a, bool b) {
   return a || b;
diff --git a/pkg/analyzer/example/parser_driver.dart b/pkg/analyzer/example/parser_driver.dart
index 8fdf1a9..2e082b7 100644
--- a/pkg/analyzer/example/parser_driver.dart
+++ b/pkg/analyzer/example/parser_driver.dart
@@ -5,7 +5,8 @@
 
 import 'dart:io';
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/scanner.dart';
diff --git a/pkg/analyzer/example/resolver_driver.dart b/pkg/analyzer/example/resolver_driver.dart
index 74ed79c..fa2af7f 100755
--- a/pkg/analyzer/example/resolver_driver.dart
+++ b/pkg/analyzer/example/resolver_driver.dart
@@ -5,8 +5,9 @@
 
 import 'dart:io';
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index d0fdc65..78de42e 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -6,8 +6,8 @@
 
 import 'dart:io';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/error.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/scanner.dart';
@@ -15,8 +15,10 @@
 import 'package:analyzer/src/string_source.dart';
 import 'package:path/path.dart' as pathos;
 
+export 'package:analyzer/dart/ast/ast.dart';
+export 'package:analyzer/dart/ast/visitor.dart';
+export 'package:analyzer/src/dart/ast/utilities.dart';
 export 'package:analyzer/src/error.dart';
-export 'package:analyzer/src/generated/ast.dart';
 export 'package:analyzer/src/generated/error.dart';
 export 'package:analyzer/src/generated/utilities_dart.dart';
 
@@ -63,22 +65,6 @@
       suppressErrors: suppressErrors, parseFunctionBodies: parseFunctionBodies);
 }
 
-CompilationUnit _parseSource(String contents, Source source,
-    {bool suppressErrors: false, bool parseFunctionBodies: true}) {
-  var reader = new CharSequenceReader(contents);
-  var errorCollector = new _ErrorCollector();
-  var scanner = new Scanner(source, reader, errorCollector);
-  var token = scanner.tokenize();
-  var parser = new Parser(source, errorCollector)
-    ..parseFunctionBodies = parseFunctionBodies;
-  var unit = parser.parseCompilationUnit(token)
-    ..lineInfo = new LineInfo(scanner.lineStarts);
-
-  if (errorCollector.hasErrors && !suppressErrors) throw errorCollector.group;
-
-  return unit;
-}
-
 /// Parses the script tag and directives in a string of Dart code into an AST.
 ///
 /// Stops parsing when the first non-directive is encountered. The rest of the
@@ -111,6 +97,22 @@
   return literal.stringValue;
 }
 
+CompilationUnit _parseSource(String contents, Source source,
+    {bool suppressErrors: false, bool parseFunctionBodies: true}) {
+  var reader = new CharSequenceReader(contents);
+  var errorCollector = new _ErrorCollector();
+  var scanner = new Scanner(source, reader, errorCollector);
+  var token = scanner.tokenize();
+  var parser = new Parser(source, errorCollector)
+    ..parseFunctionBodies = parseFunctionBodies;
+  var unit = parser.parseCompilationUnit(token)
+    ..lineInfo = new LineInfo(scanner.lineStarts);
+
+  if (errorCollector.hasErrors && !suppressErrors) throw errorCollector.group;
+
+  return unit;
+}
+
 /// A simple error listener that collects errors into an [AnalysisErrorGroup].
 class _ErrorCollector extends AnalysisErrorListener {
   final _errors = <AnalysisError>[];
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
new file mode 100644
index 0000000..1237fd1
--- /dev/null
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -0,0 +1,7988 @@
+// Copyright (c) 2014, 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.dart.ast.ast;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart' show AuxiliaryElements;
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+/**
+ * Two or more string literals that are implicitly concatenated because of being
+ * adjacent (separated only by whitespace).
+ *
+ * While the grammar only allows adjacent strings when all of the strings are of
+ * the same kind (single line or multi-line), this class doesn't enforce that
+ * restriction.
+ *
+ * > adjacentStrings ::=
+ * >     [StringLiteral] [StringLiteral]+
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AdjacentStrings extends StringLiteral {
+  /**
+   * Initialize a newly created list of adjacent strings. To be syntactically
+   * valid, the list of [strings] must contain at least two elements.
+   */
+  factory AdjacentStrings(List<StringLiteral> strings) = AdjacentStringsImpl;
+
+  /**
+   * Return the strings that are implicitly concatenated.
+   */
+  NodeList<StringLiteral> get strings;
+}
+
+/**
+ * An AST node that can be annotated with both a documentation comment and a
+ * list of annotations.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AnnotatedNode extends AstNode {
+  /**
+   * Return the documentation comment associated with this node, or `null` if
+   * this node does not have a documentation comment associated with it.
+   */
+  Comment get documentationComment;
+
+  /**
+   * Set the documentation comment associated with this node to the given
+   * [comment].
+   */
+  void set documentationComment(Comment comment);
+
+  /**
+   * Return the first token following the comment and metadata.
+   */
+  Token get firstTokenAfterCommentAndMetadata;
+
+  /**
+   * Return the annotations associated with this node.
+   */
+  NodeList<Annotation> get metadata;
+
+  /**
+   * Return a list containing the comment and annotations associated with this
+   * node, sorted in lexical order.
+   */
+  List<AstNode> get sortedCommentAndAnnotations;
+}
+
+/**
+ * An annotation that can be associated with an AST node.
+ *
+ * > metadata ::=
+ * >     annotation*
+ * >
+ * > annotation ::=
+ * >     '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Annotation extends AstNode {
+  /**
+   * Initialize a newly created annotation. Both the [period] and the
+   * [constructorName] can be `null` if the annotation is not referencing a
+   * named constructor. The [arguments] can be `null` if the annotation is not
+   * referencing a constructor.
+   */
+  factory Annotation(
+      Token atSign,
+      Identifier name,
+      Token period,
+      SimpleIdentifier constructorName,
+      ArgumentList arguments) = AnnotationImpl;
+
+  /**
+   * Return the arguments to the constructor being invoked, or `null` if this
+   * annotation is not the invocation of a constructor.
+   */
+  ArgumentList get arguments;
+
+  /**
+   * Set the arguments to the constructor being invoked to the given [arguments].
+   */
+  void set arguments(ArgumentList arguments);
+
+  /**
+   * Return the at sign that introduced the annotation.
+   */
+  Token get atSign;
+
+  /**
+   * Set the at sign that introduced the annotation to the given [token].
+   */
+  void set atSign(Token token);
+
+  /**
+   * Return the name of the constructor being invoked, or `null` if this
+   * annotation is not the invocation of a named constructor.
+   */
+  SimpleIdentifier get constructorName;
+
+  /**
+   * Set the name of the constructor being invoked to the given [name].
+   */
+  void set constructorName(SimpleIdentifier name);
+
+  /**
+   * Return the element associated with this annotation, or `null` if the AST
+   * structure has not been resolved or if this annotation could not be
+   * resolved.
+   */
+  Element get element;
+
+  /**
+   * Set the element associated with this annotation to the given [element].
+   */
+  void set element(Element element);
+
+  /**
+   * Return the element annotation representing this annotation in the element model.
+   */
+  ElementAnnotation get elementAnnotation;
+
+  /**
+   * Set the element annotation representing this annotation in the element
+   * model to the given [annotation].
+   */
+  void set elementAnnotation(ElementAnnotation annotation);
+
+  /**
+   * Return the name of the class defining the constructor that is being invoked
+   * or the name of the field that is being referenced.
+   */
+  Identifier get name;
+
+  /**
+   * Set the name of the class defining the constructor that is being invoked or
+   * the name of the field that is being referenced to the given [name].
+   */
+  void set name(Identifier name);
+
+  /**
+   * Return the period before the constructor name, or `null` if this annotation
+   * is not the invocation of a named constructor.
+   */
+  Token get period;
+
+  /**
+   * Set the period before the constructor name to the given [token].
+   */
+  void set period(Token token);
+}
+
+/**
+ * A list of arguments in the invocation of an executable element (that is, a
+ * function, method, or constructor).
+ *
+ * > argumentList ::=
+ * >     '(' arguments? ')'
+ * >
+ * > arguments ::=
+ * >     [NamedExpression] (',' [NamedExpression])*
+ * >   | [Expression] (',' [Expression])* (',' [NamedExpression])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ArgumentList extends AstNode {
+  /**
+   * Initialize a newly created list of arguments. The list of [arguments] can
+   * be `null` if there are no arguments.
+   */
+  factory ArgumentList(Token leftParenthesis, List<Expression> arguments,
+      Token rightParenthesis) = ArgumentListImpl;
+
+  /**
+   * Return the expressions producing the values of the arguments. Although the
+   * language requires that positional arguments appear before named arguments,
+   * this class allows them to be intermixed.
+   */
+  NodeList<Expression> get arguments;
+
+  /**
+   * Set the parameter elements corresponding to each of the arguments in this
+   * list to the given list of [parameters]. The list of parameters must be the
+   * same length as the number of arguments, but can contain `null` entries if a
+   * given argument does not correspond to a formal parameter.
+   */
+  void set correspondingPropagatedParameters(List<ParameterElement> parameters);
+
+  /**
+   * Set the parameter elements corresponding to each of the arguments in this
+   * list to the given list of [parameters]. The list of parameters must be the
+   * same length as the number of arguments, but can contain `null` entries if a
+   * given argument does not correspond to a formal parameter.
+   */
+  void set correspondingStaticParameters(List<ParameterElement> parameters);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+}
+
+/**
+ * An as expression.
+ *
+ * > asExpression ::=
+ * >     [Expression] 'as' [TypeName]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AsExpression extends Expression {
+  /**
+   * Initialize a newly created as expression.
+   */
+  factory AsExpression(Expression expression, Token asOperator, TypeName type) =
+      AsExpressionImpl;
+
+  /**
+   * Return the 'as' operator.
+   */
+  Token get asOperator;
+
+  /**
+   * Set the 'as' operator to the given [token].
+   */
+  void set asOperator(Token token);
+
+  /**
+   * Return the expression used to compute the value being cast.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression used to compute the value being cast to the given
+   * [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the name of the type being cast to.
+   */
+  TypeName get type;
+
+  /**
+   * Set the name of the type being cast to to the given [name].
+   */
+  void set type(TypeName name);
+}
+
+/**
+ * An assert statement.
+ *
+ * > assertStatement ::=
+ * >     'assert' '(' [Expression] ')' ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AssertStatement extends Statement {
+  /**
+   * Initialize a newly created assert statement. The [comma] and [message] can
+   * be `null` if there is no message.
+   */
+  factory AssertStatement(
+      Token assertKeyword,
+      Token leftParenthesis,
+      Expression condition,
+      Token comma,
+      Expression message,
+      Token rightParenthesis,
+      Token semicolon) = AssertStatementImpl;
+
+  /**
+   * Return the token representing the 'assert' keyword.
+   */
+  Token get assertKeyword;
+
+  /**
+   * Set the token representing the 'assert' keyword to the given [token].
+   */
+  void set assertKeyword(Token token);
+
+  /**
+   * Return the comma between the [condition] and the [message], or `null` if no
+   * message was supplied.
+   */
+  Token get comma;
+
+  /**
+   * Set the comma between the [condition] and the [message] to the given [token].
+   */
+  void set comma(Token token);
+
+  /**
+   * Return the condition that is being asserted to be `true`.
+   */
+  Expression get condition;
+
+  /**
+   * Set the condition that is being asserted to be `true` to the given
+   * [expression].
+   */
+  void set condition(Expression condition);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the message to report if the assertion fails, or `null` if no
+   * message was supplied.
+   */
+  Expression get message;
+
+  /**
+   * Set the message to report if the assertion fails to the given
+   * [expression].
+   */
+  void set message(Expression expression);
+
+  /**
+   *  Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   *  Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * An assignment expression.
+ *
+ * > assignmentExpression ::=
+ * >     [Expression] operator [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AssignmentExpression extends Expression {
+  /**
+   * Initialize a newly created assignment expression.
+   */
+  factory AssignmentExpression(
+          Expression leftHandSide, Token operator, Expression rightHandSide) =
+      AssignmentExpressionImpl;
+
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  MethodElement get bestElement;
+
+  /**
+   * Return the expression used to compute the left hand side.
+   */
+  Expression get leftHandSide;
+
+  /**
+   * Return the expression used to compute the left hand side.
+   */
+  void set leftHandSide(Expression expression);
+
+  /**
+   * Return the assignment operator being applied.
+   */
+  Token get operator;
+
+  /**
+   * Set the assignment operator being applied to the given [token].
+   */
+  void set operator(Token token);
+
+  /**
+   * Return the element associated with the operator based on the propagated
+   * type of the left-hand-side, or `null` if the AST structure has not been
+   * resolved, if the operator is not a compound operator, or if the operator
+   * could not be resolved.
+   */
+  MethodElement get propagatedElement;
+
+  /**
+   * Set the element associated with the operator based on the propagated
+   * type of the left-hand-side to the given [element].
+   */
+  void set propagatedElement(MethodElement element);
+
+  /**
+   * Return the expression used to compute the right hand side.
+   */
+  Expression get rightHandSide;
+
+  /**
+   * Set the expression used to compute the left hand side to the given
+   * [expression].
+   */
+  void set rightHandSide(Expression expression);
+
+  /**
+   * Return the element associated with the operator based on the static type of
+   * the left-hand-side, or `null` if the AST structure has not been resolved,
+   * if the operator is not a compound operator, or if the operator could not be
+   * resolved.
+   */
+  MethodElement get staticElement;
+
+  /**
+   * Set the element associated with the operator based on the static type of
+   * the left-hand-side to the given [element].
+   */
+  void set staticElement(MethodElement element);
+}
+
+/**
+ * A node in the AST structure for a Dart program.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AstNode {
+  /**
+   * An empty list of AST nodes.
+   */
+  static const List<AstNode> EMPTY_LIST = const <AstNode>[];
+
+  /**
+   * A comparator that can be used to sort AST nodes in lexical order. In other
+   * words, `compare` will return a negative value if the offset of the first
+   * node is less than the offset of the second node, zero (0) if the nodes have
+   * the same offset, and a positive value if the offset of the first node is
+   * greater than the offset of the second node.
+   */
+  static Comparator<AstNode> LEXICAL_ORDER =
+      (AstNode first, AstNode second) => first.offset - second.offset;
+
+  /**
+   * Return the first token included in this node's source range.
+   */
+  Token get beginToken;
+
+  /**
+   * Return an iterator that can be used to iterate through all the entities
+   * (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;
+
+  /**
+   * Return the offset of the character immediately following the last character
+   * of this node's source range. This is equivalent to
+   * `node.getOffset() + node.getLength()`. For a compilation unit this will be
+   * equal to the length of the unit's source. For synthetic nodes this will be
+   * equivalent to the node's offset (because the length is zero (0) by
+   * definition).
+   */
+  int get end;
+
+  /**
+   * Return the last token included in this node's source range.
+   */
+  Token get endToken;
+
+  /**
+   * Return `true` if this node is a synthetic node. A synthetic node is a node
+   * that was introduced by the parser in order to recover from an error in the
+   * code. Synthetic nodes always have a length of zero (`0`).
+   */
+  bool get isSynthetic;
+
+  /**
+   * Return the number of characters in the node's source range.
+   */
+  int get length;
+
+  /**
+   * Return the offset from the beginning of the file to the first character in
+   * the node's source range.
+   */
+  int get offset;
+
+  /**
+   * Return this node's parent node, or `null` if this node is the root of an
+   * AST structure.
+   *
+   * Note that the relationship between an AST node and its parent node may
+   * change over the lifetime of a node.
+   */
+  AstNode get parent;
+
+  /**
+   * Return the node at the root of this node's AST structure. Note that this
+   * method's performance is linear with respect to the depth of the node in the
+   * AST structure (O(depth)).
+   */
+  AstNode get root;
+
+  /**
+   * 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);
+
+  /**
+   * Return the most immediate ancestor of this node for which the [predicate]
+   * returns `true`, or `null` if there is no such ancestor. Note that this node
+   * will never be returned.
+   */
+  AstNode getAncestor(Predicate<AstNode> predicate);
+
+  /**
+   * Return the value of the property with the given [name], or `null` if this
+   * node does not have a property with the given name.
+   */
+  Object getProperty(String name);
+
+  /**
+   * Set the value of the property with the given [name] to the given [value].
+   * If the value is `null`, the property will effectively be removed.
+   */
+  void setProperty(String name, Object value);
+
+  /**
+   * Return a textual description of this node in a form approximating valid
+   * source. The returned string will not be valid source primarily in the case
+   * where the node itself is not well-formed.
+   */
+  String toSource();
+
+  /**
+   * Use the given [visitor] to visit all of the children of this node. The
+   * children will be visited in lexical order.
+   */
+  void visitChildren(AstVisitor visitor);
+}
+
+/**
+ * An object that can be used to visit an AST structure.
+ *
+ * Clients may extend or implement this class.
+ */
+abstract class AstVisitor<R> {
+  R visitAdjacentStrings(AdjacentStrings node);
+
+  R visitAnnotation(Annotation node);
+
+  R visitArgumentList(ArgumentList node);
+
+  R visitAsExpression(AsExpression node);
+
+  R visitAssertStatement(AssertStatement assertStatement);
+
+  R visitAssignmentExpression(AssignmentExpression node);
+
+  R visitAwaitExpression(AwaitExpression node);
+
+  R visitBinaryExpression(BinaryExpression node);
+
+  R visitBlock(Block node);
+
+  R visitBlockFunctionBody(BlockFunctionBody node);
+
+  R visitBooleanLiteral(BooleanLiteral node);
+
+  R visitBreakStatement(BreakStatement node);
+
+  R visitCascadeExpression(CascadeExpression node);
+
+  R visitCatchClause(CatchClause node);
+
+  R visitClassDeclaration(ClassDeclaration node);
+
+  R visitClassTypeAlias(ClassTypeAlias node);
+
+  R visitComment(Comment node);
+
+  R visitCommentReference(CommentReference node);
+
+  R visitCompilationUnit(CompilationUnit node);
+
+  R visitConditionalExpression(ConditionalExpression node);
+
+  R visitConfiguration(Configuration node);
+
+  R visitConstructorDeclaration(ConstructorDeclaration node);
+
+  R visitConstructorFieldInitializer(ConstructorFieldInitializer node);
+
+  R visitConstructorName(ConstructorName node);
+
+  R visitContinueStatement(ContinueStatement node);
+
+  R visitDeclaredIdentifier(DeclaredIdentifier node);
+
+  R visitDefaultFormalParameter(DefaultFormalParameter node);
+
+  R visitDoStatement(DoStatement node);
+
+  R visitDottedName(DottedName node);
+
+  R visitDoubleLiteral(DoubleLiteral node);
+
+  R visitEmptyFunctionBody(EmptyFunctionBody node);
+
+  R visitEmptyStatement(EmptyStatement node);
+
+  R visitEnumConstantDeclaration(EnumConstantDeclaration node);
+
+  R visitEnumDeclaration(EnumDeclaration node);
+
+  R visitExportDirective(ExportDirective node);
+
+  R visitExpressionFunctionBody(ExpressionFunctionBody node);
+
+  R visitExpressionStatement(ExpressionStatement node);
+
+  R visitExtendsClause(ExtendsClause node);
+
+  R visitFieldDeclaration(FieldDeclaration node);
+
+  R visitFieldFormalParameter(FieldFormalParameter node);
+
+  R visitForEachStatement(ForEachStatement node);
+
+  R visitFormalParameterList(FormalParameterList node);
+
+  R visitForStatement(ForStatement node);
+
+  R visitFunctionDeclaration(FunctionDeclaration node);
+
+  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node);
+
+  R visitFunctionExpression(FunctionExpression node);
+
+  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node);
+
+  R visitFunctionTypeAlias(FunctionTypeAlias functionTypeAlias);
+
+  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node);
+
+  R visitHideCombinator(HideCombinator node);
+
+  R visitIfStatement(IfStatement node);
+
+  R visitImplementsClause(ImplementsClause node);
+
+  R visitImportDirective(ImportDirective node);
+
+  R visitIndexExpression(IndexExpression node);
+
+  R visitInstanceCreationExpression(InstanceCreationExpression node);
+
+  R visitIntegerLiteral(IntegerLiteral node);
+
+  R visitInterpolationExpression(InterpolationExpression node);
+
+  R visitInterpolationString(InterpolationString node);
+
+  R visitIsExpression(IsExpression node);
+
+  R visitLabel(Label node);
+
+  R visitLabeledStatement(LabeledStatement node);
+
+  R visitLibraryDirective(LibraryDirective node);
+
+  R visitLibraryIdentifier(LibraryIdentifier node);
+
+  R visitListLiteral(ListLiteral node);
+
+  R visitMapLiteral(MapLiteral node);
+
+  R visitMapLiteralEntry(MapLiteralEntry node);
+
+  R visitMethodDeclaration(MethodDeclaration node);
+
+  R visitMethodInvocation(MethodInvocation node);
+
+  R visitNamedExpression(NamedExpression node);
+
+  R visitNativeClause(NativeClause node);
+
+  R visitNativeFunctionBody(NativeFunctionBody node);
+
+  R visitNullLiteral(NullLiteral node);
+
+  R visitParenthesizedExpression(ParenthesizedExpression node);
+
+  R visitPartDirective(PartDirective node);
+
+  R visitPartOfDirective(PartOfDirective node);
+
+  R visitPostfixExpression(PostfixExpression node);
+
+  R visitPrefixedIdentifier(PrefixedIdentifier node);
+
+  R visitPrefixExpression(PrefixExpression node);
+
+  R visitPropertyAccess(PropertyAccess node);
+
+  R visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node);
+
+  R visitRethrowExpression(RethrowExpression node);
+
+  R visitReturnStatement(ReturnStatement node);
+
+  R visitScriptTag(ScriptTag node);
+
+  R visitShowCombinator(ShowCombinator node);
+
+  R visitSimpleFormalParameter(SimpleFormalParameter node);
+
+  R visitSimpleIdentifier(SimpleIdentifier node);
+
+  R visitSimpleStringLiteral(SimpleStringLiteral node);
+
+  R visitStringInterpolation(StringInterpolation node);
+
+  R visitSuperConstructorInvocation(SuperConstructorInvocation node);
+
+  R visitSuperExpression(SuperExpression node);
+
+  R visitSwitchCase(SwitchCase node);
+
+  R visitSwitchDefault(SwitchDefault node);
+
+  R visitSwitchStatement(SwitchStatement node);
+
+  R visitSymbolLiteral(SymbolLiteral node);
+
+  R visitThisExpression(ThisExpression node);
+
+  R visitThrowExpression(ThrowExpression node);
+
+  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node);
+
+  R visitTryStatement(TryStatement node);
+
+  R visitTypeArgumentList(TypeArgumentList node);
+
+  R visitTypeName(TypeName node);
+
+  R visitTypeParameter(TypeParameter node);
+
+  R visitTypeParameterList(TypeParameterList node);
+
+  R visitVariableDeclaration(VariableDeclaration node);
+
+  R visitVariableDeclarationList(VariableDeclarationList node);
+
+  R visitVariableDeclarationStatement(VariableDeclarationStatement node);
+
+  R visitWhileStatement(WhileStatement node);
+
+  R visitWithClause(WithClause node);
+
+  R visitYieldStatement(YieldStatement node);
+}
+
+/**
+ * An await expression.
+ *
+ * > awaitExpression ::=
+ * >     'await' [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class AwaitExpression extends Expression {
+  /**
+   * Initialize a newly created await expression.
+   */
+  factory AwaitExpression(Token awaitKeyword, Expression expression) =
+      AwaitExpressionImpl;
+
+  /**
+   * Return the 'await' keyword.
+   */
+  Token get awaitKeyword;
+
+  /**
+   * Set the 'await' keyword to the given [token].
+   */
+  void set awaitKeyword(Token token);
+
+  /**
+   * Return the expression whose value is being waited on.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression whose value is being waited on to the given [expression].
+   */
+  void set expression(Expression expression);
+}
+
+/**
+ * A binary (infix) expression.
+ *
+ * > binaryExpression ::=
+ * >     [Expression] [Token] [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class BinaryExpression extends Expression {
+  /**
+   * Initialize a newly created binary expression.
+   */
+  factory BinaryExpression(
+          Expression leftOperand, Token operator, Expression rightOperand) =
+      BinaryExpressionImpl;
+
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  MethodElement get bestElement;
+
+  /**
+   * Return the expression used to compute the left operand.
+   */
+  Expression get leftOperand;
+
+  /**
+   * Set the expression used to compute the left operand to the given
+   * [expression].
+   */
+  void set leftOperand(Expression expression);
+
+  /**
+   * Return the binary operator being applied.
+   */
+  Token get operator;
+
+  /**
+   * Set the binary operator being applied to the given [token].
+   */
+  void set operator(Token token);
+
+  /**
+   * Return the element associated with the operator based on the propagated
+   * type of the left operand, or `null` if the AST structure has not been
+   * resolved, if the operator is not user definable, or if the operator could
+   * not be resolved.
+   */
+  MethodElement get propagatedElement;
+
+  /**
+   * Set the element associated with the operator based on the propagated
+   * type of the left operand to the given [element].
+   */
+  void set propagatedElement(MethodElement element);
+
+  /**
+   * Return the expression used to compute the right operand.
+   */
+  Expression get rightOperand;
+
+  /**
+   * Set the expression used to compute the right operand to the given
+   * [expression].
+   */
+  void set rightOperand(Expression expression);
+
+  /**
+   * Return the element associated with the operator based on the static type of
+   * the left operand, or `null` if the AST structure has not been resolved, if
+   * the operator is not user definable, or if the operator could not be
+   * resolved.
+   */
+  MethodElement get staticElement;
+
+  /**
+   * Set the element associated with the operator based on the static type of
+   * the left operand to the given [element].
+   */
+  void set staticElement(MethodElement element);
+}
+
+/**
+ * A sequence of statements.
+ *
+ * > block ::=
+ * >     '{' statement* '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Block extends Statement {
+  /**
+   * Initialize a newly created block of code.
+   */
+  factory Block(
+          Token leftBracket, List<Statement> statements, Token rightBracket) =
+      BlockImpl;
+
+  /**
+   * Return the left curly bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left curly bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the right curly bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right curly bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+
+  /**
+   * Return the statements contained in the block.
+   */
+  NodeList<Statement> get statements;
+}
+
+/**
+ * A function body that consists of a block of statements.
+ *
+ * > blockFunctionBody ::=
+ * >     ('async' | 'async' '*' | 'sync' '*')? [Block]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class BlockFunctionBody extends FunctionBody {
+  /**
+   * Initialize a newly created function body consisting of a block of
+   * statements. The [keyword] can be `null` if there is no keyword specified
+   * for the block. The [star] can be `null` if there is no star following the
+   * keyword (and must be `null` if there is no keyword).
+   */
+  factory BlockFunctionBody(Token keyword, Token star, Block block) =
+      BlockFunctionBodyImpl;
+
+  /**
+   * Return the block representing the body of the function.
+   */
+  Block get block;
+
+  /**
+   * Set the block representing the body of the function to the given [block].
+   */
+  void set block(Block block);
+
+  /**
+   * Set token representing the 'async' or 'sync' keyword to the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Set the star following the 'async' or 'sync' keyword to the given [token].
+   */
+  void set star(Token token);
+}
+
+/**
+ * A boolean literal expression.
+ *
+ * > booleanLiteral ::=
+ * >     'false' | 'true'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class BooleanLiteral extends Literal {
+  /**
+   * Initialize a newly created boolean literal.
+   */
+  factory BooleanLiteral(Token literal, bool value) = BooleanLiteralImpl;
+
+  /**
+   * Return the token representing the literal.
+   */
+  Token get literal;
+
+  /**
+   * Set the token representing the literal to the given [token].
+   */
+  void set literal(Token token);
+
+  /**
+   * Return the value of the literal.
+   */
+  bool get value;
+}
+
+/**
+ * A break statement.
+ *
+ * > breakStatement ::=
+ * >     'break' [SimpleIdentifier]? ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class BreakStatement extends Statement {
+  /**
+   * Initialize a newly created break statement. The [label] can be `null` if
+   * there is no label associated with the statement.
+   */
+  factory BreakStatement(
+          Token breakKeyword, SimpleIdentifier label, Token semicolon) =
+      BreakStatementImpl;
+
+  /**
+   * Return the token representing the 'break' keyword.
+   */
+  Token get breakKeyword;
+
+  /**
+   * Set the token representing the 'break' keyword to the given [token].
+   */
+  void set breakKeyword(Token token);
+
+  /**
+   * Return the label associated with the statement, or `null` if there is no
+   * label.
+   */
+  SimpleIdentifier get label;
+
+  /**
+   * Set the label associated with the statement to the given [identifier].
+   */
+  void set label(SimpleIdentifier identifier);
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the node from which this break statement is breaking. This will be
+   * either a [Statement] (in the case of breaking out of a loop), a
+   * [SwitchMember] (in the case of a labeled break statement whose label
+   * matches a label on a switch case in an enclosing switch statement), or
+   * `null` if the AST has not yet been resolved or if the target could not be
+   * resolved. Note that if the source code has errors, the target might be
+   * invalid (e.g. trying to break to a switch case).
+   */
+  AstNode get target;
+
+  /**
+   * Set the node from which this break statement is breaking to the given
+   * [node].
+   */
+  void set target(AstNode node);
+}
+
+/**
+ * A sequence of cascaded expressions: expressions that share a common target.
+ * There are three kinds of expressions that can be used in a cascade
+ * expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
+ *
+ * > cascadeExpression ::=
+ * >     [Expression] cascadeSection*
+ * >
+ * > cascadeSection ::=
+ * >     '..'  (cascadeSelector arguments*) (assignableSelector arguments*)*
+ * >     (assignmentOperator expressionWithoutCascade)?
+ * >
+ * > cascadeSelector ::=
+ * >     '[ ' expression '] '
+ * >   | identifier
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class CascadeExpression extends Expression {
+  /**
+   * Initialize a newly created cascade expression. The list of
+   * [cascadeSections] must contain at least one element.
+   */
+  factory CascadeExpression(
+          Expression target, List<Expression> cascadeSections) =
+      CascadeExpressionImpl;
+
+  /**
+   * Return the cascade sections sharing the common target.
+   */
+  NodeList<Expression> get cascadeSections;
+
+  /**
+   * Return the target of the cascade sections.
+   */
+  Expression get target;
+
+  /**
+   * Set the target of the cascade sections to the given [expression].
+   */
+  void set target(Expression target);
+}
+
+/**
+ * A catch clause within a try statement.
+ *
+ * > onPart ::=
+ * >     catchPart [Block]
+ * >   | 'on' type catchPart? [Block]
+ * >
+ * > catchPart ::=
+ * >     'catch' '(' [SimpleIdentifier] (',' [SimpleIdentifier])? ')'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class CatchClause extends AstNode {
+  /**
+   * Initialize a newly created catch clause. The [onKeyword] and
+   * [exceptionType] can be `null` if the clause will catch all exceptions. The
+   * [comma] and [stackTraceParameter] can be `null` if the stack trace
+   * parameter is not defined.
+   */
+  factory CatchClause(
+      Token onKeyword,
+      TypeName exceptionType,
+      Token catchKeyword,
+      Token leftParenthesis,
+      SimpleIdentifier exceptionParameter,
+      Token comma,
+      SimpleIdentifier stackTraceParameter,
+      Token rightParenthesis,
+      Block body) = CatchClauseImpl;
+
+  /**
+   * Return the body of the catch block.
+   */
+  Block get body;
+
+  /**
+   * Set the body of the catch block to the given [block].
+   */
+  void set body(Block block);
+
+  /**
+   * Return the token representing the 'catch' keyword, or `null` if there is no
+   * 'catch' keyword.
+   */
+  Token get catchKeyword;
+
+  /**
+   * Set the token representing the 'catch' keyword to the given [token].
+   */
+  void set catchKeyword(Token token);
+
+  /**
+   * Return the comma separating the exception parameter from the stack trace
+   * parameter, or `null` if there is no stack trace parameter.
+   */
+  Token get comma;
+
+  /**
+   * Set the comma separating the exception parameter from the stack trace
+   * parameter to the given [token].
+   */
+  void set comma(Token token);
+
+  /**
+   * Return the parameter whose value will be the exception that was thrown, or
+   * `null` if there is no 'catch' keyword.
+   */
+  SimpleIdentifier get exceptionParameter;
+
+  /**
+   * Set the parameter whose value will be the exception that was thrown to the
+   * given [parameter].
+   */
+  void set exceptionParameter(SimpleIdentifier parameter);
+
+  /**
+   * Return the type of exceptions caught by this catch clause, or `null` if
+   * this catch clause catches every type of exception.
+   */
+  TypeName get exceptionType;
+
+  /**
+   * Set the type of exceptions caught by this catch clause to the given
+   * [exceptionType].
+   */
+  void set exceptionType(TypeName exceptionType);
+
+  /**
+   * Return the left parenthesis, or `null` if there is no 'catch' keyword.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the token representing the 'on' keyword, or `null` if there is no 'on'
+   * keyword.
+   */
+  Token get onKeyword;
+
+  /**
+   * Set the token representing the 'on' keyword to the given [token].
+   */
+  void set onKeyword(Token token);
+
+  /**
+   * Return the right parenthesis, or `null` if there is no 'catch' keyword.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the parameter whose value will be the stack trace associated with
+   * the exception, or `null` if there is no stack trace parameter.
+   */
+  SimpleIdentifier get stackTraceParameter;
+
+  /**
+   * Set the parameter whose value will be the stack trace associated with the
+   * exception to the given [parameter].
+   */
+  void set stackTraceParameter(SimpleIdentifier parameter);
+}
+
+/**
+ * The declaration of a class.
+ *
+ * > classDeclaration ::=
+ * >     'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]?
+ * >     ([ExtendsClause] [WithClause]?)?
+ * >     [ImplementsClause]?
+ * >     '{' [ClassMember]* '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ClassDeclaration extends NamedCompilationUnitMember {
+  /**
+   * Initialize a newly created class declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the class does not have the
+   * corresponding attribute. The [abstractKeyword] can be `null` if the class
+   * is not abstract. The [typeParameters] can be `null` if the class does not
+   * have any type parameters. Any or all of the [extendsClause], [withClause],
+   * and [implementsClause] can be `null` if the class does not have the
+   * corresponding clause. The list of [members] can be `null` if the class does
+   * not have any members.
+   */
+  factory ClassDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      Token abstractKeyword,
+      Token classKeyword,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      ExtendsClause extendsClause,
+      WithClause withClause,
+      ImplementsClause implementsClause,
+      Token leftBracket,
+      List<ClassMember> members,
+      Token rightBracket) = ClassDeclarationImpl;
+
+  /**
+   * Return the 'abstract' keyword, or `null` if the keyword was absent.
+   */
+  Token get abstractKeyword;
+
+  /**
+   * Set the 'abstract' keyword to the given [token].
+   */
+  void set abstractKeyword(Token token);
+
+  /**
+   * Return the token representing the 'class' keyword to the given [token].
+   */
+  Token get classKeyword;
+
+  /**
+   * Set the token representing the 'class' keyword.
+   */
+  void set classKeyword(Token token);
+
+  @override
+  ClassElement get element;
+
+  /**
+   * Return the extends clause for this class, or `null` if the class does not
+   * extend any other class.
+   */
+  ExtendsClause get extendsClause;
+
+  /**
+   * Set the extends clause for this class to the given [extendsClause].
+   */
+  void set extendsClause(ExtendsClause extendsClause);
+
+  /**
+   * Return the implements clause for the class, or `null` if the class does not
+   * implement any interfaces.
+   */
+  ImplementsClause get implementsClause;
+
+  /**
+   * Set the implements clause for the class to the given [implementsClause].
+   */
+  void set implementsClause(ImplementsClause implementsClause);
+
+  /**
+   * Return `true` if this class is declared to be an abstract class.
+   */
+  bool get isAbstract;
+
+  /**
+   * Return the left curly bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left curly bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the members defined by the class.
+   */
+  NodeList<ClassMember> get members;
+
+  /**
+   * Return the native clause for this class, or `null` if the class does not
+   * have a native clause.
+   */
+  NativeClause get nativeClause;
+
+  /**
+   * Set the native clause for this class to the given [nativeClause].
+   */
+  void set nativeClause(NativeClause nativeClause);
+
+  /**
+   * Return the right curly bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right curly bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+
+  /**
+   * Return the type parameters for the class, or `null` if the class does not
+   * have any type parameters.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters for the class to the given list of [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+
+  /**
+   * Return the with clause for the class, or `null` if the class does not have
+   * a with clause.
+   */
+  WithClause get withClause;
+
+  /**
+   * Set the with clause for the class to the given [withClause].
+   */
+  void set withClause(WithClause withClause);
+
+  /**
+   * Return the constructor declared in the class with the given [name], or
+   * `null` if there is no such constructor. If the [name] is `null` then the
+   * default constructor will be searched for.
+   */
+  ConstructorDeclaration getConstructor(String name);
+
+  /**
+   * Return the field declared in the class with the given [name], or `null` if
+   * there is no such field.
+   */
+  VariableDeclaration getField(String name);
+
+  /**
+   * Return the method declared in the class with the given [name], or `null` if
+   * there is no such method.
+   */
+  MethodDeclaration getMethod(String name);
+}
+
+/**
+ * A node that declares a name within the scope of a class.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ClassMember extends Declaration {}
+
+/**
+ * A class type alias.
+ *
+ * > classTypeAlias ::=
+ * >     [SimpleIdentifier] [TypeParameterList]? '=' 'abstract'? mixinApplication
+ * >
+ * > mixinApplication ::=
+ * >     [TypeName] [WithClause] [ImplementsClause]? ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ClassTypeAlias extends TypeAlias {
+  /**
+   * Initialize a newly created class type alias. Either or both of the
+   * [comment] and [metadata] can be `null` if the class type alias does not
+   * have the corresponding attribute. The [typeParameters] can be `null` if the
+   * class does not have any type parameters. The [abstractKeyword] can be
+   * `null` if the class is not abstract. The [implementsClause] can be `null`
+   * if the class does not implement any interfaces.
+   */
+  factory ClassTypeAlias(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      Token equals,
+      Token abstractKeyword,
+      TypeName superclass,
+      WithClause withClause,
+      ImplementsClause implementsClause,
+      Token semicolon) = ClassTypeAliasImpl;
+
+  /**
+   * Return the token for the 'abstract' keyword, or `null` if this is not
+   * defining an abstract class.
+   */
+  Token get abstractKeyword;
+
+  /**
+   * Set the token for the 'abstract' keyword to the given [token].
+   */
+  void set abstractKeyword(Token token);
+
+  /**
+   * Return the token for the '=' separating the name from the definition.
+   */
+  Token get equals;
+
+  /**
+   * Set the token for the '=' separating the name from the definition to the
+   * given [token].
+   */
+  void set equals(Token token);
+
+  /**
+   * Return the implements clause for this class, or `null` if there is no
+   * implements clause.
+   */
+  ImplementsClause get implementsClause;
+
+  /**
+   * Set the implements clause for this class to the given [implementsClause].
+   */
+  void set implementsClause(ImplementsClause implementsClause);
+
+  /**
+   * Return `true` if this class is declared to be an abstract class.
+   */
+  bool get isAbstract;
+
+  /**
+   * Return the name of the superclass of the class being declared.
+   */
+  TypeName get superclass;
+
+  /**
+   * Set the name of the superclass of the class being declared to the given
+   * [superclass] name.
+   */
+  void set superclass(TypeName superclass);
+
+  /**
+   * Return the type parameters for the class, or `null` if the class does not
+   * have any type parameters.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters for the class to the given list of [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+
+  /**
+   * Return the with clause for this class.
+   */
+  WithClause get withClause;
+
+  /**
+   * Set the with clause for this class to the given with [withClause].
+   */
+  void set withClause(WithClause withClause);
+}
+
+/**
+ * A combinator associated with an import or export directive.
+ *
+ * > combinator ::=
+ * >     [HideCombinator]
+ * >   | [ShowCombinator]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Combinator extends AstNode {
+  /**
+   * Return the 'hide' or 'show' keyword specifying what kind of processing is
+   * to be done on the names.
+   */
+  Token get keyword;
+
+  /**
+   * Set the 'hide' or 'show' keyword specifying what kind of processing is
+   * to be done on the names to the given [token].
+   */
+  void set keyword(Token token);
+}
+
+/**
+ * A comment within the source code.
+ *
+ * > comment ::=
+ * >     endOfLineComment
+ * >   | blockComment
+ * >   | documentationComment
+ * >
+ * > endOfLineComment ::=
+ * >     '//' (CHARACTER - EOL)* EOL
+ * >
+ * > blockComment ::=
+ * >     '/ *' CHARACTER* '&#42;/'
+ * >
+ * > documentationComment ::=
+ * >     '/ **' (CHARACTER | [CommentReference])* '&#42;/'
+ * >   | ('///' (CHARACTER - EOL)* EOL)+
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Comment extends AstNode {
+  /**
+   * Initialize a newly created comment. The list of [tokens] must contain at
+   * least one token. The [type] is the type of the comment. The list of
+   * [references] can be empty if the comment does not contain any embedded
+   * references.
+   */
+  factory Comment(List<Token> tokens, CommentType type,
+      List<CommentReference> references) = CommentImpl;
+
+  /**
+   * Return `true` if this is a block comment.
+   */
+  bool get isBlock;
+
+  /**
+   * Return `true` if this is a documentation comment.
+   */
+  bool get isDocumentation;
+
+  /**
+   * Return `true` if this is an end-of-line comment.
+   */
+  bool get isEndOfLine;
+
+  /**
+   * Return the references embedded within the documentation comment.
+   */
+  NodeList<CommentReference> get references;
+
+  /**
+   * Return the tokens representing the comment.
+   */
+  List<Token> get tokens;
+
+  /**
+   * Create a block comment consisting of the given [tokens].
+   */
+  static Comment createBlockComment(List<Token> tokens) =>
+      CommentImpl.createBlockComment(tokens);
+
+  /**
+   * Create a documentation comment consisting of the given [tokens].
+   */
+  static Comment createDocumentationComment(List<Token> tokens) =>
+      CommentImpl.createDocumentationComment(tokens);
+
+  /**
+   * Create a documentation comment consisting of the given [tokens] and having
+   * the given [references] embedded within it.
+   */
+  static Comment createDocumentationCommentWithReferences(
+          List<Token> tokens, List<CommentReference> references) =>
+      CommentImpl.createDocumentationCommentWithReferences(tokens, references);
+
+  /**
+   * Create an end-of-line comment consisting of the given [tokens].
+   */
+  static Comment createEndOfLineComment(List<Token> tokens) =>
+      CommentImpl.createEndOfLineComment(tokens);
+}
+
+/**
+ * A reference to a Dart element that is found within a documentation comment.
+ *
+ * > commentReference ::=
+ * >     '[' 'new'? [Identifier] ']'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class CommentReference extends AstNode {
+  /**
+   * Initialize a newly created reference to a Dart element. The [newKeyword]
+   * can be `null` if the reference is not to a constructor.
+   */
+  factory CommentReference(Token newKeyword, Identifier identifier) =
+      CommentReferenceImpl;
+
+  /**
+   * Return the identifier being referenced.
+   */
+  Identifier get identifier;
+
+  /**
+   * Set the identifier being referenced to the given [identifier].
+   */
+  void set identifier(Identifier identifier);
+
+  /**
+   * Return the token representing the 'new' keyword, or `null` if there was no
+   * 'new' keyword.
+   */
+  Token get newKeyword;
+
+  /**
+   * Set the token representing the 'new' keyword to the given [token].
+   */
+  void set newKeyword(Token token);
+}
+
+/**
+ * A compilation unit.
+ *
+ * While the grammar restricts the order of the directives and declarations
+ * within a compilation unit, this class does not enforce those restrictions.
+ * In particular, the children of a compilation unit will be visited in lexical
+ * order even if lexical order does not conform to the restrictions of the
+ * grammar.
+ *
+ * > compilationUnit ::=
+ * >     directives declarations
+ * >
+ * > directives ::=
+ * >     [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
+ * >   | [PartOfDirective]
+ * >
+ * > namespaceDirective ::=
+ * >     [ImportDirective]
+ * >   | [ExportDirective]
+ * >
+ * > declarations ::=
+ * >     [CompilationUnitMember]*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class CompilationUnit extends AstNode {
+  /**
+   * Initialize a newly created compilation unit to have the given directives
+   * and declarations. The [scriptTag] can be `null` if there is no script tag
+   * in the compilation unit. The list of [directives] can be `null` if there
+   * are no directives in the compilation unit. The list of [declarations] can
+   * be `null` if there are no declarations in the compilation unit.
+   */
+  factory CompilationUnit(
+      Token beginToken,
+      ScriptTag scriptTag,
+      List<Directive> directives,
+      List<CompilationUnitMember> declarations,
+      Token endToken) = CompilationUnitImpl;
+
+  /**
+   * Set the first token included in this node's source range to the given
+   * [token].
+   */
+  void set beginToken(Token token);
+
+  /**
+   * Return the declarations contained in this compilation unit.
+   */
+  NodeList<CompilationUnitMember> get declarations;
+
+  /**
+   * Return the directives contained in this compilation unit.
+   */
+  NodeList<Directive> get directives;
+
+  /**
+   * Return the element associated with this compilation unit, or `null` if the
+   * AST structure has not been resolved.
+   */
+  CompilationUnitElement get element;
+
+  /**
+   * Set the element associated with this compilation unit to the given
+   * [element].
+   */
+  void set element(CompilationUnitElement element);
+
+  /**
+   * Set the last token included in this node's source range to the given
+   * [token].
+   */
+  void set endToken(Token token);
+
+  /**
+   * Return the line information for this compilation unit.
+   */
+  LineInfo get lineInfo;
+
+  /**
+   * Set the line information for this compilation unit to the given [info].
+   */
+  void set lineInfo(LineInfo info);
+
+  /**
+   * Return the script tag at the beginning of the compilation unit, or `null`
+   * if there is no script tag in this compilation unit.
+   */
+  ScriptTag get scriptTag;
+
+  /**
+   * Set the script tag at the beginning of the compilation unit to the given
+   * [scriptTag].
+   */
+  void set scriptTag(ScriptTag scriptTag);
+
+  /**
+   * Return a list containing all of the directives and declarations in this
+   * compilation unit, sorted in lexical order.
+   */
+  List<AstNode> get sortedDirectivesAndDeclarations;
+}
+
+/**
+ * A node that declares one or more names within the scope of a compilation
+ * unit.
+ *
+ * > compilationUnitMember ::=
+ * >     [ClassDeclaration]
+ * >   | [TypeAlias]
+ * >   | [FunctionDeclaration]
+ * >   | [MethodDeclaration]
+ * >   | [VariableDeclaration]
+ * >   | [VariableDeclaration]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class CompilationUnitMember extends Declaration {}
+
+/**
+ * A conditional expression.
+ *
+ * > conditionalExpression ::=
+ * >     [Expression] '?' [Expression] ':' [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ConditionalExpression extends Expression {
+  /**
+   * Initialize a newly created conditional expression.
+   */
+  factory ConditionalExpression(
+      Expression condition,
+      Token question,
+      Expression thenExpression,
+      Token colon,
+      Expression elseExpression) = ConditionalExpressionImpl;
+
+  /**
+   * Return the token used to separate the then expression from the else
+   * expression.
+   */
+  Token get colon;
+
+  /**
+   * Set the token used to separate the then expression from the else expression
+   * to the given [token].
+   */
+  void set colon(Token token);
+
+  /**
+   * Return the condition used to determine which of the expressions is executed
+   * next.
+   */
+  Expression get condition;
+
+  /**
+   * Set the condition used to determine which of the expressions is executed
+   * next to the given [expression].
+   */
+  void set condition(Expression expression);
+
+  /**
+   * Return the expression that is executed if the condition evaluates to
+   * `false`.
+   */
+  Expression get elseExpression;
+
+  /**
+   * Set the expression that is executed if the condition evaluates to `false`
+   * to the given [expression].
+   */
+  void set elseExpression(Expression expression);
+
+  /**
+   * Return the token used to separate the condition from the then expression.
+   */
+  Token get question;
+
+  /**
+   * Set the token used to separate the condition from the then expression to
+   * the given [token].
+   */
+  void set question(Token token);
+
+  /**
+   * Return the expression that is executed if the condition evaluates to
+   * `true`.
+   */
+  Expression get thenExpression;
+
+  /**
+   * Set the expression that is executed if the condition evaluates to `true` to
+   * the given [expression].
+   */
+  void set thenExpression(Expression expression);
+}
+
+/**
+ * A configuration in either an import or export directive.
+ *
+ * > configuration ::=
+ * >     'if' '(' test ')' uri
+ * >
+ * > test ::=
+ * >     dottedName ('==' stringLiteral)?
+ * >
+ * > dottedName ::=
+ * >     identifier ('.' identifier)*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Configuration extends AstNode {
+  /**
+   * Initialize a newly created configuration.
+   */
+  factory Configuration(
+      Token ifKeyword,
+      Token leftParenthesis,
+      DottedName name,
+      Token equalToken,
+      StringLiteral value,
+      Token rightParenthesis,
+      StringLiteral libraryUri) = ConfigurationImpl;
+
+  /**
+   * Return the token for the equal operator, or `null` if the condition does
+   * not include an equality test.
+   */
+  Token get equalToken;
+
+  /**
+   * Set the token for the equal operator to the given [token].
+   */
+  void set equalToken(Token token);
+
+  /**
+   * Return the token for the 'if' keyword.
+   */
+  Token get ifKeyword;
+
+  /**
+   * Set the token for the 'if' keyword to the given [token].
+   */
+  void set ifKeyword(Token token);
+
+  /**
+   * Return the token for the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the token for the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the URI of the implementation library to be used if the condition is
+   * true.
+   */
+  StringLiteral get libraryUri;
+
+  /**
+   * Set the URI of the implementation library to be used if the condition is
+   * true to the given [uri].
+   */
+  void set libraryUri(StringLiteral uri);
+
+  /**
+   * Return the name of the declared variable whose value is being used in the
+   * condition.
+   */
+  DottedName get name;
+
+  /**
+   * Set the name of the declared variable whose value is being used in the
+   * condition to the given [name].
+   */
+  void set name(DottedName name);
+
+  /**
+   * Return the token for the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the token for the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the value to which the value of the declared variable will be
+   * compared, or `null` if the condition does not include an equality test.
+   */
+  StringLiteral get value;
+
+  /**
+   * Set the value to which the value of the declared variable will be
+   * compared to the given [value].
+   */
+  void set value(StringLiteral value);
+}
+
+/**
+ * A constructor declaration.
+ *
+ * > constructorDeclaration ::=
+ * >     constructorSignature [FunctionBody]?
+ * >   | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier])? arguments
+ * >
+ * > constructorSignature ::=
+ * >     'external'? constructorName formalParameterList initializerList?
+ * >   | 'external'? 'factory' factoryName formalParameterList initializerList?
+ * >   | 'external'? 'const'  constructorName formalParameterList initializerList?
+ * >
+ * > constructorName ::=
+ * >     [SimpleIdentifier] ('.' [SimpleIdentifier])?
+ * >
+ * > factoryName ::=
+ * >     [Identifier] ('.' [SimpleIdentifier])?
+ * >
+ * > initializerList ::=
+ * >     ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ConstructorDeclaration extends ClassMember {
+  /**
+   * Initialize a newly created constructor declaration. The [externalKeyword]
+   * can be `null` if the constructor is not external. Either or both of the
+   * [comment] and [metadata] can be `null` if the constructor does not have the
+   * corresponding attribute. The [constKeyword] can be `null` if the
+   * constructor cannot be used to create a constant. The [factoryKeyword] can
+   * be `null` if the constructor is not a factory. The [period] and [name] can
+   * both be `null` if the constructor is not a named constructor. The
+   * [separator] can be `null` if the constructor does not have any initializers
+   * and does not redirect to a different constructor. The list of
+   * [initializers] can be `null` if the constructor does not have any
+   * initializers. The [redirectedConstructor] can be `null` if the constructor
+   * does not redirect to a different constructor. The [body] can be `null` if
+   * the constructor does not have a body.
+   */
+  factory ConstructorDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      Token externalKeyword,
+      Token constKeyword,
+      Token factoryKeyword,
+      Identifier returnType,
+      Token period,
+      SimpleIdentifier name,
+      FormalParameterList parameters,
+      Token separator,
+      List<ConstructorInitializer> initializers,
+      ConstructorName redirectedConstructor,
+      FunctionBody body) = ConstructorDeclarationImpl;
+
+  /**
+   * Return the body of the constructor, or `null` if the constructor does not
+   * have a body.
+   */
+  FunctionBody get body;
+
+  /**
+   * Set the body of the constructor to the given [functionBody].
+   */
+  void set body(FunctionBody functionBody);
+
+  /**
+   * Return the token for the 'const' keyword, or `null` if the constructor is
+   * not a const constructor.
+   */
+  Token get constKeyword;
+
+  /**
+   * Set the token for the 'const' keyword to the given [token].
+   */
+  void set constKeyword(Token token);
+
+  @override
+  ConstructorElement get element;
+
+  /**
+   * Set the element associated with this constructor to the given [element].
+   */
+  void set element(ConstructorElement element);
+
+  /**
+   * Return the token for the 'external' keyword to the given [token].
+   */
+  Token get externalKeyword;
+
+  /**
+   * Set the token for the 'external' keyword, or `null` if the constructor
+   * is not external.
+   */
+  void set externalKeyword(Token token);
+
+  /**
+   * Return the token for the 'factory' keyword, or `null` if the constructor is
+   * not a factory constructor.
+   */
+  Token get factoryKeyword;
+
+  /**
+   * Set the token for the 'factory' keyword to the given [token].
+   */
+  void set factoryKeyword(Token token);
+
+  /**
+   * Return the initializers associated with the constructor.
+   */
+  NodeList<ConstructorInitializer> get initializers;
+
+  /**
+   * Return the name of the constructor, or `null` if the constructor being
+   * declared is unnamed.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the constructor to the given [identifier].
+   */
+  void set name(SimpleIdentifier identifier);
+
+  /**
+   * Return the parameters associated with the constructor.
+   */
+  FormalParameterList get parameters;
+
+  /**
+   * Set the parameters associated with the constructor to the given list of
+   * [parameters].
+   */
+  void set parameters(FormalParameterList parameters);
+
+  /**
+   * Return the token for the period before the constructor name, or `null` if
+   * the constructor being declared is unnamed.
+   */
+  Token get period;
+
+  /**
+   * Set the token for the period before the constructor name to the given
+   * [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the name of the constructor to which this constructor will be
+   * redirected, or `null` if this is not a redirecting factory constructor.
+   */
+  ConstructorName get redirectedConstructor;
+
+  /**
+   * Set the name of the constructor to which this constructor will be
+   * redirected to the given [redirectedConstructor] name.
+   */
+  void set redirectedConstructor(ConstructorName redirectedConstructor);
+
+  /**
+   * Return the type of object being created. This can be different than the
+   * type in which the constructor is being declared if the constructor is the
+   * implementation of a factory constructor.
+   */
+  Identifier get returnType;
+
+  /**
+   * Set the type of object being created to the given [typeName].
+   */
+  void set returnType(Identifier typeName);
+
+  /**
+   * Return the token for the separator (colon or equals) before the initializer
+   * list or redirection, or `null` if there are no initializers.
+   */
+  Token get separator;
+
+  /**
+   * Set the token for the separator (colon or equals) before the initializer
+   * list or redirection to the given [token].
+   */
+  void set separator(Token token);
+}
+
+/**
+ * The initialization of a field within a constructor's initialization list.
+ *
+ * > fieldInitializer ::=
+ * >     ('this' '.')? [SimpleIdentifier] '=' [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ConstructorFieldInitializer extends ConstructorInitializer {
+  /**
+   * Initialize a newly created field initializer to initialize the field with
+   * the given name to the value of the given expression. The [thisKeyword] and
+   * [period] can be `null` if the 'this' keyword was not specified.
+   */
+  factory ConstructorFieldInitializer(
+      Token thisKeyword,
+      Token period,
+      SimpleIdentifier fieldName,
+      Token equals,
+      Expression expression) = ConstructorFieldInitializerImpl;
+
+  /**
+   * Return the token for the equal sign between the field name and the
+   * expression.
+   */
+  Token get equals;
+
+  /**
+   * Set the token for the equal sign between the field name and the
+   * expression to the given [token].
+   */
+  void set equals(Token token);
+
+  /**
+   * Return the expression computing the value to which the field will be
+   * initialized.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression computing the value to which the field will be
+   * initialized to the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the name of the field being initialized.
+   */
+  SimpleIdentifier get fieldName;
+
+  /**
+   * Set the name of the field being initialized to the given [identifier].
+   */
+  void set fieldName(SimpleIdentifier identifier);
+
+  /**
+   * Return the token for the period after the 'this' keyword, or `null` if
+   * there is no 'this' keyword.
+   */
+  Token get period;
+
+  /**
+   * Set the token for the period after the 'this' keyword to the given [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the token for the 'this' keyword, or `null` if there is no 'this'
+   * keyword.
+   */
+  Token get thisKeyword;
+
+  /**
+   * Set the token for the 'this' keyword to the given [token].
+   */
+  void set thisKeyword(Token token);
+}
+
+/**
+ * A node that can occur in the initializer list of a constructor declaration.
+ *
+ * > constructorInitializer ::=
+ * >     [SuperConstructorInvocation]
+ * >   | [ConstructorFieldInitializer]
+ * >   | [RedirectingConstructorInvocation]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ConstructorInitializer extends AstNode {}
+
+/**
+ * The name of a constructor.
+ *
+ * > constructorName ::=
+ * >     type ('.' identifier)?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ConstructorName extends AstNode {
+  /**
+   * Initialize a newly created constructor name. The [period] and [name] can be
+   * `null` if the constructor being named is the unnamed constructor.
+   */
+  factory ConstructorName(TypeName type, Token period, SimpleIdentifier name) =
+      ConstructorNameImpl;
+
+  /**
+   * Return the name of the constructor, or `null` if the specified constructor
+   * is the unnamed constructor.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the constructor to the given [name].
+   */
+  void set name(SimpleIdentifier name);
+
+  /**
+   * Return the token for the period before the constructor name, or `null` if
+   * the specified constructor is the unnamed constructor.
+   */
+  Token get period;
+
+  /**
+   * Set the token for the period before the constructor name to the given
+   * [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the element associated with this constructor name based on static
+   * type information, or `null` if the AST structure has not been resolved or
+   * if this constructor name could not be resolved.
+   */
+  ConstructorElement get staticElement;
+
+  /**
+   * Set the element associated with this constructor name based on static type
+   * information to the given [element].
+   */
+  void set staticElement(ConstructorElement element);
+
+  /**
+   * Return the name of the type defining the constructor.
+   */
+  TypeName get type;
+
+  /**
+   * Set the name of the type defining the constructor to the given [type] name.
+   */
+  void set type(TypeName type);
+}
+
+/**
+ * A continue statement.
+ *
+ * > continueStatement ::=
+ * >     'continue' [SimpleIdentifier]? ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ContinueStatement extends Statement {
+  /**
+   * Initialize a newly created continue statement. The [label] can be `null` if
+   * there is no label associated with the statement.
+   */
+  factory ContinueStatement(
+          Token continueKeyword, SimpleIdentifier label, Token semicolon) =
+      ContinueStatementImpl;
+
+  /**
+   * Return the token representing the 'continue' keyword.
+   */
+  Token get continueKeyword;
+
+  /**
+   * Set the token representing the 'continue' keyword to the given [token].
+   */
+  void set continueKeyword(Token token);
+
+  /**
+   * Return the label associated with the statement, or `null` if there is no
+   * label.
+   */
+  SimpleIdentifier get label;
+
+  /**
+   * Set the label associated with the statement to the given [identifier].
+   */
+  void set label(SimpleIdentifier identifier);
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the node to which this continue statement is continuing. This will
+   * be either a [Statement] (in the case of continuing a loop), a
+   * [SwitchMember] (in the case of continuing from one switch case to another),
+   * or `null` if the AST has not yet been resolved or if the target could not
+   * be resolved. Note that if the source code has errors, the target might be
+   * invalid (e.g. the target may be in an enclosing function).
+   */
+  AstNode get target;
+
+  /**
+   * Set the node to which this continue statement is continuing to the given
+   * [node].
+   */
+  void set target(AstNode node);
+}
+
+/**
+ * A node that represents the declaration of one or more names. Each declared
+ * name is visible within a name scope.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Declaration extends AnnotatedNode {
+  /**
+   * Return the element associated with this declaration, or `null` if either
+   * this node corresponds to a list of declarations or if the AST structure has
+   * not been resolved.
+   */
+  Element get element;
+}
+
+/**
+ * The declaration of a single identifier.
+ *
+ * > declaredIdentifier ::=
+ * >     [Annotation] finalConstVarOrType [SimpleIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DeclaredIdentifier extends Declaration {
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The [keyword] can be `null` if a type name is
+   * given. The [type] must be `null` if the keyword is 'var'.
+   */
+  factory DeclaredIdentifier(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      TypeName type,
+      SimpleIdentifier identifier) = DeclaredIdentifierImpl;
+
+  @override
+  LocalVariableElement get element;
+
+  /**
+   * Return the name of the variable being declared.
+   */
+  SimpleIdentifier get identifier;
+
+  /**
+   * Set the name of the variable being declared to the given [identifier].
+   */
+  void set identifier(SimpleIdentifier identifier);
+
+  /**
+   * Return `true` if this variable was declared with the 'const' modifier.
+   */
+  bool get isConst;
+
+  /**
+   * Return `true` if this variable was declared with the 'final' modifier.
+   * Variables that are declared with the 'const' modifier will return `false`
+   * even though they are implicitly final.
+   */
+  bool get isFinal;
+
+  /**
+   * Return the token representing either the 'final', 'const' or 'var' keyword,
+   * or `null` if no keyword was used.
+   */
+  Token get keyword;
+
+  /**
+   * Set the token representing either the 'final', 'const' or 'var' keyword to
+   * the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the name of the declared type of the parameter, or `null` if the
+   * parameter does not have a declared type.
+   */
+  TypeName get type;
+
+  /**
+   * Set the name of the declared type of the parameter to the given [typeName].
+   */
+  void set type(TypeName typeName);
+}
+
+/**
+ * A formal parameter with a default value. There are two kinds of parameters
+ * that are both represented by this class: named formal parameters and
+ * positional formal parameters.
+ *
+ * > defaultFormalParameter ::=
+ * >     [NormalFormalParameter] ('=' [Expression])?
+ * >
+ * > defaultNamedParameter ::=
+ * >     [NormalFormalParameter] (':' [Expression])?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DefaultFormalParameter extends FormalParameter {
+  /**
+   * Initialize a newly created default formal parameter. The [separator] and
+   * [defaultValue] can be `null` if there is no default value.
+   */
+  factory DefaultFormalParameter(
+      NormalFormalParameter parameter,
+      ParameterKind kind,
+      Token separator,
+      Expression defaultValue) = DefaultFormalParameterImpl;
+
+  /**
+   * Return the expression computing the default value for the parameter, or
+   * `null` if there is no default value.
+   */
+  Expression get defaultValue;
+
+  /**
+   * Set the expression computing the default value for the parameter to the
+   * given [expression].
+   */
+  void set defaultValue(Expression expression);
+
+  /**
+   * Set the kind of this parameter to the given [kind].
+   */
+  void set kind(ParameterKind kind);
+
+  /**
+   * Return the formal parameter with which the default value is associated.
+   */
+  NormalFormalParameter get parameter;
+
+  /**
+   * Set the formal parameter with which the default value is associated to the
+   * given [formalParameter].
+   */
+  void set parameter(NormalFormalParameter formalParameter);
+
+  /**
+   * Return the token separating the parameter from the default value, or `null`
+   * if there is no default value.
+   */
+  Token get separator;
+
+  /**
+   * Set the token separating the parameter from the default value to the given
+   * [token].
+   */
+  void set separator(Token token);
+}
+
+/**
+ * A node that represents a directive.
+ *
+ * > directive ::=
+ * >     [ExportDirective]
+ * >   | [ImportDirective]
+ * >   | [LibraryDirective]
+ * >   | [PartDirective]
+ * >   | [PartOfDirective]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Directive extends AnnotatedNode {
+  /**
+   * Return the element associated with this directive, or `null` if the AST
+   * structure has not been resolved or if this directive could not be resolved.
+   */
+  Element get element;
+
+  /**
+   * Set the element associated with this directive to the given [element].
+   */
+  void set element(Element element);
+
+  /**
+   * Return the token representing the keyword that introduces this directive
+   * ('import', 'export', 'library' or 'part').
+   */
+  Token get keyword;
+}
+
+/**
+ * A do statement.
+ *
+ * > doStatement ::=
+ * >     'do' [Statement] 'while' '(' [Expression] ')' ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DoStatement extends Statement {
+  /**
+   * Initialize a newly created do loop.
+   */
+  factory DoStatement(
+      Token doKeyword,
+      Statement body,
+      Token whileKeyword,
+      Token leftParenthesis,
+      Expression condition,
+      Token rightParenthesis,
+      Token semicolon) = DoStatementImpl;
+
+  /**
+   * Return the body of the loop.
+   */
+  Statement get body;
+
+  /**
+   * Set the body of the loop to the given [statement].
+   */
+  void set body(Statement statement);
+
+  /**
+   * Return the condition that determines when the loop will terminate.
+   */
+  Expression get condition;
+
+  /**
+   * Set the condition that determines when the loop will terminate to the given
+   * [expression].
+   */
+  void set condition(Expression expression);
+
+  /**
+   * Return the token representing the 'do' keyword.
+   */
+  Token get doKeyword;
+
+  /**
+   * Set the token representing the 'do' keyword to the given [token].
+   */
+  void set doKeyword(Token token);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the token representing the 'while' keyword.
+   */
+  Token get whileKeyword;
+
+  /**
+   * Set the token representing the 'while' keyword to the given [token].
+   */
+  void set whileKeyword(Token token);
+}
+
+/**
+ * A dotted name, used in a configuration within an import or export directive.
+ *
+ * > dottedName ::=
+ * >     [SimpleIdentifier] ('.' [SimpleIdentifier])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DottedName extends AstNode {
+  /**
+   * Initialize a newly created dotted name.
+   */
+  factory DottedName(List<SimpleIdentifier> components) = DottedNameImpl;
+
+  /**
+   * Return the components of the identifier.
+   */
+  NodeList<SimpleIdentifier> get components;
+}
+
+/**
+ * A floating point literal expression.
+ *
+ * > doubleLiteral ::=
+ * >     decimalDigit+ ('.' decimalDigit*)? exponent?
+ * >   | '.' decimalDigit+ exponent?
+ * >
+ * > exponent ::=
+ * >     ('e' | 'E') ('+' | '-')? decimalDigit+
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DoubleLiteral extends Literal {
+  /**
+   * Initialize a newly created floating point literal.
+   */
+  factory DoubleLiteral(Token literal, double value) = DoubleLiteralImpl;
+
+  /**
+   * Return the token representing the literal.
+   */
+  Token get literal;
+
+  /**
+   * Set the token representing the literal to the given [token].
+   */
+  void set literal(Token token);
+
+  /**
+   * Return the value of the literal.
+   */
+  double get value;
+
+  /**
+   * Set the value of the literal to the given [value].
+   */
+  void set value(double value);
+}
+
+/**
+ * An empty function body, which can only appear in constructors or abstract
+ * methods.
+ *
+ * > emptyFunctionBody ::=
+ * >     ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class EmptyFunctionBody extends FunctionBody {
+  /**
+   * Initialize a newly created function body.
+   */
+  factory EmptyFunctionBody(Token semicolon) = EmptyFunctionBodyImpl;
+
+  /**
+   * Return the token representing the semicolon that marks the end of the
+   * function body.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the token representing the semicolon that marks the end of the
+   * function body to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * An empty statement.
+ *
+ * > emptyStatement ::=
+ * >     ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class EmptyStatement extends Statement {
+  /**
+   * Initialize a newly created empty statement.
+   */
+  factory EmptyStatement(Token semicolon) = EmptyStatementImpl;
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * The declaration of an enum constant.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class EnumConstantDeclaration extends Declaration {
+  /**
+   * Initialize a newly created enum constant declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the constant does not have the
+   * corresponding attribute. (Technically, enum constants cannot have metadata,
+   * but we allow it for consistency.)
+   */
+  factory EnumConstantDeclaration(
+          Comment comment, List<Annotation> metadata, SimpleIdentifier name) =
+      EnumConstantDeclarationImpl;
+
+  /**
+   * Return the name of the constant.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the constant to the given [name].
+   */
+  void set name(SimpleIdentifier name);
+}
+
+/**
+ * The declaration of an enumeration.
+ *
+ * > enumType ::=
+ * >     metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] (',' [SimpleIdentifier])* (',')? '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class EnumDeclaration extends NamedCompilationUnitMember {
+  /**
+   * Initialize a newly created enumeration declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The list of [constants] must contain at least one
+   * value.
+   */
+  factory EnumDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      Token enumKeyword,
+      SimpleIdentifier name,
+      Token leftBracket,
+      List<EnumConstantDeclaration> constants,
+      Token rightBracket) = EnumDeclarationImpl;
+
+  /**
+   * Return the enumeration constants being declared.
+   */
+  NodeList<EnumConstantDeclaration> get constants;
+
+  @override
+  ClassElement get element;
+
+  /**
+   * Return the 'enum' keyword.
+   */
+  Token get enumKeyword;
+
+  /**
+   * Set the 'enum' keyword to the given [token].
+   */
+  void set enumKeyword(Token token);
+
+  /**
+   * Return the left curly bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left curly bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the right curly bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right curly bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+}
+
+/**
+ * An export directive.
+ *
+ * > exportDirective ::=
+ * >     [Annotation] 'export' [StringLiteral] [Combinator]* ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ExportDirective extends NamespaceDirective {
+  /**
+   * Initialize a newly created export directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute. The list of [combinators] can be `null` if there
+   * are no combinators.
+   */
+  factory ExportDirective(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      StringLiteral libraryUri,
+      List<Configuration> configurations,
+      List<Combinator> combinators,
+      Token semicolon) = ExportDirectiveImpl;
+}
+
+/**
+ * A node that represents an expression.
+ *
+ * > expression ::=
+ * >     [AssignmentExpression]
+ * >   | [ConditionalExpression] cascadeSection*
+ * >   | [ThrowExpression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Expression extends AstNode {
+  /**
+   * An empty list of expressions.
+   */
+  static const List<Expression> EMPTY_LIST = const <Expression>[];
+
+  /**
+   * Return the best parameter element information available for this
+   * expression. If type propagation was able to find a better parameter element
+   * than static analysis, that type will be returned. Otherwise, the result of
+   * static analysis will be returned.
+   */
+  ParameterElement get bestParameterElement;
+
+  /**
+   * Return the best type information available for this expression. If type
+   * propagation was able to find a better type than static analysis, that type
+   * will be returned. Otherwise, the result of static analysis will be
+   * returned. If no type analysis has been performed, then the type 'dynamic'
+   * will be returned.
+   */
+  DartType get bestType;
+
+  /**
+   * Return `true` if this expression is syntactically valid for the LHS of an
+   * [AssignmentExpression].
+   */
+  bool get isAssignable;
+
+  /**
+   * Return the precedence of this expression. The precedence is a positive
+   * integer value that defines how the source code is parsed into an AST. For
+   * example `a * b + c` is parsed as `(a * b) + c` because the precedence of
+   * `*` is greater than the precedence of `+`.
+   *
+   * Clients should not assume that returned values will stay the same, they
+   * might change as result of specification change. Only relative order should
+   * be used.
+   */
+  int get precedence;
+
+  /**
+   * If this expression is an argument to an invocation, and the AST structure
+   * has been resolved, and the function being invoked is known based on
+   * propagated type information, and this expression corresponds to one of the
+   * parameters of the function being invoked, then return the parameter element
+   * representing the parameter to which the value of this expression will be
+   * bound. Otherwise, return `null`.
+   */
+  ParameterElement get propagatedParameterElement;
+
+  /**
+   * Return the propagated type of this expression, or `null` if type
+   * propagation has not been performed on the AST structure.
+   */
+  DartType get propagatedType;
+
+  /**
+   * Set the propagated type of this expression to the given [type].
+   */
+  void set propagatedType(DartType type);
+
+  /**
+   * If this expression is an argument to an invocation, and the AST structure
+   * has been resolved, and the function being invoked is known based on static
+   * type information, and this expression corresponds to one of the parameters
+   * of the function being invoked, then return the parameter element
+   * representing the parameter to which the value of this expression will be
+   * bound. Otherwise, return `null`.
+   */
+  ParameterElement get staticParameterElement;
+
+  /**
+   * Return the static type of this expression, or `null` if the AST structure
+   * has not been resolved.
+   */
+  DartType get staticType;
+
+  /**
+   * Set the static type of this expression to the given [type].
+   */
+  void set staticType(DartType type);
+}
+
+/**
+ * A function body consisting of a single expression.
+ *
+ * > expressionFunctionBody ::=
+ * >     'async'? '=>' [Expression] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ExpressionFunctionBody extends FunctionBody {
+  /**
+   * Initialize a newly created function body consisting of a block of
+   * statements. The [keyword] can be `null` if the function body is not an
+   * async function body.
+   */
+  factory ExpressionFunctionBody(Token keyword, Token functionDefinition,
+      Expression expression, Token semicolon) = ExpressionFunctionBodyImpl;
+
+  /**
+   * Return the expression representing the body of the function.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression representing the body of the function to the given
+   * [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the token introducing the expression that represents the body of the
+   * function.
+   */
+  Token get functionDefinition;
+
+  /**
+   * Set the token introducing the expression that represents the body of the
+   * function to the given [token].
+   */
+  void set functionDefinition(Token token);
+
+  /**
+   * Set token representing the 'async' or 'sync' keyword to the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * An expression used as a statement.
+ *
+ * > expressionStatement ::=
+ * >     [Expression]? ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ExpressionStatement extends Statement {
+  /**
+   * Initialize a newly created expression statement.
+   */
+  factory ExpressionStatement(Expression expression, Token semicolon) =
+      ExpressionStatementImpl;
+
+  /**
+   * Return the expression that comprises the statement.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression that comprises the statement to the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the semicolon terminating the statement, or `null` if the expression is a
+   * function expression and therefore isn't followed by a semicolon.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * The "extends" clause in a class declaration.
+ *
+ * > extendsClause ::=
+ * >     'extends' [TypeName]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ExtendsClause extends AstNode {
+  /**
+   * Initialize a newly created extends clause.
+   */
+  factory ExtendsClause(Token extendsKeyword, TypeName superclass) =
+      ExtendsClauseImpl;
+
+  /**
+   * Return the token representing the 'extends' keyword.
+   */
+  Token get extendsKeyword;
+
+  /**
+   * Set the token representing the 'extends' keyword to the given [token].
+   */
+  void set extendsKeyword(Token token);
+
+  /**
+   * Return the name of the class that is being extended.
+   */
+  TypeName get superclass;
+
+  /**
+   * Set the name of the class that is being extended to the given [name].
+   */
+  void set superclass(TypeName name);
+}
+
+/**
+ * The declaration of one or more fields of the same type.
+ *
+ * > fieldDeclaration ::=
+ * >     'static'? [VariableDeclarationList] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FieldDeclaration extends ClassMember {
+  /**
+   * Initialize a newly created field declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The [staticKeyword] can be `null` if the field is
+   * not a static field.
+   */
+  factory FieldDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      Token staticKeyword,
+      VariableDeclarationList fieldList,
+      Token semicolon) = FieldDeclarationImpl;
+
+  /**
+   * Return the fields being declared.
+   */
+  VariableDeclarationList get fields;
+
+  /**
+   * Set the fields being declared to the given list of [fields].
+   */
+  void set fields(VariableDeclarationList fields);
+
+  /**
+   * Return `true` if the fields are declared to be static.
+   */
+  bool get isStatic;
+
+  /**
+   * Return the semicolon terminating the declaration.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the declaration to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the token representing the 'static' keyword, or `null` if the fields
+   * are not static.
+   */
+  Token get staticKeyword;
+
+  /**
+   * Set the token representing the 'static' keyword to the given [token].
+   */
+  void set staticKeyword(Token token);
+}
+
+/**
+ * A field formal parameter.
+ *
+ * > fieldFormalParameter ::=
+ * >     ('final' [TypeName] | 'const' [TypeName] | 'var' | [TypeName])?
+ * >     'this' '.' [SimpleIdentifier] ([TypeParameterList]? [FormalParameterList])?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FieldFormalParameter extends NormalFormalParameter {
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [keyword] can be `null` if there is a type.
+   * The [type] must be `null` if the keyword is 'var'. The [thisKeyword] and
+   * [period] can be `null` if the keyword 'this' was not provided.  The
+   * [parameters] can be `null` if this is not a function-typed field formal
+   * parameter.
+   */
+  factory FieldFormalParameter(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      TypeName type,
+      Token thisKeyword,
+      Token period,
+      SimpleIdentifier identifier,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters) = FieldFormalParameterImpl;
+
+  /**
+   * Return the token representing either the 'final', 'const' or 'var' keyword,
+   * or `null` if no keyword was used.
+   */
+  Token get keyword;
+
+  /**
+   * Set the token representing either the 'final', 'const' or 'var' keyword to
+   * the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the parameters of the function-typed parameter, or `null` if this is
+   * not a function-typed field formal parameter.
+   */
+  FormalParameterList get parameters;
+
+  /**
+   * Set the parameters of the function-typed parameter to the given
+   * [parameters].
+   */
+  void set parameters(FormalParameterList parameters);
+
+  /**
+   * Return the token representing the period.
+   */
+  Token get period;
+
+  /**
+   * Set the token representing the period to the given [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the token representing the 'this' keyword.
+   */
+  Token get thisKeyword;
+
+  /**
+   * Set the token representing the 'this' keyword to the given [token].
+   */
+  void set thisKeyword(Token token);
+
+  /**
+   * Return the name of the declared type of the parameter, or `null` if the
+   * parameter does not have a declared type. Note that if this is a
+   * function-typed field formal parameter this is the return type of the
+   * function.
+   */
+  TypeName get type;
+
+  /**
+   * Set the name of the declared type of the parameter to the given [typeName].
+   */
+  void set type(TypeName typeName);
+
+  /**
+   * Return the type parameters associated with this method, or `null` if this
+   * method is not a generic method.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters associated with this method to the given
+   * [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+}
+
+/**
+ * A for-each statement.
+ *
+ * > forEachStatement ::=
+ * >     'await'? 'for' '(' [DeclaredIdentifier] 'in' [Expression] ')' [Block]
+ * >   | 'await'? 'for' '(' [SimpleIdentifier] 'in' [Expression] ')' [Block]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ForEachStatement extends Statement {
+  /**
+   * Initialize a newly created for-each statement whose loop control variable
+   * is declared internally (in the for-loop part). The [awaitKeyword] can be
+   * `null` if this is not an asynchronous for loop.
+   */
+  factory ForEachStatement.withDeclaration(
+      Token awaitKeyword,
+      Token forKeyword,
+      Token leftParenthesis,
+      DeclaredIdentifier loopVariable,
+      Token inKeyword,
+      Expression iterator,
+      Token rightParenthesis,
+      Statement body) = ForEachStatementImpl.withDeclaration;
+
+  /**
+   * Initialize a newly created for-each statement whose loop control variable
+   * is declared outside the for loop. The [awaitKeyword] can be `null` if this
+   * is not an asynchronous for loop.
+   */
+  factory ForEachStatement.withReference(
+      Token awaitKeyword,
+      Token forKeyword,
+      Token leftParenthesis,
+      SimpleIdentifier identifier,
+      Token inKeyword,
+      Expression iterator,
+      Token rightParenthesis,
+      Statement body) = ForEachStatementImpl.withReference;
+
+  /**
+   * Return the token representing the 'await' keyword, or `null` if there is no
+   * 'await' keyword.
+   */
+  Token get awaitKeyword;
+
+  /**
+   * Set the token representing the 'await' keyword to the given [token].
+   */
+  void set awaitKeyword(Token token);
+
+  /**
+   * Return the body of the loop.
+   */
+  Statement get body;
+
+  /**
+   * Set the body of the loop to the given [statement].
+   */
+  void set body(Statement statement);
+
+  /**
+   * Return the token representing the 'for' keyword.
+   */
+  Token get forKeyword;
+
+  /**
+   * Set the token representing the 'for' keyword to the given [token].
+   */
+  void set forKeyword(Token token);
+
+  /**
+   * Return the loop variable, or `null` if the loop variable is declared in the
+   * 'for'.
+   */
+  SimpleIdentifier get identifier;
+
+  /**
+   * Set the loop variable to the given [identifier].
+   */
+  void set identifier(SimpleIdentifier identifier);
+
+  /**
+   * Return the token representing the 'in' keyword.
+   */
+  Token get inKeyword;
+
+  /**
+   * Set the token representing the 'in' keyword to the given [token].
+   */
+  void set inKeyword(Token token);
+
+  /**
+   * Return the expression evaluated to produce the iterator.
+   */
+  Expression get iterable;
+
+  /**
+   * Set the expression evaluated to produce the iterator to the given
+   * [expression].
+   */
+  void set iterable(Expression expression);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the declaration of the loop variable, or `null` if the loop variable
+   * is a simple identifier.
+   */
+  DeclaredIdentifier get loopVariable;
+
+  /**
+   * Set the declaration of the loop variable to the given [variable].
+   */
+  void set loopVariable(DeclaredIdentifier variable);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+}
+
+/**
+ * A node representing a parameter to a function.
+ *
+ * > formalParameter ::=
+ * >     [NormalFormalParameter]
+ * >   | [DefaultFormalParameter]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FormalParameter extends AstNode {
+  /**
+   * Return the element representing this parameter, or `null` if this parameter
+   * has not been resolved.
+   */
+  ParameterElement get element;
+
+  /**
+   * Return the name of the parameter being declared.
+   */
+  SimpleIdentifier get identifier;
+
+  /**
+   * Return `true` if this parameter was declared with the 'const' modifier.
+   */
+  bool get isConst;
+
+  /**
+   * Return `true` if this parameter was declared with the 'final' modifier.
+   * Parameters that are declared with the 'const' modifier will return `false`
+   * even though they are implicitly final.
+   */
+  bool get isFinal;
+
+  /**
+   * Return the kind of this parameter.
+   */
+  ParameterKind get kind;
+
+  /**
+   * Return the annotations associated with this parameter.
+   */
+  NodeList<Annotation> get metadata;
+}
+
+/**
+ * The formal parameter list of a method declaration, function declaration, or
+ * function type alias.
+ *
+ * While the grammar requires all optional formal parameters to follow all of
+ * the normal formal parameters and at most one grouping of optional formal
+ * parameters, this class does not enforce those constraints. All parameters are
+ * flattened into a single list, which can have any or all kinds of parameters
+ * (normal, named, and positional) in any order.
+ *
+ * > formalParameterList ::=
+ * >     '(' ')'
+ * >   | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
+ * >   | '(' optionalFormalParameters ')'
+ * >
+ * > normalFormalParameters ::=
+ * >     [NormalFormalParameter] (',' [NormalFormalParameter])*
+ * >
+ * > optionalFormalParameters ::=
+ * >     optionalPositionalFormalParameters
+ * >   | namedFormalParameters
+ * >
+ * > optionalPositionalFormalParameters ::=
+ * >     '[' [DefaultFormalParameter] (',' [DefaultFormalParameter])* ']'
+ * >
+ * > namedFormalParameters ::=
+ * >     '{' [DefaultFormalParameter] (',' [DefaultFormalParameter])* '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FormalParameterList extends AstNode {
+  /**
+   * Initialize a newly created parameter list. The list of [parameters] can be
+   * `null` if there are no parameters. The [leftDelimiter] and [rightDelimiter]
+   * can be `null` if there are no optional parameters.
+   */
+  factory FormalParameterList(
+      Token leftParenthesis,
+      List<FormalParameter> parameters,
+      Token leftDelimiter,
+      Token rightDelimiter,
+      Token rightParenthesis) = FormalParameterListImpl;
+
+  /**
+   * Return the left square bracket ('[') or left curly brace ('{') introducing
+   * the optional parameters, or `null` if there are no optional parameters.
+   */
+  Token get leftDelimiter;
+
+  /**
+   * Set the left square bracket ('[') or left curly brace ('{') introducing
+   * the optional parameters to the given [token].
+   */
+  void set leftDelimiter(Token token);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return a list containing the elements representing the parameters in this
+   * list. The list will contain `null`s if the parameters in this list have not
+   * been resolved.
+   */
+  List<ParameterElement> get parameterElements;
+
+  /**
+   * Return the parameters associated with the method.
+   */
+  NodeList<FormalParameter> get parameters;
+
+  /**
+   * Return the right square bracket (']') or right curly brace ('}') terminating the
+   * optional parameters, or `null` if there are no optional parameters.
+   */
+  Token get rightDelimiter;
+
+  /**
+   * Set the right square bracket (']') or right curly brace ('}') terminating the
+   * optional parameters to the given [token].
+   */
+  void set rightDelimiter(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+}
+
+/**
+ * A for statement.
+ *
+ * > forStatement ::=
+ * >     'for' '(' forLoopParts ')' [Statement]
+ * >
+ * > forLoopParts ::=
+ * >     forInitializerStatement ';' [Expression]? ';' [Expression]?
+ * >
+ * > forInitializerStatement ::=
+ * >     [DefaultFormalParameter]
+ * >   | [Expression]?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ForStatement extends Statement {
+  /**
+   * Initialize a newly created for statement. Either the [variableList] or the
+   * [initialization] must be `null`. Either the [condition] and the list of
+   * [updaters] can be `null` if the loop does not have the corresponding
+   * attribute.
+   */
+  factory ForStatement(
+      Token forKeyword,
+      Token leftParenthesis,
+      VariableDeclarationList variableList,
+      Expression initialization,
+      Token leftSeparator,
+      Expression condition,
+      Token rightSeparator,
+      List<Expression> updaters,
+      Token rightParenthesis,
+      Statement body) = ForStatementImpl;
+
+  /**
+   * Return the body of the loop.
+   */
+  Statement get body;
+
+  /**
+   * Set the body of the loop to the given [statement].
+   */
+  void set body(Statement statement);
+
+  /**
+   * Return the condition used to determine when to terminate the loop, or
+   * `null` if there is no condition.
+   */
+  Expression get condition;
+
+  /**
+   * Set the condition used to determine when to terminate the loop to the given
+   * [expression].
+   */
+  void set condition(Expression expression);
+
+  /**
+   * Return the token representing the 'for' keyword.
+   */
+  Token get forKeyword;
+
+  /**
+   * Set the token representing the 'for' keyword to the given [token].
+   */
+  void set forKeyword(Token token);
+
+  /**
+   * Return the initialization expression, or `null` if there is no
+   * initialization expression.
+   */
+  Expression get initialization;
+
+  /**
+   * Set the initialization expression to the given [expression].
+   */
+  void set initialization(Expression initialization);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the semicolon separating the initializer and the condition.
+   */
+  Token get leftSeparator;
+
+  /**
+   * Set the semicolon separating the initializer and the condition to the given
+   * [token].
+   */
+  void set leftSeparator(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the semicolon separating the condition and the updater.
+   */
+  Token get rightSeparator;
+
+  /**
+   * Set the semicolon separating the condition and the updater to the given
+   * [token].
+   */
+  void set rightSeparator(Token token);
+
+  /**
+   * Return the list of expressions run after each execution of the loop body.
+   */
+  NodeList<Expression> get updaters;
+
+  /**
+   * Return the declaration of the loop variables, or `null` if there are no
+   * variables.
+   */
+  VariableDeclarationList get variables;
+
+  /**
+   * Set the declaration of the loop variables to the given [variableList].
+   */
+  void set variables(VariableDeclarationList variableList);
+}
+
+/**
+ * A node representing the body of a function or method.
+ *
+ * > functionBody ::=
+ * >     [BlockFunctionBody]
+ * >   | [EmptyFunctionBody]
+ * >   | [ExpressionFunctionBody]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionBody extends AstNode {
+  /**
+   * Return `true` if this function body is asynchronous.
+   */
+  bool get isAsynchronous;
+
+  /**
+   * Return `true` if this function body is a generator.
+   */
+  bool get isGenerator;
+
+  /**
+   * Return `true` if this function body is synchronous.
+   */
+  bool get isSynchronous;
+
+  /**
+   * Return the token representing the 'async' or 'sync' keyword, or `null` if
+   * there is no such keyword.
+   */
+  Token get keyword;
+
+  /**
+   * Return the star following the 'async' or 'sync' keyword, or `null` if there
+   * is no star.
+   */
+  Token get star;
+}
+
+/**
+ * A top-level declaration.
+ *
+ * > functionDeclaration ::=
+ * >     'external' functionSignature
+ * >   | functionSignature [FunctionBody]
+ * >
+ * > functionSignature ::=
+ * >     [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionDeclaration extends NamedCompilationUnitMember {
+  /**
+   * Initialize a newly created function declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the function does not have the
+   * corresponding attribute. The [externalKeyword] can be `null` if the
+   * function is not an external function. The [returnType] can be `null` if no
+   * return type was specified. The [propertyKeyword] can be `null` if the
+   * function is neither a getter or a setter.
+   */
+  factory FunctionDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      Token externalKeyword,
+      TypeName returnType,
+      Token propertyKeyword,
+      SimpleIdentifier name,
+      FunctionExpression functionExpression) = FunctionDeclarationImpl;
+
+  @override
+  ExecutableElement get element;
+
+  /**
+   * Return the token representing the 'external' keyword, or `null` if this is
+   * not an external function.
+   */
+  Token get externalKeyword;
+
+  /**
+   * Set the token representing the 'external' keyword to the given [token].
+   */
+  void set externalKeyword(Token token);
+
+  /**
+   * Return the function expression being wrapped.
+   */
+  FunctionExpression get functionExpression;
+
+  /**
+   * Set the function expression being wrapped to the given
+   * [functionExpression].
+   */
+  void set functionExpression(FunctionExpression functionExpression);
+
+  /**
+   * Return `true` if this function declares a getter.
+   */
+  bool get isGetter;
+
+  /**
+   * Return `true` if this function declares a setter.
+   */
+  bool get isSetter;
+
+  /**
+   * Return the token representing the 'get' or 'set' keyword, or `null` if this
+   * is a function declaration rather than a property declaration.
+   */
+  Token get propertyKeyword;
+
+  /**
+   * Set the token representing the 'get' or 'set' keyword to the given [token].
+   */
+  void set propertyKeyword(Token token);
+
+  /**
+   * Return the return type of the function, or `null` if no return type was
+   * declared.
+   */
+  TypeName get returnType;
+
+  /**
+   * Set the return type of the function to the given [returnType].
+   */
+  void set returnType(TypeName returnType);
+}
+
+/**
+ * A [FunctionDeclaration] used as a statement.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionDeclarationStatement extends Statement {
+  /**
+   * Initialize a newly created function declaration statement.
+   */
+  factory FunctionDeclarationStatement(
+          FunctionDeclaration functionDeclaration) =
+      FunctionDeclarationStatementImpl;
+
+  /**
+   * Return the function declaration being wrapped.
+   */
+  FunctionDeclaration get functionDeclaration;
+
+  /**
+   * Set the function declaration being wrapped to the given
+   * [functionDeclaration].
+   */
+  void set functionDeclaration(FunctionDeclaration functionDeclaration);
+}
+
+/**
+ * A function expression.
+ *
+ * > functionExpression ::=
+ * >     [TypeParameterList]? [FormalParameterList] [FunctionBody]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionExpression extends Expression {
+  /**
+   * Initialize a newly created function declaration.
+   */
+  factory FunctionExpression(
+      TypeParameterList typeParameters,
+      FormalParameterList parameters,
+      FunctionBody body) = FunctionExpressionImpl;
+
+  /**
+   * Return the body of the function, or `null` if this is an external function.
+   */
+  FunctionBody get body;
+
+  /**
+   * Set the body of the function to the given [functionBody].
+   */
+  void set body(FunctionBody functionBody);
+
+  /**
+   * Return the element associated with the function, or `null` if the AST
+   * structure has not been resolved.
+   */
+  ExecutableElement get element;
+
+  /**
+   * Set the element associated with the function to the given [element].
+   */
+  void set element(ExecutableElement element);
+
+  /**
+   * Return the parameters associated with the function.
+   */
+  FormalParameterList get parameters;
+
+  /**
+   * Set the parameters associated with the function to the given list of
+   * [parameters].
+   */
+  void set parameters(FormalParameterList parameters);
+
+  /**
+   * Return the type parameters associated with this method, or `null` if this
+   * method is not a generic method.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters associated with this method to the given
+   * [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+}
+
+/**
+ * The invocation of a function resulting from evaluating an expression.
+ * Invocations of methods and other forms of functions are represented by
+ * [MethodInvocation] nodes. Invocations of getters and setters are represented
+ * by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+ *
+ * > functionExpressionInvocation ::=
+ * >     [Expression] [TypeArgumentList]? [ArgumentList]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionExpressionInvocation extends Expression {
+  /**
+   * Initialize a newly created function expression invocation.
+   */
+  factory FunctionExpressionInvocation(
+      Expression function,
+      TypeArgumentList typeArguments,
+      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);
+
+  /**
+   * Return the best element available for the function being invoked. If
+   * resolution was able to find a better element based on type propagation,
+   * that element will be returned. Otherwise, the element found using the
+   * result of static analysis will be returned. If resolution has not been
+   * performed, then `null` will be returned.
+   */
+  ExecutableElement get bestElement;
+
+  /**
+   * Return the expression producing the function being invoked.
+   */
+  Expression get function;
+
+  /**
+   * Set the expression producing the function being invoked to the given
+   * [expression].
+   */
+  void set function(Expression expression);
+
+  /**
+   * Return 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.
+   */
+  ExecutableElement get propagatedElement;
+
+  /**
+   * Set the element associated with the function being invoked based on
+   * propagated type information to the given [element].
+   */
+  void set propagatedElement(ExecutableElement element);
+
+  /**
+   * Return the function type of the method 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;
+
+  /**
+   * Set the function type of the method invocation based on the propagated type
+   * information to the given [type].
+   */
+  void set propagatedInvokeType(DartType type);
+
+  /**
+   * Return 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.
+   */
+  ExecutableElement get staticElement;
+
+  /**
+   * Set the element associated with the function being invoked based on static
+   * type information to the given [element].
+   */
+  void set staticElement(ExecutableElement element);
+
+  /**
+   * Return the function type of the method 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;
+
+  /**
+   * Set the function type of the method invocation based on the static type
+   * information to the given [type].
+   */
+  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].
+   */
+  void set typeArguments(TypeArgumentList typeArguments);
+}
+
+/**
+ * A function type alias.
+ *
+ * > functionTypeAlias ::=
+ * >     functionPrefix [TypeParameterList]? [FormalParameterList] ';'
+ * >
+ * > functionPrefix ::=
+ * >     [TypeName]? [SimpleIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionTypeAlias extends TypeAlias {
+  /**
+   * Initialize a newly created function type alias. Either or both of the
+   * [comment] and [metadata] can be `null` if the function does not have the
+   * corresponding attribute. The [returnType] can be `null` if no return type
+   * was specified. The [typeParameters] can be `null` if the function has no
+   * type parameters.
+   */
+  factory FunctionTypeAlias(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      TypeName returnType,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters,
+      Token semicolon) = FunctionTypeAliasImpl;
+
+  /**
+   * Return the parameters associated with the function type.
+   */
+  FormalParameterList get parameters;
+
+  /**
+   * Set the parameters associated with the function type to the given list of
+   * [parameters].
+   */
+  void set parameters(FormalParameterList parameters);
+
+  /**
+   * Return the name of the return type of the function type being defined, or
+   * `null` if no return type was given.
+   */
+  TypeName get returnType;
+
+  /**
+   * Set the name of the return type of the function type being defined to the
+   * given [typeName].
+   */
+  void set returnType(TypeName typeName);
+
+  /**
+   * Return the type parameters for the function type, or `null` if the function
+   * type does not have any type parameters.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters for the function type to the given list of
+   * [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+}
+
+/**
+ * A function-typed formal parameter.
+ *
+ * > functionSignature ::=
+ * >     [TypeName]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FunctionTypedFormalParameter extends NormalFormalParameter {
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [returnType] can be `null` if no return type
+   * was specified.
+   */
+  factory FunctionTypedFormalParameter(
+      Comment comment,
+      List<Annotation> metadata,
+      TypeName returnType,
+      SimpleIdentifier identifier,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters) = FunctionTypedFormalParameterImpl;
+
+  /**
+   * Return the parameters of the function-typed parameter.
+   */
+  FormalParameterList get parameters;
+
+  /**
+   * Set the parameters of the function-typed parameter to the given
+   * [parameters].
+   */
+  void set parameters(FormalParameterList parameters);
+
+  /**
+   * Return the return type of the function, or `null` if the function does not
+   * have a return type.
+   */
+  TypeName get returnType;
+
+  /**
+   * Set the return type of the function to the given [type].
+   */
+  void set returnType(TypeName type);
+
+  /**
+   * Return the type parameters associated with this function, or `null` if
+   * this function is not a generic function.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters associated with this method to the given
+   * [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+}
+
+/**
+ * A combinator that restricts the names being imported to those that are not in
+ * a given list.
+ *
+ * > hideCombinator ::=
+ * >     'hide' [SimpleIdentifier] (',' [SimpleIdentifier])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class HideCombinator extends Combinator {
+  /**
+   * Initialize a newly created import show combinator.
+   */
+  factory HideCombinator(Token keyword, List<SimpleIdentifier> hiddenNames) =
+      HideCombinatorImpl;
+
+  /**
+   * Return the list of names from the library that are hidden by this
+   * combinator.
+   */
+  NodeList<SimpleIdentifier> get hiddenNames;
+}
+
+/**
+ * A node that represents an identifier.
+ *
+ * > identifier ::=
+ * >     [SimpleIdentifier]
+ * >   | [PrefixedIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Identifier extends Expression {
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  Element get bestElement;
+
+  /**
+   * Return the lexical representation of the identifier.
+   */
+  String get name;
+
+  /**
+   * Return the element associated with this identifier based on propagated type
+   * information, or `null` if the AST structure has not been resolved or if
+   * this identifier could not be resolved. One example of the latter case is an
+   * identifier that is not defined within the scope in which it appears.
+   */
+  Element get propagatedElement;
+
+  /**
+   * Return the element associated with this identifier based on static type
+   * information, or `null` if the AST structure has not been resolved or if
+   * this identifier could not be resolved. One example of the latter case is an
+   * identifier that is not defined within the scope in which it appears
+   */
+  Element get staticElement;
+
+  /**
+   * Return `true` if the given [name] is visible only within the library in
+   * which it is declared.
+   */
+  static bool isPrivateName(String name) =>
+      StringUtilities.startsWithChar(name, 0x5F); // '_'
+}
+
+/**
+ * An if statement.
+ *
+ * > ifStatement ::=
+ * >     'if' '(' [Expression] ')' [Statement] ('else' [Statement])?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class IfStatement extends Statement {
+  /**
+   * Initialize a newly created if statement. The [elseKeyword] and
+   * [elseStatement] can be `null` if there is no else clause.
+   */
+  factory IfStatement(
+      Token ifKeyword,
+      Token leftParenthesis,
+      Expression condition,
+      Token rightParenthesis,
+      Statement thenStatement,
+      Token elseKeyword,
+      Statement elseStatement) = IfStatementImpl;
+
+  /**
+   * Return the condition used to determine which of the statements is executed
+   * next.
+   */
+  Expression get condition;
+
+  /**
+   * Set the condition used to determine which of the statements is executed
+   * next to the given [expression].
+   */
+  void set condition(Expression expression);
+
+  /**
+   * Return the token representing the 'else' keyword, or `null` if there is no
+   * else statement.
+   */
+  Token get elseKeyword;
+
+  /**
+   * Set the token representing the 'else' keyword to the given [token].
+   */
+  void set elseKeyword(Token token);
+
+  /**
+   * Return the statement that is executed if the condition evaluates to
+   * `false`, or `null` if there is no else statement.
+   */
+  Statement get elseStatement;
+
+  /**
+   * Set the statement that is executed if the condition evaluates to `false`
+   * to the given [statement].
+   */
+  void set elseStatement(Statement statement);
+
+  /**
+   * Return the token representing the 'if' keyword.
+   */
+  Token get ifKeyword;
+
+  /**
+   * Set the token representing the 'if' keyword to the given [token].
+   */
+  void set ifKeyword(Token token);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the statement that is executed if the condition evaluates to `true`.
+   */
+  Statement get thenStatement;
+
+  /**
+   * Set the statement that is executed if the condition evaluates to `true` to
+   * the given [statement].
+   */
+  void set thenStatement(Statement statement);
+}
+
+/**
+ * The "implements" clause in an class declaration.
+ *
+ * > implementsClause ::=
+ * >     'implements' [TypeName] (',' [TypeName])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ImplementsClause extends AstNode {
+  /**
+   * Initialize a newly created implements clause.
+   */
+  factory ImplementsClause(Token implementsKeyword, List<TypeName> interfaces) =
+      ImplementsClauseImpl;
+
+  /**
+   * Return the token representing the 'implements' keyword.
+   */
+  Token get implementsKeyword;
+
+  /**
+   * Set the token representing the 'implements' keyword to the given [token].
+   */
+  void set implementsKeyword(Token token);
+
+  /**
+   * Return the list of the interfaces that are being implemented.
+   */
+  NodeList<TypeName> get interfaces;
+}
+
+/**
+ * An import directive.
+ *
+ * > importDirective ::=
+ * >     [Annotation] 'import' [StringLiteral] ('as' identifier)? [Combinator]* ';'
+ * >   | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier [Combinator]* ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ImportDirective extends NamespaceDirective {
+  static Comparator<ImportDirective> COMPARATOR =
+      (ImportDirective import1, ImportDirective import2) {
+    //
+    // uri
+    //
+    StringLiteral uri1 = import1.uri;
+    StringLiteral uri2 = import2.uri;
+    String uriStr1 = uri1.stringValue;
+    String uriStr2 = uri2.stringValue;
+    if (uriStr1 != null || uriStr2 != null) {
+      if (uriStr1 == null) {
+        return -1;
+      } else if (uriStr2 == null) {
+        return 1;
+      } else {
+        int compare = uriStr1.compareTo(uriStr2);
+        if (compare != 0) {
+          return compare;
+        }
+      }
+    }
+    //
+    // as
+    //
+    SimpleIdentifier prefix1 = import1.prefix;
+    SimpleIdentifier prefix2 = import2.prefix;
+    String prefixStr1 = prefix1 != null ? prefix1.name : null;
+    String prefixStr2 = prefix2 != null ? prefix2.name : null;
+    if (prefixStr1 != null || prefixStr2 != null) {
+      if (prefixStr1 == null) {
+        return -1;
+      } else if (prefixStr2 == null) {
+        return 1;
+      } else {
+        int compare = prefixStr1.compareTo(prefixStr2);
+        if (compare != 0) {
+          return compare;
+        }
+      }
+    }
+    //
+    // hides and shows
+    //
+    NodeList<Combinator> combinators1 = import1.combinators;
+    List<String> allHides1 = new List<String>();
+    List<String> allShows1 = new List<String>();
+    for (Combinator combinator in combinators1) {
+      if (combinator is HideCombinator) {
+        NodeList<SimpleIdentifier> hides = combinator.hiddenNames;
+        for (SimpleIdentifier simpleIdentifier in hides) {
+          allHides1.add(simpleIdentifier.name);
+        }
+      } else {
+        NodeList<SimpleIdentifier> shows =
+            (combinator as ShowCombinator).shownNames;
+        for (SimpleIdentifier simpleIdentifier in shows) {
+          allShows1.add(simpleIdentifier.name);
+        }
+      }
+    }
+    NodeList<Combinator> combinators2 = import2.combinators;
+    List<String> allHides2 = new List<String>();
+    List<String> allShows2 = new List<String>();
+    for (Combinator combinator in combinators2) {
+      if (combinator is HideCombinator) {
+        NodeList<SimpleIdentifier> hides = combinator.hiddenNames;
+        for (SimpleIdentifier simpleIdentifier in hides) {
+          allHides2.add(simpleIdentifier.name);
+        }
+      } else {
+        NodeList<SimpleIdentifier> shows =
+            (combinator as ShowCombinator).shownNames;
+        for (SimpleIdentifier simpleIdentifier in shows) {
+          allShows2.add(simpleIdentifier.name);
+        }
+      }
+    }
+    // test lengths of combinator lists first
+    if (allHides1.length != allHides2.length) {
+      return allHides1.length - allHides2.length;
+    }
+    if (allShows1.length != allShows2.length) {
+      return allShows1.length - allShows2.length;
+    }
+    // next ensure that the lists are equivalent
+    if (!javaCollectionContainsAll(allHides1, allHides2)) {
+      return -1;
+    }
+    if (!javaCollectionContainsAll(allShows1, allShows2)) {
+      return -1;
+    }
+    return 0;
+  };
+
+  /**
+   * Initialize a newly created import directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the function does not have the
+   * corresponding attribute. The [deferredKeyword] can be `null` if the import
+   * is not deferred. The [asKeyword] and [prefix] can be `null` if the import
+   * does not specify a prefix. The list of [combinators] can be `null` if there
+   * are no combinators.
+   */
+  factory ImportDirective(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      StringLiteral libraryUri,
+      List<Configuration> configurations,
+      Token deferredKeyword,
+      Token asKeyword,
+      SimpleIdentifier prefix,
+      List<Combinator> combinators,
+      Token semicolon) = ImportDirectiveImpl;
+
+  /**
+   * Return the token representing the 'as' keyword, or `null` if the imported
+   * names are not prefixed.
+   */
+  Token get asKeyword;
+
+  /**
+   * Set the token representing the 'as' keyword to the given [token].
+   */
+  void set asKeyword(Token token);
+
+  /**
+   * Return the token representing the 'deferred' keyword, or `null` if the
+   * imported URI is not deferred.
+   */
+  Token get deferredKeyword;
+
+  /**
+   * Set the token representing the 'deferred' keyword to the given [token].
+   */
+  void set deferredKeyword(Token token);
+
+  /**
+   * Return the prefix to be used with the imported names, or `null` if the
+   * imported names are not prefixed.
+   */
+  SimpleIdentifier get prefix;
+
+  /**
+   * Set the prefix to be used with the imported names to the given [identifier].
+   */
+  void set prefix(SimpleIdentifier identifier);
+}
+
+/**
+ * An index expression.
+ *
+ * > indexExpression ::=
+ * >     [Expression] '[' [Expression] ']'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class IndexExpression extends Expression {
+  /**
+   * Initialize a newly created index expression.
+   */
+  factory IndexExpression.forCascade(Token period, Token leftBracket,
+      Expression index, Token rightBracket) = IndexExpressionImpl.forCascade;
+
+  /**
+   * Initialize a newly created index expression.
+   */
+  factory IndexExpression.forTarget(Expression target, Token leftBracket,
+      Expression index, Token rightBracket) = IndexExpressionImpl.forTarget;
+
+  /**
+   * Return the auxiliary elements associated with this identifier, or `null` if
+   * this identifier is not in both a getter and setter context. The auxiliary
+   * elements hold the static and propagated elements associated with the getter
+   * context.
+   */
+  // TODO(brianwilkerson) Replace this API.
+  AuxiliaryElements get auxiliaryElements;
+
+  /**
+   * Set the auxiliary elements associated with this identifier to the given
+   * [elements].
+   */
+  // TODO(brianwilkerson) Replace this API.
+  void set auxiliaryElements(AuxiliaryElements elements);
+
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  MethodElement get bestElement;
+
+  /**
+   * Return the expression used to compute the index.
+   */
+  Expression get index;
+
+  /**
+   * Set the expression used to compute the index to the given [expression].
+   */
+  void set index(Expression expression);
+
+  /**
+   * Return `true` if this expression is cascaded. If it is, then the target of
+   * this expression is not stored locally but is stored in the nearest ancestor
+   * that is a [CascadeExpression].
+   */
+  bool get isCascaded;
+
+  /**
+   * Return the left square bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left square bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the period ("..") before a cascaded index expression, or `null` if
+   * this index expression is not part of a cascade expression.
+   */
+  Token get period;
+
+  /**
+   * Set the period ("..") before a cascaded index expression to the given
+   * [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the element associated with the operator based on the propagated
+   * type of the target, or `null` if the AST structure has not been resolved or
+   * if the operator could not be resolved.
+   */
+  MethodElement get propagatedElement;
+
+  /**
+   * Set the element associated with the operator based on the propagated
+   * type of the target to the given [element].
+   */
+  void set propagatedElement(MethodElement element);
+
+  /**
+   * Return the expression used to compute the object being indexed. If this
+   * index expression is not part of a cascade expression, then this is the same
+   * as [target]. If this index expression is part of a cascade expression, then
+   * the target expression stored with the cascade expression is returned.
+   */
+  Expression get realTarget;
+
+  /**
+   * Return the right square bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Return the element associated with the operator based on the static type of
+   * the target, or `null` if the AST structure has not been resolved or if the
+   * operator could not be resolved.
+   */
+  MethodElement get staticElement;
+
+  /**
+   * Set the element associated with the operator based on the static type of
+   * the target to the given [element].
+   */
+  void set staticElement(MethodElement element);
+
+  /**
+   * Return the expression used to compute the object being indexed, or `null`
+   * if this index expression is part of a cascade expression.
+   *
+   * Use [realTarget] to get the target independent of whether this is part of a
+   * cascade expression.
+   */
+  Expression get target;
+
+  /**
+   * Set the expression used to compute the object being indexed to the given
+   * [expression].
+   */
+  void set target(Expression expression);
+
+  /**
+   * Return `true` if this expression is computing a right-hand value (that is,
+   * if this expression is in a context where the operator '[]' will be
+   * invoked).
+   *
+   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+   * are they mutually exclusive. In other words, it is possible for both
+   * methods to return `true` when invoked on the same node.
+   */
+  // TODO(brianwilkerson) Convert this to a getter.
+  bool inGetterContext();
+
+  /**
+   * Return `true` if this expression is computing a left-hand value (that is,
+   * if this expression is in a context where the operator '[]=' will be
+   * invoked).
+   *
+   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+   * are they mutually exclusive. In other words, it is possible for both
+   * methods to return `true` when invoked on the same node.
+   */
+  // TODO(brianwilkerson) Convert this to a getter.
+  bool inSetterContext();
+}
+
+/**
+ * An instance creation expression.
+ *
+ * > newExpression ::=
+ * >     ('new' | 'const') [TypeName] ('.' [SimpleIdentifier])? [ArgumentList]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class InstanceCreationExpression extends Expression {
+  /**
+   * Initialize a newly created instance creation expression.
+   */
+  factory InstanceCreationExpression(
+      Token keyword,
+      ConstructorName constructorName,
+      ArgumentList argumentList) = InstanceCreationExpressionImpl;
+
+  /**
+   * Return the list of arguments to the constructor.
+   */
+  ArgumentList get argumentList;
+
+  /**
+   * Set the list of arguments to the constructor to the given [argumentList].
+   */
+  void set argumentList(ArgumentList argumentList);
+
+  /**
+   * Return the name of the constructor to be invoked.
+   */
+  ConstructorName get constructorName;
+
+  /**
+   * Set the name of the constructor to be invoked to the given [name].
+   */
+  void set constructorName(ConstructorName name);
+
+  /**
+   * Return `true` if this creation expression is used to invoke a constant
+   * constructor.
+   */
+  bool get isConst;
+
+  /**
+   * Return the 'new' or 'const' keyword used to indicate how an object should
+   * be created.
+   */
+  Token get keyword;
+
+  /**
+   * Set the 'new' or 'const' keyword used to indicate how an object should be
+   * created to the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the element associated with the constructor based on static type
+   * information, or `null` if the AST structure has not been resolved or if the
+   * constructor could not be resolved.
+   */
+  ConstructorElement get staticElement;
+
+  /**
+   * Set the element associated with the constructor based on static type
+   * information to the given [element].
+   */
+  void set staticElement(ConstructorElement element);
+}
+
+/**
+ * An integer literal expression.
+ *
+ * > integerLiteral ::=
+ * >     decimalIntegerLiteral
+ * >   | hexadecimalIntegerLiteral
+ * >
+ * > decimalIntegerLiteral ::=
+ * >     decimalDigit+
+ * >
+ * > hexadecimalIntegerLiteral ::=
+ * >     '0x' hexadecimalDigit+
+ * >   | '0X' hexadecimalDigit+
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class IntegerLiteral extends Literal {
+  /**
+   * Initialize a newly created integer literal.
+   */
+  factory IntegerLiteral(Token literal, int value) = IntegerLiteralImpl;
+
+  /**
+   * Return the token representing the literal.
+   */
+  Token get literal;
+
+  /**
+   * Set the token representing the literal to the given [token].
+   */
+  void set literal(Token token);
+
+  /**
+   * Return the value of the literal.
+   */
+  int get value;
+
+  /**
+   * Set the value of the literal to the given [value].
+   */
+  void set value(int value);
+}
+
+/**
+ * A node within a [StringInterpolation].
+ *
+ * > interpolationElement ::=
+ * >     [InterpolationExpression]
+ * >   | [InterpolationString]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class InterpolationElement extends AstNode {}
+
+/**
+ * An expression embedded in a string interpolation.
+ *
+ * > interpolationExpression ::=
+ * >     '$' [SimpleIdentifier]
+ * >   | '$' '{' [Expression] '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class InterpolationExpression extends InterpolationElement {
+  /**
+   * Initialize a newly created interpolation expression.
+   */
+  factory InterpolationExpression(
+          Token leftBracket, Expression expression, Token rightBracket) =
+      InterpolationExpressionImpl;
+
+  /**
+   * Return the expression to be evaluated for the value to be converted into a
+   * string.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression to be evaluated for the value to be converted into a
+   * string to the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the token used to introduce the interpolation expression; either '$'
+   * if the expression is a simple identifier or '${' if the expression is a
+   * full expression.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the token used to introduce the interpolation expression; either '$'
+   * if the expression is a simple identifier or '${' if the expression is a
+   * full expression to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the right curly bracket, or `null` if the expression is an
+   * identifier without brackets.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right curly bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+}
+
+/**
+ * A non-empty substring of an interpolated string.
+ *
+ * > interpolationString ::=
+ * >     characters
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class InterpolationString extends InterpolationElement {
+  /**
+   * Initialize a newly created string of characters that are part of a string
+   * interpolation.
+   */
+  factory InterpolationString(Token contents, String value) =
+      InterpolationStringImpl;
+
+  /**
+   * Return the characters that will be added to the string.
+   */
+  Token get contents;
+
+  /**
+   * Set the characters that will be added to the string to the given [token].
+   */
+  void set contents(Token token);
+
+  /**
+   * Return the offset of the after-last contents character.
+   */
+  int get contentsEnd;
+
+  /**
+   * Return the offset of the first contents character.
+   */
+  int get contentsOffset;
+
+  /**
+   * Return the value of the literal.
+   */
+  String get value;
+
+  /**
+   * Set the value of the literal to the given [value].
+   */
+  void set value(String value);
+}
+
+/**
+ * An is expression.
+ *
+ * > isExpression ::=
+ * >     [Expression] 'is' '!'? [TypeName]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class IsExpression extends Expression {
+  /**
+   * Initialize a newly created is expression. The [notOperator] can be `null`
+   * if the sense of the test is not negated.
+   */
+  factory IsExpression(Expression expression, Token isOperator,
+      Token notOperator, TypeName type) = IsExpressionImpl;
+
+  /**
+   * Return the expression used to compute the value whose type is being tested.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression used to compute the value whose type is being tested to
+   * the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the is operator.
+   */
+  Token get isOperator;
+
+  /**
+   * Set the is operator to the given [token].
+   */
+  void set isOperator(Token token);
+
+  /**
+   * Return the not operator, or `null` if the sense of the test is not negated.
+   */
+  Token get notOperator;
+
+  /**
+   * Set the not operator to the given [token].
+   */
+  void set notOperator(Token token);
+
+  /**
+   * Return the name of the type being tested for.
+   */
+  TypeName get type;
+
+  /**
+   * Set the name of the type being tested for to the given [name].
+   */
+  void set type(TypeName name);
+}
+
+/**
+ * A label on either a [LabeledStatement] or a [NamedExpression].
+ *
+ * > label ::=
+ * >     [SimpleIdentifier] ':'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Label extends AstNode {
+  /**
+   * Initialize a newly created label.
+   */
+  factory Label(SimpleIdentifier label, Token colon) = LabelImpl;
+
+  /**
+   * Return the colon that separates the label from the statement.
+   */
+  Token get colon;
+
+  /**
+   * Set the colon that separates the label from the statement to the given
+   * [token].
+   */
+  void set colon(Token token);
+
+  /**
+   * Return the label being associated with the statement.
+   */
+  SimpleIdentifier get label;
+
+  /**
+   * Set the label being associated with the statement to the given [label].
+   */
+  void set label(SimpleIdentifier label);
+}
+
+/**
+ * A statement that has a label associated with them.
+ *
+ * > labeledStatement ::=
+ * >    [Label]+ [Statement]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class LabeledStatement extends Statement {
+  /**
+   * Initialize a newly created labeled statement.
+   */
+  factory LabeledStatement(List<Label> labels, Statement statement) =
+      LabeledStatementImpl;
+
+  /**
+   * Return the labels being associated with the statement.
+   */
+  NodeList<Label> get labels;
+
+  /**
+   * Return the statement with which the labels are being associated.
+   */
+  Statement get statement;
+
+  /**
+   * Set the statement with which the labels are being associated to the given
+   * [statement].
+   */
+  void set statement(Statement statement);
+}
+
+/**
+ * A library directive.
+ *
+ * > libraryDirective ::=
+ * >     [Annotation] 'library' [Identifier] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class LibraryDirective extends Directive {
+  /**
+   * Initialize a newly created library directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  factory LibraryDirective(
+      Comment comment,
+      List<Annotation> metadata,
+      Token libraryKeyword,
+      LibraryIdentifier name,
+      Token semicolon) = LibraryDirectiveImpl;
+
+  /**
+   * Return the token representing the 'library' keyword.
+   */
+  Token get libraryKeyword;
+
+  /**
+   * Set the token representing the 'library' keyword to the given [token].
+   */
+  void set libraryKeyword(Token token);
+
+  /**
+   * Return the name of the library being defined.
+   */
+  LibraryIdentifier get name;
+
+  /**
+   * Set the name of the library being defined to the given [name].
+   */
+  void set name(LibraryIdentifier name);
+
+  /**
+   * Return the semicolon terminating the directive.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the directive to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * The identifier for a library.
+ *
+ * > libraryIdentifier ::=
+ * >     [SimpleIdentifier] ('.' [SimpleIdentifier])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class LibraryIdentifier extends Identifier {
+  /**
+   * Initialize a newly created prefixed identifier.
+   */
+  factory LibraryIdentifier(List<SimpleIdentifier> components) =
+      LibraryIdentifierImpl;
+
+  /**
+   * Return the components of the identifier.
+   */
+  NodeList<SimpleIdentifier> get components;
+}
+
+/**
+ * A list literal.
+ *
+ * > listLiteral ::=
+ * >     'const'? ('<' [TypeName] '>')? '[' ([Expression] ','?)? ']'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ListLiteral extends TypedLiteral {
+  /**
+   * Initialize a newly created list literal. The [constKeyword] can be `null`
+   * if the literal is not a constant. The [typeArguments] can be `null` if no
+   * type arguments were declared. The list of [elements] can be `null` if the
+   * list is empty.
+   */
+  factory ListLiteral(
+      Token constKeyword,
+      TypeArgumentList typeArguments,
+      Token leftBracket,
+      List<Expression> elements,
+      Token rightBracket) = ListLiteralImpl;
+
+  /**
+   * Return the expressions used to compute the elements of the list.
+   */
+  NodeList<Expression> get elements;
+
+  /**
+   * Return the left square bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left square bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the right square bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right square bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+}
+
+/**
+ * A node that represents a literal expression.
+ *
+ * > literal ::=
+ * >     [BooleanLiteral]
+ * >   | [DoubleLiteral]
+ * >   | [IntegerLiteral]
+ * >   | [ListLiteral]
+ * >   | [MapLiteral]
+ * >   | [NullLiteral]
+ * >   | [StringLiteral]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Literal extends Expression {}
+
+/**
+ * A literal map.
+ *
+ * > mapLiteral ::=
+ * >     'const'? ('<' [TypeName] (',' [TypeName])* '>')?
+ * >     '{' ([MapLiteralEntry] (',' [MapLiteralEntry])* ','?)? '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class MapLiteral extends TypedLiteral {
+  /**
+   * Initialize a newly created map literal. The [constKeyword] can be `null` if
+   * the literal is not a constant. The [typeArguments] can be `null` if no type
+   * arguments were declared. The [entries] can be `null` if the map is empty.
+   */
+  factory MapLiteral(
+      Token constKeyword,
+      TypeArgumentList typeArguments,
+      Token leftBracket,
+      List<MapLiteralEntry> entries,
+      Token rightBracket) = MapLiteralImpl;
+
+  /**
+   * Return the entries in the map.
+   */
+  NodeList<MapLiteralEntry> get entries;
+
+  /**
+   * Return the left curly bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left curly bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the right curly bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right curly bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+}
+
+/**
+ * A single key/value pair in a map literal.
+ *
+ * > mapLiteralEntry ::=
+ * >     [Expression] ':' [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class MapLiteralEntry extends AstNode {
+  /**
+   * Initialize a newly created map literal entry.
+   */
+  factory MapLiteralEntry(Expression key, Token separator, Expression value) =
+      MapLiteralEntryImpl;
+
+  /**
+   * Return the expression computing the key with which the value will be
+   * associated.
+   */
+  Expression get key;
+
+  /**
+   * Set the expression computing the key with which the value will be
+   * associated to the given [string].
+   */
+  void set key(Expression string);
+
+  /**
+   * Return the colon that separates the key from the value.
+   */
+  Token get separator;
+
+  /**
+   * Set the colon that separates the key from the value to the given [token].
+   */
+  void set separator(Token token);
+
+  /**
+   * Return the expression computing the value that will be associated with the
+   * key.
+   */
+  Expression get value;
+
+  /**
+   * Set the expression computing the value that will be associated with the key
+   * to the given [expression].
+   */
+  void set value(Expression expression);
+}
+
+/**
+ * A method declaration.
+ *
+ * > methodDeclaration ::=
+ * >     methodSignature [FunctionBody]
+ * >
+ * > methodSignature ::=
+ * >     'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')?
+ * >     methodName [TypeParameterList] [FormalParameterList]
+ * >
+ * > methodName ::=
+ * >     [SimpleIdentifier]
+ * >   | 'operator' [SimpleIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class MethodDeclaration extends ClassMember {
+  /**
+   * Initialize a newly created method declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The [externalKeyword] can be `null` if the method
+   * is not external. The [modifierKeyword] can be `null` if the method is
+   * neither abstract nor static. The [returnType] can be `null` if no return
+   * type was specified. The [propertyKeyword] can be `null` if the method is
+   * neither a getter or a setter. The [operatorKeyword] can be `null` if the
+   * method does not implement an operator. The [parameters] must be `null` if
+   * this method declares a getter.
+   */
+  factory MethodDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      Token externalKeyword,
+      Token modifierKeyword,
+      TypeName returnType,
+      Token propertyKeyword,
+      Token operatorKeyword,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters,
+      FunctionBody body) = MethodDeclarationImpl;
+
+  /**
+   * Return the body of the method.
+   */
+  FunctionBody get body;
+
+  /**
+   * Set the body of the method to the given [functionBody].
+   */
+  void set body(FunctionBody functionBody);
+
+  @override
+  ExecutableElement get element;
+
+  /**
+   * Return the token for the 'external' keyword, or `null` if the constructor
+   * is not external.
+   */
+  Token get externalKeyword;
+
+  /**
+   * Set the token for the 'external' keyword to the given [token].
+   */
+  void set externalKeyword(Token token);
+
+  /**
+   * Return `true` if this method is declared to be an abstract method.
+   */
+  bool get isAbstract;
+
+  /**
+   * Return `true` if this method declares a getter.
+   */
+  bool get isGetter;
+
+  /**
+   * Return `true` if this method declares an operator.
+   */
+  bool get isOperator;
+
+  /**
+   * Return `true` if this method declares a setter.
+   */
+  bool get isSetter;
+
+  /**
+   * Return `true` if this method is declared to be a static method.
+   */
+  bool get isStatic;
+
+  /**
+   * Return the token representing the 'abstract' or 'static' keyword, or `null`
+   * if neither modifier was specified.
+   */
+  Token get modifierKeyword;
+
+  /**
+   * Set the token representing the 'abstract' or 'static' keyword to the given
+   * [token].
+   */
+  void set modifierKeyword(Token token);
+
+  /**
+   * Return the name of the method.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the method to the given [identifier].
+   */
+  void set name(SimpleIdentifier identifier);
+
+  /**
+   * Return the token representing the 'operator' keyword, or `null` if this
+   * method does not declare an operator.
+   */
+  Token get operatorKeyword;
+
+  /**
+   * Set the token representing the 'operator' keyword to the given [token].
+   */
+  void set operatorKeyword(Token token);
+
+  /**
+   * Return the parameters associated with the method, or `null` if this method
+   * declares a getter.
+   */
+  FormalParameterList get parameters;
+
+  /**
+   * Set the parameters associated with the method to the given list of
+   * [parameters].
+   */
+  void set parameters(FormalParameterList parameters);
+
+  /**
+   * Return the token representing the 'get' or 'set' keyword, or `null` if this
+   * is a method declaration rather than a property declaration.
+   */
+  Token get propertyKeyword;
+
+  /**
+   * Set the token representing the 'get' or 'set' keyword to the given [token].
+   */
+  void set propertyKeyword(Token token);
+
+  /**
+   * Return the return type of the method, or `null` if no return type was
+   * declared.
+   */
+  TypeName get returnType;
+
+  /**
+   * Set the return type of the method to the given [typeName].
+   */
+  void set returnType(TypeName typeName);
+
+  /**
+   * Return the type parameters associated with this method, or `null` if this
+   * method is not a generic method.
+   */
+  TypeParameterList get typeParameters;
+
+  /**
+   * Set the type parameters associated with this method to the given
+   * [typeParameters].
+   */
+  void set typeParameters(TypeParameterList typeParameters);
+}
+
+/**
+ * The invocation of either a function or a method. Invocations of functions
+ * resulting from evaluating an expression are represented by
+ * [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
+ * represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+ *
+ * > methodInvocation ::=
+ * >     ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class MethodInvocation extends Expression {
+  /**
+   * Initialize a newly created method invocation. The [target] and [operator]
+   * can be `null` if there is no target.
+   */
+  factory MethodInvocation(
+      Expression target,
+      Token operator,
+      SimpleIdentifier methodName,
+      TypeArgumentList typeArguments,
+      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);
+
+  /**
+   * Return `true` if this expression is cascaded. If it is, then the target of
+   * this expression is not stored locally but is stored in the nearest ancestor
+   * that is a [CascadeExpression].
+   */
+  bool get isCascaded;
+
+  /**
+   * Return the name of the method being invoked.
+   */
+  SimpleIdentifier get methodName;
+
+  /**
+   * Set the name of the method being invoked to the given [identifier].
+   */
+  void set methodName(SimpleIdentifier identifier);
+
+  /**
+   * Return the operator that separates the target from the method name, or
+   * `null` if there is no target. In an ordinary method invocation this will be
+   *  * period ('.'). In a cascade section this will be the cascade operator
+   * ('..').
+   */
+  Token get operator;
+
+  /**
+   * Set the operator that separates the target from the method name to the
+   * given [token].
+   */
+  void set operator(Token token);
+
+  /**
+   * Return the function type of the method 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;
+
+  /**
+   * Set the function type of the method invocation based on the propagated type
+   * information to the given [type].
+   */
+  void set propagatedInvokeType(DartType type);
+
+  /**
+   * Return the expression used to compute the receiver of the invocation. If
+   * this invocation is not part of a cascade expression, then this is the same
+   * as [target]. If this invocation is part of a cascade expression, then the
+   * target stored with the cascade expression is returned.
+   */
+  Expression get realTarget;
+
+  /**
+   * Return the function type of the method 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;
+
+  /**
+   * Set the function type of the method invocation based on the static type
+   * information to the given [type].
+   */
+  void set staticInvokeType(DartType type);
+
+  /**
+   * Return 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`)
+   * or if this method invocation is part of a cascade expression.
+   *
+   * Use [realTarget] to get the target independent of whether this is part of a
+   * cascade expression.
+   */
+  Expression get target;
+
+  /**
+   * Set the expression producing the object on which the method is defined to
+   * the given [expression].
+   */
+  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].
+   */
+  void set typeArguments(TypeArgumentList typeArguments);
+}
+
+/**
+ * A node that declares a single name within the scope of a compilation unit.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NamedCompilationUnitMember extends CompilationUnitMember {
+  /**
+   * Return the name of the member being declared.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the member being declared to the given [identifier].
+   */
+  void set name(SimpleIdentifier identifier);
+}
+
+/**
+ * An expression that has a name associated with it. They are used in method
+ * invocations when there are named parameters.
+ *
+ * > namedExpression ::=
+ * >     [Label] [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NamedExpression extends Expression {
+  /**
+   * Initialize a newly created named expression..
+   */
+  factory NamedExpression(Label name, Expression expression) =
+      NamedExpressionImpl;
+
+  /**
+   * Return the element representing the parameter being named by this
+   * expression, or `null` if the AST structure has not been resolved or if
+   * there is no parameter with the same name as this expression.
+   */
+  ParameterElement get element;
+
+  /**
+   * Return the expression with which the name is associated.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression with which the name is associated to the given
+   * [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the name associated with the expression.
+   */
+  Label get name;
+
+  /**
+   * Set the name associated with the expression to the given [identifier].
+   */
+  void set name(Label identifier);
+}
+
+/**
+ * A node that represents a directive that impacts the namespace of a library.
+ *
+ * > directive ::=
+ * >     [ExportDirective]
+ * >   | [ImportDirective]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NamespaceDirective extends UriBasedDirective {
+  /**
+   * Return the combinators used to control how names are imported or exported.
+   */
+  NodeList<Combinator> get combinators;
+
+  /**
+   * Return the configurations used to control which library will actually be
+   * loaded at run-time.
+   */
+  NodeList<Configuration> get configurations;
+
+  /**
+   * Set the token representing the keyword that introduces this directive
+   * ('import', 'export', 'library' or 'part') to the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the semicolon terminating the directive.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the directive to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * The "native" clause in an class declaration.
+ *
+ * > nativeClause ::=
+ * >     'native' [StringLiteral]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NativeClause extends AstNode {
+  /**
+   * Initialize a newly created native clause.
+   */
+  factory NativeClause(Token nativeKeyword, StringLiteral name) =
+      NativeClauseImpl;
+
+  /**
+   * Return the name of the native object that implements the class.
+   */
+  StringLiteral get name;
+
+  /**
+   * Set the name of the native object that implements the class to the given
+   * [name].
+   */
+  void set name(StringLiteral name);
+
+  /**
+   * Return the token representing the 'native' keyword.
+   */
+  Token get nativeKeyword;
+
+  /**
+   * Set the token representing the 'native' keyword to the given [token].
+   */
+  void set nativeKeyword(Token token);
+}
+
+/**
+ * A function body that consists of a native keyword followed by a string
+ * literal.
+ *
+ * > nativeFunctionBody ::=
+ * >     'native' [SimpleStringLiteral] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NativeFunctionBody extends FunctionBody {
+  /**
+   * Initialize a newly created function body consisting of the 'native' token,
+   * a string literal, and a semicolon.
+   */
+  factory NativeFunctionBody(
+          Token nativeKeyword, StringLiteral stringLiteral, Token semicolon) =
+      NativeFunctionBodyImpl;
+
+  /**
+   * Return the token representing 'native' that marks the start of the function
+   * body.
+   */
+  Token get nativeKeyword;
+
+  /**
+   * Set the token representing 'native' that marks the start of the function
+   * body to the given [token].
+   */
+  void set nativeKeyword(Token token);
+
+  /**
+   * Return the token representing the semicolon that marks the end of the
+   * function body.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the token representing the semicolon that marks the end of the
+   * function body to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the string literal representing the string after the 'native' token.
+   */
+  StringLiteral get stringLiteral;
+
+  /**
+   * Set the string literal representing the string after the 'native' token to
+   * the given [stringLiteral].
+   */
+  void set stringLiteral(StringLiteral stringLiteral);
+}
+
+/**
+ * A list of AST nodes that have a common parent.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NodeList<E extends AstNode> implements List<E> {
+  /**
+   * Initialize a newly created list of nodes such that all of the nodes that
+   * are added to the list will have their parent set to the given [owner]. The
+   * list will initially be populated with the given [elements].
+   */
+  factory NodeList(AstNode owner, [List<E> elements]) = NodeListImpl;
+
+  /**
+   * Return the first token included in this node list's source range, or `null`
+   * if the list is empty.
+   */
+  Token get beginToken;
+
+  /**
+   * Return the last token included in this node list's source range, or `null`
+   * if the list is empty.
+   */
+  Token get endToken;
+
+  /**
+   * Return the node that is the parent of each of the elements in the list.
+   */
+  AstNode get owner;
+
+  /**
+   * Set the node that is the parent of each of the elements in the list to the
+   * given [node].
+   */
+  @deprecated // Never intended for public use.
+  void set owner(AstNode node);
+
+  /**
+   * Return the node at the given [index] in the list or throw a [RangeError] if
+   * [index] is out of bounds.
+   */
+  E operator [](int index);
+
+  /**
+   * Set the node at the given [index] in the list to the given [node] or throw
+   * a [RangeError] if [index] is out of bounds.
+   */
+  void operator []=(int index, E node);
+
+  /**
+   * Use the given [visitor] to visit each of the nodes in this list.
+   */
+  accept(AstVisitor visitor);
+}
+
+/**
+ * A formal parameter that is required (is not optional).
+ *
+ * > normalFormalParameter ::=
+ * >     [FunctionTypedFormalParameter]
+ * >   | [FieldFormalParameter]
+ * >   | [SimpleFormalParameter]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NormalFormalParameter extends FormalParameter {
+  /**
+   * Return the documentation comment associated with this parameter, or `null`
+   * if this parameter does not have a documentation comment associated with it.
+   */
+  Comment get documentationComment;
+
+  /**
+   * Set the documentation comment associated with this parameter to the given
+   * [comment].
+   */
+  void set documentationComment(Comment comment);
+
+  /**
+   * Set the name of the parameter being declared to the given [identifier].
+   */
+  void set identifier(SimpleIdentifier identifier);
+
+  /**
+   * Set the metadata associated with this node to the given [metadata].
+   */
+  void set metadata(List<Annotation> metadata);
+
+  /**
+   * Return a list containing the comment and annotations associated with this
+   * parameter, sorted in lexical order.
+   */
+  List<AstNode> get sortedCommentAndAnnotations;
+}
+
+/**
+ * A null literal expression.
+ *
+ * > nullLiteral ::=
+ * >     'null'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class NullLiteral extends Literal {
+  /**
+   * Initialize a newly created null literal.
+   */
+  factory NullLiteral(Token literal) = NullLiteralImpl;
+
+  /**
+   * Return the token representing the literal.
+   */
+  Token get literal;
+
+  /**
+   * Set the token representing the literal to the given [token].
+   */
+  void set literal(Token token);
+}
+
+/**
+ * A parenthesized expression.
+ *
+ * > parenthesizedExpression ::=
+ * >     '(' [Expression] ')'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ParenthesizedExpression extends Expression {
+  /**
+   * Initialize a newly created parenthesized expression.
+   */
+  factory ParenthesizedExpression(Token leftParenthesis, Expression expression,
+      Token rightParenthesis) = ParenthesizedExpressionImpl;
+
+  /**
+   * Return the expression within the parentheses.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression within the parentheses to the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+}
+
+/**
+ * A part directive.
+ *
+ * > partDirective ::=
+ * >     [Annotation] 'part' [StringLiteral] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class PartDirective extends UriBasedDirective {
+  /**
+   * Initialize a newly created part directive. Either or both of the [comment]
+   * and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  factory PartDirective(
+      Comment comment,
+      List<Annotation> metadata,
+      Token partKeyword,
+      StringLiteral partUri,
+      Token semicolon) = PartDirectiveImpl;
+
+  /**
+   * Return the token representing the 'part' keyword.
+   */
+  Token get partKeyword;
+
+  /**
+   * Set the token representing the 'part' keyword to the given [token].
+   */
+  void set partKeyword(Token token);
+
+  /**
+   * Return the semicolon terminating the directive.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the directive to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * A part-of directive.
+ *
+ * > partOfDirective ::=
+ * >     [Annotation] 'part' 'of' [Identifier] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class PartOfDirective extends Directive {
+  /**
+   * Initialize a newly created part-of directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  factory PartOfDirective(
+      Comment comment,
+      List<Annotation> metadata,
+      Token partKeyword,
+      Token ofKeyword,
+      LibraryIdentifier libraryName,
+      Token semicolon) = PartOfDirectiveImpl;
+
+  /**
+   * Return the name of the library that the containing compilation unit is part
+   * of.
+   */
+  LibraryIdentifier get libraryName;
+
+  /**
+   * Set the name of the library that the containing compilation unit is part of
+   * to the given [libraryName].
+   */
+  void set libraryName(LibraryIdentifier libraryName);
+
+  /**
+   * Return the token representing the 'of' keyword.
+   */
+  Token get ofKeyword;
+
+  /**
+   * Set the token representing the 'of' keyword to the given [token].
+   */
+  void set ofKeyword(Token token);
+
+  /**
+   * Return the token representing the 'part' keyword.
+   */
+  Token get partKeyword;
+
+  /**
+   * Set the token representing the 'part' keyword to the given [token].
+   */
+  void set partKeyword(Token token);
+
+  /**
+   * Return the semicolon terminating the directive.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the directive to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * A postfix unary expression.
+ *
+ * > postfixExpression ::=
+ * >     [Expression] [Token]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class PostfixExpression extends Expression {
+  /**
+   * Initialize a newly created postfix expression.
+   */
+  factory PostfixExpression(Expression operand, Token operator) =
+      PostfixExpressionImpl;
+
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  MethodElement get bestElement;
+
+  /**
+   * Return the expression computing the operand for the operator.
+   */
+  Expression get operand;
+
+  /**
+   * Set the expression computing the operand for the operator to the given
+   * [expression].
+   */
+  void set operand(Expression expression);
+
+  /**
+   * Return the postfix operator being applied to the operand.
+   */
+  Token get operator;
+
+  /**
+   * Set the postfix operator being applied to the operand to the given [token].
+   */
+  void set operator(Token token);
+
+  /**
+   * Return the element associated with this the operator based on the
+   * propagated type of the operand, or `null` if the AST structure has not been
+   * resolved, if the operator is not user definable, or if the operator could
+   * not be resolved.
+   */
+  MethodElement get propagatedElement;
+
+  /**
+   * Set the element associated with this the operator based on the propagated
+   * type of the operand to the given [element].
+   */
+  void set propagatedElement(MethodElement element);
+
+  /**
+   * Return the element associated with the operator based on the static type of
+   * the operand, or `null` if the AST structure has not been resolved, if the
+   * operator is not user definable, or if the operator could not be resolved.
+   */
+  MethodElement get staticElement;
+
+  /**
+   * Set the element associated with the operator based on the static type of
+   * the operand to the given [element].
+   */
+  void set staticElement(MethodElement element);
+}
+
+/**
+ * An identifier that is prefixed or an access to an object property where the
+ * target of the property access is a simple identifier.
+ *
+ * > prefixedIdentifier ::=
+ * >     [SimpleIdentifier] '.' [SimpleIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class PrefixedIdentifier extends Identifier {
+  /**
+   * Initialize a newly created prefixed identifier.
+   */
+  factory PrefixedIdentifier(
+          SimpleIdentifier prefix, Token period, SimpleIdentifier identifier) =
+      PrefixedIdentifierImpl;
+
+  /**
+   * Return the identifier being prefixed.
+   */
+  SimpleIdentifier get identifier;
+
+  /**
+   * Set the identifier being prefixed to the given [identifier].
+   */
+  void set identifier(SimpleIdentifier identifier);
+
+  /**
+   * Return `true` if this type is a deferred type. If the AST structure has not
+   * been resolved, then return `false`.
+   *
+   * 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
+   * </i>p.T</i> where <i>p</i> is a deferred prefix.
+   */
+  bool get isDeferred;
+
+  /**
+   * Return the period used to separate the prefix from the identifier.
+   */
+  Token get period;
+
+  /**
+   * Set the period used to separate the prefix from the identifier to the given
+   * [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the prefix associated with the library in which the identifier is
+   * defined.
+   */
+  SimpleIdentifier get prefix;
+
+  /**
+   * Set the prefix associated with the library in which the identifier is
+   * defined to the given [identifier].
+   */
+  void set prefix(SimpleIdentifier identifier);
+}
+
+/**
+ * A prefix unary expression.
+ *
+ * > prefixExpression ::=
+ * >     [Token] [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class PrefixExpression extends Expression {
+  /**
+   * Initialize a newly created prefix expression.
+   */
+  factory PrefixExpression(Token operator, Expression operand) =
+      PrefixExpressionImpl;
+
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  MethodElement get bestElement;
+
+  /**
+   * Return the expression computing the operand for the operator.
+   */
+  Expression get operand;
+
+  /**
+   * Set the expression computing the operand for the operator to the given
+   * [expression].
+   */
+  void set operand(Expression expression);
+
+  /**
+   * Return the prefix operator being applied to the operand.
+   */
+  Token get operator;
+
+  /**
+   * Set the prefix operator being applied to the operand to the given [token].
+   */
+  void set operator(Token token);
+
+  /**
+   * Return the element associated with the operator based on the propagated
+   * type of the operand, or `null` if the AST structure has not been resolved,
+   * if the operator is not user definable, or if the operator could not be
+   * resolved.
+   */
+  MethodElement get propagatedElement;
+
+  /**
+   * Set the element associated with the operator based on the propagated type
+   * of the operand to the given [element].
+   */
+  void set propagatedElement(MethodElement element);
+
+  /**
+   * Return the element associated with the operator based on the static type of
+   * the operand, or `null` if the AST structure has not been resolved, if the
+   * operator is not user definable, or if the operator could not be resolved.
+   */
+  MethodElement get staticElement;
+
+  /**
+   * Set the element associated with the operator based on the static type of
+   * the operand to the given [element].
+   */
+  void set staticElement(MethodElement element);
+}
+
+/**
+ * The access of a property of an object.
+ *
+ * Note, however, that accesses to properties of objects can also be represented
+ * as [PrefixedIdentifier] nodes in cases where the target is also a simple
+ * identifier.
+ *
+ * > propertyAccess ::=
+ * >     [Expression] '.' [SimpleIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class PropertyAccess extends Expression {
+  /**
+   * Initialize a newly created property access expression.
+   */
+  factory PropertyAccess(
+          Expression target, Token operator, SimpleIdentifier propertyName) =
+      PropertyAccessImpl;
+
+  /**
+   * Return `true` if this expression is cascaded. If it is, then the target of
+   * this expression is not stored locally but is stored in the nearest ancestor
+   * that is a [CascadeExpression].
+   */
+  bool get isCascaded;
+
+  /**
+   * Return the property access operator.
+   */
+  Token get operator;
+
+  /**
+   * Set the property access operator to the given [token].
+   */
+  void set operator(Token token);
+
+  /**
+   * Return the name of the property being accessed.
+   */
+  SimpleIdentifier get propertyName;
+
+  /**
+   * Set the name of the property being accessed to the given [identifier].
+   */
+  void set propertyName(SimpleIdentifier identifier);
+
+  /**
+   * Return the expression used to compute the receiver of the invocation. If
+   * this invocation is not part of a cascade expression, then this is the same
+   * as [target]. If this invocation is part of a cascade expression, then the
+   * target stored with the cascade expression is returned.
+   */
+  Expression get realTarget;
+
+  /**
+   * Return the expression computing the object defining the property being
+   * accessed, or `null` if this property access is part of a cascade expression.
+   *
+   * Use [realTarget] to get the target independent of whether this is part of a
+   * cascade expression.
+   */
+  Expression get target;
+
+  /**
+   * Set the expression computing the object defining the property being
+   * accessed to the given [expression].
+   */
+  void set target(Expression expression);
+}
+
+/**
+ * The invocation of a constructor in the same class from within a constructor's
+ * initialization list.
+ *
+ * > redirectingConstructorInvocation ::=
+ * >     'this' ('.' identifier)? arguments
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class RedirectingConstructorInvocation extends ConstructorInitializer {
+  /**
+   * Initialize a newly created redirecting invocation to invoke the constructor
+   * with the given name with the given arguments. The [constructorName] can be
+   * `null` if the constructor being invoked is the unnamed constructor.
+   */
+  factory RedirectingConstructorInvocation(
+      Token thisKeyword,
+      Token period,
+      SimpleIdentifier constructorName,
+      ArgumentList argumentList) = RedirectingConstructorInvocationImpl;
+
+  /**
+   * Return the list of arguments to the constructor.
+   */
+  ArgumentList get argumentList;
+
+  /**
+   * Set the list of arguments to the constructor to the given [argumentList].
+   */
+  void set argumentList(ArgumentList argumentList);
+
+  /**
+   * Return the name of the constructor that is being invoked, or `null` if the
+   * unnamed constructor is being invoked.
+   */
+  SimpleIdentifier get constructorName;
+
+  /**
+   * Set the name of the constructor that is being invoked to the given
+   * [identifier].
+   */
+  void set constructorName(SimpleIdentifier identifier);
+
+  /**
+   * Return the token for the period before the name of the constructor that is
+   * being invoked, or `null` if the unnamed constructor is being invoked.
+   */
+  Token get period;
+
+  /**
+   * Set the token for the period before the name of the constructor that is
+   * being invoked to the given [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the element associated with the constructor based on static type
+   * information, or `null` if the AST structure has not been resolved or if the
+   * constructor could not be resolved.
+   */
+  ConstructorElement get staticElement;
+
+  /**
+   * Set the element associated with the constructor based on static type
+   * information to the given [element].
+   */
+  void set staticElement(ConstructorElement element);
+
+  /**
+   * Return the token for the 'this' keyword.
+   */
+  Token get thisKeyword;
+
+  /**
+   * Set the token for the 'this' keyword to the given [token].
+   */
+  void set thisKeyword(Token token);
+}
+
+/**
+ * A rethrow expression.
+ *
+ * > rethrowExpression ::=
+ * >     'rethrow'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class RethrowExpression extends Expression {
+  /**
+   * Initialize a newly created rethrow expression.
+   */
+  factory RethrowExpression(Token rethrowKeyword) = RethrowExpressionImpl;
+
+  /**
+   * Return the token representing the 'rethrow' keyword.
+   */
+  Token get rethrowKeyword;
+
+  /**
+   * Set the token representing the 'rethrow' keyword to the given [token].
+   */
+  void set rethrowKeyword(Token token);
+}
+
+/**
+ * A return statement.
+ *
+ * > returnStatement ::=
+ * >     'return' [Expression]? ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ReturnStatement extends Statement {
+  /**
+   * Initialize a newly created return statement. The [expression] can be `null`
+   * if no explicit value was provided.
+   */
+  factory ReturnStatement(
+          Token returnKeyword, Expression expression, Token semicolon) =
+      ReturnStatementImpl;
+
+  /**
+   * Return the expression computing the value to be returned, or `null` if no
+   * explicit value was provided.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression computing the value to be returned to the given
+   * [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the token representing the 'return' keyword.
+   */
+  Token get returnKeyword;
+
+  /**
+   * Set the token representing the 'return' keyword to the given [token].
+   */
+  void set returnKeyword(Token token);
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+}
+
+/**
+ * A script tag that can optionally occur at the beginning of a compilation unit.
+ *
+ * > scriptTag ::=
+ * >     '#!' (~NEWLINE)* NEWLINE
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ScriptTag extends AstNode {
+  /**
+   * Initialize a newly created script tag.
+   */
+  factory ScriptTag(Token scriptTag) = ScriptTagImpl;
+
+  /**
+   * Return the token representing this script tag.
+   */
+  Token get scriptTag;
+
+  /**
+   * Set the token representing this script tag to the given [token].
+   */
+  void set scriptTag(Token token);
+}
+
+/**
+ * A combinator that restricts the names being imported to those in a given list.
+ *
+ * > showCombinator ::=
+ * >     'show' [SimpleIdentifier] (',' [SimpleIdentifier])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ShowCombinator extends Combinator {
+  /**
+   * Initialize a newly created import show combinator.
+   */
+  factory ShowCombinator(Token keyword, List<SimpleIdentifier> shownNames) =
+      ShowCombinatorImpl;
+
+  /**
+   * Return the list of names from the library that are made visible by this
+   * combinator.
+   */
+  NodeList<SimpleIdentifier> get shownNames;
+}
+
+/**
+ * A simple formal parameter.
+ *
+ * > simpleFormalParameter ::=
+ * >     ('final' [TypeName] | 'var' | [TypeName])? [SimpleIdentifier]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SimpleFormalParameter extends NormalFormalParameter {
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [keyword] can be `null` if a type was
+   * specified. The [type] must be `null` if the keyword is 'var'.
+   */
+  factory SimpleFormalParameter(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      TypeName type,
+      SimpleIdentifier identifier) = SimpleFormalParameterImpl;
+
+  /**
+   * Return the token representing either the 'final', 'const' or 'var' keyword,
+   * or `null` if no keyword was used.
+   */
+  Token get keyword;
+
+  /**
+   * Set the token representing either the 'final', 'const' or 'var' keyword to
+   * the given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the name of the declared type of the parameter, or `null` if the
+   * parameter does not have a declared type.
+   */
+  TypeName get type;
+
+  /**
+   * Set the name of the declared type of the parameter to the given [typeName].
+   */
+  void set type(TypeName typeName);
+}
+
+/**
+ * A simple identifier.
+ *
+ * > simpleIdentifier ::=
+ * >     initialCharacter internalCharacter*
+ * >
+ * > initialCharacter ::= '_' | '$' | letter
+ * >
+ * > internalCharacter ::= '_' | '$' | letter | digit
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SimpleIdentifier extends Identifier {
+  /**
+   * Initialize a newly created identifier.
+   */
+  factory SimpleIdentifier(Token token) = SimpleIdentifierImpl;
+
+  /**
+   * Return the auxiliary elements associated with this identifier, or `null` if
+   * this identifier is not in both a getter and setter context. The auxiliary
+   * elements hold the static and propagated elements associated with the getter
+   * context.
+   */
+  // TODO(brianwilkerson) Replace this API.
+  AuxiliaryElements get auxiliaryElements;
+
+  /**
+   * Set the auxiliary elements associated with this identifier to the given
+   * [elements].
+   */
+  // TODO(brianwilkerson) Replace this API.
+  void set auxiliaryElements(AuxiliaryElements elements);
+
+  /**
+   * Return `true` if this identifier is the "name" part of a prefixed
+   * identifier or a method invocation.
+   */
+  bool get isQualified;
+
+  /**
+   * Set the element associated with this identifier based on propagated type
+   * information to the given [element].
+   */
+  void set propagatedElement(Element element);
+
+  /**
+   * Set the element associated with this identifier based on static type
+   * information to the given [element].
+   */
+  void set staticElement(Element element);
+
+  /**
+   * Return the token representing the identifier.
+   */
+  Token get token;
+
+  /**
+   * Set the token representing the identifier to the given [token].
+   */
+  void set token(Token token);
+
+  /**
+   * Return `true` if this identifier is the name being declared in a
+   * declaration.
+   */
+  // TODO(brianwilkerson) Convert this to a getter.
+  bool inDeclarationContext();
+
+  /**
+   * Return `true` if this expression is computing a right-hand value.
+   *
+   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+   * are they mutually exclusive. In other words, it is possible for both
+   * methods to return `true` when invoked on the same node.
+   */
+  // TODO(brianwilkerson) Convert this to a getter.
+  bool inGetterContext();
+
+  /**
+   * Return `true` if this expression is computing a left-hand value.
+   *
+   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+   * are they mutually exclusive. In other words, it is possible for both
+   * methods to return `true` when invoked on the same node.
+   */
+  // TODO(brianwilkerson) Convert this to a getter.
+  bool inSetterContext();
+}
+
+/**
+ * A string literal expression that does not contain any interpolations.
+ *
+ * > simpleStringLiteral ::=
+ * >     rawStringLiteral
+ * >   | basicStringLiteral
+ * >
+ * > rawStringLiteral ::=
+ * >     'r' basicStringLiteral
+ * >
+ * > simpleStringLiteral ::=
+ * >     multiLineStringLiteral
+ * >   | singleLineStringLiteral
+ * >
+ * > multiLineStringLiteral ::=
+ * >     "'''" characters "'''"
+ * >   | '"""' characters '"""'
+ * >
+ * > singleLineStringLiteral ::=
+ * >     "'" characters "'"
+ * >   | '"' characters '"'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SimpleStringLiteral extends SingleStringLiteral {
+  /**
+   * Initialize a newly created simple string literal.
+   */
+  factory SimpleStringLiteral(Token literal, String value) =
+      SimpleStringLiteralImpl;
+
+  /**
+   * Return the token representing the literal.
+   */
+  Token get literal;
+
+  /**
+   * Set the token representing the literal to the given [token].
+   */
+  void set literal(Token token);
+
+  /**
+   * Return the value of the literal.
+   */
+  String get value;
+
+  /**
+   * Set the value of the literal to the given [string].
+   */
+  void set value(String string);
+}
+
+/**
+ * A single string literal expression.
+ *
+ * > singleStringLiteral ::=
+ * >     [SimpleStringLiteral]
+ * >   | [StringInterpolation]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SingleStringLiteral extends StringLiteral {
+  /**
+   * Return the offset of the after-last contents character.
+   */
+  int get contentsEnd;
+
+  /**
+   * Return the offset of the first contents character.
+   * If the string is multiline, then leading whitespaces are skipped.
+   */
+  int get contentsOffset;
+
+  /**
+   * Return `true` if this string literal is a multi-line string.
+   */
+  bool get isMultiline;
+
+  /**
+   * Return `true` if this string literal is a raw string.
+   */
+  bool get isRaw;
+
+  /**
+   * Return `true` if this string literal uses single quotes (' or ''').
+   * Return `false` if this string literal uses double quotes (" or """).
+   */
+  bool get isSingleQuoted;
+}
+
+/**
+ * A node that represents a statement.
+ *
+ * > statement ::=
+ * >     [Block]
+ * >   | [VariableDeclarationStatement]
+ * >   | [ForStatement]
+ * >   | [ForEachStatement]
+ * >   | [WhileStatement]
+ * >   | [DoStatement]
+ * >   | [SwitchStatement]
+ * >   | [IfStatement]
+ * >   | [TryStatement]
+ * >   | [BreakStatement]
+ * >   | [ContinueStatement]
+ * >   | [ReturnStatement]
+ * >   | [ExpressionStatement]
+ * >   | [FunctionDeclarationStatement]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Statement extends AstNode {
+  /**
+   * If this is a labeled statement, return the unlabeled portion of the
+   * statement, otherwise return the statement itself.
+   */
+  Statement get unlabeled;
+}
+
+/**
+ * A string interpolation literal.
+ *
+ * > stringInterpolation ::=
+ * >     ''' [InterpolationElement]* '''
+ * >   | '"' [InterpolationElement]* '"'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class StringInterpolation extends SingleStringLiteral {
+  /**
+   * Initialize a newly created string interpolation expression.
+   */
+  factory StringInterpolation(List<InterpolationElement> elements) =
+      StringInterpolationImpl;
+
+  /**
+   * Return the elements that will be composed to produce the resulting string.
+   */
+  NodeList<InterpolationElement> get elements;
+}
+
+/**
+ * A string literal expression.
+ *
+ * > stringLiteral ::=
+ * >     [SimpleStringLiteral]
+ * >   | [AdjacentStrings]
+ * >   | [StringInterpolation]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class StringLiteral extends Literal {
+  /**
+   * Return the value of the string literal, or `null` if the string is not a
+   * constant string without any string interpolation.
+   */
+  String get stringValue;
+}
+
+/**
+ * The invocation of a superclass' constructor from within a constructor's
+ * initialization list.
+ *
+ * > superInvocation ::=
+ * >     'super' ('.' [SimpleIdentifier])? [ArgumentList]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SuperConstructorInvocation extends ConstructorInitializer {
+  /**
+   * Initialize a newly created super invocation to invoke the inherited
+   * constructor with the given name with the given arguments. The [period] and
+   * [constructorName] can be `null` if the constructor being invoked is the
+   * unnamed constructor.
+   */
+  factory SuperConstructorInvocation(
+      Token superKeyword,
+      Token period,
+      SimpleIdentifier constructorName,
+      ArgumentList argumentList) = SuperConstructorInvocationImpl;
+
+  /**
+   * Return the list of arguments to the constructor.
+   */
+  ArgumentList get argumentList;
+
+  /**
+   * Set the list of arguments to the constructor to the given [argumentList].
+   */
+  void set argumentList(ArgumentList argumentList);
+
+  /**
+   * Return the name of the constructor that is being invoked, or `null` if the
+   * unnamed constructor is being invoked.
+   */
+  SimpleIdentifier get constructorName;
+
+  /**
+   * Set the name of the constructor that is being invoked to the given
+   * [identifier].
+   */
+  void set constructorName(SimpleIdentifier identifier);
+
+  /**
+   * Return the token for the period before the name of the constructor that is
+   * being invoked, or `null` if the unnamed constructor is being invoked.
+   */
+  Token get period;
+
+  /**
+   * Set the token for the period before the name of the constructor that is
+   * being invoked to the given [token].
+   */
+  void set period(Token token);
+
+  /**
+   * Return the element associated with the constructor based on static type
+   * information, or `null` if the AST structure has not been resolved or if the
+   * constructor could not be resolved.
+   */
+  ConstructorElement get staticElement;
+
+  /**
+   * Set the element associated with the constructor based on static type
+   * information to the given [element].
+   */
+  void set staticElement(ConstructorElement element);
+
+  /**
+   * Return the token for the 'super' keyword.
+   */
+  Token get superKeyword;
+
+  /**
+   * Set the token for the 'super' keyword to the given [token].
+   */
+  void set superKeyword(Token token);
+}
+
+/**
+ * A super expression.
+ *
+ * > superExpression ::=
+ * >     'super'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SuperExpression extends Expression {
+  /**
+   * Initialize a newly created super expression.
+   */
+  factory SuperExpression(Token superKeyword) = SuperExpressionImpl;
+
+  /**
+   * Return the token representing the 'super' keyword.
+   */
+  Token get superKeyword;
+
+  /**
+   * Set the token representing the 'super' keyword to the given [token].
+   */
+  void set superKeyword(Token token);
+}
+
+/**
+ * A case in a switch statement.
+ *
+ * > switchCase ::=
+ * >     [SimpleIdentifier]* 'case' [Expression] ':' [Statement]*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SwitchCase extends SwitchMember {
+  /**
+   * Initialize a newly created switch case. The list of [labels] can be `null`
+   * if there are no labels.
+   */
+  factory SwitchCase(List<Label> labels, Token keyword, Expression expression,
+      Token colon, List<Statement> statements) = SwitchCaseImpl;
+
+  /**
+   * Return the expression controlling whether the statements will be executed.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression controlling whether the statements will be executed to
+   * the given [expression].
+   */
+  void set expression(Expression expression);
+}
+
+/**
+ * The default case in a switch statement.
+ *
+ * > switchDefault ::=
+ * >     [SimpleIdentifier]* 'default' ':' [Statement]*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SwitchDefault extends SwitchMember {
+  /**
+   * Initialize a newly created switch default. The list of [labels] can be
+   * `null` if there are no labels.
+   */
+  factory SwitchDefault(List<Label> labels, Token keyword, Token colon,
+      List<Statement> statements) = SwitchDefaultImpl;
+}
+
+/**
+ * An element within a switch statement.
+ *
+ * > switchMember ::=
+ * >     switchCase
+ * >   | switchDefault
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SwitchMember extends AstNode {
+  /**
+   * Return the colon separating the keyword or the expression from the
+   * statements.
+   */
+  Token get colon;
+
+  /**
+   * Set the colon separating the keyword or the expression from the
+   * statements to the given [token].
+   */
+  void set colon(Token token);
+
+  /**
+   * Return the token representing the 'case' or 'default' keyword.
+   */
+  Token get keyword;
+
+  /**
+   * Set the token representing the 'case' or 'default' keyword to the given
+   * [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the labels associated with the switch member.
+   */
+  NodeList<Label> get labels;
+
+  /**
+   * Return the statements that will be executed if this switch member is
+   * selected.
+   */
+  NodeList<Statement> get statements;
+}
+
+/**
+ * A switch statement.
+ *
+ * > switchStatement ::=
+ * >     'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SwitchStatement extends Statement {
+  /**
+   * Initialize a newly created switch statement. The list of [members] can be
+   * `null` if there are no switch members.
+   */
+  factory SwitchStatement(
+      Token switchKeyword,
+      Token leftParenthesis,
+      Expression expression,
+      Token rightParenthesis,
+      Token leftBracket,
+      List<SwitchMember> members,
+      Token rightBracket) = SwitchStatementImpl;
+
+  /**
+   * Return the expression used to determine which of the switch members will be
+   * selected.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression used to determine which of the switch members will be
+   * selected to the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the left curly bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left curly bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the switch members that can be selected by the expression.
+   */
+  NodeList<SwitchMember> get members;
+
+  /**
+   * Return the right curly bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right curly bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the token representing the 'switch' keyword.
+   */
+  Token get switchKeyword;
+
+  /**
+   * Set the token representing the 'switch' keyword to the given [token].
+   */
+  void set switchKeyword(Token token);
+}
+
+/**
+ * A symbol literal expression.
+ *
+ * > symbolLiteral ::=
+ * >     '#' (operator | (identifier ('.' identifier)*))
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class SymbolLiteral extends Literal {
+  /**
+   * Initialize a newly created symbol literal.
+   */
+  factory SymbolLiteral(Token poundSign, List<Token> components) =
+      SymbolLiteralImpl;
+
+  /**
+   * Return the components of the literal.
+   */
+  List<Token> get components;
+
+  /**
+   * Return the token introducing the literal.
+   */
+  Token get poundSign;
+
+  /**
+   * Set the token introducing the literal to the given [token].
+   */
+  void set poundSign(Token token);
+}
+
+/**
+ * A this expression.
+ *
+ * > thisExpression ::=
+ * >     'this'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ThisExpression extends Expression {
+  /**
+   * Initialize a newly created this expression.
+   */
+  factory ThisExpression(Token thisKeyword) = ThisExpressionImpl;
+
+  /**
+   * Return the token representing the 'this' keyword.
+   */
+  Token get thisKeyword;
+
+  /**
+   * Set the token representing the 'this' keyword to the given [token].
+   */
+  void set thisKeyword(Token token);
+}
+
+/**
+ * A throw expression.
+ *
+ * > throwExpression ::=
+ * >     'throw' [Expression]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class ThrowExpression extends Expression {
+  /**
+   * Initialize a newly created throw expression.
+   */
+  factory ThrowExpression(Token throwKeyword, Expression expression) =
+      ThrowExpressionImpl;
+
+  /**
+   * Return the expression computing the exception to be thrown.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression computing the exception to be thrown to the given
+   * [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the token representing the 'throw' keyword.
+   */
+  Token get throwKeyword;
+
+  /**
+   * Set the token representing the 'throw' keyword to the given [token].
+   */
+  void set throwKeyword(Token token);
+}
+
+/**
+ * The declaration of one or more top-level variables of the same type.
+ *
+ * > topLevelVariableDeclaration ::=
+ * >     ('final' | 'const') type? staticFinalDeclarationList ';'
+ * >   | variableDeclaration ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TopLevelVariableDeclaration extends CompilationUnitMember {
+  /**
+   * Initialize a newly created top-level variable declaration. Either or both
+   * of the [comment] and [metadata] can be `null` if the variable does not have
+   * the corresponding attribute.
+   */
+  factory TopLevelVariableDeclaration(
+      Comment comment,
+      List<Annotation> metadata,
+      VariableDeclarationList variableList,
+      Token semicolon) = TopLevelVariableDeclarationImpl;
+
+  /**
+   * Return the semicolon terminating the declaration.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the declaration to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the top-level variables being declared.
+   */
+  VariableDeclarationList get variables;
+
+  /**
+   * Set the top-level variables being declared to the given list of
+   * [variables].
+   */
+  void set variables(VariableDeclarationList variables);
+}
+
+/**
+ * A try statement.
+ *
+ * > tryStatement ::=
+ * >     'try' [Block] ([CatchClause]+ finallyClause? | finallyClause)
+ * >
+ * > finallyClause ::=
+ * >     'finally' [Block]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TryStatement extends Statement {
+  /**
+   * Initialize a newly created try statement. The list of [catchClauses] can be
+   * `null` if there are no catch clauses. The [finallyKeyword] and
+   * [finallyBlock] can be `null` if there is no finally clause.
+   */
+  factory TryStatement(
+      Token tryKeyword,
+      Block body,
+      List<CatchClause> catchClauses,
+      Token finallyKeyword,
+      Block finallyBlock) = TryStatementImpl;
+
+  /**
+   * Return the body of the statement.
+   */
+  Block get body;
+
+  /**
+   * Set the body of the statement to the given [block].
+   */
+  void set body(Block block);
+
+  /**
+   * Return the catch clauses contained in the try statement.
+   */
+  NodeList<CatchClause> get catchClauses;
+
+  /**
+   * Return the finally block contained in the try statement, or `null` if the
+   * statement does not contain a finally clause.
+   */
+  Block get finallyBlock;
+
+  /**
+   * Set the finally block contained in the try statement to the given [block].
+   */
+  void set finallyBlock(Block block);
+
+  /**
+   * Return the token representing the 'finally' keyword, or `null` if the
+   * statement does not contain a finally clause.
+   */
+  Token get finallyKeyword;
+
+  /**
+   * Set the token representing the 'finally' keyword to the given [token].
+   */
+  void set finallyKeyword(Token token);
+
+  /**
+   * Return the token representing the 'try' keyword.
+   */
+  Token get tryKeyword;
+
+  /**
+   * Set the token representing the 'try' keyword to the given [token].
+   */
+  void set tryKeyword(Token token);
+}
+
+/**
+ * The declaration of a type alias.
+ *
+ * > typeAlias ::=
+ * >     'typedef' typeAliasBody
+ * >
+ * > typeAliasBody ::=
+ * >     classTypeAlias
+ * >   | functionTypeAlias
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TypeAlias extends NamedCompilationUnitMember {
+  /**
+   * Return the semicolon terminating the declaration.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the declaration to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the token representing the 'typedef' keyword.
+   */
+  Token get typedefKeyword;
+
+  /**
+   * Set the token representing the 'typedef' keyword to the given [token].
+   */
+  void set typedefKeyword(Token token);
+}
+
+/**
+ * A list of type arguments.
+ *
+ * > typeArguments ::=
+ * >     '<' typeName (',' typeName)* '>'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TypeArgumentList extends AstNode {
+  /**
+   * Initialize a newly created list of type arguments.
+   */
+  factory TypeArgumentList(
+          Token leftBracket, List<TypeName> arguments, Token rightBracket) =
+      TypeArgumentListImpl;
+
+  /**
+   * Return the type arguments associated with the type.
+   */
+  NodeList<TypeName> get arguments;
+
+  /**
+   * Return the left bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Set the left bracket to the given [token].
+   */
+  void set leftBracket(Token token);
+
+  /**
+   * Return the right bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Set the right bracket to the given [token].
+   */
+  void set rightBracket(Token token);
+}
+
+/**
+ * A literal that has a type associated with it.
+ *
+ * > typedLiteral ::=
+ * >     [ListLiteral]
+ * >   | [MapLiteral]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TypedLiteral extends Literal {
+  /**
+   * Return the token representing the 'const' keyword, or `null` if the literal
+   * is not a constant.
+   */
+  Token get constKeyword;
+
+  /**
+   * Set the token representing the 'const' keyword to the given [token].
+   */
+  void set constKeyword(Token token);
+
+  /**
+   * Return the type argument associated with this literal, or `null` if no type
+   * arguments were declared.
+   */
+  TypeArgumentList get typeArguments;
+
+  /**
+   * Set the type argument associated with this literal to the given
+   * [typeArguments].
+   */
+  void set typeArguments(TypeArgumentList typeArguments);
+}
+
+/**
+ * The name of a type, which can optionally include type arguments.
+ *
+ * > typeName ::=
+ * >     [Identifier] typeArguments?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TypeName extends AstNode {
+  /**
+   * Initialize a newly created type name. The [typeArguments] can be `null` if
+   * there are no type arguments.
+   */
+  factory TypeName(Identifier name, TypeArgumentList typeArguments) =
+      TypeNameImpl;
+
+  /**
+   * Return `true` if this type is a deferred type.
+   *
+   * 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
+   * </i>p.T</i> where <i>p</i> is a deferred prefix.
+   */
+  bool get isDeferred;
+
+  /**
+   * Return the name of the type.
+   */
+  Identifier get name;
+
+  /**
+   * Set the name of the type to the given [identifier].
+   */
+  void set name(Identifier identifier);
+
+  /**
+   * Return the type being named, or `null` if the AST structure has not been
+   * resolved.
+   */
+  DartType get type;
+
+  /**
+   * Set the type being named to the given [type].
+   */
+  void set type(DartType type);
+
+  /**
+   * Return the type arguments associated with the type, or `null` if there are
+   * no type arguments.
+   */
+  TypeArgumentList get typeArguments;
+
+  /**
+   * Set the type arguments associated with the type to the given
+   * [typeArguments].
+   */
+  void set typeArguments(TypeArgumentList typeArguments);
+}
+
+/**
+ * A type parameter.
+ *
+ * > typeParameter ::=
+ * >     [SimpleIdentifier] ('extends' [TypeName])?
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TypeParameter extends Declaration {
+  /**
+   * Initialize a newly created type parameter. Either or both of the [comment]
+   * and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [extendsKeyword] and [bound] can be `null` if
+   * the parameter does not have an upper bound.
+   */
+  factory TypeParameter(
+      Comment comment,
+      List<Annotation> metadata,
+      SimpleIdentifier name,
+      Token extendsKeyword,
+      TypeName bound) = TypeParameterImpl;
+
+  /**
+   * Return the name of the upper bound for legal arguments, or `null` if there
+   * is no explicit upper bound.
+   */
+  TypeName get bound;
+
+  /**
+   * Set the name of the upper bound for legal arguments to the given
+   * [typeName].
+   */
+  void set bound(TypeName typeName);
+
+  /**
+   * Return the token representing the 'extends' keyword, or `null` if there is
+   * no explicit upper bound.
+   */
+  Token get extendsKeyword;
+
+  /**
+   * Set the token representing the 'extends' keyword to the given [token].
+   */
+  void set extendsKeyword(Token token);
+
+  /**
+   * Return the name of the type parameter.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the type parameter to the given [identifier].
+   */
+  void set name(SimpleIdentifier identifier);
+}
+
+/**
+ * Type parameters within a declaration.
+ *
+ * > typeParameterList ::=
+ * >     '<' [TypeParameter] (',' [TypeParameter])* '>'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class TypeParameterList extends AstNode {
+  /**
+   * Initialize a newly created list of type parameters.
+   */
+  factory TypeParameterList(
+      Token leftBracket,
+      List<TypeParameter> typeParameters,
+      Token rightBracket) = TypeParameterListImpl;
+
+  /**
+   * Return the left angle bracket.
+   */
+  Token get leftBracket;
+
+  /**
+   * Return the right angle bracket.
+   */
+  Token get rightBracket;
+
+  /**
+   * Return the type parameters for the type.
+   */
+  NodeList<TypeParameter> get typeParameters;
+}
+
+/**
+ * A directive that references a URI.
+ *
+ * > uriBasedDirective ::=
+ * >     [ExportDirective]
+ * >   | [ImportDirective]
+ * >   | [PartDirective]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class UriBasedDirective extends Directive {
+  /**
+   * Return the source to which the URI was resolved.
+   */
+  Source get source;
+
+  /**
+   * Set the source to which the URI was resolved to the given [source].
+   */
+  void set source(Source source);
+
+  /**
+   * Return the URI referenced by this directive.
+   */
+  StringLiteral get uri;
+
+  /**
+   * Set the URI referenced by this directive to the given [uri].
+   */
+  void set uri(StringLiteral uri);
+
+  /**
+   * Return the content of the URI.
+   */
+  String get uriContent;
+
+  /**
+   * Set the content of the URI to the given [content].
+   */
+  void set uriContent(String content);
+
+  /**
+   * Return the element associated with the URI of this directive, or `null` if
+   * the AST structure has not been resolved or if the URI could not be
+   * resolved. Examples of the latter case include a directive that contains an
+   * invalid URL or a URL that does not exist.
+   */
+  Element get uriElement;
+
+  /**
+   * Validate this directive, but do not check for existence. Return a code
+   * indicating the problem if there is one, or `null` no problem
+   */
+  UriValidationCode validate();
+}
+
+/**
+ * Validation codes returned by [UriBasedDirective.validate].
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class UriValidationCode {
+  static const UriValidationCode INVALID_URI =
+      UriValidationCodeImpl.INVALID_URI;
+
+  static const UriValidationCode URI_WITH_INTERPOLATION =
+      UriValidationCodeImpl.URI_WITH_INTERPOLATION;
+
+  static const UriValidationCode URI_WITH_DART_EXT_SCHEME =
+      UriValidationCodeImpl.URI_WITH_DART_EXT_SCHEME;
+}
+
+/**
+ * An identifier that has an initial value associated with it. Instances of this
+ * class are always children of the class [VariableDeclarationList].
+ *
+ * > variableDeclaration ::=
+ * >     [SimpleIdentifier] ('=' [Expression])?
+ *
+ * TODO(paulberry): the grammar does not allow metadata to be associated with
+ * a VariableDeclaration, and currently we don't record comments for it either.
+ * Consider changing the class hierarchy so that [VariableDeclaration] does not
+ * extend [Declaration].
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class VariableDeclaration extends Declaration {
+  /**
+   * Initialize a newly created variable declaration. The [equals] and
+   * [initializer] can be `null` if there is no initializer.
+   */
+  factory VariableDeclaration(
+          SimpleIdentifier name, Token equals, Expression initializer) =
+      VariableDeclarationImpl;
+
+  @override
+  VariableElement get element;
+
+  /**
+   * Return the equal sign separating the variable name from the initial value,
+   * or `null` if the initial value was not specified.
+   */
+  Token get equals;
+
+  /**
+   * Set the equal sign separating the variable name from the initial value to
+   * the given [token].
+   */
+  void set equals(Token token);
+
+  /**
+   * Return the expression used to compute the initial value for the variable,
+   * or `null` if the initial value was not specified.
+   */
+  Expression get initializer;
+
+  /**
+   * Set the expression used to compute the initial value for the variable to
+   * the given [expression].
+   */
+  void set initializer(Expression expression);
+
+  /**
+   * Return `true` if this variable was declared with the 'const' modifier.
+   */
+  bool get isConst;
+
+  /**
+   * Return `true` if this variable was declared with the 'final' modifier.
+   * Variables that are declared with the 'const' modifier will return `false`
+   * even though they are implicitly final.
+   */
+  bool get isFinal;
+
+  /**
+   * Return the name of the variable being declared.
+   */
+  SimpleIdentifier get name;
+
+  /**
+   * Set the name of the variable being declared to the given [identifier].
+   */
+  void set name(SimpleIdentifier identifier);
+}
+
+/**
+ * The declaration of one or more variables of the same type.
+ *
+ * > variableDeclarationList ::=
+ * >     finalConstVarOrType [VariableDeclaration] (',' [VariableDeclaration])*
+ * >
+ * > finalConstVarOrType ::=
+ * >   | 'final' [TypeName]?
+ * >   | 'const' [TypeName]?
+ * >   | 'var'
+ * >   | [TypeName]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class VariableDeclarationList extends AnnotatedNode {
+  /**
+   * Initialize a newly created variable declaration list. Either or both of the
+   * [comment] and [metadata] can be `null` if the variable list does not have
+   * the corresponding attribute. The [keyword] can be `null` if a type was
+   * specified. The [type] must be `null` if the keyword is 'var'.
+   */
+  factory VariableDeclarationList(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      TypeName type,
+      List<VariableDeclaration> variables) = VariableDeclarationListImpl;
+
+  /**
+   * Return `true` if the variables in this list were declared with the 'const'
+   * modifier.
+   */
+  bool get isConst;
+
+  /**
+   * Return `true` if the variables in this list were declared with the 'final'
+   * modifier. Variables that are declared with the 'const' modifier will return
+   * `false` even though they are implicitly final. (In other words, this is a
+   * syntactic check rather than a semantic check.)
+   */
+  bool get isFinal;
+
+  /**
+   * Return the token representing the 'final', 'const' or 'var' keyword, or
+   * `null` if no keyword was included.
+   */
+  Token get keyword;
+
+  /**
+   * Set the token representing the 'final', 'const' or 'var' keyword to the
+   * given [token].
+   */
+  void set keyword(Token token);
+
+  /**
+   * Return the type of the variables being declared, or `null` if no type was
+   * provided.
+   */
+  TypeName get type;
+
+  /**
+   * Set the type of the variables being declared to the given [typeName].
+   */
+  void set type(TypeName typeName);
+
+  /**
+   * Return a list containing the individual variables being declared.
+   */
+  NodeList<VariableDeclaration> get variables;
+}
+
+/**
+ * A list of variables that are being declared in a context where a statement is
+ * required.
+ *
+ * > variableDeclarationStatement ::=
+ * >     [VariableDeclarationList] ';'
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class VariableDeclarationStatement extends Statement {
+  /**
+   * Initialize a newly created variable declaration statement.
+   */
+  factory VariableDeclarationStatement(
+          VariableDeclarationList variableList, Token semicolon) =
+      VariableDeclarationStatementImpl;
+
+  /**
+   * Return the semicolon terminating the statement.
+   */
+  Token get semicolon;
+
+  /**
+   * Set the semicolon terminating the statement to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the variables being declared.
+   */
+  VariableDeclarationList get variables;
+
+  /**
+   * Set the variables being declared to the given list of [variables].
+   */
+  void set variables(VariableDeclarationList variables);
+}
+
+/**
+ * A while statement.
+ *
+ * > whileStatement ::=
+ * >     'while' '(' [Expression] ')' [Statement]
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class WhileStatement extends Statement {
+  /**
+   * Initialize a newly created while statement.
+   */
+  factory WhileStatement(
+      Token whileKeyword,
+      Token leftParenthesis,
+      Expression condition,
+      Token rightParenthesis,
+      Statement body) = WhileStatementImpl;
+
+  /**
+   * Return the body of the loop.
+   */
+  Statement get body;
+
+  /**
+   * Set the body of the loop to the given [statement].
+   */
+  void set body(Statement statement);
+
+  /**
+   * Return the expression used to determine whether to execute the body of the
+   * loop.
+   */
+  Expression get condition;
+
+  /**
+   * Set the expression used to determine whether to execute the body of the
+   * loop to the given [expression].
+   */
+  void set condition(Expression expression);
+
+  /**
+   * Return the left parenthesis.
+   */
+  Token get leftParenthesis;
+
+  /**
+   * Set the left parenthesis to the given [token].
+   */
+  void set leftParenthesis(Token token);
+
+  /**
+   * Return the right parenthesis.
+   */
+  Token get rightParenthesis;
+
+  /**
+   * Set the right parenthesis to the given [token].
+   */
+  void set rightParenthesis(Token token);
+
+  /**
+   * Return the token representing the 'while' keyword.
+   */
+  Token get whileKeyword;
+
+  /**
+   * Set the token representing the 'while' keyword to the given [token].
+   */
+  void set whileKeyword(Token token);
+}
+
+/**
+ * The with clause in a class declaration.
+ *
+ * > withClause ::=
+ * >     'with' [TypeName] (',' [TypeName])*
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class WithClause extends AstNode {
+  /**
+   * Initialize a newly created with clause.
+   */
+  factory WithClause(Token withKeyword, List<TypeName> mixinTypes) =
+      WithClauseImpl;
+
+  /**
+   * Return the names of the mixins that were specified.
+   */
+  NodeList<TypeName> get mixinTypes;
+
+  /**
+   * Return the token representing the 'with' keyword.
+   */
+  Token get withKeyword;
+
+  /**
+   * Set the token representing the 'with' keyword to the given [token].
+   */
+  void set withKeyword(Token token);
+}
+
+/**
+ * A yield statement.
+ *
+ * > yieldStatement ::=
+ * >     'yield' '*'? [Expression] ‘;’
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class YieldStatement extends Statement {
+  /**
+   * Initialize a newly created yield expression. The [star] can be `null` if no
+   * star was provided.
+   */
+  factory YieldStatement(Token yieldKeyword, Token star, Expression expression,
+      Token semicolon) = YieldStatementImpl;
+
+  /**
+   * Return the expression whose value will be yielded.
+   */
+  Expression get expression;
+
+  /**
+   * Set the expression whose value will be yielded to the given [expression].
+   */
+  void set expression(Expression expression);
+
+  /**
+   * Return the semicolon following the expression.
+   */
+  Token get semicolon;
+
+  /**
+   * Return the semicolon following the expression to the given [token].
+   */
+  void set semicolon(Token token);
+
+  /**
+   * Return the star optionally following the 'yield' keyword.
+   */
+  Token get star;
+
+  /**
+   * Return the star optionally following the 'yield' keyword to the given [token].
+   */
+  void set star(Token token);
+
+  /**
+   * Return the 'yield' keyword.
+   */
+  Token get yieldKeyword;
+
+  /**
+   * Return the 'yield' keyword to the given [token].
+   */
+  void set yieldKeyword(Token token);
+}
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index c9b345a..7e2848e 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -6,7 +6,7 @@
 
 import 'dart:collection';
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
 
 /**
  * An AST visitor that will recursively visit all of the nodes in an AST
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index ab468ed..bb52303d 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -4,8 +4,8 @@
 
 library analyzer.dart.element.element;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart' show DartObject;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/java_core.dart';
@@ -1347,6 +1347,11 @@
   bool get isBrowserApplication;
 
   /**
+   * Return `true` if this library is the dart:async library.
+   */
+  bool get isDartAsync;
+
+  /**
    * Return `true` if this library is the dart:core library.
    */
   bool get isDartCore;
@@ -1470,154 +1475,6 @@
 }
 
 /**
- * The enumeration `Modifier` defines constants for all of the modifiers defined
- * by the Dart language and for a few additional flags that are useful.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-class Modifier extends Enum<Modifier> {
-  /**
-   * Indicates that the modifier 'abstract' was applied to the element.
-   */
-  static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0);
-
-  /**
-   * Indicates that an executable element has a body marked as being
-   * asynchronous.
-   */
-  static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1);
-
-  /**
-   * Indicates that the modifier 'const' was applied to the element.
-   */
-  static const Modifier CONST = const Modifier('CONST', 2);
-
-  /**
-   * Indicates that the import element represents a deferred library.
-   */
-  static const Modifier DEFERRED = const Modifier('DEFERRED', 3);
-
-  /**
-   * Indicates that a class element was defined by an enum declaration.
-   */
-  static const Modifier ENUM = const Modifier('ENUM', 4);
-
-  /**
-   * Indicates that a class element was defined by an enum declaration.
-   */
-  static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5);
-
-  /**
-   * Indicates that the modifier 'factory' was applied to the element.
-   */
-  static const Modifier FACTORY = const Modifier('FACTORY', 6);
-
-  /**
-   * Indicates that the modifier 'final' was applied to the element.
-   */
-  static const Modifier FINAL = const Modifier('FINAL', 7);
-
-  /**
-   * Indicates that an executable element has a body marked as being a
-   * generator.
-   */
-  static const Modifier GENERATOR = const Modifier('GENERATOR', 8);
-
-  /**
-   * Indicates that the pseudo-modifier 'get' was applied to the element.
-   */
-  static const Modifier GETTER = const Modifier('GETTER', 9);
-
-  /**
-   * A flag used for libraries indicating that the defining compilation unit
-   * contains at least one import directive whose URI uses the "dart-ext"
-   * scheme.
-   */
-  static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10);
-
-  /**
-   * Indicates that the associated element did not have an explicit type
-   * associated with it. If the element is an [ExecutableElement], then the
-   * type being referred to is the return type.
-   */
-  static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 11);
-
-  /**
-   * Indicates that a class can validly be used as a mixin.
-   */
-  static const Modifier MIXIN = const Modifier('MIXIN', 12);
-
-  /**
-   * Indicates that a class is a mixin application.
-   */
-  static const Modifier MIXIN_APPLICATION =
-      const Modifier('MIXIN_APPLICATION', 13);
-
-  /**
-   * 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', 14);
-
-  /**
-   * 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', 15);
-
-  /**
-   * Indicates that a class contains an explicit reference to 'super'.
-   */
-  static const Modifier REFERENCES_SUPER =
-      const Modifier('REFERENCES_SUPER', 16);
-
-  /**
-   * Indicates that the pseudo-modifier 'set' was applied to the element.
-   */
-  static const Modifier SETTER = const Modifier('SETTER', 17);
-
-  /**
-   * Indicates that the modifier 'static' was applied to the element.
-   */
-  static const Modifier STATIC = const Modifier('STATIC', 18);
-
-  /**
-   * Indicates that the element does not appear in the source code but was
-   * implicitly created. For example, if a class does not define any
-   * constructors, an implicit zero-argument constructor will be created and it
-   * will be marked as being synthetic.
-   */
-  static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 19);
-
-  static const List<Modifier> values = const [
-    ABSTRACT,
-    ASYNCHRONOUS,
-    CONST,
-    DEFERRED,
-    ENUM,
-    EXTERNAL,
-    FACTORY,
-    FINAL,
-    GENERATOR,
-    GETTER,
-    HAS_EXT_URI,
-    IMPLICIT_TYPE,
-    MIXIN,
-    MIXIN_APPLICATION,
-    POTENTIALLY_MUTATED_IN_CONTEXT,
-    POTENTIALLY_MUTATED_IN_SCOPE,
-    REFERENCES_SUPER,
-    SETTER,
-    STATIC,
-    SYNTHETIC
-  ];
-
-  const Modifier(String name, int ordinal) : super(name, ordinal);
-}
-
-/**
  * A pseudo-element that represents multiple elements defined within a single
  * scope that have the same name. This situation is not allowed by the language,
  * so objects implementing this interface always represent an error. As a
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 548dc1d..5b92819 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart' show InterfaceTypeImpl;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystem;
 
 /**
  * The type associated with elements in the element model.
@@ -38,6 +39,12 @@
   bool get isBottom;
 
   /**
+   * Return `true` if this type represents the type 'Future' defined in the
+   * dart:async library.
+   */
+  bool get isDartAsyncFuture;
+
+  /**
    * Return `true` if this type represents the type 'Function' defined in the
    * dart:core library.
    */
@@ -70,6 +77,19 @@
   String get name;
 
   /**
+   * Implements the function "flatten" defined in the spec, where T is this
+   * type:
+   *
+   *     If T = Future<S> then flatten(T) = flatten(S).
+   *
+   *     Otherwise if T <: Future then let S be a type such that T << Future<S>
+   *     and for all R, if T << Future<R> then S << R.  Then flatten(T) = S.
+   *
+   *     In any other circumstance, flatten(T) = T.
+   */
+  DartType flattenFutures(TypeSystem typeSystem);
+
+  /**
    * Return `true` if this type is assignable to the given [type]. A type
    * <i>T</i> may be assigned to a type <i>S</i>, written <i>T</i> &hArr;
    * <i>S</i>, iff either <i>T</i> <: <i>S</i> or <i>S</i> <: <i>T</i>.
@@ -137,16 +157,6 @@
   List<TypeParameterElement> get boundTypeParameters;
 
   /**
-   * The formal type parameters of this generic function.
-   * For example `<T> T -> T`.
-   *
-   * These are distinct from the [typeParameters] list, which contains type
-   * parameters from surrounding contexts, and thus are free type variables from
-   * the perspective of this function type.
-   */
-  List<TypeParameterElement> get typeFormals;
-
-  /**
    * Return a map from the names of named parameters to the types of the named
    * parameters of this type of function. The entries in the map will be
    * iterated in the same order as the order in which the named parameters were
@@ -184,6 +194,16 @@
   DartType get returnType;
 
   /**
+   * The formal type parameters of this generic function.
+   * For example `<T> T -> T`.
+   *
+   * These are distinct from the [typeParameters] list, which contains type
+   * parameters from surrounding contexts, and thus are free type variables from
+   * the perspective of this function type.
+   */
+  List<TypeParameterElement> get typeFormals;
+
+  /**
    * Return the type resulting from instantiating (replacing) the given
    * [argumentTypes] for this function's bound type parameters.
    */
diff --git a/pkg/analyzer/lib/source/embedder.dart b/pkg/analyzer/lib/source/embedder.dart
index c82e4f3..f77ff7c 100644
--- a/pkg/analyzer/lib/source/embedder.dart
+++ b/pkg/analyzer/lib/source/embedder.dart
@@ -8,12 +8,18 @@
 import 'dart:core' hide Resource;
 
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
+import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource;
-import 'package:path/path.dart' as pathos;
 import 'package:yaml/yaml.dart';
 
+const String _DART_COLON_PREFIX = 'dart:';
+
 /// Given a packageMap, check in each package's lib directory for the
 /// existence of an `_embedder.yaml` file. If the file contains a top level
 /// YamlMap, it will be added to the [embedderYamls] map.
@@ -79,7 +85,6 @@
     embedderYamls[libDir] = yaml;
   }
 
-
   /// Read the contents of [libDir]/[EMBEDDER_FILE_NAME] as a string.
   /// Returns null if the file doesn't exist.
   String _readEmbedderYaml(Folder libDir) {
@@ -104,14 +109,14 @@
 ///
 /// If a key doesn't begin with `dart:` it is ignored.
 ///
-class EmbedderUriResolver extends UriResolver {
-  static const String DART_COLON_PREFIX = 'dart:';
-
+class EmbedderUriResolver extends DartUriResolver {
   final Map<String, String> _urlMappings = <String, String>{};
 
   /// Construct a [EmbedderUriResolver] from a package map
   /// (see [PackageMapProvider]).
-  EmbedderUriResolver(Map<Folder, YamlMap> embedderYamls) {
+  EmbedderUriResolver(Map<Folder, YamlMap> embedderYamls)
+      : super(new EmbedderSdk()) {
+    (dartSdk as EmbedderSdk)._resolver = this;
     if (embedderYamls == null) {
       return;
     }
@@ -126,108 +131,159 @@
     if (embedder_libs is! YamlMap) {
       return;
     }
-    (embedder_libs as YamlMap).forEach((k, v) =>
-        _processEmbedderLibs(k, v, libDir));
+    (embedder_libs as YamlMap)
+        .forEach((k, v) => _processEmbedderLibs(k, v, libDir));
   }
 
   /// Install the mapping from [name] to [libDir]/[file].
   void _processEmbedderLibs(String name, String file, Folder libDir) {
-    if (!name.startsWith(DART_COLON_PREFIX)) {
+    if (!name.startsWith(_DART_COLON_PREFIX)) {
       // SDK libraries must begin with 'dart:'.
       // TODO(pquitslund): Notify developer that something is wrong with the
       // _embedder.yaml file in libDir.
       return;
     }
-    String key = name;
-    String value = libDir.canonicalizePath(file);
-    _urlMappings[key] = value;
+    String libPath = libDir.canonicalizePath(file);
+    _urlMappings[name] = libPath;
+    String shortName = name.substring(_DART_COLON_PREFIX.length);
+    SdkLibraryImpl library = new SdkLibraryImpl(shortName);
+    library.path = libPath;
+    (dartSdk as EmbedderSdk)._librariesMap.setLibrary(name, library);
   }
 
   /// Number of embedder libraries.
   int get length => _urlMappings.length;
 
-  /// Return the path mapping for [libName] or null if there is none.
-  String operator [](String libName) => _urlMappings[libName];
-
-  @override
-  Source resolveAbsolute(Uri importUri, [Uri actualUri]) {
-    String libraryName = _libraryName(importUri);
-    String partPath = _partPath(importUri);
-    // Lookup library name in mappings.
-    String mapping = _urlMappings[libraryName];
-    if (mapping == null) {
-      // Not found.
-      return null;
-    }
-    // This mapping points to the main entry file of the dart: library.
-    Uri libraryEntry = new Uri.file(mapping);
-    if (!libraryEntry.isAbsolute) {
-      // We expect an absolute path.
-      return null;
-    }
-
-    if (partPath != null) {
-      return _resolvePart(libraryEntry, partPath, importUri);
-    } else {
-      return _resolveEntry(libraryEntry, importUri);
-    }
-  }
-
   @override
   Uri restoreAbsolute(Source source) {
-    String extensionName = _findExtensionNameFor(source.fullName);
-    if (extensionName != null) {
-      return Uri.parse(extensionName);
-    }
-    // TODO(johnmccutchan): Handle restoring parts.
-    return null;
+    Source sdkSource = dartSdk.fromFileUri(Uri.parse(source.fullName));
+    return sdkSource?.uri;
   }
+}
 
-  /// Return the extension name for [fullName] or `null`.
-  String _findExtensionNameFor(String fullName) {
-    String result;
-    _urlMappings.forEach((extensionName, pathMapping) {
-      if (pathMapping == fullName) {
-        result = extensionName;
+class EmbedderSdk implements DartSdk {
+  // TODO(danrubel) Refactor this with DirectoryBasedDartSdk
+
+  /// The resolver associated with this embedder sdk.
+  EmbedderUriResolver _resolver;
+
+  /// The [AnalysisContext] which is used for all of the sources in this sdk.
+  InternalAnalysisContext _analysisContext;
+
+  /// The library map that is populated by visiting the AST structure parsed from
+  /// the contents of the libraries file.
+  final LibraryMap _librariesMap = new LibraryMap();
+
+  @override
+  AnalysisContext get context {
+    if (_analysisContext == null) {
+      _analysisContext = new SdkAnalysisContext();
+      SourceFactory factory = new SourceFactory([_resolver]);
+      _analysisContext.sourceFactory = factory;
+      List<String> uris = this.uris;
+      ChangeSet changeSet = new ChangeSet();
+      for (String uri in uris) {
+        changeSet.addedSource(factory.forUri(uri));
       }
-    });
-    return result;
-  }
-
-  /// Return the library name of [importUri].
-  String _libraryName(Uri importUri) {
-    String uri = importUri.toString();
-    int index = uri.indexOf('/');
-    if (index >= 0) {
-      return uri.substring(0, index);
+      _analysisContext.applyChanges(changeSet);
     }
-    return uri;
+    return _analysisContext;
   }
 
-  /// Return the part path of [importUri].
-  String _partPath(Uri importUri) {
-    String uri = importUri.toString();
-    int index = uri.indexOf('/');
-    if (index >= 0) {
-      return uri.substring(index + 1);
+  @override
+  List<SdkLibrary> get sdkLibraries => _librariesMap.sdkLibraries;
+
+  // TODO(danrubel) Determine SDK version
+  @override
+  String get sdkVersion => '0';
+
+  @override
+  List<String> get uris => _librariesMap.uris;
+
+  @override
+  Source fromFileUri(Uri uri) {
+    JavaFile file = new JavaFile.fromUri(uri);
+    String filePath = file.getAbsolutePath();
+
+    String path;
+    for (SdkLibrary library in _librariesMap.sdkLibraries) {
+      String libraryPath = library.path.replaceAll('/', JavaFile.separator);
+      if (filePath == libraryPath) {
+        path = '$_DART_COLON_PREFIX${library.shortName}';
+        break;
+      }
+    }
+    if (path == null) {
+      for (SdkLibrary library in _librariesMap.sdkLibraries) {
+        String libraryPath = library.path.replaceAll('/', JavaFile.separator);
+        int index = libraryPath.lastIndexOf(JavaFile.separator);
+        if (index == -1) {
+          continue;
+        }
+        String prefix = libraryPath.substring(0, index + 1);
+        if (!filePath.startsWith(prefix)) {
+          continue;
+        }
+        var relPath = filePath
+            .substring(prefix.length).replaceAll(JavaFile.separator, '/');
+        path = '$_DART_COLON_PREFIX${library.shortName}/$relPath';
+        break;
+      }
+    }
+
+    if (path != null) {
+      try {
+        return new FileBasedSource(file, parseUriWithException(path));
+      } on URISyntaxException catch (exception, stackTrace) {
+        AnalysisEngine.instance.logger.logInformation(
+            "Failed to create URI: $path",
+            new CaughtException(exception, stackTrace));
+        return null;
+      }
     }
     return null;
   }
 
-  /// Resolve an import of an sdk extension.
-  Source _resolveEntry(Uri libraryEntry, Uri importUri) {
-    // Library entry.
-    JavaFile javaFile = new JavaFile.fromUri(libraryEntry);
-    return new FileBasedSource(javaFile, importUri);
-  }
+  @override
+  SdkLibrary getSdkLibrary(String dartUri) => _librariesMap.getLibrary(dartUri);
 
-  /// Resolve a 'part' statement inside an sdk extension.
-  Source _resolvePart(Uri libraryEntry, String partPath, Uri importUri) {
-    // Library part.
-    String directory = pathos.dirname(libraryEntry.path);
-    Uri partUri = new Uri.file(pathos.join(directory, partPath));
-    assert(partUri.isAbsolute);
-    JavaFile javaFile = new JavaFile.fromUri(partUri);
-    return new FileBasedSource(javaFile, importUri);
+  @override
+  Source mapDartUri(String dartUri) {
+    String libraryName;
+    String relativePath;
+    int index = dartUri.indexOf('/');
+    if (index >= 0) {
+      libraryName = dartUri.substring(0, index);
+      relativePath = dartUri.substring(index + 1);
+    } else {
+      libraryName = dartUri;
+      relativePath = "";
+    }
+    SdkLibrary library = getSdkLibrary(libraryName);
+    if (library == null) {
+      return null;
+    }
+    String srcPath;
+    if (relativePath.isEmpty) {
+      srcPath = library.path;
+    } else {
+      String libraryPath = library.path;
+      int index = libraryPath.lastIndexOf(JavaFile.separator);
+      if (index == -1) {
+        index = libraryPath.lastIndexOf('/');
+        if (index == -1) {
+          return null;
+        }
+      }
+      String prefix = libraryPath.substring(0, index + 1);
+      srcPath = '$prefix$relativePath';
+    }
+    String filePath = srcPath.replaceAll('/', JavaFile.separator);
+    try {
+      JavaFile file = new JavaFile(filePath);
+      return new FileBasedSource(file, parseUriWithException(dartUri));
+    } on URISyntaxException {
+      return null;
+    }
   }
 }
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 4714557..09c35ac 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -7,14 +7,16 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/plugin/task.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -24,6 +26,7 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/dart_work_manager.dart';
@@ -185,6 +188,9 @@
    */
   List<AnalysisListener> _listeners = new List<AnalysisListener>();
 
+  @override
+  ResultProvider resultProvider;
+
   /**
    * The most recently incrementally resolved source, or `null` when it was
    * already validated, or the most recent change was not incrementally resolved.
@@ -459,13 +465,19 @@
     if (coreElement == null) {
       throw new AnalysisException("Could not create an element for dart:core");
     }
-    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-    if (asyncSource == null) {
-      throw new AnalysisException("Could not create a source for dart:async");
-    }
-    LibraryElement asyncElement = computeLibraryElement(asyncSource);
-    if (asyncElement == null) {
-      throw new AnalysisException("Could not create an element for dart:async");
+    LibraryElement asyncElement;
+    if (analysisOptions.enableAsync) {
+      Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+      if (asyncSource == null) {
+        throw new AnalysisException("Could not create a source for dart:async");
+      }
+      asyncElement = computeLibraryElement(asyncSource);
+      if (asyncElement == null) {
+        throw new AnalysisException(
+            "Could not create an element for dart:async");
+      }
+    } else {
+      asyncElement = createMockAsyncLib(coreElement);
     }
     _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     return _typeProvider;
@@ -489,26 +501,20 @@
   @override
   bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
     return PerformanceStatistics.summary.makeCurrentWhile(() {
-      AnalysisTarget target = entry.target;
-      // TYPE_PROVIDER
-      if (target is AnalysisContextTarget && result == TYPE_PROVIDER) {
-        DartSdk dartSdk = sourceFactory.dartSdk;
-        if (dartSdk != null) {
-          AnalysisContext sdkContext = dartSdk.context;
-          if (!identical(sdkContext, this) &&
-              sdkContext is InternalAnalysisContext) {
-            return sdkContext.aboutToComputeResult(entry, result);
-          }
+      // Use this helper if it is set.
+      if (resultProvider != null && resultProvider.compute(entry, result)) {
+        return true;
+      }
+      // Ask the SDK.
+      DartSdk dartSdk = sourceFactory.dartSdk;
+      if (dartSdk != null) {
+        AnalysisContext sdkContext = dartSdk.context;
+        if (!identical(sdkContext, this) &&
+            sdkContext is InternalAnalysisContext) {
+          return sdkContext.aboutToComputeResult(entry, result);
         }
       }
-      // A result for a Source.
-      Source source = target.source;
-      if (source != null) {
-        InternalAnalysisContext context = _cache.getContextFor(source);
-        if (!identical(context, this)) {
-          return context.aboutToComputeResult(entry, result);
-        }
-      }
+      // Cannot provide the result.
       return false;
     });
   }
@@ -640,8 +646,8 @@
   }
 
   @override
-  Object /*=V*/ computeResult /*<V>*/ (
-      AnalysisTarget target, ResultDescriptor /*<V>*/ descriptor) {
+  Object/*=V*/ computeResult/*<V>*/(
+      AnalysisTarget target, ResultDescriptor/*<V>*/ descriptor) {
     // Make sure we are not trying to invoke the task model in a reentrant
     // fashion.
     assert(!driver.isTaskRunning);
@@ -675,6 +681,54 @@
     ]);
   }
 
+  /**
+   * Create a minimalistic mock dart:async library
+   * to stand in for a real one if one does not exist
+   * facilitating creation a type provider without dart:async.
+   */
+  LibraryElement createMockAsyncLib(LibraryElement coreLibrary) {
+    InterfaceType objType = coreLibrary.getType('Object').type;
+
+    ClassElement _classElement(String typeName, [List<String> parameterNames]) {
+      ClassElementImpl element =
+          new ClassElementImpl.forNode(AstFactory.identifier3(typeName));
+      element.supertype = objType;
+      InterfaceTypeImpl type = new InterfaceTypeImpl(element);
+      element.type = type;
+      if (parameterNames != null) {
+        int count = parameterNames.length;
+        if (count > 0) {
+          List<TypeParameterElementImpl> typeParameters =
+              new List<TypeParameterElementImpl>(count);
+          List<TypeParameterTypeImpl> typeArguments =
+              new List<TypeParameterTypeImpl>(count);
+          for (int i = 0; i < count; i++) {
+            TypeParameterElementImpl typeParameter =
+                new TypeParameterElementImpl.forNode(
+                    AstFactory.identifier3(parameterNames[i]));
+            typeParameters[i] = typeParameter;
+            typeArguments[i] = new TypeParameterTypeImpl(typeParameter);
+            typeParameter.type = typeArguments[i];
+          }
+          element.typeParameters = typeParameters;
+          type.typeArguments = typeArguments;
+        }
+      }
+      return element;
+    }
+
+    InterfaceType futureType = _classElement('Future', ['T']).type;
+    InterfaceType streamType = _classElement('Stream', ['T']).type;
+    CompilationUnitElementImpl asyncUnit =
+        new CompilationUnitElementImpl("mock_async.dart");
+    asyncUnit.types = <ClassElement>[futureType.element, streamType.element];
+    LibraryElementImpl mockLib = new LibraryElementImpl.forNode(
+        this, AstFactory.libraryIdentifier2(["dart.async"]));
+    mockLib.definingCompilationUnit = asyncUnit;
+    mockLib.publicNamespace = new PublicNamespaceBuilder().build(mockLib);
+    return mockLib;
+  }
+
   @override
   void dispose() {
     _disposed = true;
@@ -2023,6 +2077,24 @@
 }
 
 /**
+ * Provider for analysis results.
+ */
+abstract class ResultProvider {
+  /**
+   * This method is invoked by an [InternalAnalysisContext] when the state of
+   * the [result] of the [entry] is [CacheState.INVALID], so it is about to be
+   * computed.
+   *
+   * If the provider knows how to provide the value, it sets the value into
+   * the [entry] with all required dependencies, and returns `true`.
+   *
+   * Otherwise, it returns `false` to indicate that the result should be
+   * computed as usually.
+   */
+  bool compute(CacheEntry entry, ResultDescriptor result);
+}
+
+/**
  * An [AnalysisContext] that only contains sources for a Dart SDK.
  */
 class SdkAnalysisContext extends AnalysisContextImpl {
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
new file mode 100644
index 0000000..26e3b76
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -0,0 +1,10805 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.dart.ast.ast;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
+import 'package:analyzer/src/generated/utilities_dart.dart';
+
+/**
+ * Two or more string literals that are implicitly concatenated because of being
+ * adjacent (separated only by whitespace).
+ *
+ * While the grammar only allows adjacent strings when all of the strings are of
+ * the same kind (single line or multi-line), this class doesn't enforce that
+ * restriction.
+ *
+ * > adjacentStrings ::=
+ * >     [StringLiteral] [StringLiteral]+
+ */
+class AdjacentStringsImpl extends StringLiteralImpl implements AdjacentStrings {
+  /**
+   * The strings that are implicitly concatenated.
+   */
+  NodeList<StringLiteral> _strings;
+
+  /**
+   * Initialize a newly created list of adjacent strings. To be syntactically
+   * valid, the list of [strings] must contain at least two elements.
+   */
+  AdjacentStringsImpl(List<StringLiteral> strings) {
+    _strings = new NodeList<StringLiteral>(this, strings);
+  }
+
+  @override
+  Token get beginToken => _strings.beginToken;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..addAll(_strings);
+
+  @override
+  Token get endToken => _strings.endToken;
+
+  @override
+  NodeList<StringLiteral> get strings => _strings;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitAdjacentStrings(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _strings.accept(visitor);
+  }
+
+  @override
+  void _appendStringValue(StringBuffer buffer) {
+    for (StringLiteralImpl stringLiteral in strings) {
+      stringLiteral._appendStringValue(buffer);
+    }
+  }
+}
+
+/**
+ * An AST node that can be annotated with both a documentation comment and a
+ * list of annotations.
+ */
+abstract class AnnotatedNodeImpl extends AstNodeImpl implements AnnotatedNode {
+  /**
+   * The documentation comment associated with this node, or `null` if this node
+   * does not have a documentation comment associated with it.
+   */
+  Comment _comment;
+
+  /**
+   * The annotations associated with this node.
+   */
+  NodeList<Annotation> _metadata;
+
+  /**
+   * Initialize a newly created annotated node. Either or both of the [comment]
+   * and [metadata] can be `null` if the node does not have the corresponding
+   * attribute.
+   */
+  AnnotatedNodeImpl(Comment comment, List<Annotation> metadata) {
+    _comment = _becomeParentOf(comment);
+    _metadata = new NodeList<Annotation>(this, metadata);
+  }
+
+  @override
+  Token get beginToken {
+    if (_comment == null) {
+      if (_metadata.isEmpty) {
+        return firstTokenAfterCommentAndMetadata;
+      }
+      return _metadata.beginToken;
+    } else if (_metadata.isEmpty) {
+      return _comment.beginToken;
+    }
+    Token commentToken = _comment.beginToken;
+    Token metadataToken = _metadata.beginToken;
+    if (commentToken.offset < metadataToken.offset) {
+      return commentToken;
+    }
+    return metadataToken;
+  }
+
+  @override
+  Comment get documentationComment => _comment;
+
+  @override
+  void set documentationComment(Comment comment) {
+    _comment = _becomeParentOf(comment);
+  }
+
+  @override
+  NodeList<Annotation> get metadata => _metadata;
+
+  @override
+  List<AstNode> get sortedCommentAndAnnotations {
+    return <AstNode>[]
+      ..add(_comment)
+      ..addAll(_metadata)
+      ..sort(AstNode.LEXICAL_ORDER);
+  }
+
+  /**
+   * Return a holder of child entities that subclasses can add to.
+   */
+  ChildEntities get _childEntities {
+    ChildEntities result = new ChildEntities();
+    if (_commentIsBeforeAnnotations()) {
+      result
+        ..add(_comment)
+        ..addAll(_metadata);
+    } else {
+      result.addAll(sortedCommentAndAnnotations);
+    }
+    return result;
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    if (_commentIsBeforeAnnotations()) {
+      _safelyVisitChild(_comment, visitor);
+      _metadata.accept(visitor);
+    } else {
+      for (AstNode child in sortedCommentAndAnnotations) {
+        child.accept(visitor);
+      }
+    }
+  }
+
+  /**
+   * Return `true` if there are no annotations before the comment. Note that a
+   * result of `true` does not imply that there is a comment, nor that there are
+   * annotations associated with this node.
+   */
+  bool _commentIsBeforeAnnotations() {
+    if (_comment == null || _metadata.isEmpty) {
+      return true;
+    }
+    Annotation firstAnnotation = _metadata[0];
+    return _comment.offset < firstAnnotation.offset;
+  }
+}
+
+/**
+ * An annotation that can be associated with an AST node.
+ *
+ * > metadata ::=
+ * >     annotation*
+ * >
+ * > annotation ::=
+ * >     '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
+ */
+class AnnotationImpl extends AstNodeImpl implements Annotation {
+  /**
+   * The at sign that introduced the annotation.
+   */
+  Token atSign;
+
+  /**
+   * The name of the class defining the constructor that is being invoked or the
+   * name of the field that is being referenced.
+   */
+  Identifier _name;
+
+  /**
+   * The period before the constructor name, or `null` if this annotation is not
+   * the invocation of a named constructor.
+   */
+  Token period;
+
+  /**
+   * The name of the constructor being invoked, or `null` if this annotation is
+   * not the invocation of a named constructor.
+   */
+  SimpleIdentifier _constructorName;
+
+  /**
+   * The arguments to the constructor being invoked, or `null` if this
+   * annotation is not the invocation of a constructor.
+   */
+  ArgumentList _arguments;
+
+  /**
+   * The element associated with this annotation, or `null` if the AST structure
+   * has not been resolved or if this annotation could not be resolved.
+   */
+  Element _element;
+
+  /**
+   * The element annotation representing this annotation in the element model.
+   */
+  ElementAnnotation elementAnnotation;
+
+  /**
+   * Initialize a newly created annotation. Both the [period] and the
+   * [constructorName] can be `null` if the annotation is not referencing a
+   * named constructor. The [arguments] can be `null` if the annotation is not
+   * referencing a constructor.
+   */
+  AnnotationImpl(this.atSign, Identifier name, this.period,
+      SimpleIdentifier constructorName, ArgumentList arguments) {
+    _name = _becomeParentOf(name);
+    _constructorName = _becomeParentOf(constructorName);
+    _arguments = _becomeParentOf(arguments);
+  }
+
+  @override
+  ArgumentList get arguments => _arguments;
+
+  @override
+  void set arguments(ArgumentList arguments) {
+    _arguments = _becomeParentOf(arguments);
+  }
+
+  @override
+  Token get beginToken => atSign;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(atSign)
+    ..add(_name)
+    ..add(period)
+    ..add(_constructorName)
+    ..add(_arguments);
+
+  @override
+  SimpleIdentifier get constructorName => _constructorName;
+
+  @override
+  void set constructorName(SimpleIdentifier name) {
+    _constructorName = _becomeParentOf(name);
+  }
+
+  @override
+  Element get element {
+    if (_element != null) {
+      return _element;
+    } else if (_name != null) {
+      return _name.staticElement;
+    }
+    return null;
+  }
+
+  @override
+  void set element(Element element) {
+    _element = element;
+  }
+
+  @override
+  Token get endToken {
+    if (_arguments != null) {
+      return _arguments.endToken;
+    } else if (_constructorName != null) {
+      return _constructorName.endToken;
+    }
+    return _name.endToken;
+  }
+
+  @override
+  Identifier get name => _name;
+
+  @override
+  void set name(Identifier name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitAnnotation(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_constructorName, visitor);
+    _safelyVisitChild(_arguments, visitor);
+  }
+}
+
+/**
+ * A list of arguments in the invocation of an executable element (that is, a
+ * function, method, or constructor).
+ *
+ * > argumentList ::=
+ * >     '(' arguments? ')'
+ * >
+ * > arguments ::=
+ * >     [NamedExpression] (',' [NamedExpression])*
+ * >   | [Expression] (',' [Expression])* (',' [NamedExpression])*
+ */
+class ArgumentListImpl extends AstNodeImpl implements ArgumentList {
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The expressions producing the values of the arguments.
+   */
+  NodeList<Expression> _arguments;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * A list containing the elements representing the parameters corresponding to
+   * each of the arguments in this list, or `null` if the AST has not been
+   * resolved or if the function or method being invoked could not be determined
+   * based on static type information. The list must be the same length as the
+   * number of arguments, but can contain `null` entries if a given argument
+   * does not correspond to a formal parameter.
+   */
+  List<ParameterElement> _correspondingStaticParameters;
+
+  /**
+   * A list containing the elements representing the parameters corresponding to
+   * each of the arguments in this list, or `null` if the AST has not been
+   * resolved or if the function or method being invoked could not be determined
+   * based on propagated type information. The list must be the same length as
+   * the number of arguments, but can contain `null` entries if a given argument
+   * does not correspond to a formal parameter.
+   */
+  List<ParameterElement> _correspondingPropagatedParameters;
+
+  /**
+   * Initialize a newly created list of arguments. The list of [arguments] can
+   * be `null` if there are no arguments.
+   */
+  ArgumentListImpl(
+      this.leftParenthesis, List<Expression> arguments, this.rightParenthesis) {
+    _arguments = new NodeList<Expression>(this, arguments);
+  }
+
+  @override
+  NodeList<Expression> get arguments => _arguments;
+
+  @override
+  Token get beginToken => leftParenthesis;
+
+  @override
+  // TODO(paulberry): Add commas.
+  Iterable get childEntities => new ChildEntities()
+    ..add(leftParenthesis)
+    ..addAll(_arguments)
+    ..add(rightParenthesis);
+
+  @override
+  void set correspondingPropagatedParameters(
+      List<ParameterElement> parameters) {
+    if (parameters.length != _arguments.length) {
+      throw new IllegalArgumentException(
+          "Expected ${_arguments.length} parameters, not ${parameters.length}");
+    }
+    _correspondingPropagatedParameters = parameters;
+  }
+
+  @override
+  void set correspondingStaticParameters(List<ParameterElement> parameters) {
+    if (parameters.length != _arguments.length) {
+      throw new IllegalArgumentException(
+          "Expected ${_arguments.length} parameters, not ${parameters.length}");
+    }
+    _correspondingStaticParameters = parameters;
+  }
+
+  @override
+  Token get endToken => rightParenthesis;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitArgumentList(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _arguments.accept(visitor);
+  }
+
+  /**
+   * If
+   * * the given [expression] is a child of this list,
+   * * the AST structure has been resolved,
+   * * the function being invoked is known based on propagated type information,
+   *   and
+   * * the expression corresponds to one of the parameters of the function being
+   *   invoked,
+   * then return the parameter element representing the parameter to which the
+   * value of the given expression will be bound. Otherwise, return `null`.
+   */
+  ParameterElement _getPropagatedParameterElementFor(Expression expression) {
+    if (_correspondingPropagatedParameters == null ||
+        _correspondingPropagatedParameters.length != _arguments.length) {
+      // Either the AST structure has not been resolved, the invocation of which
+      // this list is a part could not be resolved, or the argument list was
+      // modified after the parameters were set.
+      return null;
+    }
+    int index = _arguments.indexOf(expression);
+    if (index < 0) {
+      // The expression isn't a child of this node.
+      return null;
+    }
+    return _correspondingPropagatedParameters[index];
+  }
+
+  /**
+   * If
+   * * the given [expression] is a child of this list,
+   * * the AST structure has been resolved,
+   * * the function being invoked is known based on static type information, and
+   * * the expression corresponds to one of the parameters of the function being
+   *   invoked,
+   * then return the parameter element representing the parameter to which the
+   * value of the given expression will be bound. Otherwise, return `null`.
+   */
+  ParameterElement _getStaticParameterElementFor(Expression expression) {
+    if (_correspondingStaticParameters == null ||
+        _correspondingStaticParameters.length != _arguments.length) {
+      // Either the AST structure has not been resolved, the invocation of which
+      // this list is a part could not be resolved, or the argument list was
+      // modified after the parameters were set.
+      return null;
+    }
+    int index = _arguments.indexOf(expression);
+    if (index < 0) {
+      // The expression isn't a child of this node.
+      return null;
+    }
+    return _correspondingStaticParameters[index];
+  }
+}
+
+/**
+ * An as expression.
+ *
+ * > asExpression ::=
+ * >     [Expression] 'as' [TypeName]
+ */
+class AsExpressionImpl extends ExpressionImpl implements AsExpression {
+  /**
+   * The expression used to compute the value being cast.
+   */
+  Expression _expression;
+
+  /**
+   * The 'as' operator.
+   */
+  Token asOperator;
+
+  /**
+   * The name of the type being cast to.
+   */
+  TypeName _type;
+
+  /**
+   * Initialize a newly created as expression.
+   */
+  AsExpressionImpl(Expression expression, this.asOperator, TypeName type) {
+    _expression = _becomeParentOf(expression);
+    _type = _becomeParentOf(type);
+  }
+
+  @override
+  Token get beginToken => _expression.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_expression)..add(asOperator)..add(_type);
+
+  @override
+  Token get endToken => _type.endToken;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 7;
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName name) {
+    _type = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitAsExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+    _safelyVisitChild(_type, visitor);
+  }
+}
+
+/**
+ * An assert statement.
+ *
+ * > assertStatement ::=
+ * >     'assert' '(' [Expression] ')' ';'
+ */
+class AssertStatementImpl extends StatementImpl implements AssertStatement {
+  /**
+   * The token representing the 'assert' keyword.
+   */
+  Token assertKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The condition that is being asserted to be `true`.
+   */
+  Expression _condition;
+
+  /**
+   * The comma, if a message expression was supplied.  Otherwise `null`.
+   */
+  Token comma;
+
+  /**
+   * The message to report if the assertion fails.  `null` if no message was
+   * supplied.
+   */
+  Expression _message;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created assert statement.
+   */
+  AssertStatementImpl(
+      this.assertKeyword,
+      this.leftParenthesis,
+      Expression condition,
+      this.comma,
+      Expression message,
+      this.rightParenthesis,
+      this.semicolon) {
+    _condition = _becomeParentOf(condition);
+    _message = _becomeParentOf(message);
+  }
+
+  @override
+  Token get beginToken => assertKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(assertKeyword)
+    ..add(leftParenthesis)
+    ..add(_condition)
+    ..add(comma)
+    ..add(_message)
+    ..add(rightParenthesis)
+    ..add(semicolon);
+
+  @override
+  Expression get condition => _condition;
+
+  @override
+  void set condition(Expression condition) {
+    _condition = _becomeParentOf(condition);
+  }
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Expression get message => _message;
+
+  @override
+  void set message(Expression expression) {
+    _message = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitAssertStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_condition, visitor);
+    _safelyVisitChild(message, visitor);
+  }
+}
+
+/**
+ * An assignment expression.
+ *
+ * > assignmentExpression ::=
+ * >     [Expression] operator [Expression]
+ */
+class AssignmentExpressionImpl extends ExpressionImpl
+    implements AssignmentExpression {
+  /**
+   * The expression used to compute the left hand side.
+   */
+  Expression _leftHandSide;
+
+  /**
+   * The assignment operator being applied.
+   */
+  Token operator;
+
+  /**
+   * The expression used to compute the right hand side.
+   */
+  Expression _rightHandSide;
+
+  /**
+   * The element associated with the operator based on the static type of the
+   * left-hand-side, or `null` if the AST structure has not been resolved, if
+   * the operator is not a compound operator, or if the operator could not be
+   * resolved.
+   */
+  MethodElement staticElement;
+
+  /**
+   * The element associated with the operator based on the propagated type of
+   * the left-hand-side, or `null` if the AST structure has not been resolved,
+   * if the operator is not a compound operator, or if the operator could not be
+   * resolved.
+   */
+  MethodElement propagatedElement;
+
+  /**
+   * Initialize a newly created assignment expression.
+   */
+  AssignmentExpressionImpl(
+      Expression leftHandSide, this.operator, Expression rightHandSide) {
+    if (leftHandSide == null || rightHandSide == null) {
+      String message;
+      if (leftHandSide == null) {
+        if (rightHandSide == null) {
+          message = "Both the left-hand and right-hand sides are null";
+        } else {
+          message = "The left-hand size is null";
+        }
+      } else {
+        message = "The right-hand size is null";
+      }
+      AnalysisEngine.instance.logger.logError(
+          message, new CaughtException(new AnalysisException(message), null));
+    }
+    _leftHandSide = _becomeParentOf(leftHandSide);
+    _rightHandSide = _becomeParentOf(rightHandSide);
+  }
+
+  @override
+  Token get beginToken => _leftHandSide.beginToken;
+
+  @override
+  MethodElement get bestElement {
+    MethodElement element = propagatedElement;
+    if (element == null) {
+      element = staticElement;
+    }
+    return element;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(_leftHandSide)
+    ..add(operator)
+    ..add(_rightHandSide);
+
+  @override
+  Token get endToken => _rightHandSide.endToken;
+
+  @override
+  Expression get leftHandSide => _leftHandSide;
+
+  @override
+  void set leftHandSide(Expression expression) {
+    _leftHandSide = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 1;
+
+  @override
+  Expression get rightHandSide => _rightHandSide;
+
+  @override
+  void set rightHandSide(Expression expression) {
+    _rightHandSide = _becomeParentOf(expression);
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on propagated type information, then return the parameter
+   * element representing the parameter to which the value of the right operand
+   * will be bound. Otherwise, return `null`.
+   */
+  ParameterElement get _propagatedParameterElementForRightHandSide {
+    ExecutableElement executableElement = null;
+    if (propagatedElement != null) {
+      executableElement = propagatedElement;
+    } else {
+      if (_leftHandSide is Identifier) {
+        Identifier identifier = _leftHandSide as Identifier;
+        Element leftElement = identifier.propagatedElement;
+        if (leftElement is ExecutableElement) {
+          executableElement = leftElement;
+        }
+      }
+      if (_leftHandSide is PropertyAccess) {
+        SimpleIdentifier identifier =
+            (_leftHandSide as PropertyAccess).propertyName;
+        Element leftElement = identifier.propagatedElement;
+        if (leftElement is ExecutableElement) {
+          executableElement = leftElement;
+        }
+      }
+    }
+    if (executableElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = executableElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on static type information, then return the parameter element
+   * representing the parameter to which the value of the right operand will be
+   * bound. Otherwise, return `null`.
+   */
+  ParameterElement get _staticParameterElementForRightHandSide {
+    ExecutableElement executableElement = null;
+    if (staticElement != null) {
+      executableElement = staticElement;
+    } else {
+      if (_leftHandSide is Identifier) {
+        Element leftElement = (_leftHandSide as Identifier).staticElement;
+        if (leftElement is ExecutableElement) {
+          executableElement = leftElement;
+        }
+      }
+      if (_leftHandSide is PropertyAccess) {
+        Element leftElement =
+            (_leftHandSide as PropertyAccess).propertyName.staticElement;
+        if (leftElement is ExecutableElement) {
+          executableElement = leftElement;
+        }
+      }
+    }
+    if (executableElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = executableElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitAssignmentExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_leftHandSide, visitor);
+    _safelyVisitChild(_rightHandSide, visitor);
+  }
+}
+
+/**
+ * A node in the AST structure for a Dart program.
+ */
+abstract class AstNodeImpl implements AstNode {
+  /**
+   * The parent of the node, or `null` if the node is the root of an AST
+   * structure.
+   */
+  AstNode _parent;
+
+  /**
+   * A table mapping the names of properties to their values, or `null` if this
+   * node does not have any properties associated with it.
+   */
+  Map<String, Object> _propertyMap;
+
+  @override
+  int get end => offset + length;
+
+  @override
+  bool get isSynthetic => false;
+
+  @override
+  int get length {
+    Token beginToken = this.beginToken;
+    Token endToken = this.endToken;
+    if (beginToken == null || endToken == null) {
+      return -1;
+    }
+    return endToken.offset + endToken.length - beginToken.offset;
+  }
+
+  @override
+  int get offset {
+    Token beginToken = this.beginToken;
+    if (beginToken == null) {
+      return -1;
+    }
+    return beginToken.offset;
+  }
+
+  @override
+  AstNode get parent => _parent;
+
+  @override
+  AstNode get root {
+    AstNode root = this;
+    AstNode parent = this.parent;
+    while (parent != null) {
+      root = parent;
+      parent = root.parent;
+    }
+    return root;
+  }
+
+  @override
+  AstNode getAncestor(Predicate<AstNode> predicate) {
+    // TODO(brianwilkerson) It is a bug that this method can return `this`.
+    AstNode node = this;
+    while (node != null && !predicate(node)) {
+      node = node.parent;
+    }
+    return node;
+  }
+
+  @override
+  Object getProperty(String name) {
+    if (_propertyMap == null) {
+      return null;
+    }
+    return _propertyMap[name];
+  }
+
+  @override
+  void setProperty(String name, Object value) {
+    if (value == null) {
+      if (_propertyMap != null) {
+        _propertyMap.remove(name);
+        if (_propertyMap.isEmpty) {
+          _propertyMap = null;
+        }
+      }
+    } else {
+      if (_propertyMap == null) {
+        _propertyMap = new HashMap<String, Object>();
+      }
+      _propertyMap[name] = value;
+    }
+  }
+
+  @override
+  String toSource() {
+    PrintStringWriter writer = new PrintStringWriter();
+    accept(new ToSourceVisitor(writer));
+    return writer.toString();
+  }
+
+  @override
+  String toString() => toSource();
+
+  /**
+   * Make this node the parent of the given [child] node. Return the child node.
+   */
+  AstNode _becomeParentOf(AstNode child) {
+    if (child != null) {
+      (child as AstNodeImpl)._parent = this;
+    }
+    return child;
+  }
+
+  /**
+   * If the given [child] is not `null`, use the given [visitor] to visit it.
+   */
+  void _safelyVisitChild(AstNode child, AstVisitor visitor) {
+    if (child != null) {
+      child.accept(visitor);
+    }
+  }
+}
+
+/**
+ * An await expression.
+ *
+ * > awaitExpression ::=
+ * >     'await' [Expression]
+ */
+class AwaitExpressionImpl extends ExpressionImpl implements AwaitExpression {
+  /**
+   * The 'await' keyword.
+   */
+  Token awaitKeyword;
+
+  /**
+   * The expression whose value is being waited on.
+   */
+  Expression _expression;
+
+  /**
+   * Initialize a newly created await expression.
+   */
+  AwaitExpressionImpl(this.awaitKeyword, Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken {
+    if (awaitKeyword != null) {
+      return awaitKeyword;
+    }
+    return _expression.beginToken;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(awaitKeyword)..add(_expression);
+
+  @override
+  Token get endToken => _expression.endToken;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 0;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitAwaitExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A binary (infix) expression.
+ *
+ * > binaryExpression ::=
+ * >     [Expression] [Token] [Expression]
+ */
+class BinaryExpressionImpl extends ExpressionImpl implements BinaryExpression {
+  /**
+   * The expression used to compute the left operand.
+   */
+  Expression _leftOperand;
+
+  /**
+   * The binary operator being applied.
+   */
+  Token operator;
+
+  /**
+   * The expression used to compute the right operand.
+   */
+  Expression _rightOperand;
+
+  /**
+   * The element associated with the operator based on the static type of the
+   * left operand, or `null` if the AST structure has not been resolved, if the
+   * operator is not user definable, or if the operator could not be resolved.
+   */
+  MethodElement staticElement;
+
+  /**
+   * The element associated with the operator based on the propagated type of
+   * the left operand, or `null` if the AST structure has not been resolved, if
+   * the operator is not user definable, or if the operator could not be
+   * resolved.
+   */
+  MethodElement propagatedElement;
+
+  /**
+   * Initialize a newly created binary expression.
+   */
+  BinaryExpressionImpl(
+      Expression leftOperand, this.operator, Expression rightOperand) {
+    _leftOperand = _becomeParentOf(leftOperand);
+    _rightOperand = _becomeParentOf(rightOperand);
+  }
+
+  @override
+  Token get beginToken => _leftOperand.beginToken;
+
+  @override
+  MethodElement get bestElement {
+    MethodElement element = propagatedElement;
+    if (element == null) {
+      element = staticElement;
+    }
+    return element;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_leftOperand)..add(operator)..add(_rightOperand);
+
+  @override
+  Token get endToken => _rightOperand.endToken;
+
+  @override
+  Expression get leftOperand => _leftOperand;
+
+  @override
+  void set leftOperand(Expression expression) {
+    _leftOperand = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => operator.type.precedence;
+
+  @override
+  Expression get rightOperand => _rightOperand;
+
+  @override
+  void set rightOperand(Expression expression) {
+    _rightOperand = _becomeParentOf(expression);
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on propagated type information, then return the parameter
+   * element representing the parameter to which the value of the right operand
+   * will be bound. Otherwise, return `null`.
+   */
+  ParameterElement get _propagatedParameterElementForRightOperand {
+    if (propagatedElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = propagatedElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on static type information, then return the parameter element
+   * representing the parameter to which the value of the right operand will be
+   * bound. Otherwise, return `null`.
+   */
+  ParameterElement get _staticParameterElementForRightOperand {
+    if (staticElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = staticElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitBinaryExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_leftOperand, visitor);
+    _safelyVisitChild(_rightOperand, visitor);
+  }
+}
+
+/**
+ * A function body that consists of a block of statements.
+ *
+ * > blockFunctionBody ::=
+ * >     ('async' | 'async' '*' | 'sync' '*')? [Block]
+ */
+class BlockFunctionBodyImpl extends FunctionBodyImpl
+    implements BlockFunctionBody {
+  /**
+   * The token representing the 'async' or 'sync' keyword, or `null` if there is
+   * no such keyword.
+   */
+  Token keyword;
+
+  /**
+   * The star optionally following the 'async' or 'sync' keyword, or `null` if
+   * there is wither no such keyword or no star.
+   */
+  Token star;
+
+  /**
+   * The block representing the body of the function.
+   */
+  Block _block;
+
+  /**
+   * Initialize a newly created function body consisting of a block of
+   * statements. The [keyword] can be `null` if there is no keyword specified
+   * for the block. The [star] can be `null` if there is no star following the
+   * keyword (and must be `null` if there is no keyword).
+   */
+  BlockFunctionBodyImpl(this.keyword, this.star, Block block) {
+    _block = _becomeParentOf(block);
+  }
+
+  @override
+  Token get beginToken {
+    if (keyword != null) {
+      return keyword;
+    }
+    return _block.beginToken;
+  }
+
+  @override
+  Block get block => _block;
+
+  @override
+  void set block(Block block) {
+    _block = _becomeParentOf(block);
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(keyword)..add(star)..add(_block);
+
+  @override
+  Token get endToken => _block.endToken;
+
+  @override
+  bool get isAsynchronous => keyword != null && keyword.lexeme == Parser.ASYNC;
+
+  @override
+  bool get isGenerator => star != null;
+
+  @override
+  bool get isSynchronous => keyword == null || keyword.lexeme != Parser.ASYNC;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitBlockFunctionBody(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_block, visitor);
+  }
+}
+
+/**
+ * A sequence of statements.
+ *
+ * > block ::=
+ * >     '{' statement* '}'
+ */
+class BlockImpl extends StatementImpl implements Block {
+  /**
+   * The left curly bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The statements contained in the block.
+   */
+  NodeList<Statement> _statements;
+
+  /**
+   * The right curly bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created block of code.
+   */
+  BlockImpl(this.leftBracket, List<Statement> statements, this.rightBracket) {
+    _statements = new NodeList<Statement>(this, statements);
+  }
+
+  @override
+  Token get beginToken => leftBracket;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(leftBracket)
+    ..addAll(_statements)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  NodeList<Statement> get statements => _statements;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitBlock(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _statements.accept(visitor);
+  }
+}
+
+/**
+ * A boolean literal expression.
+ *
+ * > booleanLiteral ::=
+ * >     'false' | 'true'
+ */
+class BooleanLiteralImpl extends LiteralImpl implements BooleanLiteral {
+  /**
+   * The token representing the literal.
+   */
+  Token literal;
+
+  /**
+   * The value of the literal.
+   */
+  bool value = false;
+
+  /**
+   * Initialize a newly created boolean literal.
+   */
+  BooleanLiteralImpl(this.literal, this.value);
+
+  @override
+  Token get beginToken => literal;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(literal);
+
+  @override
+  Token get endToken => literal;
+
+  @override
+  bool get isSynthetic => literal.isSynthetic;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitBooleanLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A break statement.
+ *
+ * > breakStatement ::=
+ * >     'break' [SimpleIdentifier]? ';'
+ */
+class BreakStatementImpl extends StatementImpl implements BreakStatement {
+  /**
+   * The token representing the 'break' keyword.
+   */
+  Token breakKeyword;
+
+  /**
+   * The label associated with the statement, or `null` if there is no label.
+   */
+  SimpleIdentifier _label;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * The AstNode which this break statement is breaking from.  This will be
+   * either a [Statement] (in the case of breaking out of a loop), a
+   * [SwitchMember] (in the case of a labeled break statement whose label
+   * matches a label on a switch case in an enclosing switch statement), or
+   * `null` if the AST has not yet been resolved or if the target could not be
+   * resolved. Note that if the source code has errors, the target might be
+   * invalid (e.g. trying to break to a switch case).
+   */
+  AstNode target;
+
+  /**
+   * Initialize a newly created break statement. The [label] can be `null` if
+   * there is no label associated with the statement.
+   */
+  BreakStatementImpl(
+      this.breakKeyword, SimpleIdentifier label, this.semicolon) {
+    _label = _becomeParentOf(label);
+  }
+
+  @override
+  Token get beginToken => breakKeyword;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(breakKeyword)..add(_label)..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  SimpleIdentifier get label => _label;
+
+  @override
+  void set label(SimpleIdentifier identifier) {
+    _label = _becomeParentOf(identifier);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitBreakStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_label, visitor);
+  }
+}
+
+/**
+ * A sequence of cascaded expressions: expressions that share a common target.
+ * There are three kinds of expressions that can be used in a cascade
+ * expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
+ *
+ * > cascadeExpression ::=
+ * >     [Expression] cascadeSection*
+ * >
+ * > cascadeSection ::=
+ * >     '..'  (cascadeSelector arguments*) (assignableSelector arguments*)*
+ * >     (assignmentOperator expressionWithoutCascade)?
+ * >
+ * > cascadeSelector ::=
+ * >     '[ ' expression '] '
+ * >   | identifier
+ */
+class CascadeExpressionImpl extends ExpressionImpl
+    implements CascadeExpression {
+  /**
+   * The target of the cascade sections.
+   */
+  Expression _target;
+
+  /**
+   * The cascade sections sharing the common target.
+   */
+  NodeList<Expression> _cascadeSections;
+
+  /**
+   * Initialize a newly created cascade expression. The list of
+   * [cascadeSections] must contain at least one element.
+   */
+  CascadeExpressionImpl(Expression target, List<Expression> cascadeSections) {
+    _target = _becomeParentOf(target);
+    _cascadeSections = new NodeList<Expression>(this, cascadeSections);
+  }
+
+  @override
+  Token get beginToken => _target.beginToken;
+
+  @override
+  NodeList<Expression> get cascadeSections => _cascadeSections;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(_target)
+    ..addAll(_cascadeSections);
+
+  @override
+  Token get endToken => _cascadeSections.endToken;
+
+  @override
+  int get precedence => 2;
+
+  @override
+  Expression get target => _target;
+
+  @override
+  void set target(Expression target) {
+    _target = _becomeParentOf(target);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitCascadeExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_target, visitor);
+    _cascadeSections.accept(visitor);
+  }
+}
+
+/**
+ * A catch clause within a try statement.
+ *
+ * > onPart ::=
+ * >     catchPart [Block]
+ * >   | 'on' type catchPart? [Block]
+ * >
+ * > catchPart ::=
+ * >     'catch' '(' [SimpleIdentifier] (',' [SimpleIdentifier])? ')'
+ */
+class CatchClauseImpl extends AstNodeImpl implements CatchClause {
+  /**
+   * The token representing the 'on' keyword, or `null` if there is no 'on'
+   * keyword.
+   */
+  Token onKeyword;
+
+  /**
+   * The type of exceptions caught by this catch clause, or `null` if this catch
+   * clause catches every type of exception.
+   */
+  TypeName _exceptionType;
+
+  /**
+   * The token representing the 'catch' keyword, or `null` if there is no
+   * 'catch' keyword.
+   */
+  Token catchKeyword;
+
+  /**
+   * The left parenthesis, or `null` if there is no 'catch' keyword.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The parameter whose value will be the exception that was thrown, or `null`
+   * if there is no 'catch' keyword.
+   */
+  SimpleIdentifier _exceptionParameter;
+
+  /**
+   * The comma separating the exception parameter from the stack trace
+   * parameter, or `null` if there is no stack trace parameter.
+   */
+  Token comma;
+
+  /**
+   * The parameter whose value will be the stack trace associated with the
+   * exception, or `null` if there is no stack trace parameter.
+   */
+  SimpleIdentifier _stackTraceParameter;
+
+  /**
+   * The right parenthesis, or `null` if there is no 'catch' keyword.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The body of the catch block.
+   */
+  Block _body;
+
+  /**
+   * Initialize a newly created catch clause. The [onKeyword] and
+   * [exceptionType] can be `null` if the clause will catch all exceptions. The
+   * [comma] and [stackTraceParameter] can be `null` if the stack trace
+   * parameter is not defined.
+   */
+  CatchClauseImpl(
+      this.onKeyword,
+      TypeName exceptionType,
+      this.catchKeyword,
+      this.leftParenthesis,
+      SimpleIdentifier exceptionParameter,
+      this.comma,
+      SimpleIdentifier stackTraceParameter,
+      this.rightParenthesis,
+      Block body) {
+    _exceptionType = _becomeParentOf(exceptionType);
+    _exceptionParameter = _becomeParentOf(exceptionParameter);
+    _stackTraceParameter = _becomeParentOf(stackTraceParameter);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  Token get beginToken {
+    if (onKeyword != null) {
+      return onKeyword;
+    }
+    return catchKeyword;
+  }
+
+  @override
+  Block get body => _body;
+
+  @override
+  void set body(Block block) {
+    _body = _becomeParentOf(block);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(onKeyword)
+    ..add(_exceptionType)
+    ..add(catchKeyword)
+    ..add(leftParenthesis)
+    ..add(_exceptionParameter)
+    ..add(comma)
+    ..add(_stackTraceParameter)
+    ..add(rightParenthesis)
+    ..add(_body);
+
+  @override
+  Token get endToken => _body.endToken;
+
+  @override
+  SimpleIdentifier get exceptionParameter => _exceptionParameter;
+
+  @override
+  void set exceptionParameter(SimpleIdentifier parameter) {
+    _exceptionParameter = _becomeParentOf(parameter);
+  }
+
+  @override
+  TypeName get exceptionType => _exceptionType;
+
+  @override
+  void set exceptionType(TypeName exceptionType) {
+    _exceptionType = _becomeParentOf(exceptionType);
+  }
+
+  @override
+  SimpleIdentifier get stackTraceParameter => _stackTraceParameter;
+
+  @override
+  void set stackTraceParameter(SimpleIdentifier parameter) {
+    _stackTraceParameter = _becomeParentOf(parameter);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitCatchClause(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_exceptionType, visitor);
+    _safelyVisitChild(_exceptionParameter, visitor);
+    _safelyVisitChild(_stackTraceParameter, visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * Helper class to allow iteration of child entities of an AST node.
+ */
+class ChildEntities extends Object with IterableMixin implements Iterable {
+  /**
+   * The list of child entities to be iterated over.
+   */
+  List _entities = [];
+
+  @override
+  Iterator get iterator => _entities.iterator;
+
+  /**
+   * Add an AST node or token as the next child entity, if it is not null.
+   */
+  void add(entity) {
+    if (entity != null) {
+      assert(entity is Token || entity is AstNode);
+      _entities.add(entity);
+    }
+  }
+
+  /**
+   * Add the given items as the next child entities, if [items] is not null.
+   */
+  void addAll(Iterable items) {
+    if (items != null) {
+      _entities.addAll(items);
+    }
+  }
+}
+
+/**
+ * The declaration of a class.
+ *
+ * > classDeclaration ::=
+ * >     'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]?
+ * >     ([ExtendsClause] [WithClause]?)?
+ * >     [ImplementsClause]?
+ * >     '{' [ClassMember]* '}'
+ */
+class ClassDeclarationImpl extends NamedCompilationUnitMemberImpl
+    implements ClassDeclaration {
+  /**
+   * The 'abstract' keyword, or `null` if the keyword was absent.
+   */
+  Token abstractKeyword;
+
+  /**
+   * The token representing the 'class' keyword.
+   */
+  Token classKeyword;
+
+  /**
+   * The type parameters for the class, or `null` if the class does not have any
+   * type parameters.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The extends clause for the class, or `null` if the class does not extend
+   * any other class.
+   */
+  ExtendsClause _extendsClause;
+
+  /**
+   * The with clause for the class, or `null` if the class does not have a with
+   * clause.
+   */
+  WithClause _withClause;
+
+  /**
+   * The implements clause for the class, or `null` if the class does not
+   * implement any interfaces.
+   */
+  ImplementsClause _implementsClause;
+
+  /**
+   * The native clause for the class, or `null` if the class does not have a
+   * native clause.
+   */
+  NativeClause _nativeClause;
+
+  /**
+   * The left curly bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The members defined by the class.
+   */
+  NodeList<ClassMember> _members;
+
+  /**
+   * The right curly bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created class declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the class does not have the
+   * corresponding attribute. The [abstractKeyword] can be `null` if the class
+   * is not abstract. The [typeParameters] can be `null` if the class does not
+   * have any type parameters. Any or all of the [extendsClause], [withClause],
+   * and [implementsClause] can be `null` if the class does not have the
+   * corresponding clause. The list of [members] can be `null` if the class does
+   * not have any members.
+   */
+  ClassDeclarationImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.abstractKeyword,
+      this.classKeyword,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      ExtendsClause extendsClause,
+      WithClause withClause,
+      ImplementsClause implementsClause,
+      this.leftBracket,
+      List<ClassMember> members,
+      this.rightBracket)
+      : super(comment, metadata, name) {
+    _typeParameters = _becomeParentOf(typeParameters);
+    _extendsClause = _becomeParentOf(extendsClause);
+    _withClause = _becomeParentOf(withClause);
+    _implementsClause = _becomeParentOf(implementsClause);
+    _members = new NodeList<ClassMember>(this, members);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(abstractKeyword)
+    ..add(classKeyword)
+    ..add(_name)
+    ..add(_typeParameters)
+    ..add(_extendsClause)
+    ..add(_withClause)
+    ..add(_implementsClause)
+    ..add(_nativeClause)
+    ..add(leftBracket)
+    ..addAll(members)
+    ..add(rightBracket);
+
+  @override
+  ClassElement get element =>
+      _name != null ? (_name.staticElement as ClassElement) : null;
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  ExtendsClause get extendsClause => _extendsClause;
+
+  @override
+  void set extendsClause(ExtendsClause extendsClause) {
+    _extendsClause = _becomeParentOf(extendsClause);
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    if (abstractKeyword != null) {
+      return abstractKeyword;
+    }
+    return classKeyword;
+  }
+
+  @override
+  ImplementsClause get implementsClause => _implementsClause;
+
+  @override
+  void set implementsClause(ImplementsClause implementsClause) {
+    _implementsClause = _becomeParentOf(implementsClause);
+  }
+
+  @override
+  bool get isAbstract => abstractKeyword != null;
+
+  @override
+  NodeList<ClassMember> get members => _members;
+
+  @override
+  NativeClause get nativeClause => _nativeClause;
+
+  @override
+  void set nativeClause(NativeClause nativeClause) {
+    _nativeClause = _becomeParentOf(nativeClause);
+  }
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  WithClause get withClause => _withClause;
+
+  @override
+  void set withClause(WithClause withClause) {
+    _withClause = _becomeParentOf(withClause);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitClassDeclaration(this);
+
+  @override
+  ConstructorDeclaration getConstructor(String name) {
+    for (ClassMember classMember in _members) {
+      if (classMember is ConstructorDeclaration) {
+        ConstructorDeclaration constructor = classMember;
+        SimpleIdentifier constructorName = constructor.name;
+        if (name == null && constructorName == null) {
+          return constructor;
+        }
+        if (constructorName != null && constructorName.name == name) {
+          return constructor;
+        }
+      }
+    }
+    return null;
+  }
+
+  @override
+  VariableDeclaration getField(String name) {
+    for (ClassMember classMember in _members) {
+      if (classMember is FieldDeclaration) {
+        FieldDeclaration fieldDeclaration = classMember;
+        NodeList<VariableDeclaration> fields =
+            fieldDeclaration.fields.variables;
+        for (VariableDeclaration field in fields) {
+          SimpleIdentifier fieldName = field.name;
+          if (fieldName != null && name == fieldName.name) {
+            return field;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @override
+  MethodDeclaration getMethod(String name) {
+    for (ClassMember classMember in _members) {
+      if (classMember is MethodDeclaration) {
+        MethodDeclaration method = classMember;
+        SimpleIdentifier methodName = method.name;
+        if (methodName != null && name == methodName.name) {
+          return method;
+        }
+      }
+    }
+    return null;
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_extendsClause, visitor);
+    _safelyVisitChild(_withClause, visitor);
+    _safelyVisitChild(_implementsClause, visitor);
+    _safelyVisitChild(_nativeClause, visitor);
+    members.accept(visitor);
+  }
+}
+
+/**
+ * A node that declares a name within the scope of a class.
+ */
+abstract class ClassMemberImpl extends DeclarationImpl implements ClassMember {
+  /**
+   * Initialize a newly created member of a class. Either or both of the
+   * [comment] and [metadata] can be `null` if the member does not have the
+   * corresponding attribute.
+   */
+  ClassMemberImpl(Comment comment, List<Annotation> metadata)
+      : super(comment, metadata);
+}
+
+/**
+ * A class type alias.
+ *
+ * > classTypeAlias ::=
+ * >     [SimpleIdentifier] [TypeParameterList]? '=' 'abstract'? mixinApplication
+ * >
+ * > mixinApplication ::=
+ * >     [TypeName] [WithClause] [ImplementsClause]? ';'
+ */
+class ClassTypeAliasImpl extends TypeAliasImpl implements ClassTypeAlias {
+  /**
+   * The type parameters for the class, or `null` if the class does not have any
+   * type parameters.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The token for the '=' separating the name from the definition.
+   */
+  Token equals;
+
+  /**
+   * The token for the 'abstract' keyword, or `null` if this is not defining an
+   * abstract class.
+   */
+  Token abstractKeyword;
+
+  /**
+   * The name of the superclass of the class being declared.
+   */
+  TypeName _superclass;
+
+  /**
+   * The with clause for this class.
+   */
+  WithClause _withClause;
+
+  /**
+   * The implements clause for this class, or `null` if there is no implements
+   * clause.
+   */
+  ImplementsClause _implementsClause;
+
+  /**
+   * Initialize a newly created class type alias. Either or both of the
+   * [comment] and [metadata] can be `null` if the class type alias does not
+   * have the corresponding attribute. The [typeParameters] can be `null` if the
+   * class does not have any type parameters. The [abstractKeyword] can be
+   * `null` if the class is not abstract. The [implementsClause] can be `null`
+   * if the class does not implement any interfaces.
+   */
+  ClassTypeAliasImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      this.equals,
+      this.abstractKeyword,
+      TypeName superclass,
+      WithClause withClause,
+      ImplementsClause implementsClause,
+      Token semicolon)
+      : super(comment, metadata, keyword, name, semicolon) {
+    _typeParameters = _becomeParentOf(typeParameters);
+    _superclass = _becomeParentOf(superclass);
+    _withClause = _becomeParentOf(withClause);
+    _implementsClause = _becomeParentOf(implementsClause);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(typedefKeyword)
+    ..add(_name)
+    ..add(_typeParameters)
+    ..add(equals)
+    ..add(abstractKeyword)
+    ..add(_superclass)
+    ..add(_withClause)
+    ..add(_implementsClause)
+    ..add(semicolon);
+
+  @override
+  ClassElement get element =>
+      _name != null ? (_name.staticElement as ClassElement) : null;
+
+  @override
+  ImplementsClause get implementsClause => _implementsClause;
+
+  @override
+  void set implementsClause(ImplementsClause implementsClause) {
+    _implementsClause = _becomeParentOf(implementsClause);
+  }
+
+  @override
+  bool get isAbstract => abstractKeyword != null;
+
+  @override
+  TypeName get superclass => _superclass;
+
+  @override
+  void set superclass(TypeName superclass) {
+    _superclass = _becomeParentOf(superclass);
+  }
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  WithClause get withClause => _withClause;
+
+  @override
+  void set withClause(WithClause withClause) {
+    _withClause = _becomeParentOf(withClause);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitClassTypeAlias(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_superclass, visitor);
+    _safelyVisitChild(_withClause, visitor);
+    _safelyVisitChild(_implementsClause, visitor);
+  }
+}
+
+/**
+ * A combinator associated with an import or export directive.
+ *
+ * > combinator ::=
+ * >     [HideCombinator]
+ * >   | [ShowCombinator]
+ */
+abstract class CombinatorImpl extends AstNodeImpl implements Combinator {
+  /**
+   * The 'hide' or 'show' keyword specifying what kind of processing is to be
+   * done on the names.
+   */
+  Token keyword;
+
+  /**
+   * Initialize a newly created combinator.
+   */
+  CombinatorImpl(this.keyword);
+
+  @override
+  Token get beginToken => keyword;
+}
+
+/**
+ * A comment within the source code.
+ *
+ * > comment ::=
+ * >     endOfLineComment
+ * >   | blockComment
+ * >   | documentationComment
+ * >
+ * > endOfLineComment ::=
+ * >     '//' (CHARACTER - EOL)* EOL
+ * >
+ * > blockComment ::=
+ * >     '/ *' CHARACTER* '&#42;/'
+ * >
+ * > documentationComment ::=
+ * >     '/ **' (CHARACTER | [CommentReference])* '&#42;/'
+ * >   | ('///' (CHARACTER - EOL)* EOL)+
+ */
+class CommentImpl extends AstNodeImpl implements Comment {
+  /**
+   * The tokens representing the comment.
+   */
+  final List<Token> tokens;
+
+  /**
+   * The type of the comment.
+   */
+  final CommentType _type;
+
+  /**
+   * The references embedded within the documentation comment. This list will be
+   * empty unless this is a documentation comment that has references embedded
+   * within it.
+   */
+  NodeList<CommentReference> _references;
+
+  /**
+   * Initialize a newly created comment. The list of [tokens] must contain at
+   * least one token. The [type] is the type of the comment. The list of
+   * [references] can be empty if the comment does not contain any embedded
+   * references.
+   */
+  CommentImpl(this.tokens, this._type, List<CommentReference> references) {
+    _references = new NodeList<CommentReference>(this, references);
+  }
+
+  @override
+  Token get beginToken => tokens[0];
+
+  @override
+  Iterable get childEntities => new ChildEntities()..addAll(tokens);
+
+  @override
+  Token get endToken => tokens[tokens.length - 1];
+
+  @override
+  bool get isBlock => _type == CommentType.BLOCK;
+
+  @override
+  bool get isDocumentation => _type == CommentType.DOCUMENTATION;
+
+  @override
+  bool get isEndOfLine => _type == CommentType.END_OF_LINE;
+
+  @override
+  NodeList<CommentReference> get references => _references;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitComment(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _references.accept(visitor);
+  }
+
+  /**
+   * Create a block comment consisting of the given [tokens].
+   */
+  static Comment createBlockComment(List<Token> tokens) =>
+      new CommentImpl(tokens, CommentType.BLOCK, null);
+
+  /**
+   * Create a documentation comment consisting of the given [tokens].
+   */
+  static Comment createDocumentationComment(List<Token> tokens) =>
+      new CommentImpl(
+          tokens, CommentType.DOCUMENTATION, new List<CommentReference>());
+
+  /**
+   * Create a documentation comment consisting of the given [tokens] and having
+   * the given [references] embedded within it.
+   */
+  static Comment createDocumentationCommentWithReferences(
+          List<Token> tokens, List<CommentReference> references) =>
+      new CommentImpl(tokens, CommentType.DOCUMENTATION, references);
+
+  /**
+   * Create an end-of-line comment consisting of the given [tokens].
+   */
+  static Comment createEndOfLineComment(List<Token> tokens) =>
+      new CommentImpl(tokens, CommentType.END_OF_LINE, null);
+}
+
+/**
+ * A reference to a Dart element that is found within a documentation comment.
+ *
+ * > commentReference ::=
+ * >     '[' 'new'? [Identifier] ']'
+ */
+class CommentReferenceImpl extends AstNodeImpl implements CommentReference {
+  /**
+   * The token representing the 'new' keyword, or `null` if there was no 'new'
+   * keyword.
+   */
+  Token newKeyword;
+
+  /**
+   * The identifier being referenced.
+   */
+  Identifier _identifier;
+
+  /**
+   * Initialize a newly created reference to a Dart element. The [newKeyword]
+   * can be `null` if the reference is not to a constructor.
+   */
+  CommentReferenceImpl(this.newKeyword, Identifier identifier) {
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  Token get beginToken => _identifier.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(newKeyword)..add(_identifier);
+
+  @override
+  Token get endToken => _identifier.endToken;
+
+  @override
+  Identifier get identifier => _identifier;
+
+  @override
+  void set identifier(Identifier identifier) {
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitCommentReference(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_identifier, visitor);
+  }
+}
+
+/**
+ * The possible types of comments that are recognized by the parser.
+ */
+class CommentType {
+  /**
+   * A block comment.
+   */
+  static const CommentType BLOCK = const CommentType('BLOCK');
+
+  /**
+   * A documentation comment.
+   */
+  static const CommentType DOCUMENTATION = const CommentType('DOCUMENTATION');
+
+  /**
+   * An end-of-line comment.
+   */
+  static const CommentType END_OF_LINE = const CommentType('END_OF_LINE');
+
+  /**
+   * The name of the comment type.
+   */
+  final String name;
+
+  /**
+   * Initialize a newly created comment type to have the given [name].
+   */
+  const CommentType(this.name);
+
+  @override
+  String toString() => name;
+}
+
+/**
+ * A compilation unit.
+ *
+ * While the grammar restricts the order of the directives and declarations
+ * within a compilation unit, this class does not enforce those restrictions.
+ * In particular, the children of a compilation unit will be visited in lexical
+ * order even if lexical order does not conform to the restrictions of the
+ * grammar.
+ *
+ * > compilationUnit ::=
+ * >     directives declarations
+ * >
+ * > directives ::=
+ * >     [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
+ * >   | [PartOfDirective]
+ * >
+ * > namespaceDirective ::=
+ * >     [ImportDirective]
+ * >   | [ExportDirective]
+ * >
+ * > declarations ::=
+ * >     [CompilationUnitMember]*
+ */
+class CompilationUnitImpl extends AstNodeImpl implements CompilationUnit {
+  /**
+   * The first token in the token stream that was parsed to form this
+   * compilation unit.
+   */
+  Token beginToken;
+
+  /**
+   * The script tag at the beginning of the compilation unit, or `null` if there
+   * is no script tag in this compilation unit.
+   */
+  ScriptTag _scriptTag;
+
+  /**
+   * The directives contained in this compilation unit.
+   */
+  NodeList<Directive> _directives;
+
+  /**
+   * The declarations contained in this compilation unit.
+   */
+  NodeList<CompilationUnitMember> _declarations;
+
+  /**
+   * The last token in the token stream that was parsed to form this compilation
+   * unit. This token should always have a type of [TokenType.EOF].
+   */
+  Token endToken;
+
+  /**
+   * The element associated with this compilation unit, or `null` if the AST
+   * structure has not been resolved.
+   */
+  CompilationUnitElement element;
+
+  /**
+   * The line information for this compilation unit.
+   */
+  LineInfo lineInfo;
+
+  /**
+   * Initialize a newly created compilation unit to have the given directives
+   * and declarations. The [scriptTag] can be `null` if there is no script tag
+   * in the compilation unit. The list of [directives] can be `null` if there
+   * are no directives in the compilation unit. The list of [declarations] can
+   * be `null` if there are no declarations in the compilation unit.
+   */
+  CompilationUnitImpl(
+      this.beginToken,
+      ScriptTag scriptTag,
+      List<Directive> directives,
+      List<CompilationUnitMember> declarations,
+      this.endToken) {
+    _scriptTag = _becomeParentOf(scriptTag);
+    _directives = new NodeList<Directive>(this, directives);
+    _declarations = new NodeList<CompilationUnitMember>(this, declarations);
+  }
+
+  @override
+  Iterable get childEntities {
+    ChildEntities result = new ChildEntities()..add(_scriptTag);
+    if (_directivesAreBeforeDeclarations) {
+      result..addAll(_directives)..addAll(_declarations);
+    } else {
+      result.addAll(sortedDirectivesAndDeclarations);
+    }
+    return result;
+  }
+
+  @override
+  NodeList<CompilationUnitMember> get declarations => _declarations;
+
+  @override
+  NodeList<Directive> get directives => _directives;
+
+  @override
+  int get length {
+    Token endToken = this.endToken;
+    if (endToken == null) {
+      return 0;
+    }
+    return endToken.offset + endToken.length;
+  }
+
+  @override
+  int get offset => 0;
+
+  @override
+  ScriptTag get scriptTag => _scriptTag;
+
+  @override
+  void set scriptTag(ScriptTag scriptTag) {
+    _scriptTag = _becomeParentOf(scriptTag);
+  }
+
+  @override
+  List<AstNode> get sortedDirectivesAndDeclarations {
+    return <AstNode>[]
+      ..addAll(_directives)
+      ..addAll(_declarations)
+      ..sort(AstNode.LEXICAL_ORDER);
+  }
+
+  /**
+   * Return `true` if all of the directives are lexically before any
+   * declarations.
+   */
+  bool get _directivesAreBeforeDeclarations {
+    if (_directives.isEmpty || _declarations.isEmpty) {
+      return true;
+    }
+    Directive lastDirective = _directives[_directives.length - 1];
+    CompilationUnitMember firstDeclaration = _declarations[0];
+    return lastDirective.offset < firstDeclaration.offset;
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitCompilationUnit(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_scriptTag, visitor);
+    if (_directivesAreBeforeDeclarations) {
+      _directives.accept(visitor);
+      _declarations.accept(visitor);
+    } else {
+      for (AstNode child in sortedDirectivesAndDeclarations) {
+        child.accept(visitor);
+      }
+    }
+  }
+}
+
+/**
+ * A node that declares one or more names within the scope of a compilation
+ * unit.
+ *
+ * > compilationUnitMember ::=
+ * >     [ClassDeclaration]
+ * >   | [TypeAlias]
+ * >   | [FunctionDeclaration]
+ * >   | [MethodDeclaration]
+ * >   | [VariableDeclaration]
+ * >   | [VariableDeclaration]
+ */
+abstract class CompilationUnitMemberImpl extends DeclarationImpl
+    implements CompilationUnitMember {
+  /**
+   * Initialize a newly created generic compilation unit member. Either or both
+   * of the [comment] and [metadata] can be `null` if the member does not have
+   * the corresponding attribute.
+   */
+  CompilationUnitMemberImpl(Comment comment, List<Annotation> metadata)
+      : super(comment, metadata);
+}
+
+/**
+ * A conditional expression.
+ *
+ * > conditionalExpression ::=
+ * >     [Expression] '?' [Expression] ':' [Expression]
+ */
+class ConditionalExpressionImpl extends ExpressionImpl
+    implements ConditionalExpression {
+  /**
+   * The condition used to determine which of the expressions is executed next.
+   */
+  Expression _condition;
+
+  /**
+   * The token used to separate the condition from the then expression.
+   */
+  Token question;
+
+  /**
+   * The expression that is executed if the condition evaluates to `true`.
+   */
+  Expression _thenExpression;
+
+  /**
+   * The token used to separate the then expression from the else expression.
+   */
+  Token colon;
+
+  /**
+   * The expression that is executed if the condition evaluates to `false`.
+   */
+  Expression _elseExpression;
+
+  /**
+   * Initialize a newly created conditional expression.
+   */
+  ConditionalExpressionImpl(Expression condition, this.question,
+      Expression thenExpression, this.colon, Expression elseExpression) {
+    _condition = _becomeParentOf(condition);
+    _thenExpression = _becomeParentOf(thenExpression);
+    _elseExpression = _becomeParentOf(elseExpression);
+  }
+
+  @override
+  Token get beginToken => _condition.beginToken;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(_condition)
+    ..add(question)
+    ..add(_thenExpression)
+    ..add(colon)
+    ..add(_elseExpression);
+
+  @override
+  Expression get condition => _condition;
+
+  @override
+  void set condition(Expression expression) {
+    _condition = _becomeParentOf(expression);
+  }
+
+  @override
+  Expression get elseExpression => _elseExpression;
+
+  @override
+  void set elseExpression(Expression expression) {
+    _elseExpression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get endToken => _elseExpression.endToken;
+
+  @override
+  int get precedence => 3;
+
+  @override
+  Expression get thenExpression => _thenExpression;
+
+  @override
+  void set thenExpression(Expression expression) {
+    _thenExpression = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitConditionalExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_condition, visitor);
+    _safelyVisitChild(_thenExpression, visitor);
+    _safelyVisitChild(_elseExpression, visitor);
+  }
+}
+
+/**
+ * A configuration in either an import or export directive.
+ *
+ *     configuration ::=
+ *         'if' '(' test ')' uri
+ *
+ *     test ::=
+ *         dottedName ('==' stringLiteral)?
+ *
+ *     dottedName ::=
+ *         identifier ('.' identifier)*
+ */
+class ConfigurationImpl extends AstNodeImpl implements Configuration {
+  Token ifKeyword;
+  Token leftParenthesis;
+  DottedName _name;
+  Token equalToken;
+  StringLiteral _value;
+  Token rightParenthesis;
+  StringLiteral _libraryUri;
+
+  ConfigurationImpl(
+      this.ifKeyword,
+      this.leftParenthesis,
+      DottedName name,
+      this.equalToken,
+      StringLiteral value,
+      this.rightParenthesis,
+      StringLiteral libraryUri) {
+    _name = _becomeParentOf(name);
+    _value = _becomeParentOf(value);
+    _libraryUri = _becomeParentOf(libraryUri);
+  }
+
+  @override
+  Token get beginToken => ifKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(ifKeyword)
+    ..add(leftParenthesis)
+    ..add(_name)
+    ..add(equalToken)
+    ..add(_value)
+    ..add(rightParenthesis)
+    ..add(_libraryUri);
+
+  @override
+  Token get endToken => _libraryUri.endToken;
+
+  @override
+  StringLiteral get libraryUri => _libraryUri;
+
+  @override
+  void set libraryUri(StringLiteral libraryUri) {
+    _libraryUri = _becomeParentOf(libraryUri);
+  }
+
+  @override
+  DottedName get name => _name;
+
+  @override
+  void set name(DottedName name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  StringLiteral get value => _value;
+
+  @override
+  void set value(StringLiteral value) {
+    _value = _becomeParentOf(value);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitConfiguration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_value, visitor);
+    _safelyVisitChild(_libraryUri, visitor);
+  }
+}
+
+/**
+ * A constructor declaration.
+ *
+ * > constructorDeclaration ::=
+ * >     constructorSignature [FunctionBody]?
+ * >   | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier])? arguments
+ * >
+ * > constructorSignature ::=
+ * >     'external'? constructorName formalParameterList initializerList?
+ * >   | 'external'? 'factory' factoryName formalParameterList initializerList?
+ * >   | 'external'? 'const'  constructorName formalParameterList initializerList?
+ * >
+ * > constructorName ::=
+ * >     [SimpleIdentifier] ('.' [SimpleIdentifier])?
+ * >
+ * > factoryName ::=
+ * >     [Identifier] ('.' [SimpleIdentifier])?
+ * >
+ * > initializerList ::=
+ * >     ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
+ */
+class ConstructorDeclarationImpl extends ClassMemberImpl
+    implements ConstructorDeclaration {
+  /**
+   * The token for the 'external' keyword, or `null` if the constructor is not
+   * external.
+   */
+  Token externalKeyword;
+
+  /**
+   * The token for the 'const' keyword, or `null` if the constructor is not a
+   * const constructor.
+   */
+  Token constKeyword;
+
+  /**
+   * The token for the 'factory' keyword, or `null` if the constructor is not a
+   * factory constructor.
+   */
+  Token factoryKeyword;
+
+  /**
+   * The type of object being created. This can be different than the type in
+   * which the constructor is being declared if the constructor is the
+   * implementation of a factory constructor.
+   */
+  Identifier _returnType;
+
+  /**
+   * The token for the period before the constructor name, or `null` if the
+   * constructor being declared is unnamed.
+   */
+  Token period;
+
+  /**
+   * The name of the constructor, or `null` if the constructor being declared is
+   * unnamed.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * The parameters associated with the constructor.
+   */
+  FormalParameterList _parameters;
+
+  /**
+   * The token for the separator (colon or equals) before the initializer list
+   * or redirection, or `null` if there are no initializers.
+   */
+  Token separator;
+
+  /**
+   * The initializers associated with the constructor.
+   */
+  NodeList<ConstructorInitializer> _initializers;
+
+  /**
+   * The name of the constructor to which this constructor will be redirected,
+   * or `null` if this is not a redirecting factory constructor.
+   */
+  ConstructorName _redirectedConstructor;
+
+  /**
+   * The body of the constructor, or `null` if the constructor does not have a
+   * body.
+   */
+  FunctionBody _body;
+
+  /**
+   * The element associated with this constructor, or `null` if the AST
+   * structure has not been resolved or if this constructor could not be
+   * resolved.
+   */
+  ConstructorElement element;
+
+  /**
+   * Initialize a newly created constructor declaration. The [externalKeyword]
+   * can be `null` if the constructor is not external. Either or both of the
+   * [comment] and [metadata] can be `null` if the constructor does not have the
+   * corresponding attribute. The [constKeyword] can be `null` if the
+   * constructor cannot be used to create a constant. The [factoryKeyword] can
+   * be `null` if the constructor is not a factory. The [period] and [name] can
+   * both be `null` if the constructor is not a named constructor. The
+   * [separator] can be `null` if the constructor does not have any initializers
+   * and does not redirect to a different constructor. The list of
+   * [initializers] can be `null` if the constructor does not have any
+   * initializers. The [redirectedConstructor] can be `null` if the constructor
+   * does not redirect to a different constructor. The [body] can be `null` if
+   * the constructor does not have a body.
+   */
+  ConstructorDeclarationImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.externalKeyword,
+      this.constKeyword,
+      this.factoryKeyword,
+      Identifier returnType,
+      this.period,
+      SimpleIdentifier name,
+      FormalParameterList parameters,
+      this.separator,
+      List<ConstructorInitializer> initializers,
+      ConstructorName redirectedConstructor,
+      FunctionBody body)
+      : super(comment, metadata) {
+    _returnType = _becomeParentOf(returnType);
+    _name = _becomeParentOf(name);
+    _parameters = _becomeParentOf(parameters);
+    _initializers = new NodeList<ConstructorInitializer>(this, initializers);
+    _redirectedConstructor = _becomeParentOf(redirectedConstructor);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  FunctionBody get body => _body;
+
+  @override
+  void set body(FunctionBody functionBody) {
+    _body = _becomeParentOf(functionBody);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(externalKeyword)
+    ..add(constKeyword)
+    ..add(factoryKeyword)
+    ..add(_returnType)
+    ..add(period)
+    ..add(_name)
+    ..add(_parameters)
+    ..add(separator)
+    ..addAll(initializers)
+    ..add(_redirectedConstructor)
+    ..add(_body);
+
+  @override
+  Token get endToken {
+    if (_body != null) {
+      return _body.endToken;
+    } else if (!_initializers.isEmpty) {
+      return _initializers.endToken;
+    }
+    return _parameters.endToken;
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    Token leftMost =
+        Token.lexicallyFirst([externalKeyword, constKeyword, factoryKeyword]);
+    if (leftMost != null) {
+      return leftMost;
+    }
+    return _returnType.beginToken;
+  }
+
+  @override
+  NodeList<ConstructorInitializer> get initializers => _initializers;
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+
+  @override
+  FormalParameterList get parameters => _parameters;
+
+  @override
+  void set parameters(FormalParameterList parameters) {
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  ConstructorName get redirectedConstructor => _redirectedConstructor;
+
+  @override
+  void set redirectedConstructor(ConstructorName redirectedConstructor) {
+    _redirectedConstructor = _becomeParentOf(redirectedConstructor);
+  }
+
+  @override
+  Identifier get returnType => _returnType;
+
+  @override
+  void set returnType(Identifier typeName) {
+    _returnType = _becomeParentOf(typeName);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitConstructorDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_returnType, visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_parameters, visitor);
+    _initializers.accept(visitor);
+    _safelyVisitChild(_redirectedConstructor, visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * The initialization of a field within a constructor's initialization list.
+ *
+ * > fieldInitializer ::=
+ * >     ('this' '.')? [SimpleIdentifier] '=' [Expression]
+ */
+class ConstructorFieldInitializerImpl extends ConstructorInitializerImpl
+    implements ConstructorFieldInitializer {
+  /**
+   * The token for the 'this' keyword, or `null` if there is no 'this' keyword.
+   */
+  Token thisKeyword;
+
+  /**
+   * The token for the period after the 'this' keyword, or `null` if there is no
+   * 'this' keyword.
+   */
+  Token period;
+
+  /**
+   * The name of the field being initialized.
+   */
+  SimpleIdentifier _fieldName;
+
+  /**
+   * The token for the equal sign between the field name and the expression.
+   */
+  Token equals;
+
+  /**
+   * The expression computing the value to which the field will be initialized.
+   */
+  Expression _expression;
+
+  /**
+   * Initialize a newly created field initializer to initialize the field with
+   * the given name to the value of the given expression. The [thisKeyword] and
+   * [period] can be `null` if the 'this' keyword was not specified.
+   */
+  ConstructorFieldInitializerImpl(this.thisKeyword, this.period,
+      SimpleIdentifier fieldName, this.equals, Expression expression) {
+    _fieldName = _becomeParentOf(fieldName);
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken {
+    if (thisKeyword != null) {
+      return thisKeyword;
+    }
+    return _fieldName.beginToken;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(thisKeyword)
+    ..add(period)
+    ..add(_fieldName)
+    ..add(equals)
+    ..add(_expression);
+
+  @override
+  Token get endToken => _expression.endToken;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  SimpleIdentifier get fieldName => _fieldName;
+
+  @override
+  void set fieldName(SimpleIdentifier identifier) {
+    _fieldName = _becomeParentOf(identifier);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitConstructorFieldInitializer(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_fieldName, visitor);
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A node that can occur in the initializer list of a constructor declaration.
+ *
+ * > constructorInitializer ::=
+ * >     [SuperConstructorInvocation]
+ * >   | [ConstructorFieldInitializer]
+ * >   | [RedirectingConstructorInvocation]
+ */
+abstract class ConstructorInitializerImpl extends AstNodeImpl
+    implements ConstructorInitializer {}
+
+/**
+ * The name of the constructor.
+ *
+ * > constructorName ::=
+ * >     type ('.' identifier)?
+ */
+class ConstructorNameImpl extends AstNodeImpl implements ConstructorName {
+  /**
+   * The name of the type defining the constructor.
+   */
+  TypeName _type;
+
+  /**
+   * The token for the period before the constructor name, or `null` if the
+   * specified constructor is the unnamed constructor.
+   */
+  Token period;
+
+  /**
+   * The name of the constructor, or `null` if the specified constructor is the
+   * unnamed constructor.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * The element associated with this constructor name based on static type
+   * information, or `null` if the AST structure has not been resolved or if
+   * this constructor name could not be resolved.
+   */
+  ConstructorElement staticElement;
+
+  /**
+   * Initialize a newly created constructor name. The [period] and [name] can be
+   * `null` if the constructor being named is the unnamed constructor.
+   */
+  ConstructorNameImpl(TypeName type, this.period, SimpleIdentifier name) {
+    _type = _becomeParentOf(type);
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  Token get beginToken => _type.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_type)..add(period)..add(_name);
+
+  @override
+  Token get endToken {
+    if (_name != null) {
+      return _name.endToken;
+    }
+    return _type.endToken;
+  }
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName type) {
+    _type = _becomeParentOf(type);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitConstructorName(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_type, visitor);
+    _safelyVisitChild(_name, visitor);
+  }
+}
+
+/**
+ * A continue statement.
+ *
+ * > continueStatement ::=
+ * >     'continue' [SimpleIdentifier]? ';'
+ */
+class ContinueStatementImpl extends StatementImpl implements ContinueStatement {
+  /**
+   * The token representing the 'continue' keyword.
+   */
+  Token continueKeyword;
+
+  /**
+   * The label associated with the statement, or `null` if there is no label.
+   */
+  SimpleIdentifier _label;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * The AstNode which this continue statement is continuing to.  This will be
+   * either a Statement (in the case of continuing a loop) or a SwitchMember
+   * (in the case of continuing from one switch case to another).  Null if the
+   * AST has not yet been resolved or if the target could not be resolved.
+   * Note that if the source code has errors, the target may be invalid (e.g.
+   * the target may be in an enclosing function).
+   */
+  AstNode target;
+
+  /**
+   * Initialize a newly created continue statement. The [label] can be `null` if
+   * there is no label associated with the statement.
+   */
+  ContinueStatementImpl(
+      this.continueKeyword, SimpleIdentifier label, this.semicolon) {
+    _label = _becomeParentOf(label);
+  }
+
+  @override
+  Token get beginToken => continueKeyword;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(continueKeyword)..add(_label)..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  SimpleIdentifier get label => _label;
+
+  @override
+  void set label(SimpleIdentifier identifier) {
+    _label = _becomeParentOf(identifier);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitContinueStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_label, visitor);
+  }
+}
+
+/**
+ * A node that represents the declaration of one or more names. Each declared
+ * name is visible within a name scope.
+ */
+abstract class DeclarationImpl extends AnnotatedNodeImpl
+    implements Declaration {
+  /**
+   * Initialize a newly created declaration. Either or both of the [comment] and
+   * [metadata] can be `null` if the declaration does not have the corresponding
+   * attribute.
+   */
+  DeclarationImpl(Comment comment, List<Annotation> metadata)
+      : super(comment, metadata);
+}
+
+/**
+ * The declaration of a single identifier.
+ *
+ * > declaredIdentifier ::=
+ * >     [Annotation] finalConstVarOrType [SimpleIdentifier]
+ */
+class DeclaredIdentifierImpl extends DeclarationImpl
+    implements DeclaredIdentifier {
+  /**
+   * The token representing either the 'final', 'const' or 'var' keyword, or
+   * `null` if no keyword was used.
+   */
+  Token keyword;
+
+  /**
+   * The name of the declared type of the parameter, or `null` if the parameter
+   * does not have a declared type.
+   */
+  TypeName _type;
+
+  /**
+   * The name of the variable being declared.
+   */
+  SimpleIdentifier _identifier;
+
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The [keyword] can be `null` if a type name is
+   * given. The [type] must be `null` if the keyword is 'var'.
+   */
+  DeclaredIdentifierImpl(Comment comment, List<Annotation> metadata,
+      this.keyword, TypeName type, SimpleIdentifier identifier)
+      : super(comment, metadata) {
+    _type = _becomeParentOf(type);
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(keyword)..add(_type)..add(_identifier);
+
+  @override
+  LocalVariableElement get element {
+    if (_identifier == null) {
+      return null;
+    }
+    return _identifier.staticElement as LocalVariableElement;
+  }
+
+  @override
+  Token get endToken => _identifier.endToken;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    if (keyword != null) {
+      return keyword;
+    } else if (_type != null) {
+      return _type.beginToken;
+    }
+    return _identifier.beginToken;
+  }
+
+  @override
+  SimpleIdentifier get identifier => _identifier;
+
+  @override
+  void set identifier(SimpleIdentifier identifier) {
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  bool get isConst =>
+      (keyword is KeywordToken) &&
+      (keyword as KeywordToken).keyword == Keyword.CONST;
+
+  @override
+  bool get isFinal =>
+      (keyword is KeywordToken) &&
+      (keyword as KeywordToken).keyword == Keyword.FINAL;
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName typeName) {
+    _type = _becomeParentOf(typeName);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitDeclaredIdentifier(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_type, visitor);
+    _safelyVisitChild(_identifier, visitor);
+  }
+}
+
+/**
+ * A formal parameter with a default value. There are two kinds of parameters
+ * that are both represented by this class: named formal parameters and
+ * positional formal parameters.
+ *
+ * > defaultFormalParameter ::=
+ * >     [NormalFormalParameter] ('=' [Expression])?
+ * >
+ * > defaultNamedParameter ::=
+ * >     [NormalFormalParameter] (':' [Expression])?
+ */
+class DefaultFormalParameterImpl extends FormalParameterImpl
+    implements DefaultFormalParameter {
+  /**
+   * The formal parameter with which the default value is associated.
+   */
+  NormalFormalParameter _parameter;
+
+  /**
+   * The kind of this parameter.
+   */
+  ParameterKind kind;
+
+  /**
+   * The token separating the parameter from the default value, or `null` if
+   * there is no default value.
+   */
+  Token separator;
+
+  /**
+   * The expression computing the default value for the parameter, or `null` if
+   * there is no default value.
+   */
+  Expression _defaultValue;
+
+  /**
+   * Initialize a newly created default formal parameter. The [separator] and
+   * [defaultValue] can be `null` if there is no default value.
+   */
+  DefaultFormalParameterImpl(NormalFormalParameter parameter, this.kind,
+      this.separator, Expression defaultValue) {
+    _parameter = _becomeParentOf(parameter);
+    _defaultValue = _becomeParentOf(defaultValue);
+  }
+
+  @override
+  Token get beginToken => _parameter.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_parameter)..add(separator)..add(_defaultValue);
+
+  @override
+  Expression get defaultValue => _defaultValue;
+
+  @override
+  void set defaultValue(Expression expression) {
+    _defaultValue = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get endToken {
+    if (_defaultValue != null) {
+      return _defaultValue.endToken;
+    }
+    return _parameter.endToken;
+  }
+
+  @override
+  SimpleIdentifier get identifier => _parameter.identifier;
+
+  @override
+  bool get isConst => _parameter != null && _parameter.isConst;
+
+  @override
+  bool get isFinal => _parameter != null && _parameter.isFinal;
+
+  @override
+  NodeList<Annotation> get metadata => _parameter.metadata;
+
+  @override
+  NormalFormalParameter get parameter => _parameter;
+
+  @override
+  void set parameter(NormalFormalParameter formalParameter) {
+    _parameter = _becomeParentOf(formalParameter);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitDefaultFormalParameter(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_parameter, visitor);
+    _safelyVisitChild(_defaultValue, visitor);
+  }
+}
+
+/**
+ * A node that represents a directive.
+ *
+ * > directive ::=
+ * >     [ExportDirective]
+ * >   | [ImportDirective]
+ * >   | [LibraryDirective]
+ * >   | [PartDirective]
+ * >   | [PartOfDirective]
+ */
+abstract class DirectiveImpl extends AnnotatedNodeImpl implements Directive {
+  /**
+   * The element associated with this directive, or `null` if the AST structure
+   * has not been resolved or if this directive could not be resolved.
+   */
+  Element element;
+
+  /**
+   * Initialize a newly create directive. Either or both of the [comment] and
+   * [metadata] can be `null` if the directive does not have the corresponding
+   * attribute.
+   */
+  DirectiveImpl(Comment comment, List<Annotation> metadata)
+      : super(comment, metadata);
+}
+
+/**
+ * A do statement.
+ *
+ * > doStatement ::=
+ * >     'do' [Statement] 'while' '(' [Expression] ')' ';'
+ */
+class DoStatementImpl extends StatementImpl implements DoStatement {
+  /**
+   * The token representing the 'do' keyword.
+   */
+  Token doKeyword;
+
+  /**
+   * The body of the loop.
+   */
+  Statement _body;
+
+  /**
+   * The token representing the 'while' keyword.
+   */
+  Token whileKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The condition that determines when the loop will terminate.
+   */
+  Expression _condition;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created do loop.
+   */
+  DoStatementImpl(
+      this.doKeyword,
+      Statement body,
+      this.whileKeyword,
+      this.leftParenthesis,
+      Expression condition,
+      this.rightParenthesis,
+      this.semicolon) {
+    _body = _becomeParentOf(body);
+    _condition = _becomeParentOf(condition);
+  }
+
+  @override
+  Token get beginToken => doKeyword;
+
+  @override
+  Statement get body => _body;
+
+  @override
+  void set body(Statement statement) {
+    _body = _becomeParentOf(statement);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(doKeyword)
+    ..add(_body)
+    ..add(whileKeyword)
+    ..add(leftParenthesis)
+    ..add(_condition)
+    ..add(rightParenthesis)
+    ..add(semicolon);
+
+  @override
+  Expression get condition => _condition;
+
+  @override
+  void set condition(Expression expression) {
+    _condition = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitDoStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_body, visitor);
+    _safelyVisitChild(_condition, visitor);
+  }
+}
+
+/**
+ * A dotted name, used in a configuration within an import or export directive.
+ *
+ * > dottedName ::=
+ * >     [SimpleIdentifier] ('.' [SimpleIdentifier])*
+ */
+class DottedNameImpl extends AstNodeImpl implements DottedName {
+  /**
+   * The components of the identifier.
+   */
+  NodeList<SimpleIdentifier> _components;
+
+  /**
+   * Initialize a newly created dotted name.
+   */
+  DottedNameImpl(List<SimpleIdentifier> components) {
+    _components = new NodeList<SimpleIdentifier>(this, components);
+  }
+
+  @override
+  Token get beginToken => _components.beginToken;
+
+  @override
+  // TODO(paulberry): add "." tokens.
+  Iterable get childEntities => new ChildEntities()..addAll(_components);
+
+  @override
+  NodeList<SimpleIdentifier> get components => _components;
+
+  @override
+  Token get endToken => _components.endToken;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitDottedName(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _components.accept(visitor);
+  }
+}
+
+/**
+ * A floating point literal expression.
+ *
+ * > doubleLiteral ::=
+ * >     decimalDigit+ ('.' decimalDigit*)? exponent?
+ * >   | '.' decimalDigit+ exponent?
+ * >
+ * > exponent ::=
+ * >     ('e' | 'E') ('+' | '-')? decimalDigit+
+ */
+class DoubleLiteralImpl extends LiteralImpl implements DoubleLiteral {
+  /**
+   * The token representing the literal.
+   */
+  Token literal;
+
+  /**
+   * The value of the literal.
+   */
+  double value;
+
+  /**
+   * Initialize a newly created floating point literal.
+   */
+  DoubleLiteralImpl(this.literal, this.value);
+
+  @override
+  Token get beginToken => literal;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(literal);
+
+  @override
+  Token get endToken => literal;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitDoubleLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * An empty function body, which can only appear in constructors or abstract
+ * methods.
+ *
+ * > emptyFunctionBody ::=
+ * >     ';'
+ */
+class EmptyFunctionBodyImpl extends FunctionBodyImpl
+    implements EmptyFunctionBody {
+  /**
+   * The token representing the semicolon that marks the end of the function
+   * body.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created function body.
+   */
+  EmptyFunctionBodyImpl(this.semicolon);
+
+  @override
+  Token get beginToken => semicolon;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitEmptyFunctionBody(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // Empty function bodies have no children.
+  }
+}
+
+/**
+ * An empty statement.
+ *
+ * > emptyStatement ::=
+ * >     ';'
+ */
+class EmptyStatementImpl extends StatementImpl implements EmptyStatement {
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created empty statement.
+   */
+  EmptyStatementImpl(this.semicolon);
+
+  @override
+  Token get beginToken => semicolon;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitEmptyStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * The declaration of an enum constant.
+ */
+class EnumConstantDeclarationImpl extends DeclarationImpl
+    implements EnumConstantDeclaration {
+  /**
+   * The name of the constant.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * Initialize a newly created enum constant declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the constant does not have the
+   * corresponding attribute. (Technically, enum constants cannot have metadata,
+   * but we allow it for consistency.)
+   */
+  EnumConstantDeclarationImpl(
+      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
+      : super(comment, metadata) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities..add(_name);
+
+  @override
+  FieldElement get element =>
+      _name == null ? null : (_name.staticElement as FieldElement);
+
+  @override
+  Token get endToken => _name.endToken;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitEnumConstantDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+  }
+}
+
+/**
+ * The declaration of an enumeration.
+ *
+ * > enumType ::=
+ * >     metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] (',' [SimpleIdentifier])* (',')? '}'
+ */
+class EnumDeclarationImpl extends NamedCompilationUnitMemberImpl
+    implements EnumDeclaration {
+  /**
+   * The 'enum' keyword.
+   */
+  Token enumKeyword;
+
+  /**
+   * The left curly bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The enumeration constants being declared.
+   */
+  NodeList<EnumConstantDeclaration> _constants;
+
+  /**
+   * The right curly bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created enumeration declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The list of [constants] must contain at least one
+   * value.
+   */
+  EnumDeclarationImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.enumKeyword,
+      SimpleIdentifier name,
+      this.leftBracket,
+      List<EnumConstantDeclaration> constants,
+      this.rightBracket)
+      : super(comment, metadata, name) {
+    _constants = new NodeList<EnumConstantDeclaration>(this, constants);
+  }
+
+  @override
+  // TODO(brianwilkerson) Add commas?
+  Iterable get childEntities => super._childEntities
+    ..add(enumKeyword)
+    ..add(_name)
+    ..add(leftBracket)
+    ..addAll(_constants)
+    ..add(rightBracket);
+
+  @override
+  NodeList<EnumConstantDeclaration> get constants => _constants;
+
+  @override
+  ClassElement get element =>
+      _name != null ? (_name.staticElement as ClassElement) : null;
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => enumKeyword;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitEnumDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+    _constants.accept(visitor);
+  }
+}
+
+/**
+ * Ephemeral identifiers are created as needed to mimic the presence of an empty
+ * identifier.
+ */
+class EphemeralIdentifier extends SimpleIdentifierImpl {
+  EphemeralIdentifier(AstNode parent, int location)
+      : super(new StringToken(TokenType.IDENTIFIER, "", location)) {
+    (parent as AstNodeImpl)._becomeParentOf(this);
+  }
+}
+
+/**
+ * An export directive.
+ *
+ * > exportDirective ::=
+ * >     [Annotation] 'export' [StringLiteral] [Combinator]* ';'
+ */
+class ExportDirectiveImpl extends NamespaceDirectiveImpl
+    implements ExportDirective {
+  /**
+   * Initialize a newly created export directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute. The list of [combinators] can be `null` if there
+   * are no combinators.
+   */
+  ExportDirectiveImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      StringLiteral libraryUri,
+      List<Configuration> configurations,
+      List<Combinator> combinators,
+      Token semicolon)
+      : super(comment, metadata, keyword, libraryUri, configurations,
+            combinators, semicolon);
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(_uri)
+    ..addAll(combinators)
+    ..add(semicolon);
+
+  @override
+  ExportElement get element => super.element as ExportElement;
+
+  @override
+  LibraryElement get uriElement {
+    if (element != null) {
+      return element.exportedLibrary;
+    }
+    return null;
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitExportDirective(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    combinators.accept(visitor);
+  }
+}
+
+/**
+ * A function body consisting of a single expression.
+ *
+ * > expressionFunctionBody ::=
+ * >     'async'? '=>' [Expression] ';'
+ */
+class ExpressionFunctionBodyImpl extends FunctionBodyImpl
+    implements ExpressionFunctionBody {
+  /**
+   * The token representing the 'async' keyword, or `null` if there is no such
+   * keyword.
+   */
+  Token keyword;
+
+  /**
+   * The token introducing the expression that represents the body of the
+   * function.
+   */
+  Token functionDefinition;
+
+  /**
+   * The expression representing the body of the function.
+   */
+  Expression _expression;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created function body consisting of a block of
+   * statements. The [keyword] can be `null` if the function body is not an
+   * async function body.
+   */
+  ExpressionFunctionBodyImpl(this.keyword, this.functionDefinition,
+      Expression expression, this.semicolon) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken {
+    if (keyword != null) {
+      return keyword;
+    }
+    return functionDefinition;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(keyword)
+    ..add(functionDefinition)
+    ..add(_expression)
+    ..add(semicolon);
+
+  @override
+  Token get endToken {
+    if (semicolon != null) {
+      return semicolon;
+    }
+    return _expression.endToken;
+  }
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  bool get isAsynchronous => keyword != null;
+
+  @override
+  bool get isSynchronous => keyword == null;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitExpressionFunctionBody(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A node that represents an expression.
+ *
+ * > expression ::=
+ * >     [AssignmentExpression]
+ * >   | [ConditionalExpression] cascadeSection*
+ * >   | [ThrowExpression]
+ */
+abstract class ExpressionImpl extends AstNodeImpl implements Expression {
+  /**
+   * The static type of this expression, or `null` if the AST structure has not
+   * been resolved.
+   */
+  DartType staticType;
+
+  /**
+   * The propagated type of this expression, or `null` if type propagation has
+   * not been performed on the AST structure.
+   */
+  DartType propagatedType;
+
+  /**
+   * Return the best parameter element information available for this
+   * expression. If type propagation was able to find a better parameter element
+   * than static analysis, that type will be returned. Otherwise, the result of
+   * static analysis will be returned.
+   */
+  ParameterElement get bestParameterElement {
+    ParameterElement propagatedElement = propagatedParameterElement;
+    if (propagatedElement != null) {
+      return propagatedElement;
+    }
+    return staticParameterElement;
+  }
+
+  @override
+  DartType get bestType {
+    if (propagatedType != null) {
+      return propagatedType;
+    } else if (staticType != null) {
+      return staticType;
+    }
+    return DynamicTypeImpl.instance;
+  }
+
+  @override
+  bool get isAssignable => false;
+
+  @override
+  ParameterElement get propagatedParameterElement {
+    AstNode parent = this.parent;
+    if (parent is ArgumentListImpl) {
+      return parent._getPropagatedParameterElementFor(this);
+    } else if (parent is IndexExpressionImpl) {
+      if (identical(parent.index, this)) {
+        return parent._propagatedParameterElementForIndex;
+      }
+    } else if (parent is BinaryExpressionImpl) {
+      if (identical(parent.rightOperand, this)) {
+        return parent._propagatedParameterElementForRightOperand;
+      }
+    } else if (parent is AssignmentExpressionImpl) {
+      if (identical(parent.rightHandSide, this)) {
+        return parent._propagatedParameterElementForRightHandSide;
+      }
+    } else if (parent is PrefixExpressionImpl) {
+      return parent._propagatedParameterElementForOperand;
+    } else if (parent is PostfixExpressionImpl) {
+      return parent._propagatedParameterElementForOperand;
+    }
+    return null;
+  }
+
+  @override
+  ParameterElement get staticParameterElement {
+    AstNode parent = this.parent;
+    if (parent is ArgumentListImpl) {
+      return parent._getStaticParameterElementFor(this);
+    } else if (parent is IndexExpressionImpl) {
+      if (identical(parent.index, this)) {
+        return parent._staticParameterElementForIndex;
+      }
+    } else if (parent is BinaryExpressionImpl) {
+      if (identical(parent.rightOperand, this)) {
+        return parent._staticParameterElementForRightOperand;
+      }
+    } else if (parent is AssignmentExpressionImpl) {
+      if (identical(parent.rightHandSide, this)) {
+        return parent._staticParameterElementForRightHandSide;
+      }
+    } else if (parent is PrefixExpressionImpl) {
+      return parent._staticParameterElementForOperand;
+    } else if (parent is PostfixExpressionImpl) {
+      return parent._staticParameterElementForOperand;
+    }
+    return null;
+  }
+}
+
+/**
+ * An expression used as a statement.
+ *
+ * > expressionStatement ::=
+ * >     [Expression]? ';'
+ */
+class ExpressionStatementImpl extends StatementImpl
+    implements ExpressionStatement {
+  /**
+   * The expression that comprises the statement.
+   */
+  Expression _expression;
+
+  /**
+   * The semicolon terminating the statement, or `null` if the expression is a
+   * function expression and therefore isn't followed by a semicolon.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created expression statement.
+   */
+  ExpressionStatementImpl(Expression expression, this.semicolon) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken => _expression.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_expression)..add(semicolon);
+
+  @override
+  Token get endToken {
+    if (semicolon != null) {
+      return semicolon;
+    }
+    return _expression.endToken;
+  }
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  bool get isSynthetic => _expression.isSynthetic && semicolon.isSynthetic;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitExpressionStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * The "extends" clause in a class declaration.
+ *
+ * > extendsClause ::=
+ * >     'extends' [TypeName]
+ */
+class ExtendsClauseImpl extends AstNodeImpl implements ExtendsClause {
+  /**
+   * The token representing the 'extends' keyword.
+   */
+  Token extendsKeyword;
+
+  /**
+   * The name of the class that is being extended.
+   */
+  TypeName _superclass;
+
+  /**
+   * Initialize a newly created extends clause.
+   */
+  ExtendsClauseImpl(this.extendsKeyword, TypeName superclass) {
+    _superclass = _becomeParentOf(superclass);
+  }
+
+  @override
+  Token get beginToken => extendsKeyword;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(extendsKeyword)..add(_superclass);
+
+  @override
+  Token get endToken => _superclass.endToken;
+
+  @override
+  TypeName get superclass => _superclass;
+
+  @override
+  void set superclass(TypeName name) {
+    _superclass = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitExtendsClause(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_superclass, visitor);
+  }
+}
+
+/**
+ * The declaration of one or more fields of the same type.
+ *
+ * > fieldDeclaration ::=
+ * >     'static'? [VariableDeclarationList] ';'
+ */
+class FieldDeclarationImpl extends ClassMemberImpl implements FieldDeclaration {
+  /**
+   * The token representing the 'static' keyword, or `null` if the fields are
+   * not static.
+   */
+  Token staticKeyword;
+
+  /**
+   * The fields being declared.
+   */
+  VariableDeclarationList _fieldList;
+
+  /**
+   * The semicolon terminating the declaration.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created field declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The [staticKeyword] can be `null` if the field is
+   * not a static field.
+   */
+  FieldDeclarationImpl(Comment comment, List<Annotation> metadata,
+      this.staticKeyword, VariableDeclarationList fieldList, this.semicolon)
+      : super(comment, metadata) {
+    _fieldList = _becomeParentOf(fieldList);
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(staticKeyword)..add(_fieldList)..add(semicolon);
+
+  @override
+  Element get element => null;
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  VariableDeclarationList get fields => _fieldList;
+
+  @override
+  void set fields(VariableDeclarationList fields) {
+    _fieldList = _becomeParentOf(fields);
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    if (staticKeyword != null) {
+      return staticKeyword;
+    }
+    return _fieldList.beginToken;
+  }
+
+  @override
+  bool get isStatic => staticKeyword != null;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFieldDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_fieldList, visitor);
+  }
+}
+
+/**
+ * A field formal parameter.
+ *
+ * > fieldFormalParameter ::=
+ * >     ('final' [TypeName] | 'const' [TypeName] | 'var' | [TypeName])?
+ * >     'this' '.' [SimpleIdentifier] ([TypeParameterList]? [FormalParameterList])?
+ */
+class FieldFormalParameterImpl extends NormalFormalParameterImpl
+    implements FieldFormalParameter {
+  /**
+   * The token representing either the 'final', 'const' or 'var' keyword, or
+   * `null` if no keyword was used.
+   */
+  Token keyword;
+
+  /**
+   * The name of the declared type of the parameter, or `null` if the parameter
+   * does not have a declared type.
+   */
+  TypeName _type;
+
+  /**
+   * The token representing the 'this' keyword.
+   */
+  Token thisKeyword;
+
+  /**
+   * The token representing the period.
+   */
+  Token period;
+
+  /**
+   * The type parameters associated with the method, or `null` if the method is
+   * not a generic method.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The parameters of the function-typed parameter, or `null` if this is not a
+   * function-typed field formal parameter.
+   */
+  FormalParameterList _parameters;
+
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [keyword] can be `null` if there is a type.
+   * The [type] must be `null` if the keyword is 'var'. The [thisKeyword] and
+   * [period] can be `null` if the keyword 'this' was not provided.  The
+   * [parameters] can be `null` if this is not a function-typed field formal
+   * parameter.
+   */
+  FieldFormalParameterImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.keyword,
+      TypeName type,
+      this.thisKeyword,
+      this.period,
+      SimpleIdentifier identifier,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters)
+      : super(comment, metadata, identifier) {
+    _type = _becomeParentOf(type);
+    _typeParameters = _becomeParentOf(typeParameters);
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  Token get beginToken {
+    if (keyword != null) {
+      return keyword;
+    } else if (_type != null) {
+      return _type.beginToken;
+    }
+    return thisKeyword;
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(keyword)
+    ..add(_type)
+    ..add(thisKeyword)
+    ..add(period)
+    ..add(identifier)
+    ..add(_parameters);
+
+  @override
+  Token get endToken {
+    if (_parameters != null) {
+      return _parameters.endToken;
+    }
+    return identifier.endToken;
+  }
+
+  @override
+  bool get isConst =>
+      (keyword is KeywordToken) &&
+      (keyword as KeywordToken).keyword == Keyword.CONST;
+
+  @override
+  bool get isFinal =>
+      (keyword is KeywordToken) &&
+      (keyword as KeywordToken).keyword == Keyword.FINAL;
+
+  @override
+  FormalParameterList get parameters => _parameters;
+
+  @override
+  void set parameters(FormalParameterList parameters) {
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName typeName) {
+    _type = _becomeParentOf(typeName);
+  }
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFieldFormalParameter(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_type, visitor);
+    _safelyVisitChild(identifier, visitor);
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_parameters, visitor);
+  }
+}
+
+/**
+ * A for-each statement.
+ *
+ * > forEachStatement ::=
+ * >     'await'? 'for' '(' [DeclaredIdentifier] 'in' [Expression] ')' [Block]
+ * >   | 'await'? 'for' '(' [SimpleIdentifier] 'in' [Expression] ')' [Block]
+ */
+class ForEachStatementImpl extends StatementImpl implements ForEachStatement {
+  /**
+   * The token representing the 'await' keyword, or `null` if there is no
+   * 'await' keyword.
+   */
+  Token awaitKeyword;
+
+  /**
+   * The token representing the 'for' keyword.
+   */
+  Token forKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The declaration of the loop variable, or `null` if the loop variable is a
+   * simple identifier.
+   */
+  DeclaredIdentifier _loopVariable;
+
+  /**
+   * The loop variable, or `null` if the loop variable is declared in the 'for'.
+   */
+  SimpleIdentifier _identifier;
+
+  /**
+   * The token representing the 'in' keyword.
+   */
+  Token inKeyword;
+
+  /**
+   * The expression evaluated to produce the iterator.
+   */
+  Expression _iterable;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The body of the loop.
+   */
+  Statement _body;
+
+  /**
+   * Initialize a newly created for-each statement whose loop control variable
+   * is declared internally (in the for-loop part). The [awaitKeyword] can be
+   * `null` if this is not an asynchronous for loop.
+   */
+  ForEachStatementImpl.withDeclaration(
+      this.awaitKeyword,
+      this.forKeyword,
+      this.leftParenthesis,
+      DeclaredIdentifier loopVariable,
+      this.inKeyword,
+      Expression iterator,
+      this.rightParenthesis,
+      Statement body) {
+    _loopVariable = _becomeParentOf(loopVariable);
+    _iterable = _becomeParentOf(iterator);
+    _body = _becomeParentOf(body);
+  }
+
+  /**
+   * Initialize a newly created for-each statement whose loop control variable
+   * is declared outside the for loop. The [awaitKeyword] can be `null` if this
+   * is not an asynchronous for loop.
+   */
+  ForEachStatementImpl.withReference(
+      this.awaitKeyword,
+      this.forKeyword,
+      this.leftParenthesis,
+      SimpleIdentifier identifier,
+      this.inKeyword,
+      Expression iterator,
+      this.rightParenthesis,
+      Statement body) {
+    _identifier = _becomeParentOf(identifier);
+    _iterable = _becomeParentOf(iterator);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  Token get beginToken => forKeyword;
+
+  @override
+  Statement get body => _body;
+
+  @override
+  void set body(Statement statement) {
+    _body = _becomeParentOf(statement);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(awaitKeyword)
+    ..add(forKeyword)
+    ..add(leftParenthesis)
+    ..add(_loopVariable)
+    ..add(_identifier)
+    ..add(inKeyword)
+    ..add(_iterable)
+    ..add(rightParenthesis)
+    ..add(_body);
+
+  @override
+  Token get endToken => _body.endToken;
+
+  @override
+  SimpleIdentifier get identifier => _identifier;
+
+  @override
+  void set identifier(SimpleIdentifier identifier) {
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  Expression get iterable => _iterable;
+
+  @override
+  void set iterable(Expression expression) {
+    _iterable = _becomeParentOf(expression);
+  }
+
+  @override
+  DeclaredIdentifier get loopVariable => _loopVariable;
+
+  @override
+  void set loopVariable(DeclaredIdentifier variable) {
+    _loopVariable = _becomeParentOf(variable);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitForEachStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_loopVariable, visitor);
+    _safelyVisitChild(_identifier, visitor);
+    _safelyVisitChild(_iterable, visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * A node representing a parameter to a function.
+ *
+ * > formalParameter ::=
+ * >     [NormalFormalParameter]
+ * >   | [DefaultFormalParameter]
+ */
+abstract class FormalParameterImpl extends AstNodeImpl
+    implements FormalParameter {
+  @override
+  ParameterElement get element {
+    SimpleIdentifier identifier = this.identifier;
+    if (identifier == null) {
+      return null;
+    }
+    return identifier.staticElement as ParameterElement;
+  }
+}
+
+/**
+ * The formal parameter list of a method declaration, function declaration, or
+ * function type alias.
+ *
+ * While the grammar requires all optional formal parameters to follow all of
+ * the normal formal parameters and at most one grouping of optional formal
+ * parameters, this class does not enforce those constraints. All parameters are
+ * flattened into a single list, which can have any or all kinds of parameters
+ * (normal, named, and positional) in any order.
+ *
+ * > formalParameterList ::=
+ * >     '(' ')'
+ * >   | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
+ * >   | '(' optionalFormalParameters ')'
+ * >
+ * > normalFormalParameters ::=
+ * >     [NormalFormalParameter] (',' [NormalFormalParameter])*
+ * >
+ * > optionalFormalParameters ::=
+ * >     optionalPositionalFormalParameters
+ * >   | namedFormalParameters
+ * >
+ * > optionalPositionalFormalParameters ::=
+ * >     '[' [DefaultFormalParameter] (',' [DefaultFormalParameter])* ']'
+ * >
+ * > namedFormalParameters ::=
+ * >     '{' [DefaultFormalParameter] (',' [DefaultFormalParameter])* '}'
+ */
+class FormalParameterListImpl extends AstNodeImpl
+    implements FormalParameterList {
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The parameters associated with the method.
+   */
+  NodeList<FormalParameter> _parameters;
+
+  /**
+   * The left square bracket ('[') or left curly brace ('{') introducing the
+   * optional parameters, or `null` if there are no optional parameters.
+   */
+  Token leftDelimiter;
+
+  /**
+   * The right square bracket (']') or right curly brace ('}') terminating the
+   * optional parameters, or `null` if there are no optional parameters.
+   */
+  Token rightDelimiter;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * Initialize a newly created parameter list. The list of [parameters] can be
+   * `null` if there are no parameters. The [leftDelimiter] and [rightDelimiter]
+   * can be `null` if there are no optional parameters.
+   */
+  FormalParameterListImpl(
+      this.leftParenthesis,
+      List<FormalParameter> parameters,
+      this.leftDelimiter,
+      this.rightDelimiter,
+      this.rightParenthesis) {
+    _parameters = new NodeList<FormalParameter>(this, parameters);
+  }
+
+  @override
+  Token get beginToken => leftParenthesis;
+
+  @override
+  Iterable get childEntities {
+    // TODO(paulberry): include commas.
+    ChildEntities result = new ChildEntities()..add(leftParenthesis);
+    bool leftDelimiterNeeded = leftDelimiter != null;
+    for (FormalParameter parameter in _parameters) {
+      if (leftDelimiterNeeded && leftDelimiter.offset < parameter.offset) {
+        result.add(leftDelimiter);
+        leftDelimiterNeeded = false;
+      }
+      result.add(parameter);
+    }
+    return result..add(rightDelimiter)..add(rightParenthesis);
+  }
+
+  @override
+  Token get endToken => rightParenthesis;
+
+  @override
+  List<ParameterElement> get parameterElements {
+    int count = _parameters.length;
+    List<ParameterElement> types = new List<ParameterElement>(count);
+    for (int i = 0; i < count; i++) {
+      types[i] = _parameters[i].element;
+    }
+    return types;
+  }
+
+  @override
+  NodeList<FormalParameter> get parameters => _parameters;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFormalParameterList(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _parameters.accept(visitor);
+  }
+}
+
+/**
+ * A for statement.
+ *
+ * > forStatement ::=
+ * >     'for' '(' forLoopParts ')' [Statement]
+ * >
+ * > forLoopParts ::=
+ * >     forInitializerStatement ';' [Expression]? ';' [Expression]?
+ * >
+ * > forInitializerStatement ::=
+ * >     [DefaultFormalParameter]
+ * >   | [Expression]?
+ */
+class ForStatementImpl extends StatementImpl implements ForStatement {
+  /**
+   * The token representing the 'for' keyword.
+   */
+  Token forKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The declaration of the loop variables, or `null` if there are no variables.
+   * Note that a for statement cannot have both a variable list and an
+   * initialization expression, but can validly have neither.
+   */
+  VariableDeclarationList _variableList;
+
+  /**
+   * The initialization expression, or `null` if there is no initialization
+   * expression. Note that a for statement cannot have both a variable list and
+   * an initialization expression, but can validly have neither.
+   */
+  Expression _initialization;
+
+  /**
+   * The semicolon separating the initializer and the condition.
+   */
+  Token leftSeparator;
+
+  /**
+   * The condition used to determine when to terminate the loop, or `null` if
+   * there is no condition.
+   */
+  Expression _condition;
+
+  /**
+   * The semicolon separating the condition and the updater.
+   */
+  Token rightSeparator;
+
+  /**
+   * The list of expressions run after each execution of the loop body.
+   */
+  NodeList<Expression> _updaters;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The body of the loop.
+   */
+  Statement _body;
+
+  /**
+   * Initialize a newly created for statement. Either the [variableList] or the
+   * [initialization] must be `null`. Either the [condition] and the list of
+   * [updaters] can be `null` if the loop does not have the corresponding
+   * attribute.
+   */
+  ForStatementImpl(
+      this.forKeyword,
+      this.leftParenthesis,
+      VariableDeclarationList variableList,
+      Expression initialization,
+      this.leftSeparator,
+      Expression condition,
+      this.rightSeparator,
+      List<Expression> updaters,
+      this.rightParenthesis,
+      Statement body) {
+    _variableList = _becomeParentOf(variableList);
+    _initialization = _becomeParentOf(initialization);
+    _condition = _becomeParentOf(condition);
+    _updaters = new NodeList<Expression>(this, updaters);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  Token get beginToken => forKeyword;
+
+  @override
+  Statement get body => _body;
+
+  @override
+  void set body(Statement statement) {
+    _body = _becomeParentOf(statement);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(forKeyword)
+    ..add(leftParenthesis)
+    ..add(_variableList)
+    ..add(_initialization)
+    ..add(leftSeparator)
+    ..add(_condition)
+    ..add(rightSeparator)
+    ..addAll(_updaters)
+    ..add(rightParenthesis)
+    ..add(_body);
+
+  @override
+  Expression get condition => _condition;
+
+  @override
+  void set condition(Expression expression) {
+    _condition = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get endToken => _body.endToken;
+
+  @override
+  Expression get initialization => _initialization;
+
+  @override
+  void set initialization(Expression initialization) {
+    _initialization = _becomeParentOf(initialization);
+  }
+
+  @override
+  NodeList<Expression> get updaters => _updaters;
+
+  @override
+  VariableDeclarationList get variables => _variableList;
+
+  @override
+  void set variables(VariableDeclarationList variableList) {
+    _variableList = _becomeParentOf(variableList);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitForStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_variableList, visitor);
+    _safelyVisitChild(_initialization, visitor);
+    _safelyVisitChild(_condition, visitor);
+    _updaters.accept(visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * A node representing the body of a function or method.
+ *
+ * > functionBody ::=
+ * >     [BlockFunctionBody]
+ * >   | [EmptyFunctionBody]
+ * >   | [ExpressionFunctionBody]
+ */
+abstract class FunctionBodyImpl extends AstNodeImpl implements FunctionBody {
+  /**
+   * Return `true` if this function body is asynchronous.
+   */
+  bool get isAsynchronous => false;
+
+  /**
+   * Return `true` if this function body is a generator.
+   */
+  bool get isGenerator => false;
+
+  /**
+   * Return `true` if this function body is synchronous.
+   */
+  bool get isSynchronous => true;
+
+  /**
+   * Return the token representing the 'async' or 'sync' keyword, or `null` if
+   * there is no such keyword.
+   */
+  Token get keyword => null;
+
+  /**
+   * Return the star following the 'async' or 'sync' keyword, or `null` if there
+   * is no star.
+   */
+  Token get star => null;
+}
+
+/**
+ * A top-level declaration.
+ *
+ * > functionDeclaration ::=
+ * >     'external' functionSignature
+ * >   | functionSignature [FunctionBody]
+ * >
+ * > functionSignature ::=
+ * >     [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
+ */
+class FunctionDeclarationImpl extends NamedCompilationUnitMemberImpl
+    implements FunctionDeclaration {
+  /**
+   * The token representing the 'external' keyword, or `null` if this is not an
+   * external function.
+   */
+  Token externalKeyword;
+
+  /**
+   * The return type of the function, or `null` if no return type was declared.
+   */
+  TypeName _returnType;
+
+  /**
+   * The token representing the 'get' or 'set' keyword, or `null` if this is a
+   * function declaration rather than a property declaration.
+   */
+  Token propertyKeyword;
+
+  /**
+   * The function expression being wrapped.
+   */
+  FunctionExpression _functionExpression;
+
+  /**
+   * Initialize a newly created function declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the function does not have the
+   * corresponding attribute. The [externalKeyword] can be `null` if the
+   * function is not an external function. The [returnType] can be `null` if no
+   * return type was specified. The [propertyKeyword] can be `null` if the
+   * function is neither a getter or a setter.
+   */
+  FunctionDeclarationImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.externalKeyword,
+      TypeName returnType,
+      this.propertyKeyword,
+      SimpleIdentifier name,
+      FunctionExpression functionExpression)
+      : super(comment, metadata, name) {
+    _returnType = _becomeParentOf(returnType);
+    _functionExpression = _becomeParentOf(functionExpression);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(externalKeyword)
+    ..add(_returnType)
+    ..add(propertyKeyword)
+    ..add(_name)
+    ..add(_functionExpression);
+
+  @override
+  ExecutableElement get element =>
+      _name != null ? (_name.staticElement as ExecutableElement) : null;
+
+  @override
+  Token get endToken => _functionExpression.endToken;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    if (externalKeyword != null) {
+      return externalKeyword;
+    } else if (_returnType != null) {
+      return _returnType.beginToken;
+    } else if (propertyKeyword != null) {
+      return propertyKeyword;
+    } else if (_name != null) {
+      return _name.beginToken;
+    }
+    return _functionExpression.beginToken;
+  }
+
+  @override
+  FunctionExpression get functionExpression => _functionExpression;
+
+  @override
+  void set functionExpression(FunctionExpression functionExpression) {
+    _functionExpression = _becomeParentOf(functionExpression);
+  }
+
+  @override
+  bool get isGetter =>
+      propertyKeyword != null &&
+      (propertyKeyword as KeywordToken).keyword == Keyword.GET;
+
+  @override
+  bool get isSetter =>
+      propertyKeyword != null &&
+      (propertyKeyword as KeywordToken).keyword == Keyword.SET;
+
+  @override
+  TypeName get returnType => _returnType;
+
+  @override
+  void set returnType(TypeName returnType) {
+    _returnType = _becomeParentOf(returnType);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFunctionDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_returnType, visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_functionExpression, visitor);
+  }
+}
+
+/**
+ * A [FunctionDeclaration] used as a statement.
+ */
+class FunctionDeclarationStatementImpl extends StatementImpl
+    implements FunctionDeclarationStatement {
+  /**
+   * The function declaration being wrapped.
+   */
+  FunctionDeclaration _functionDeclaration;
+
+  /**
+   * Initialize a newly created function declaration statement.
+   */
+  FunctionDeclarationStatementImpl(FunctionDeclaration functionDeclaration) {
+    _functionDeclaration = _becomeParentOf(functionDeclaration);
+  }
+
+  @override
+  Token get beginToken => _functionDeclaration.beginToken;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(_functionDeclaration);
+
+  @override
+  Token get endToken => _functionDeclaration.endToken;
+
+  @override
+  FunctionDeclaration get functionDeclaration => _functionDeclaration;
+
+  @override
+  void set functionDeclaration(FunctionDeclaration functionDeclaration) {
+    _functionDeclaration = _becomeParentOf(functionDeclaration);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFunctionDeclarationStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_functionDeclaration, visitor);
+  }
+}
+
+/**
+ * A function expression.
+ *
+ * > functionExpression ::=
+ * >     [TypeParameterList]? [FormalParameterList] [FunctionBody]
+ */
+class FunctionExpressionImpl extends ExpressionImpl
+    implements FunctionExpression {
+  /**
+   * The type parameters associated with the method, or `null` if the method is
+   * not a generic method.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The parameters associated with the function.
+   */
+  FormalParameterList _parameters;
+
+  /**
+   * The body of the function, or `null` if this is an external function.
+   */
+  FunctionBody _body;
+
+  /**
+   * The element associated with the function, or `null` if the AST structure
+   * has not been resolved.
+   */
+  ExecutableElement element;
+
+  /**
+   * Initialize a newly created function declaration.
+   */
+  FunctionExpressionImpl(TypeParameterList typeParameters,
+      FormalParameterList parameters, FunctionBody body) {
+    _typeParameters = _becomeParentOf(typeParameters);
+    _parameters = _becomeParentOf(parameters);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  Token get beginToken {
+    if (_typeParameters != null) {
+      return _typeParameters.beginToken;
+    } else if (_parameters != null) {
+      return _parameters.beginToken;
+    } else if (_body != null) {
+      return _body.beginToken;
+    }
+    // This should never be reached because external functions must be named,
+    // hence either the body or the name should be non-null.
+    throw new IllegalStateException("Non-external functions must have a body");
+  }
+
+  @override
+  FunctionBody get body => _body;
+
+  @override
+  void set body(FunctionBody functionBody) {
+    _body = _becomeParentOf(functionBody);
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_parameters)..add(_body);
+
+  @override
+  Token get endToken {
+    if (_body != null) {
+      return _body.endToken;
+    } else if (_parameters != null) {
+      return _parameters.endToken;
+    }
+    // This should never be reached because external functions must be named,
+    // hence either the body or the name should be non-null.
+    throw new IllegalStateException("Non-external functions must have a body");
+  }
+
+  @override
+  FormalParameterList get parameters => _parameters;
+
+  @override
+  void set parameters(FormalParameterList parameters) {
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  int get precedence => 16;
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFunctionExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_parameters, visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * The invocation of a function resulting from evaluating an expression.
+ * Invocations of methods and other forms of functions are represented by
+ * [MethodInvocation] nodes. Invocations of getters and setters are represented
+ * by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+ *
+ * > functionExpressionInvocation ::=
+ * >     [Expression] [TypeArgumentList]? [ArgumentList]
+ */
+class FunctionExpressionInvocationImpl extends ExpressionImpl
+    implements FunctionExpressionInvocation {
+  /**
+   * The expression producing the function being invoked.
+   */
+  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.
+   */
+  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.
+   */
+  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) {
+    _function = _becomeParentOf(function);
+    _typeArguments = _becomeParentOf(typeArguments);
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  ArgumentList get argumentList => _argumentList;
+
+  @override
+  void set argumentList(ArgumentList argumentList) {
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  Token get beginToken => _function.beginToken;
+
+  @override
+  ExecutableElement get bestElement {
+    ExecutableElement element = propagatedElement;
+    if (element == null) {
+      element = staticElement;
+    }
+    return element;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_function)..add(_argumentList);
+
+  @override
+  Token get endToken => _argumentList.endToken;
+
+  @override
+  Expression get function => _function;
+
+  @override
+  void set function(Expression expression) {
+    _function = _becomeParentOf(expression);
+  }
+
+  @override
+  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
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_function, visitor);
+    _safelyVisitChild(_typeArguments, visitor);
+    _safelyVisitChild(_argumentList, visitor);
+  }
+}
+
+/**
+ * A function type alias.
+ *
+ * > functionTypeAlias ::=
+ * >     functionPrefix [TypeParameterList]? [FormalParameterList] ';'
+ * >
+ * > functionPrefix ::=
+ * >     [TypeName]? [SimpleIdentifier]
+ */
+class FunctionTypeAliasImpl extends TypeAliasImpl implements FunctionTypeAlias {
+  /**
+   * The name of the return type of the function type being defined, or `null`
+   * if no return type was given.
+   */
+  TypeName _returnType;
+
+  /**
+   * The type parameters for the function type, or `null` if the function type
+   * does not have any type parameters.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The parameters associated with the function type.
+   */
+  FormalParameterList _parameters;
+
+  /**
+   * Initialize a newly created function type alias. Either or both of the
+   * [comment] and [metadata] can be `null` if the function does not have the
+   * corresponding attribute. The [returnType] can be `null` if no return type
+   * was specified. The [typeParameters] can be `null` if the function has no
+   * type parameters.
+   */
+  FunctionTypeAliasImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      TypeName returnType,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters,
+      Token semicolon)
+      : super(comment, metadata, keyword, name, semicolon) {
+    _returnType = _becomeParentOf(returnType);
+    _typeParameters = _becomeParentOf(typeParameters);
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(typedefKeyword)
+    ..add(_returnType)
+    ..add(_name)
+    ..add(_typeParameters)
+    ..add(_parameters)
+    ..add(semicolon);
+
+  @override
+  FunctionTypeAliasElement get element =>
+      _name != null ? (_name.staticElement as FunctionTypeAliasElement) : null;
+
+  @override
+  FormalParameterList get parameters => _parameters;
+
+  @override
+  void set parameters(FormalParameterList parameters) {
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  TypeName get returnType => _returnType;
+
+  @override
+  void set returnType(TypeName typeName) {
+    _returnType = _becomeParentOf(typeName);
+  }
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFunctionTypeAlias(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_returnType, visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_parameters, visitor);
+  }
+}
+
+/**
+ * A function-typed formal parameter.
+ *
+ * > functionSignature ::=
+ * >     [TypeName]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
+ */
+class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl
+    implements FunctionTypedFormalParameter {
+  /**
+   * The return type of the function, or `null` if the function does not have a
+   * return type.
+   */
+  TypeName _returnType;
+
+  /**
+   * The type parameters associated with the function, or `null` if the function
+   * is not a generic function.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The parameters of the function-typed parameter.
+   */
+  FormalParameterList _parameters;
+
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [returnType] can be `null` if no return type
+   * was specified.
+   */
+  FunctionTypedFormalParameterImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      TypeName returnType,
+      SimpleIdentifier identifier,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters)
+      : super(comment, metadata, identifier) {
+    _returnType = _becomeParentOf(returnType);
+    _typeParameters = _becomeParentOf(typeParameters);
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  Token get beginToken {
+    if (_returnType != null) {
+      return _returnType.beginToken;
+    }
+    return identifier.beginToken;
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(_returnType)..add(identifier)..add(parameters);
+
+  @override
+  Token get endToken => _parameters.endToken;
+
+  @override
+  bool get isConst => false;
+
+  @override
+  bool get isFinal => false;
+
+  @override
+  FormalParameterList get parameters => _parameters;
+
+  @override
+  void set parameters(FormalParameterList parameters) {
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  TypeName get returnType => _returnType;
+
+  @override
+  void set returnType(TypeName type) {
+    _returnType = _becomeParentOf(type);
+  }
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitFunctionTypedFormalParameter(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_returnType, visitor);
+    _safelyVisitChild(identifier, visitor);
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_parameters, visitor);
+  }
+}
+
+/**
+ * A combinator that restricts the names being imported to those that are not in
+ * a given list.
+ *
+ * > hideCombinator ::=
+ * >     'hide' [SimpleIdentifier] (',' [SimpleIdentifier])*
+ */
+class HideCombinatorImpl extends CombinatorImpl implements HideCombinator {
+  /**
+   * The list of names from the library that are hidden by this combinator.
+   */
+  NodeList<SimpleIdentifier> _hiddenNames;
+
+  /**
+   * Initialize a newly created import show combinator.
+   */
+  HideCombinatorImpl(Token keyword, List<SimpleIdentifier> hiddenNames)
+      : super(keyword) {
+    _hiddenNames = new NodeList<SimpleIdentifier>(this, hiddenNames);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(keyword)
+    ..addAll(_hiddenNames);
+
+  @override
+  Token get endToken => _hiddenNames.endToken;
+
+  @override
+  NodeList<SimpleIdentifier> get hiddenNames => _hiddenNames;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitHideCombinator(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _hiddenNames.accept(visitor);
+  }
+}
+
+/**
+ * A node that represents an identifier.
+ *
+ * > identifier ::=
+ * >     [SimpleIdentifier]
+ * >   | [PrefixedIdentifier]
+ */
+abstract class IdentifierImpl extends ExpressionImpl implements Identifier {
+  /**
+   * Return the best element available for this operator. If resolution was able
+   * to find a better element based on type propagation, that element will be
+   * returned. Otherwise, the element found using the result of static analysis
+   * will be returned. If resolution has not been performed, then `null` will be
+   * returned.
+   */
+  Element get bestElement;
+
+  @override
+  bool get isAssignable => true;
+}
+
+/**
+ * An if statement.
+ *
+ * > ifStatement ::=
+ * >     'if' '(' [Expression] ')' [Statement] ('else' [Statement])?
+ */
+class IfStatementImpl extends StatementImpl implements IfStatement {
+  /**
+   * The token representing the 'if' keyword.
+   */
+  Token ifKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The condition used to determine which of the statements is executed next.
+   */
+  Expression _condition;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The statement that is executed if the condition evaluates to `true`.
+   */
+  Statement _thenStatement;
+
+  /**
+   * The token representing the 'else' keyword, or `null` if there is no else
+   * statement.
+   */
+  Token elseKeyword;
+
+  /**
+   * The statement that is executed if the condition evaluates to `false`, or
+   * `null` if there is no else statement.
+   */
+  Statement _elseStatement;
+
+  /**
+   * Initialize a newly created if statement. The [elseKeyword] and
+   * [elseStatement] can be `null` if there is no else clause.
+   */
+  IfStatementImpl(
+      this.ifKeyword,
+      this.leftParenthesis,
+      Expression condition,
+      this.rightParenthesis,
+      Statement thenStatement,
+      this.elseKeyword,
+      Statement elseStatement) {
+    _condition = _becomeParentOf(condition);
+    _thenStatement = _becomeParentOf(thenStatement);
+    _elseStatement = _becomeParentOf(elseStatement);
+  }
+
+  @override
+  Token get beginToken => ifKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(ifKeyword)
+    ..add(leftParenthesis)
+    ..add(_condition)
+    ..add(rightParenthesis)
+    ..add(_thenStatement)
+    ..add(elseKeyword)
+    ..add(_elseStatement);
+
+  @override
+  Expression get condition => _condition;
+
+  @override
+  void set condition(Expression expression) {
+    _condition = _becomeParentOf(expression);
+  }
+
+  @override
+  Statement get elseStatement => _elseStatement;
+
+  @override
+  void set elseStatement(Statement statement) {
+    _elseStatement = _becomeParentOf(statement);
+  }
+
+  @override
+  Token get endToken {
+    if (_elseStatement != null) {
+      return _elseStatement.endToken;
+    }
+    return _thenStatement.endToken;
+  }
+
+  @override
+  Statement get thenStatement => _thenStatement;
+
+  @override
+  void set thenStatement(Statement statement) {
+    _thenStatement = _becomeParentOf(statement);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitIfStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_condition, visitor);
+    _safelyVisitChild(_thenStatement, visitor);
+    _safelyVisitChild(_elseStatement, visitor);
+  }
+}
+
+/**
+ * The "implements" clause in an class declaration.
+ *
+ * > implementsClause ::=
+ * >     'implements' [TypeName] (',' [TypeName])*
+ */
+class ImplementsClauseImpl extends AstNodeImpl implements ImplementsClause {
+  /**
+   * The token representing the 'implements' keyword.
+   */
+  Token implementsKeyword;
+
+  /**
+   * The interfaces that are being implemented.
+   */
+  NodeList<TypeName> _interfaces;
+
+  /**
+   * Initialize a newly created implements clause.
+   */
+  ImplementsClauseImpl(this.implementsKeyword, List<TypeName> interfaces) {
+    _interfaces = new NodeList<TypeName>(this, interfaces);
+  }
+
+  @override
+  Token get beginToken => implementsKeyword;
+
+  @override
+  // TODO(paulberry): add commas.
+  Iterable get childEntities => new ChildEntities()
+    ..add(implementsKeyword)
+    ..addAll(interfaces);
+
+  @override
+  Token get endToken => _interfaces.endToken;
+
+  @override
+  NodeList<TypeName> get interfaces => _interfaces;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitImplementsClause(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _interfaces.accept(visitor);
+  }
+}
+
+/**
+ * An import directive.
+ *
+ * > importDirective ::=
+ * >     [Annotation] 'import' [StringLiteral] ('as' identifier)? [Combinator]* ';'
+ * >   | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier [Combinator]* ';'
+ */
+class ImportDirectiveImpl extends NamespaceDirectiveImpl
+    implements ImportDirective {
+  /**
+   * The token representing the 'deferred' keyword, or `null` if the imported is
+   * not deferred.
+   */
+  Token deferredKeyword;
+
+  /**
+   * The token representing the 'as' keyword, or `null` if the imported names are
+   * not prefixed.
+   */
+  Token asKeyword;
+
+  /**
+   * The prefix to be used with the imported names, or `null` if the imported
+   * names are not prefixed.
+   */
+  SimpleIdentifier _prefix;
+
+  /**
+   * Initialize a newly created import directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the function does not have the
+   * corresponding attribute. The [deferredKeyword] can be `null` if the import
+   * is not deferred. The [asKeyword] and [prefix] can be `null` if the import
+   * does not specify a prefix. The list of [combinators] can be `null` if there
+   * are no combinators.
+   */
+  ImportDirectiveImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      Token keyword,
+      StringLiteral libraryUri,
+      List<Configuration> configurations,
+      this.deferredKeyword,
+      this.asKeyword,
+      SimpleIdentifier prefix,
+      List<Combinator> combinators,
+      Token semicolon)
+      : super(comment, metadata, keyword, libraryUri, configurations,
+            combinators, semicolon) {
+    _prefix = _becomeParentOf(prefix);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(_uri)
+    ..add(deferredKeyword)
+    ..add(asKeyword)
+    ..add(_prefix)
+    ..addAll(combinators)
+    ..add(semicolon);
+
+  @override
+  ImportElement get element => super.element as ImportElement;
+
+  @override
+  SimpleIdentifier get prefix => _prefix;
+
+  @override
+  void set prefix(SimpleIdentifier identifier) {
+    _prefix = _becomeParentOf(identifier);
+  }
+
+  @override
+  LibraryElement get uriElement {
+    ImportElement element = this.element;
+    if (element == null) {
+      return null;
+    }
+    return element.importedLibrary;
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitImportDirective(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_prefix, visitor);
+    combinators.accept(visitor);
+  }
+}
+
+/**
+ * An index expression.
+ *
+ * > indexExpression ::=
+ * >     [Expression] '[' [Expression] ']'
+ */
+class IndexExpressionImpl extends ExpressionImpl implements IndexExpression {
+  /**
+   * The expression used to compute the object being indexed, or `null` if this
+   * index expression is part of a cascade expression.
+   */
+  Expression _target;
+
+  /**
+   * The period ("..") before a cascaded index expression, or `null` if this
+   * index expression is not part of a cascade expression.
+   */
+  Token period;
+
+  /**
+   * The left square bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The expression used to compute the index.
+   */
+  Expression _index;
+
+  /**
+   * The right square bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * The element associated with the operator based on the static type of the
+   * target, or `null` if the AST structure has not been resolved or if the
+   * operator could not be resolved.
+   */
+  MethodElement staticElement;
+
+  /**
+   * The element associated with the operator based on the propagated type of
+   * the target, or `null` if the AST structure has not been resolved or if the
+   * operator could not be resolved.
+   */
+  MethodElement propagatedElement;
+
+  /**
+   * If this expression is both in a getter and setter context, the
+   * [AuxiliaryElements] will be set to hold onto the static and propagated
+   * information. The auxiliary element will hold onto the elements from the
+   * getter context.
+   */
+  AuxiliaryElements auxiliaryElements = null;
+
+  /**
+   * Initialize a newly created index expression.
+   */
+  IndexExpressionImpl.forCascade(
+      this.period, this.leftBracket, Expression index, this.rightBracket) {
+    _index = _becomeParentOf(index);
+  }
+
+  /**
+   * Initialize a newly created index expression.
+   */
+  IndexExpressionImpl.forTarget(Expression target, this.leftBracket,
+      Expression index, this.rightBracket) {
+    _target = _becomeParentOf(target);
+    _index = _becomeParentOf(index);
+  }
+
+  @override
+  Token get beginToken {
+    if (_target != null) {
+      return _target.beginToken;
+    }
+    return period;
+  }
+
+  @override
+  MethodElement get bestElement {
+    MethodElement element = propagatedElement;
+    if (element == null) {
+      element = staticElement;
+    }
+    return element;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(_target)
+    ..add(period)
+    ..add(leftBracket)
+    ..add(_index)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  Expression get index => _index;
+
+  @override
+  void set index(Expression expression) {
+    _index = _becomeParentOf(expression);
+  }
+
+  @override
+  bool get isAssignable => true;
+
+  @override
+  bool get isCascaded => period != null;
+
+  @override
+  int get precedence => 15;
+
+  @override
+  Expression get realTarget {
+    if (isCascaded) {
+      AstNode ancestor = parent;
+      while (ancestor is! CascadeExpression) {
+        if (ancestor == null) {
+          return _target;
+        }
+        ancestor = ancestor.parent;
+      }
+      return (ancestor as CascadeExpression).target;
+    }
+    return _target;
+  }
+
+  @override
+  Expression get target => _target;
+
+  @override
+  void set target(Expression expression) {
+    _target = _becomeParentOf(expression);
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on propagated type information, then return the parameter
+   * element representing the parameter to which the value of the index
+   * expression will be bound. Otherwise, return `null`.
+   */
+  ParameterElement get _propagatedParameterElementForIndex {
+    if (propagatedElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = propagatedElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on static type information, then return the parameter element
+   * representing the parameter to which the value of the index expression will
+   * be bound. Otherwise, return `null`.
+   */
+  ParameterElement get _staticParameterElementForIndex {
+    if (staticElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = staticElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitIndexExpression(this);
+
+  @override
+  bool inGetterContext() {
+    // TODO(brianwilkerson) Convert this to a getter.
+    AstNode parent = this.parent;
+    if (parent is AssignmentExpression) {
+      AssignmentExpression assignment = parent;
+      if (identical(assignment.leftHandSide, this) &&
+          assignment.operator.type == TokenType.EQ) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @override
+  bool inSetterContext() {
+    // TODO(brianwilkerson) Convert this to a getter.
+    AstNode parent = this.parent;
+    if (parent is PrefixExpression) {
+      return parent.operator.type.isIncrementOperator;
+    } else if (parent is PostfixExpression) {
+      return true;
+    } else if (parent is AssignmentExpression) {
+      return identical(parent.leftHandSide, this);
+    }
+    return false;
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_target, visitor);
+    _safelyVisitChild(_index, visitor);
+  }
+}
+
+/**
+ * An instance creation expression.
+ *
+ * > newExpression ::=
+ * >     ('new' | 'const') [TypeName] ('.' [SimpleIdentifier])? [ArgumentList]
+ */
+class InstanceCreationExpressionImpl extends ExpressionImpl
+    implements InstanceCreationExpression {
+  /**
+   * The 'new' or 'const' keyword used to indicate how an object should be
+   * created.
+   */
+  Token keyword;
+
+  /**
+   * The name of the constructor to be invoked.
+   */
+  ConstructorName _constructorName;
+
+  /**
+   * The list of arguments to the constructor.
+   */
+  ArgumentList _argumentList;
+
+  /**
+   * The element associated with the constructor based on static type
+   * information, or `null` if the AST structure has not been resolved or if the
+   * constructor could not be resolved.
+   */
+  ConstructorElement staticElement;
+
+  /**
+   * Initialize a newly created instance creation expression.
+   */
+  InstanceCreationExpressionImpl(this.keyword, ConstructorName constructorName,
+      ArgumentList argumentList) {
+    _constructorName = _becomeParentOf(constructorName);
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  ArgumentList get argumentList => _argumentList;
+
+  @override
+  void set argumentList(ArgumentList argumentList) {
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  Token get beginToken => keyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(keyword)
+    ..add(_constructorName)
+    ..add(_argumentList);
+
+  @override
+  ConstructorName get constructorName => _constructorName;
+
+  @override
+  void set constructorName(ConstructorName name) {
+    _constructorName = _becomeParentOf(name);
+  }
+
+  @override
+  Token get endToken => _argumentList.endToken;
+
+  @override
+  bool get isConst =>
+      keyword is KeywordToken &&
+      (keyword as KeywordToken).keyword == Keyword.CONST;
+
+  @override
+  int get precedence => 16;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitInstanceCreationExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_constructorName, visitor);
+    _safelyVisitChild(_argumentList, visitor);
+  }
+}
+
+/**
+ * An integer literal expression.
+ *
+ * > integerLiteral ::=
+ * >     decimalIntegerLiteral
+ * >   | hexadecimalIntegerLiteral
+ * >
+ * > decimalIntegerLiteral ::=
+ * >     decimalDigit+
+ * >
+ * > hexadecimalIntegerLiteral ::=
+ * >     '0x' hexadecimalDigit+
+ * >   | '0X' hexadecimalDigit+
+ */
+class IntegerLiteralImpl extends LiteralImpl implements IntegerLiteral {
+  /**
+   * The token representing the literal.
+   */
+  Token literal;
+
+  /**
+   * The value of the literal.
+   */
+  int value = 0;
+
+  /**
+   * Initialize a newly created integer literal.
+   */
+  IntegerLiteralImpl(this.literal, this.value);
+
+  @override
+  Token get beginToken => literal;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(literal);
+
+  @override
+  Token get endToken => literal;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitIntegerLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A node within a [StringInterpolation].
+ *
+ * > interpolationElement ::=
+ * >     [InterpolationExpression]
+ * >   | [InterpolationString]
+ */
+abstract class InterpolationElementImpl extends AstNodeImpl
+    implements InterpolationElement {}
+
+/**
+ * An expression embedded in a string interpolation.
+ *
+ * > interpolationExpression ::=
+ * >     '$' [SimpleIdentifier]
+ * >   | '$' '{' [Expression] '}'
+ */
+class InterpolationExpressionImpl extends InterpolationElementImpl
+    implements InterpolationExpression {
+  /**
+   * The token used to introduce the interpolation expression; either '$' if the
+   * expression is a simple identifier or '${' if the expression is a full
+   * expression.
+   */
+  Token leftBracket;
+
+  /**
+   * The expression to be evaluated for the value to be converted into a string.
+   */
+  Expression _expression;
+
+  /**
+   * The right curly bracket, or `null` if the expression is an identifier
+   * without brackets.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created interpolation expression.
+   */
+  InterpolationExpressionImpl(
+      this.leftBracket, Expression expression, this.rightBracket) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken => leftBracket;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(leftBracket)
+    ..add(_expression)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken {
+    if (rightBracket != null) {
+      return rightBracket;
+    }
+    return _expression.endToken;
+  }
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitInterpolationExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A non-empty substring of an interpolated string.
+ *
+ * > interpolationString ::=
+ * >     characters
+ */
+class InterpolationStringImpl extends InterpolationElementImpl
+    implements InterpolationString {
+  /**
+   * The characters that will be added to the string.
+   */
+  Token contents;
+
+  /**
+   * The value of the literal.
+   */
+  String value;
+
+  /**
+   * Initialize a newly created string of characters that are part of a string
+   * interpolation.
+   */
+  InterpolationStringImpl(this.contents, this.value);
+
+  @override
+  Token get beginToken => contents;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(contents);
+
+  @override
+  int get contentsEnd {
+    String lexeme = contents.lexeme;
+    return offset + new StringLexemeHelper(lexeme, true, true).end;
+  }
+
+  @override
+  int get contentsOffset {
+    int offset = contents.offset;
+    String lexeme = contents.lexeme;
+    return offset + new StringLexemeHelper(lexeme, true, true).start;
+  }
+
+  @override
+  Token get endToken => contents;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitInterpolationString(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {}
+}
+
+/**
+ * An is expression.
+ *
+ * > isExpression ::=
+ * >     [Expression] 'is' '!'? [TypeName]
+ */
+class IsExpressionImpl extends ExpressionImpl implements IsExpression {
+  /**
+   * The expression used to compute the value whose type is being tested.
+   */
+  Expression _expression;
+
+  /**
+   * The is operator.
+   */
+  Token isOperator;
+
+  /**
+   * The not operator, or `null` if the sense of the test is not negated.
+   */
+  Token notOperator;
+
+  /**
+   * The name of the type being tested for.
+   */
+  TypeName _type;
+
+  /**
+   * Initialize a newly created is expression. The [notOperator] can be `null`
+   * if the sense of the test is not negated.
+   */
+  IsExpressionImpl(
+      Expression expression, this.isOperator, this.notOperator, TypeName type) {
+    _expression = _becomeParentOf(expression);
+    _type = _becomeParentOf(type);
+  }
+
+  @override
+  Token get beginToken => _expression.beginToken;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(_expression)
+    ..add(isOperator)
+    ..add(notOperator)
+    ..add(_type);
+
+  @override
+  Token get endToken => _type.endToken;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 7;
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName name) {
+    _type = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitIsExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+    _safelyVisitChild(_type, visitor);
+  }
+}
+
+/**
+ * A statement that has a label associated with them.
+ *
+ * > labeledStatement ::=
+ * >    [Label]+ [Statement]
+ */
+class LabeledStatementImpl extends StatementImpl implements LabeledStatement {
+  /**
+   * The labels being associated with the statement.
+   */
+  NodeList<Label> _labels;
+
+  /**
+   * The statement with which the labels are being associated.
+   */
+  Statement _statement;
+
+  /**
+   * Initialize a newly created labeled statement.
+   */
+  LabeledStatementImpl(List<Label> labels, Statement statement) {
+    _labels = new NodeList<Label>(this, labels);
+    _statement = _becomeParentOf(statement);
+  }
+
+  @override
+  Token get beginToken {
+    if (!_labels.isEmpty) {
+      return _labels.beginToken;
+    }
+    return _statement.beginToken;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..addAll(_labels)
+    ..add(_statement);
+
+  @override
+  Token get endToken => _statement.endToken;
+
+  @override
+  NodeList<Label> get labels => _labels;
+
+  @override
+  Statement get statement => _statement;
+
+  @override
+  void set statement(Statement statement) {
+    _statement = _becomeParentOf(statement);
+  }
+
+  @override
+  Statement get unlabeled => _statement.unlabeled;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitLabeledStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _labels.accept(visitor);
+    _safelyVisitChild(_statement, visitor);
+  }
+}
+
+/**
+ * A label on either a [LabeledStatement] or a [NamedExpression].
+ *
+ * > label ::=
+ * >     [SimpleIdentifier] ':'
+ */
+class LabelImpl extends AstNodeImpl implements Label {
+  /**
+   * The label being associated with the statement.
+   */
+  SimpleIdentifier _label;
+
+  /**
+   * The colon that separates the label from the statement.
+   */
+  Token colon;
+
+  /**
+   * Initialize a newly created label.
+   */
+  LabelImpl(SimpleIdentifier label, this.colon) {
+    _label = _becomeParentOf(label);
+  }
+
+  @override
+  Token get beginToken => _label.beginToken;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(_label)..add(colon);
+
+  @override
+  Token get endToken => colon;
+
+  @override
+  SimpleIdentifier get label => _label;
+
+  @override
+  void set label(SimpleIdentifier label) {
+    _label = _becomeParentOf(label);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitLabel(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_label, visitor);
+  }
+}
+
+/**
+ * A library directive.
+ *
+ * > libraryDirective ::=
+ * >     [Annotation] 'library' [Identifier] ';'
+ */
+class LibraryDirectiveImpl extends DirectiveImpl implements LibraryDirective {
+  /**
+   * The token representing the 'library' keyword.
+   */
+  Token libraryKeyword;
+
+  /**
+   * The name of the library being defined.
+   */
+  LibraryIdentifier _name;
+
+  /**
+   * The semicolon terminating the directive.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created library directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  LibraryDirectiveImpl(Comment comment, List<Annotation> metadata,
+      this.libraryKeyword, LibraryIdentifier name, this.semicolon)
+      : super(comment, metadata) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(libraryKeyword)..add(_name)..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => libraryKeyword;
+
+  @override
+  Token get keyword => libraryKeyword;
+
+  @override
+  LibraryIdentifier get name => _name;
+
+  @override
+  void set name(LibraryIdentifier name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitLibraryDirective(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+  }
+}
+
+/**
+ * The identifier for a library.
+ *
+ * > libraryIdentifier ::=
+ * >     [SimpleIdentifier] ('.' [SimpleIdentifier])*
+ */
+class LibraryIdentifierImpl extends IdentifierImpl
+    implements LibraryIdentifier {
+  /**
+   * The components of the identifier.
+   */
+  NodeList<SimpleIdentifier> _components;
+
+  /**
+   * Initialize a newly created prefixed identifier.
+   */
+  LibraryIdentifierImpl(List<SimpleIdentifier> components) {
+    _components = new NodeList<SimpleIdentifier>(this, components);
+  }
+
+  @override
+  Token get beginToken => _components.beginToken;
+
+  @override
+  Element get bestElement => staticElement;
+
+  @override
+  // TODO(paulberry): add "." tokens.
+  Iterable get childEntities => new ChildEntities()..addAll(_components);
+
+  @override
+  NodeList<SimpleIdentifier> get components => _components;
+
+  @override
+  Token get endToken => _components.endToken;
+
+  @override
+  String get name {
+    StringBuffer buffer = new StringBuffer();
+    bool needsPeriod = false;
+    for (SimpleIdentifier identifier in _components) {
+      if (needsPeriod) {
+        buffer.write(".");
+      } else {
+        needsPeriod = true;
+      }
+      buffer.write(identifier.name);
+    }
+    return buffer.toString();
+  }
+
+  @override
+  int get precedence => 15;
+
+  @override
+  Element get propagatedElement => null;
+
+  @override
+  Element get staticElement => null;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitLibraryIdentifier(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _components.accept(visitor);
+  }
+}
+
+/**
+ * A list literal.
+ *
+ * > listLiteral ::=
+ * >     'const'? ('<' [TypeName] '>')? '[' ([Expression] ','?)? ']'
+ */
+class ListLiteralImpl extends TypedLiteralImpl implements ListLiteral {
+  /**
+   * The left square bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The expressions used to compute the elements of the list.
+   */
+  NodeList<Expression> _elements;
+
+  /**
+   * The right square bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created list literal. The [constKeyword] can be `null`
+   * if the literal is not a constant. The [typeArguments] can be `null` if no
+   * type arguments were declared. The list of [elements] can be `null` if the
+   * list is empty.
+   */
+  ListLiteralImpl(Token constKeyword, TypeArgumentList typeArguments,
+      this.leftBracket, List<Expression> elements, this.rightBracket)
+      : super(constKeyword, typeArguments) {
+    _elements = new NodeList<Expression>(this, elements);
+  }
+
+  @override
+  Token get beginToken {
+    if (constKeyword != null) {
+      return constKeyword;
+    }
+    TypeArgumentList typeArguments = this.typeArguments;
+    if (typeArguments != null) {
+      return typeArguments.beginToken;
+    }
+    return leftBracket;
+  }
+
+  @override
+  // TODO(paulberry): add commas.
+  Iterable get childEntities => super._childEntities
+    ..add(leftBracket)
+    ..addAll(_elements)
+    ..add(rightBracket);
+
+  @override
+  NodeList<Expression> get elements => _elements;
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitListLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _elements.accept(visitor);
+  }
+}
+
+/**
+ * A node that represents a literal expression.
+ *
+ * > literal ::=
+ * >     [BooleanLiteral]
+ * >   | [DoubleLiteral]
+ * >   | [IntegerLiteral]
+ * >   | [ListLiteral]
+ * >   | [MapLiteral]
+ * >   | [NullLiteral]
+ * >   | [StringLiteral]
+ */
+abstract class LiteralImpl extends ExpressionImpl implements Literal {
+  @override
+  int get precedence => 16;
+}
+
+/**
+ * A single key/value pair in a map literal.
+ *
+ * > mapLiteralEntry ::=
+ * >     [Expression] ':' [Expression]
+ */
+class MapLiteralEntryImpl extends AstNodeImpl implements MapLiteralEntry {
+  /**
+   * The expression computing the key with which the value will be associated.
+   */
+  Expression _key;
+
+  /**
+   * The colon that separates the key from the value.
+   */
+  Token separator;
+
+  /**
+   * The expression computing the value that will be associated with the key.
+   */
+  Expression _value;
+
+  /**
+   * Initialize a newly created map literal entry.
+   */
+  MapLiteralEntryImpl(Expression key, this.separator, Expression value) {
+    _key = _becomeParentOf(key);
+    _value = _becomeParentOf(value);
+  }
+
+  @override
+  Token get beginToken => _key.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_key)..add(separator)..add(_value);
+
+  @override
+  Token get endToken => _value.endToken;
+
+  @override
+  Expression get key => _key;
+
+  @override
+  void set key(Expression string) {
+    _key = _becomeParentOf(string);
+  }
+
+  @override
+  Expression get value => _value;
+
+  @override
+  void set value(Expression expression) {
+    _value = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitMapLiteralEntry(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_key, visitor);
+    _safelyVisitChild(_value, visitor);
+  }
+}
+
+/**
+ * A literal map.
+ *
+ * > mapLiteral ::=
+ * >     'const'? ('<' [TypeName] (',' [TypeName])* '>')?
+ * >     '{' ([MapLiteralEntry] (',' [MapLiteralEntry])* ','?)? '}'
+ */
+class MapLiteralImpl extends TypedLiteralImpl implements MapLiteral {
+  /**
+   * The left curly bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The entries in the map.
+   */
+  NodeList<MapLiteralEntry> _entries;
+
+  /**
+   * The right curly bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created map literal. The [constKeyword] can be `null` if
+   * the literal is not a constant. The [typeArguments] can be `null` if no type
+   * arguments were declared. The [entries] can be `null` if the map is empty.
+   */
+  MapLiteralImpl(Token constKeyword, TypeArgumentList typeArguments,
+      this.leftBracket, List<MapLiteralEntry> entries, this.rightBracket)
+      : super(constKeyword, typeArguments) {
+    _entries = new NodeList<MapLiteralEntry>(this, entries);
+  }
+
+  @override
+  Token get beginToken {
+    if (constKeyword != null) {
+      return constKeyword;
+    }
+    TypeArgumentList typeArguments = this.typeArguments;
+    if (typeArguments != null) {
+      return typeArguments.beginToken;
+    }
+    return leftBracket;
+  }
+
+  @override
+  // TODO(paulberry): add commas.
+  Iterable get childEntities => super._childEntities
+    ..add(leftBracket)
+    ..addAll(entries)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  NodeList<MapLiteralEntry> get entries => _entries;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitMapLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _entries.accept(visitor);
+  }
+}
+
+/**
+ * A method declaration.
+ *
+ * > methodDeclaration ::=
+ * >     methodSignature [FunctionBody]
+ * >
+ * > methodSignature ::=
+ * >     'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')?
+ * >     methodName [TypeParameterList] [FormalParameterList]
+ * >
+ * > methodName ::=
+ * >     [SimpleIdentifier]
+ * >   | 'operator' [SimpleIdentifier]
+ */
+class MethodDeclarationImpl extends ClassMemberImpl
+    implements MethodDeclaration {
+  /**
+   * The token for the 'external' keyword, or `null` if the constructor is not
+   * external.
+   */
+  Token externalKeyword;
+
+  /**
+   * The token representing the 'abstract' or 'static' keyword, or `null` if
+   * neither modifier was specified.
+   */
+  Token modifierKeyword;
+
+  /**
+   * The return type of the method, or `null` if no return type was declared.
+   */
+  TypeName _returnType;
+
+  /**
+   * The token representing the 'get' or 'set' keyword, or `null` if this is a
+   * method declaration rather than a property declaration.
+   */
+  Token propertyKeyword;
+
+  /**
+   * The token representing the 'operator' keyword, or `null` if this method
+   * does not declare an operator.
+   */
+  Token operatorKeyword;
+
+  /**
+   * The name of the method.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * The type parameters associated with the method, or `null` if the method is
+   * not a generic method.
+   */
+  TypeParameterList _typeParameters;
+
+  /**
+   * The parameters associated with the method, or `null` if this method
+   * declares a getter.
+   */
+  FormalParameterList _parameters;
+
+  /**
+   * The body of the method.
+   */
+  FunctionBody _body;
+
+  /**
+   * Initialize a newly created method declaration. Either or both of the
+   * [comment] and [metadata] can be `null` if the declaration does not have the
+   * corresponding attribute. The [externalKeyword] can be `null` if the method
+   * is not external. The [modifierKeyword] can be `null` if the method is
+   * neither abstract nor static. The [returnType] can be `null` if no return
+   * type was specified. The [propertyKeyword] can be `null` if the method is
+   * neither a getter or a setter. The [operatorKeyword] can be `null` if the
+   * method does not implement an operator. The [parameters] must be `null` if
+   * this method declares a getter.
+   */
+  MethodDeclarationImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.externalKeyword,
+      this.modifierKeyword,
+      TypeName returnType,
+      this.propertyKeyword,
+      this.operatorKeyword,
+      SimpleIdentifier name,
+      TypeParameterList typeParameters,
+      FormalParameterList parameters,
+      FunctionBody body)
+      : super(comment, metadata) {
+    _returnType = _becomeParentOf(returnType);
+    _name = _becomeParentOf(name);
+    _typeParameters = _becomeParentOf(typeParameters);
+    _parameters = _becomeParentOf(parameters);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  FunctionBody get body => _body;
+
+  @override
+  void set body(FunctionBody functionBody) {
+    _body = _becomeParentOf(functionBody);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(externalKeyword)
+    ..add(modifierKeyword)
+    ..add(_returnType)
+    ..add(propertyKeyword)
+    ..add(operatorKeyword)
+    ..add(_name)
+    ..add(_parameters)
+    ..add(_body);
+
+  /**
+   * Return the element associated with this method, or `null` if the AST
+   * structure has not been resolved. The element can either be a
+   * [MethodElement], if this represents the declaration of a normal method, or
+   * a [PropertyAccessorElement] if this represents the declaration of either a
+   * getter or a setter.
+   */
+  @override
+  ExecutableElement get element =>
+      _name != null ? (_name.staticElement as ExecutableElement) : null;
+
+  @override
+  Token get endToken => _body.endToken;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    if (modifierKeyword != null) {
+      return modifierKeyword;
+    } else if (_returnType != null) {
+      return _returnType.beginToken;
+    } else if (propertyKeyword != null) {
+      return propertyKeyword;
+    } else if (operatorKeyword != null) {
+      return operatorKeyword;
+    }
+    return _name.beginToken;
+  }
+
+  @override
+  bool get isAbstract {
+    FunctionBody body = _body;
+    return externalKeyword == null &&
+        (body is EmptyFunctionBody && !body.semicolon.isSynthetic);
+  }
+
+  @override
+  bool get isGetter =>
+      propertyKeyword != null &&
+      (propertyKeyword as KeywordToken).keyword == Keyword.GET;
+
+  @override
+  bool get isOperator => operatorKeyword != null;
+
+  @override
+  bool get isSetter =>
+      propertyKeyword != null &&
+      (propertyKeyword as KeywordToken).keyword == Keyword.SET;
+
+  @override
+  bool get isStatic =>
+      modifierKeyword != null &&
+      (modifierKeyword as KeywordToken).keyword == Keyword.STATIC;
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+
+  @override
+  FormalParameterList get parameters => _parameters;
+
+  @override
+  void set parameters(FormalParameterList parameters) {
+    _parameters = _becomeParentOf(parameters);
+  }
+
+  @override
+  TypeName get returnType => _returnType;
+
+  @override
+  void set returnType(TypeName typeName) {
+    _returnType = _becomeParentOf(typeName);
+  }
+
+  @override
+  TypeParameterList get typeParameters => _typeParameters;
+
+  @override
+  void set typeParameters(TypeParameterList typeParameters) {
+    _typeParameters = _becomeParentOf(typeParameters);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitMethodDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_returnType, visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_typeParameters, visitor);
+    _safelyVisitChild(_parameters, visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * The invocation of either a function or a method. Invocations of functions
+ * resulting from evaluating an expression are represented by
+ * [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
+ * represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+ *
+ * > methodInvocation ::=
+ * >     ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
+ */
+class MethodInvocationImpl extends ExpressionImpl 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`).
+   */
+  Expression _target;
+
+  /**
+   * The operator that separates the target from the method name, or `null`
+   * if there is no target. In an ordinary method invocation this will be a
+   * period ('.'). In a cascade section this will be the cascade operator
+   * ('..').
+   */
+  Token operator;
+
+  /**
+   * The name of the method being invoked.
+   */
+  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.
+   */
+  MethodInvocationImpl(
+      Expression target,
+      this.operator,
+      SimpleIdentifier methodName,
+      TypeArgumentList typeArguments,
+      ArgumentList 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
+  Token get beginToken {
+    if (_target != null) {
+      return _target.beginToken;
+    } else if (operator != null) {
+      return operator;
+    }
+    return _methodName.beginToken;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(_target)
+    ..add(operator)
+    ..add(_methodName)
+    ..add(_argumentList);
+
+  @override
+  Token get endToken => _argumentList.endToken;
+
+  @override
+  bool get isCascaded =>
+      operator != null && operator.type == TokenType.PERIOD_PERIOD;
+
+  @override
+  SimpleIdentifier get methodName => _methodName;
+
+  @override
+  void set methodName(SimpleIdentifier identifier) {
+    _methodName = _becomeParentOf(identifier);
+  }
+
+  @override
+  int get precedence => 15;
+
+  @override
+  Expression get realTarget {
+    if (isCascaded) {
+      AstNode ancestor = parent;
+      while (ancestor is! CascadeExpression) {
+        if (ancestor == null) {
+          return _target;
+        }
+        ancestor = ancestor.parent;
+      }
+      return (ancestor as CascadeExpression).target;
+    }
+    return _target;
+  }
+
+  @override
+  Expression get target => _target;
+
+  @override
+  void set target(Expression expression) {
+    _target = _becomeParentOf(expression);
+  }
+
+  @override
+  TypeArgumentList get typeArguments => _typeArguments;
+
+  @override
+  void set typeArguments(TypeArgumentList typeArguments) {
+    _typeArguments = _becomeParentOf(typeArguments);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitMethodInvocation(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_target, visitor);
+    _safelyVisitChild(_methodName, visitor);
+    _safelyVisitChild(_typeArguments, visitor);
+    _safelyVisitChild(_argumentList, visitor);
+  }
+}
+
+/**
+ * A node that declares a single name within the scope of a compilation unit.
+ */
+abstract class NamedCompilationUnitMemberImpl extends CompilationUnitMemberImpl
+    implements NamedCompilationUnitMember {
+  /**
+   * The name of the member being declared.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * Initialize a newly created compilation unit member with the given [name].
+   * Either or both of the [comment] and [metadata] can be `null` if the member
+   * does not have the corresponding attribute.
+   */
+  NamedCompilationUnitMemberImpl(
+      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
+      : super(comment, metadata) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+}
+
+/**
+ * An expression that has a name associated with it. They are used in method
+ * invocations when there are named parameters.
+ *
+ * > namedExpression ::=
+ * >     [Label] [Expression]
+ */
+class NamedExpressionImpl extends ExpressionImpl implements NamedExpression {
+  /**
+   * The name associated with the expression.
+   */
+  Label _name;
+
+  /**
+   * The expression with which the name is associated.
+   */
+  Expression _expression;
+
+  /**
+   * Initialize a newly created named expression..
+   */
+  NamedExpressionImpl(Label name, Expression expression) {
+    _name = _becomeParentOf(name);
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken => _name.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_name)..add(_expression);
+
+  @override
+  ParameterElement get element {
+    Element element = _name.label.staticElement;
+    if (element is ParameterElement) {
+      return element;
+    }
+    return null;
+  }
+
+  @override
+  Token get endToken => _expression.endToken;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Label get name => _name;
+
+  @override
+  void set name(Label identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+
+  @override
+  int get precedence => 0;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitNamedExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A node that represents a directive that impacts the namespace of a library.
+ *
+ * > directive ::=
+ * >     [ExportDirective]
+ * >   | [ImportDirective]
+ */
+abstract class NamespaceDirectiveImpl extends UriBasedDirectiveImpl
+    implements NamespaceDirective {
+  /**
+   * The token representing the 'import' or 'export' keyword.
+   */
+  Token keyword;
+
+  /**
+   * The configurations used to control which library will actually be loaded at
+   * run-time.
+   */
+  NodeList<Configuration> _configurations;
+
+  /**
+   * The combinators used to control which names are imported or exported.
+   */
+  NodeList<Combinator> _combinators;
+
+  /**
+   * The semicolon terminating the directive.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created namespace directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute. The list of [combinators] can be `null` if there
+   * are no combinators.
+   */
+  NamespaceDirectiveImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.keyword,
+      StringLiteral libraryUri,
+      List<Configuration> configurations,
+      List<Combinator> combinators,
+      this.semicolon)
+      : super(comment, metadata, libraryUri) {
+    _configurations = new NodeList<Configuration>(this, configurations);
+    _combinators = new NodeList<Combinator>(this, combinators);
+  }
+
+  @override
+  NodeList<Combinator> get combinators => _combinators;
+
+  @override
+  NodeList<Configuration> get configurations => _configurations;
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => keyword;
+
+  @override
+  LibraryElement get uriElement;
+}
+
+/**
+ * The "native" clause in an class declaration.
+ *
+ * > nativeClause ::=
+ * >     'native' [StringLiteral]
+ */
+class NativeClauseImpl extends AstNodeImpl implements NativeClause {
+  /**
+   * The token representing the 'native' keyword.
+   */
+  Token nativeKeyword;
+
+  /**
+   * The name of the native object that implements the class.
+   */
+  StringLiteral _name;
+
+  /**
+   * Initialize a newly created native clause.
+   */
+  NativeClauseImpl(this.nativeKeyword, StringLiteral name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  Token get beginToken => nativeKeyword;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(nativeKeyword)..add(_name);
+
+  @override
+  Token get endToken => _name.endToken;
+
+  @override
+  StringLiteral get name => _name;
+
+  @override
+  void set name(StringLiteral name) {
+    _name = _becomeParentOf(name);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitNativeClause(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_name, visitor);
+  }
+}
+
+/**
+ * A function body that consists of a native keyword followed by a string
+ * literal.
+ *
+ * > nativeFunctionBody ::=
+ * >     'native' [SimpleStringLiteral] ';'
+ */
+class NativeFunctionBodyImpl extends FunctionBodyImpl
+    implements NativeFunctionBody {
+  /**
+   * The token representing 'native' that marks the start of the function body.
+   */
+  Token nativeKeyword;
+
+  /**
+   * The string literal, after the 'native' token.
+   */
+  StringLiteral _stringLiteral;
+
+  /**
+   * The token representing the semicolon that marks the end of the function
+   * body.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created function body consisting of the 'native' token,
+   * a string literal, and a semicolon.
+   */
+  NativeFunctionBodyImpl(
+      this.nativeKeyword, StringLiteral stringLiteral, this.semicolon) {
+    _stringLiteral = _becomeParentOf(stringLiteral);
+  }
+
+  @override
+  Token get beginToken => nativeKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(nativeKeyword)
+    ..add(_stringLiteral)
+    ..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  StringLiteral get stringLiteral => _stringLiteral;
+
+  @override
+  void set stringLiteral(StringLiteral stringLiteral) {
+    _stringLiteral = _becomeParentOf(stringLiteral);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitNativeFunctionBody(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_stringLiteral, visitor);
+  }
+}
+
+/**
+ * A list of AST nodes that have a common parent.
+ */
+class NodeListImpl<E extends AstNode> extends Object
+    with ListMixin<E>
+    implements NodeList<E> {
+  /**
+   * The node that is the parent of each of the elements in the list.
+   */
+  AstNodeImpl owner;
+
+  /**
+   * The elements contained in the list.
+   */
+  List<E> _elements = <E>[];
+
+  /**
+   * Initialize a newly created list of nodes such that all of the nodes that
+   * are added to the list will have their parent set to the given [owner]. The
+   * list will initially be populated with the given [elements].
+   */
+  NodeListImpl(this.owner, [List<E> elements]) {
+    addAll(elements);
+  }
+
+  @override
+  Token get beginToken {
+    if (_elements.length == 0) {
+      return null;
+    }
+    return _elements[0].beginToken;
+  }
+
+  @override
+  Token get endToken {
+    int length = _elements.length;
+    if (length == 0) {
+      return null;
+    }
+    return _elements[length - 1].endToken;
+  }
+
+  int get length => _elements.length;
+
+  @deprecated // Never intended for public use.
+  @override
+  void set length(int newLength) {
+    throw new UnsupportedError("Cannot resize NodeList.");
+  }
+
+  E operator [](int index) {
+    if (index < 0 || index >= _elements.length) {
+      throw new RangeError("Index: $index, Size: ${_elements.length}");
+    }
+    return _elements[index];
+  }
+
+  void operator []=(int index, E node) {
+    if (index < 0 || index >= _elements.length) {
+      throw new RangeError("Index: $index, Size: ${_elements.length}");
+    }
+    owner._becomeParentOf(node);
+    _elements[index] = node;
+  }
+
+  @override
+  accept(AstVisitor visitor) {
+    int length = _elements.length;
+    for (var i = 0; i < length; i++) {
+      _elements[i].accept(visitor);
+    }
+  }
+
+  @override
+  void add(E node) {
+    insert(length, node);
+  }
+
+  @override
+  bool addAll(Iterable<E> nodes) {
+    if (nodes != null && !nodes.isEmpty) {
+      _elements.addAll(nodes);
+      for (E node in nodes) {
+        owner._becomeParentOf(node);
+      }
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  void clear() {
+    _elements = <E>[];
+  }
+
+  @override
+  void insert(int index, E node) {
+    int length = _elements.length;
+    if (index < 0 || index > length) {
+      throw new RangeError("Index: $index, Size: ${_elements.length}");
+    }
+    owner._becomeParentOf(node);
+    if (length == 0) {
+      _elements.add(node);
+    } else {
+      _elements.insert(index, node);
+    }
+  }
+
+  @override
+  E removeAt(int index) {
+    if (index < 0 || index >= _elements.length) {
+      throw new RangeError("Index: $index, Size: ${_elements.length}");
+    }
+    E removedNode = _elements[index];
+    _elements.removeAt(index);
+    return removedNode;
+  }
+}
+
+/**
+ * A formal parameter that is required (is not optional).
+ *
+ * > normalFormalParameter ::=
+ * >     [FunctionTypedFormalParameter]
+ * >   | [FieldFormalParameter]
+ * >   | [SimpleFormalParameter]
+ */
+abstract class NormalFormalParameterImpl extends FormalParameterImpl
+    implements NormalFormalParameter {
+  /**
+   * The documentation comment associated with this parameter, or `null` if this
+   * parameter does not have a documentation comment associated with it.
+   */
+  Comment _comment;
+
+  /**
+   * The annotations associated with this parameter.
+   */
+  NodeList<Annotation> _metadata;
+
+  /**
+   * The name of the parameter being declared.
+   */
+  SimpleIdentifier _identifier;
+
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute.
+   */
+  NormalFormalParameterImpl(
+      Comment comment, List<Annotation> metadata, SimpleIdentifier identifier) {
+    _comment = _becomeParentOf(comment);
+    _metadata = new NodeList<Annotation>(this, metadata);
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  Comment get documentationComment => _comment;
+
+  @override
+  void set documentationComment(Comment comment) {
+    _comment = _becomeParentOf(comment);
+  }
+
+  @override
+  SimpleIdentifier get identifier => _identifier;
+
+  @override
+  void set identifier(SimpleIdentifier identifier) {
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  ParameterKind get kind {
+    AstNode parent = this.parent;
+    if (parent is DefaultFormalParameter) {
+      return parent.kind;
+    }
+    return ParameterKind.REQUIRED;
+  }
+
+  @override
+  NodeList<Annotation> get metadata => _metadata;
+
+  @override
+  void set metadata(List<Annotation> metadata) {
+    _metadata.clear();
+    _metadata.addAll(metadata);
+  }
+
+  @override
+  List<AstNode> get sortedCommentAndAnnotations {
+    return <AstNode>[]
+      ..add(_comment)
+      ..addAll(_metadata)
+      ..sort(AstNode.LEXICAL_ORDER);
+  }
+
+  ChildEntities get _childEntities {
+    ChildEntities result = new ChildEntities();
+    if (_commentIsBeforeAnnotations()) {
+      result
+        ..add(_comment)
+        ..addAll(_metadata);
+    } else {
+      result.addAll(sortedCommentAndAnnotations);
+    }
+    return result;
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    //
+    // Note that subclasses are responsible for visiting the identifier because
+    // they often need to visit other nodes before visiting the identifier.
+    //
+    if (_commentIsBeforeAnnotations()) {
+      _safelyVisitChild(_comment, visitor);
+      _metadata.accept(visitor);
+    } else {
+      for (AstNode child in sortedCommentAndAnnotations) {
+        child.accept(visitor);
+      }
+    }
+  }
+
+  /**
+   * Return `true` if the comment is lexically before any annotations.
+   */
+  bool _commentIsBeforeAnnotations() {
+    if (_comment == null || _metadata.isEmpty) {
+      return true;
+    }
+    Annotation firstAnnotation = _metadata[0];
+    return _comment.offset < firstAnnotation.offset;
+  }
+}
+
+/**
+ * A null literal expression.
+ *
+ * > nullLiteral ::=
+ * >     'null'
+ */
+class NullLiteralImpl extends LiteralImpl implements NullLiteral {
+  /**
+   * The token representing the literal.
+   */
+  Token literal;
+
+  /**
+   * Initialize a newly created null literal.
+   */
+  NullLiteralImpl(this.literal);
+
+  @override
+  Token get beginToken => literal;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(literal);
+
+  @override
+  Token get endToken => literal;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitNullLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A parenthesized expression.
+ *
+ * > parenthesizedExpression ::=
+ * >     '(' [Expression] ')'
+ */
+class ParenthesizedExpressionImpl extends ExpressionImpl
+    implements ParenthesizedExpression {
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The expression within the parentheses.
+   */
+  Expression _expression;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * Initialize a newly created parenthesized expression.
+   */
+  ParenthesizedExpressionImpl(
+      this.leftParenthesis, Expression expression, this.rightParenthesis) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken => leftParenthesis;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(leftParenthesis)
+    ..add(_expression)
+    ..add(rightParenthesis);
+
+  @override
+  Token get endToken => rightParenthesis;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 15;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitParenthesizedExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A part directive.
+ *
+ * > partDirective ::=
+ * >     [Annotation] 'part' [StringLiteral] ';'
+ */
+class PartDirectiveImpl extends UriBasedDirectiveImpl implements PartDirective {
+  /**
+   * The token representing the 'part' keyword.
+   */
+  Token partKeyword;
+
+  /**
+   * The semicolon terminating the directive.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created part directive. Either or both of the [comment]
+   * and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  PartDirectiveImpl(Comment comment, List<Annotation> metadata,
+      this.partKeyword, StringLiteral partUri, this.semicolon)
+      : super(comment, metadata, partUri);
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(partKeyword)..add(_uri)..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => partKeyword;
+
+  @override
+  Token get keyword => partKeyword;
+
+  @override
+  CompilationUnitElement get uriElement => element as CompilationUnitElement;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitPartDirective(this);
+}
+
+/**
+ * A part-of directive.
+ *
+ * > partOfDirective ::=
+ * >     [Annotation] 'part' 'of' [Identifier] ';'
+ */
+class PartOfDirectiveImpl extends DirectiveImpl implements PartOfDirective {
+  /**
+   * The token representing the 'part' keyword.
+   */
+  Token partKeyword;
+
+  /**
+   * The token representing the 'of' keyword.
+   */
+  Token ofKeyword;
+
+  /**
+   * The name of the library that the containing compilation unit is part of.
+   */
+  LibraryIdentifier _libraryName;
+
+  /**
+   * The semicolon terminating the directive.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created part-of directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  PartOfDirectiveImpl(
+      Comment comment,
+      List<Annotation> metadata,
+      this.partKeyword,
+      this.ofKeyword,
+      LibraryIdentifier libraryName,
+      this.semicolon)
+      : super(comment, metadata) {
+    _libraryName = _becomeParentOf(libraryName);
+  }
+
+  @override
+  Iterable get childEntities => super._childEntities
+    ..add(partKeyword)
+    ..add(ofKeyword)
+    ..add(_libraryName)
+    ..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => partKeyword;
+
+  @override
+  Token get keyword => partKeyword;
+
+  @override
+  LibraryIdentifier get libraryName => _libraryName;
+
+  @override
+  void set libraryName(LibraryIdentifier libraryName) {
+    _libraryName = _becomeParentOf(libraryName);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitPartOfDirective(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_libraryName, visitor);
+  }
+}
+
+/**
+ * A postfix unary expression.
+ *
+ * > postfixExpression ::=
+ * >     [Expression] [Token]
+ */
+class PostfixExpressionImpl extends ExpressionImpl
+    implements PostfixExpression {
+  /**
+   * The expression computing the operand for the operator.
+   */
+  Expression _operand;
+
+  /**
+   * The postfix operator being applied to the operand.
+   */
+  Token operator;
+
+  /**
+   * The element associated with this the operator based on the propagated type
+   * of the operand, or `null` if the AST structure has not been resolved, if
+   * the operator is not user definable, or if the operator could not be
+   * resolved.
+   */
+  MethodElement propagatedElement;
+
+  /**
+   * The element associated with the operator based on the static type of the
+   * operand, or `null` if the AST structure has not been resolved, if the
+   * operator is not user definable, or if the operator could not be resolved.
+   */
+  MethodElement staticElement;
+
+  /**
+   * Initialize a newly created postfix expression.
+   */
+  PostfixExpressionImpl(Expression operand, this.operator) {
+    _operand = _becomeParentOf(operand);
+  }
+
+  @override
+  Token get beginToken => _operand.beginToken;
+
+  @override
+  MethodElement get bestElement {
+    MethodElement element = propagatedElement;
+    if (element == null) {
+      element = staticElement;
+    }
+    return element;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_operand)..add(operator);
+
+  @override
+  Token get endToken => operator;
+
+  @override
+  Expression get operand => _operand;
+
+  @override
+  void set operand(Expression expression) {
+    _operand = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 15;
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on propagated type information, then return the parameter
+   * element representing the parameter to which the value of the operand will
+   * be bound. Otherwise, return `null`.
+   */
+  ParameterElement get _propagatedParameterElementForOperand {
+    if (propagatedElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = propagatedElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on static type information, then return the parameter element
+   * representing the parameter to which the value of the operand will be bound.
+   * Otherwise, return `null`.
+   */
+  ParameterElement get _staticParameterElementForOperand {
+    if (staticElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = staticElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitPostfixExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_operand, visitor);
+  }
+}
+
+/**
+ * An identifier that is prefixed or an access to an object property where the
+ * target of the property access is a simple identifier.
+ *
+ * > prefixedIdentifier ::=
+ * >     [SimpleIdentifier] '.' [SimpleIdentifier]
+ */
+class PrefixedIdentifierImpl extends IdentifierImpl
+    implements PrefixedIdentifier {
+  /**
+   * The prefix associated with the library in which the identifier is defined.
+   */
+  SimpleIdentifier _prefix;
+
+  /**
+   * The period used to separate the prefix from the identifier.
+   */
+  Token period;
+
+  /**
+   * The identifier being prefixed.
+   */
+  SimpleIdentifier _identifier;
+
+  /**
+   * Initialize a newly created prefixed identifier.
+   */
+  PrefixedIdentifierImpl(
+      SimpleIdentifier prefix, this.period, SimpleIdentifier identifier) {
+    _prefix = _becomeParentOf(prefix);
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  Token get beginToken => _prefix.beginToken;
+
+  @override
+  Element get bestElement {
+    if (_identifier == null) {
+      return null;
+    }
+    return _identifier.bestElement;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_prefix)..add(period)..add(_identifier);
+
+  @override
+  Token get endToken => _identifier.endToken;
+
+  @override
+  SimpleIdentifier get identifier => _identifier;
+
+  @override
+  void set identifier(SimpleIdentifier identifier) {
+    _identifier = _becomeParentOf(identifier);
+  }
+
+  @override
+  bool get isDeferred {
+    Element element = _prefix.staticElement;
+    if (element is! PrefixElement) {
+      return false;
+    }
+    PrefixElement prefixElement = element as PrefixElement;
+    List<ImportElement> imports =
+        prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
+    if (imports.length != 1) {
+      return false;
+    }
+    return imports[0].isDeferred;
+  }
+
+  @override
+  String get name => "${_prefix.name}.${_identifier.name}";
+
+  @override
+  int get precedence => 15;
+
+  @override
+  SimpleIdentifier get prefix => _prefix;
+
+  @override
+  void set prefix(SimpleIdentifier identifier) {
+    _prefix = _becomeParentOf(identifier);
+  }
+
+  @override
+  Element get propagatedElement {
+    if (_identifier == null) {
+      return null;
+    }
+    return _identifier.propagatedElement;
+  }
+
+  @override
+  Element get staticElement {
+    if (_identifier == null) {
+      return null;
+    }
+    return _identifier.staticElement;
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitPrefixedIdentifier(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_prefix, visitor);
+    _safelyVisitChild(_identifier, visitor);
+  }
+}
+
+/**
+ * A prefix unary expression.
+ *
+ * > prefixExpression ::=
+ * >     [Token] [Expression]
+ */
+class PrefixExpressionImpl extends ExpressionImpl implements PrefixExpression {
+  /**
+   * The prefix operator being applied to the operand.
+   */
+  Token operator;
+
+  /**
+   * The expression computing the operand for the operator.
+   */
+  Expression _operand;
+
+  /**
+   * The element associated with the operator based on the static type of the
+   * operand, or `null` if the AST structure has not been resolved, if the
+   * operator is not user definable, or if the operator could not be resolved.
+   */
+  MethodElement staticElement;
+
+  /**
+   * The element associated with the operator based on the propagated type of
+   * the operand, or `null` if the AST structure has not been resolved, if the
+   * operator is not user definable, or if the operator could not be resolved.
+   */
+  MethodElement propagatedElement;
+
+  /**
+   * Initialize a newly created prefix expression.
+   */
+  PrefixExpressionImpl(this.operator, Expression operand) {
+    _operand = _becomeParentOf(operand);
+  }
+
+  @override
+  Token get beginToken => operator;
+
+  @override
+  MethodElement get bestElement {
+    MethodElement element = propagatedElement;
+    if (element == null) {
+      element = staticElement;
+    }
+    return element;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(operator)..add(_operand);
+
+  @override
+  Token get endToken => _operand.endToken;
+
+  @override
+  Expression get operand => _operand;
+
+  @override
+  void set operand(Expression expression) {
+    _operand = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 14;
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on propagated type information, then return the parameter
+   * element representing the parameter to which the value of the operand will
+   * be bound. Otherwise, return `null`.
+   */
+  ParameterElement get _propagatedParameterElementForOperand {
+    if (propagatedElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = propagatedElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  /**
+   * If the AST structure has been resolved, and the function being invoked is
+   * known based on static type information, then return the parameter element
+   * representing the parameter to which the value of the operand will be bound.
+   * Otherwise, return `null`.
+   */
+  ParameterElement get _staticParameterElementForOperand {
+    if (staticElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = staticElement.parameters;
+    if (parameters.length < 1) {
+      return null;
+    }
+    return parameters[0];
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitPrefixExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_operand, visitor);
+  }
+}
+
+/**
+ * The access of a property of an object.
+ *
+ * Note, however, that accesses to properties of objects can also be represented
+ * as [PrefixedIdentifier] nodes in cases where the target is also a simple
+ * identifier.
+ *
+ * > propertyAccess ::=
+ * >     [Expression] '.' [SimpleIdentifier]
+ */
+class PropertyAccessImpl extends ExpressionImpl implements PropertyAccess {
+  /**
+   * The expression computing the object defining the property being accessed.
+   */
+  Expression _target;
+
+  /**
+   * The property access operator.
+   */
+  Token operator;
+
+  /**
+   * The name of the property being accessed.
+   */
+  SimpleIdentifier _propertyName;
+
+  /**
+   * Initialize a newly created property access expression.
+   */
+  PropertyAccessImpl(
+      Expression target, this.operator, SimpleIdentifier propertyName) {
+    _target = _becomeParentOf(target);
+    _propertyName = _becomeParentOf(propertyName);
+  }
+
+  @override
+  Token get beginToken {
+    if (_target != null) {
+      return _target.beginToken;
+    }
+    return operator;
+  }
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_target)..add(operator)..add(_propertyName);
+
+  @override
+  Token get endToken => _propertyName.endToken;
+
+  @override
+  bool get isAssignable => true;
+
+  @override
+  bool get isCascaded =>
+      operator != null && operator.type == TokenType.PERIOD_PERIOD;
+
+  @override
+  int get precedence => 15;
+
+  @override
+  SimpleIdentifier get propertyName => _propertyName;
+
+  @override
+  void set propertyName(SimpleIdentifier identifier) {
+    _propertyName = _becomeParentOf(identifier);
+  }
+
+  @override
+  Expression get realTarget {
+    if (isCascaded) {
+      AstNode ancestor = parent;
+      while (ancestor is! CascadeExpression) {
+        if (ancestor == null) {
+          return _target;
+        }
+        ancestor = ancestor.parent;
+      }
+      return (ancestor as CascadeExpression).target;
+    }
+    return _target;
+  }
+
+  @override
+  Expression get target => _target;
+
+  @override
+  void set target(Expression expression) {
+    _target = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitPropertyAccess(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_target, visitor);
+    _safelyVisitChild(_propertyName, visitor);
+  }
+}
+
+/**
+ * The invocation of a constructor in the same class from within a constructor's
+ * initialization list.
+ *
+ * > redirectingConstructorInvocation ::=
+ * >     'this' ('.' identifier)? arguments
+ */
+class RedirectingConstructorInvocationImpl extends ConstructorInitializerImpl
+    implements RedirectingConstructorInvocation {
+  /**
+   * The token for the 'this' keyword.
+   */
+  Token thisKeyword;
+
+  /**
+   * The token for the period before the name of the constructor that is being
+   * invoked, or `null` if the unnamed constructor is being invoked.
+   */
+  Token period;
+
+  /**
+   * The name of the constructor that is being invoked, or `null` if the unnamed
+   * constructor is being invoked.
+   */
+  SimpleIdentifier _constructorName;
+
+  /**
+   * The list of arguments to the constructor.
+   */
+  ArgumentList _argumentList;
+
+  /**
+   * The element associated with the constructor based on static type
+   * information, or `null` if the AST structure has not been resolved or if the
+   * constructor could not be resolved.
+   */
+  ConstructorElement staticElement;
+
+  /**
+   * Initialize a newly created redirecting invocation to invoke the constructor
+   * with the given name with the given arguments. The [constructorName] can be
+   * `null` if the constructor being invoked is the unnamed constructor.
+   */
+  RedirectingConstructorInvocationImpl(this.thisKeyword, this.period,
+      SimpleIdentifier constructorName, ArgumentList argumentList) {
+    _constructorName = _becomeParentOf(constructorName);
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  ArgumentList get argumentList => _argumentList;
+
+  @override
+  void set argumentList(ArgumentList argumentList) {
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  Token get beginToken => thisKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(thisKeyword)
+    ..add(period)
+    ..add(_constructorName)
+    ..add(_argumentList);
+
+  @override
+  SimpleIdentifier get constructorName => _constructorName;
+
+  @override
+  void set constructorName(SimpleIdentifier identifier) {
+    _constructorName = _becomeParentOf(identifier);
+  }
+
+  @override
+  Token get endToken => _argumentList.endToken;
+
+  @override
+  accept(AstVisitor visitor) =>
+      visitor.visitRedirectingConstructorInvocation(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_constructorName, visitor);
+    _safelyVisitChild(_argumentList, visitor);
+  }
+}
+
+/**
+ * A rethrow expression.
+ *
+ * > rethrowExpression ::=
+ * >     'rethrow'
+ */
+class RethrowExpressionImpl extends ExpressionImpl
+    implements RethrowExpression {
+  /**
+   * The token representing the 'rethrow' keyword.
+   */
+  Token rethrowKeyword;
+
+  /**
+   * Initialize a newly created rethrow expression.
+   */
+  RethrowExpressionImpl(this.rethrowKeyword);
+
+  @override
+  Token get beginToken => rethrowKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(rethrowKeyword);
+
+  @override
+  Token get endToken => rethrowKeyword;
+
+  @override
+  int get precedence => 0;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitRethrowExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A return statement.
+ *
+ * > returnStatement ::=
+ * >     'return' [Expression]? ';'
+ */
+class ReturnStatementImpl extends StatementImpl implements ReturnStatement {
+  /**
+   * The token representing the 'return' keyword.
+   */
+  Token returnKeyword;
+
+  /**
+   * The expression computing the value to be returned, or `null` if no explicit
+   * value was provided.
+   */
+  Expression _expression;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created return statement. The [expression] can be `null`
+   * if no explicit value was provided.
+   */
+  ReturnStatementImpl(
+      this.returnKeyword, Expression expression, this.semicolon) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken => returnKeyword;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(returnKeyword)..add(_expression)..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitReturnStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * A script tag that can optionally occur at the beginning of a compilation unit.
+ *
+ * > scriptTag ::=
+ * >     '#!' (~NEWLINE)* NEWLINE
+ */
+class ScriptTagImpl extends AstNodeImpl implements ScriptTag {
+  /**
+   * The token representing this script tag.
+   */
+  Token scriptTag;
+
+  /**
+   * Initialize a newly created script tag.
+   */
+  ScriptTagImpl(this.scriptTag);
+
+  @override
+  Token get beginToken => scriptTag;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(scriptTag);
+
+  @override
+  Token get endToken => scriptTag;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitScriptTag(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A combinator that restricts the names being imported to those in a given list.
+ *
+ * > showCombinator ::=
+ * >     'show' [SimpleIdentifier] (',' [SimpleIdentifier])*
+ */
+class ShowCombinatorImpl extends CombinatorImpl implements ShowCombinator {
+  /**
+   * The list of names from the library that are made visible by this combinator.
+   */
+  NodeList<SimpleIdentifier> _shownNames;
+
+  /**
+   * Initialize a newly created import show combinator.
+   */
+  ShowCombinatorImpl(Token keyword, List<SimpleIdentifier> shownNames)
+      : super(keyword) {
+    _shownNames = new NodeList<SimpleIdentifier>(this, shownNames);
+  }
+
+  @override
+  // TODO(paulberry): add commas.
+  Iterable get childEntities => new ChildEntities()
+    ..add(keyword)
+    ..addAll(_shownNames);
+
+  @override
+  Token get endToken => _shownNames.endToken;
+
+  @override
+  NodeList<SimpleIdentifier> get shownNames => _shownNames;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitShowCombinator(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _shownNames.accept(visitor);
+  }
+}
+
+/**
+ * A simple formal parameter.
+ *
+ * > simpleFormalParameter ::=
+ * >     ('final' [TypeName] | 'var' | [TypeName])? [SimpleIdentifier]
+ */
+class SimpleFormalParameterImpl extends NormalFormalParameterImpl
+    implements SimpleFormalParameter {
+  /**
+   * The token representing either the 'final', 'const' or 'var' keyword, or
+   * `null` if no keyword was used.
+   */
+  Token keyword;
+
+  /**
+   * The name of the declared type of the parameter, or `null` if the parameter
+   * does not have a declared type.
+   */
+  TypeName _type;
+
+  /**
+   * Initialize a newly created formal parameter. Either or both of the
+   * [comment] and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [keyword] can be `null` if a type was
+   * specified. The [type] must be `null` if the keyword is 'var'.
+   */
+  SimpleFormalParameterImpl(Comment comment, List<Annotation> metadata,
+      this.keyword, TypeName type, SimpleIdentifier identifier)
+      : super(comment, metadata, identifier) {
+    _type = _becomeParentOf(type);
+  }
+
+  @override
+  Token get beginToken {
+    NodeList<Annotation> metadata = this.metadata;
+    if (!metadata.isEmpty) {
+      return metadata.beginToken;
+    } else if (keyword != null) {
+      return keyword;
+    } else if (_type != null) {
+      return _type.beginToken;
+    }
+    return identifier.beginToken;
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(keyword)..add(_type)..add(identifier);
+
+  @override
+  Token get endToken => identifier.endToken;
+
+  @override
+  bool get isConst =>
+      (keyword is KeywordToken) &&
+      (keyword as KeywordToken).keyword == Keyword.CONST;
+
+  @override
+  bool get isFinal =>
+      (keyword is KeywordToken) &&
+      (keyword as KeywordToken).keyword == Keyword.FINAL;
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName typeName) {
+    _type = _becomeParentOf(typeName);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSimpleFormalParameter(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_type, visitor);
+    _safelyVisitChild(identifier, visitor);
+  }
+}
+
+/**
+ * A simple identifier.
+ *
+ * > simpleIdentifier ::=
+ * >     initialCharacter internalCharacter*
+ * >
+ * > initialCharacter ::= '_' | '$' | letter
+ * >
+ * > internalCharacter ::= '_' | '$' | letter | digit
+ */
+class SimpleIdentifierImpl extends IdentifierImpl implements SimpleIdentifier {
+  /**
+   * The token representing the identifier.
+   */
+  Token token;
+
+  /**
+   * The element associated with this identifier based on static type
+   * information, or `null` if the AST structure has not been resolved or if
+   * this identifier could not be resolved.
+   */
+  Element _staticElement;
+
+  /**
+   * The element associated with this identifier based on propagated type
+   * information, or `null` if the AST structure has not been resolved or if
+   * this identifier could not be resolved.
+   */
+  Element _propagatedElement;
+
+  /**
+   * If this expression is both in a getter and setter context, the
+   * [AuxiliaryElements] will be set to hold onto the static and propagated
+   * information. The auxiliary element will hold onto the elements from the
+   * getter context.
+   */
+  AuxiliaryElements auxiliaryElements = null;
+
+  /**
+   * Initialize a newly created identifier.
+   */
+  SimpleIdentifierImpl(this.token);
+
+  @override
+  Token get beginToken => token;
+
+  @override
+  Element get bestElement {
+    if (_propagatedElement == null) {
+      return _staticElement;
+    }
+    return _propagatedElement;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(token);
+
+  @override
+  Token get endToken => token;
+
+  @override
+  bool get isQualified {
+    AstNode parent = this.parent;
+    if (parent is PrefixedIdentifier) {
+      return identical(parent.identifier, this);
+    }
+    if (parent is PropertyAccess) {
+      return identical(parent.propertyName, this);
+    }
+    if (parent is MethodInvocation) {
+      MethodInvocation invocation = parent;
+      return identical(invocation.methodName, this) &&
+          invocation.realTarget != null;
+    }
+    return false;
+  }
+
+  @override
+  bool get isSynthetic => token.isSynthetic;
+
+  @override
+  String get name => token.lexeme;
+
+  @override
+  int get precedence => 16;
+
+  @override
+  Element get propagatedElement => _propagatedElement;
+
+  @override
+  void set propagatedElement(Element element) {
+    _propagatedElement = _validateElement(element);
+  }
+
+  @override
+  Element get staticElement => _staticElement;
+
+  @override
+  void set staticElement(Element element) {
+    _staticElement = _validateElement(element);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSimpleIdentifier(this);
+
+  @override
+  bool inDeclarationContext() {
+    // TODO(brianwilkerson) Convert this to a getter.
+    AstNode parent = this.parent;
+    if (parent is CatchClause) {
+      CatchClause clause = parent;
+      return identical(this, clause.exceptionParameter) ||
+          identical(this, clause.stackTraceParameter);
+    } else if (parent is ClassDeclaration) {
+      return identical(this, parent.name);
+    } else if (parent is ClassTypeAlias) {
+      return identical(this, parent.name);
+    } else if (parent is ConstructorDeclaration) {
+      return identical(this, parent.name);
+    } else if (parent is DeclaredIdentifier) {
+      return identical(this, parent.identifier);
+    } else if (parent is EnumDeclaration) {
+      return identical(this, parent.name);
+    } else if (parent is EnumConstantDeclaration) {
+      return identical(this, parent.name);
+    } else if (parent is FunctionDeclaration) {
+      return identical(this, parent.name);
+    } else if (parent is FunctionTypeAlias) {
+      return identical(this, parent.name);
+    } else if (parent is ImportDirective) {
+      return identical(this, parent.prefix);
+    } else if (parent is Label) {
+      return identical(this, parent.label) &&
+          (parent.parent is LabeledStatement);
+    } else if (parent is MethodDeclaration) {
+      return identical(this, parent.name);
+    } else if (parent is FunctionTypedFormalParameter ||
+        parent is SimpleFormalParameter) {
+      return identical(this, (parent as NormalFormalParameter).identifier);
+    } else if (parent is TypeParameter) {
+      return identical(this, parent.name);
+    } else if (parent is VariableDeclaration) {
+      return identical(this, parent.name);
+    }
+    return false;
+  }
+
+  @override
+  bool inGetterContext() {
+    // TODO(brianwilkerson) Convert this to a getter.
+    AstNode parent = this.parent;
+    AstNode target = this;
+    // skip prefix
+    if (parent is PrefixedIdentifier) {
+      PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
+      if (identical(prefixed.prefix, this)) {
+        return true;
+      }
+      parent = prefixed.parent;
+      target = prefixed;
+    } else if (parent is PropertyAccess) {
+      PropertyAccess access = parent as PropertyAccess;
+      if (identical(access.target, this)) {
+        return true;
+      }
+      parent = access.parent;
+      target = access;
+    }
+    // skip label
+    if (parent is Label) {
+      return false;
+    }
+    // analyze usage
+    if (parent is AssignmentExpression) {
+      if (identical(parent.leftHandSide, target) &&
+          parent.operator.type == TokenType.EQ) {
+        return false;
+      }
+    }
+    if (parent is ForEachStatement) {
+      if (identical(parent.identifier, target)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @override
+  bool inSetterContext() {
+    // TODO(brianwilkerson) Convert this to a getter.
+    AstNode parent = this.parent;
+    AstNode target = this;
+    // skip prefix
+    if (parent is PrefixedIdentifier) {
+      PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
+      // if this is the prefix, then return false
+      if (identical(prefixed.prefix, this)) {
+        return false;
+      }
+      parent = prefixed.parent;
+      target = prefixed;
+    } else if (parent is PropertyAccess) {
+      PropertyAccess access = parent as PropertyAccess;
+      if (identical(access.target, this)) {
+        return false;
+      }
+      parent = access.parent;
+      target = access;
+    }
+    // analyze usage
+    if (parent is PrefixExpression) {
+      return parent.operator.type.isIncrementOperator;
+    } else if (parent is PostfixExpression) {
+      return true;
+    } else if (parent is AssignmentExpression) {
+      return identical(parent.leftHandSide, target);
+    } else if (parent is ForEachStatement) {
+      return identical(parent.identifier, target);
+    }
+    return false;
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+
+  /**
+   * Return the given element if it is valid, or report the problem and return
+   * `null` if it is not appropriate.
+   *
+   * The [parent] is the parent of the element, used for reporting when there is
+   * a problem.
+   * The [isValid] is `true` if the element is appropriate.
+   * The [element] is the element to be associated with this identifier.
+   */
+  Element _returnOrReportElement(
+      AstNode parent, bool isValid, Element element) {
+    if (!isValid) {
+      AnalysisEngine.instance.logger.logInformation(
+          "Internal error: attempting to set the name of a ${parent.runtimeType} to a ${element.runtimeType}",
+          new CaughtException(new AnalysisException(), null));
+      return null;
+    }
+    return element;
+  }
+
+  /**
+   * Return the given [element] if it is an appropriate element based on the
+   * parent of this identifier, or `null` if it is not appropriate.
+   */
+  Element _validateElement(Element element) {
+    if (element == null) {
+      return null;
+    }
+    AstNode parent = this.parent;
+    if (parent is ClassDeclaration && identical(parent.name, this)) {
+      return _returnOrReportElement(parent, element is ClassElement, element);
+    } else if (parent is ClassTypeAlias && identical(parent.name, this)) {
+      return _returnOrReportElement(parent, element is ClassElement, element);
+    } else if (parent is DeclaredIdentifier &&
+        identical(parent.identifier, this)) {
+      return _returnOrReportElement(
+          parent, element is LocalVariableElement, element);
+    } else if (parent is FormalParameter &&
+        identical(parent.identifier, this)) {
+      return _returnOrReportElement(
+          parent, element is ParameterElement, element);
+    } else if (parent is FunctionDeclaration && identical(parent.name, this)) {
+      return _returnOrReportElement(
+          parent, element is ExecutableElement, element);
+    } else if (parent is FunctionTypeAlias && identical(parent.name, this)) {
+      return _returnOrReportElement(
+          parent, element is FunctionTypeAliasElement, element);
+    } else if (parent is MethodDeclaration && identical(parent.name, this)) {
+      return _returnOrReportElement(
+          parent, element is ExecutableElement, element);
+    } else if (parent is TypeParameter && identical(parent.name, this)) {
+      return _returnOrReportElement(
+          parent, element is TypeParameterElement, element);
+    } else if (parent is VariableDeclaration && identical(parent.name, this)) {
+      return _returnOrReportElement(
+          parent, element is VariableElement, element);
+    }
+    return element;
+  }
+}
+
+/**
+ * A string literal expression that does not contain any interpolations.
+ *
+ * > simpleStringLiteral ::=
+ * >     rawStringLiteral
+ * >   | basicStringLiteral
+ * >
+ * > rawStringLiteral ::=
+ * >     'r' basicStringLiteral
+ * >
+ * > simpleStringLiteral ::=
+ * >     multiLineStringLiteral
+ * >   | singleLineStringLiteral
+ * >
+ * > multiLineStringLiteral ::=
+ * >     "'''" characters "'''"
+ * >   | '"""' characters '"""'
+ * >
+ * > singleLineStringLiteral ::=
+ * >     "'" characters "'"
+ * >   | '"' characters '"'
+ */
+class SimpleStringLiteralImpl extends SingleStringLiteralImpl
+    implements SimpleStringLiteral {
+  /**
+   * The token representing the literal.
+   */
+  Token literal;
+
+  /**
+   * The value of the literal.
+   */
+  String _value;
+
+  /**
+   * Initialize a newly created simple string literal.
+   */
+  SimpleStringLiteralImpl(this.literal, String value) {
+    _value = StringUtilities.intern(value);
+  }
+
+  @override
+  Token get beginToken => literal;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(literal);
+
+  @override
+  int get contentsEnd => offset + _helper.end;
+
+  @override
+  int get contentsOffset => offset + _helper.start;
+
+  @override
+  Token get endToken => literal;
+
+  @override
+  bool get isMultiline => _helper.isMultiline;
+
+  @override
+  bool get isRaw => _helper.isRaw;
+
+  @override
+  bool get isSingleQuoted => _helper.isSingleQuoted;
+
+  @override
+  bool get isSynthetic => literal.isSynthetic;
+
+  @override
+  String get value => _value;
+
+  @override
+  void set value(String string) {
+    _value = StringUtilities.intern(_value);
+  }
+
+  StringLexemeHelper get _helper {
+    return new StringLexemeHelper(literal.lexeme, true, true);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSimpleStringLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+
+  @override
+  void _appendStringValue(StringBuffer buffer) {
+    buffer.write(value);
+  }
+}
+
+/**
+ * A single string literal expression.
+ *
+ * > singleStringLiteral ::=
+ * >     [SimpleStringLiteral]
+ * >   | [StringInterpolation]
+ */
+abstract class SingleStringLiteralImpl extends StringLiteralImpl
+    implements SingleStringLiteral {}
+
+/**
+ * A node that represents a statement.
+ *
+ * > statement ::=
+ * >     [Block]
+ * >   | [VariableDeclarationStatement]
+ * >   | [ForStatement]
+ * >   | [ForEachStatement]
+ * >   | [WhileStatement]
+ * >   | [DoStatement]
+ * >   | [SwitchStatement]
+ * >   | [IfStatement]
+ * >   | [TryStatement]
+ * >   | [BreakStatement]
+ * >   | [ContinueStatement]
+ * >   | [ReturnStatement]
+ * >   | [ExpressionStatement]
+ * >   | [FunctionDeclarationStatement]
+ */
+abstract class StatementImpl extends AstNodeImpl implements Statement {
+  @override
+  Statement get unlabeled => this;
+}
+
+/**
+ * A string interpolation literal.
+ *
+ * > stringInterpolation ::=
+ * >     ''' [InterpolationElement]* '''
+ * >   | '"' [InterpolationElement]* '"'
+ */
+class StringInterpolationImpl extends SingleStringLiteralImpl
+    implements StringInterpolation {
+  /**
+   * The elements that will be composed to produce the resulting string.
+   */
+  NodeList<InterpolationElement> _elements;
+
+  /**
+   * Initialize a newly created string interpolation expression.
+   */
+  StringInterpolationImpl(List<InterpolationElement> elements) {
+    _elements = new NodeList<InterpolationElement>(this, elements);
+  }
+
+  @override
+  Token get beginToken => _elements.beginToken;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..addAll(_elements);
+
+  @override
+  int get contentsEnd {
+    InterpolationString element = _elements.last;
+    return element.contentsEnd;
+  }
+
+  @override
+  int get contentsOffset {
+    InterpolationString element = _elements.first;
+    return element.contentsOffset;
+  }
+
+  /**
+   * Return the elements that will be composed to produce the resulting string.
+   */
+  NodeList<InterpolationElement> get elements => _elements;
+
+  @override
+  Token get endToken => _elements.endToken;
+
+  @override
+  bool get isMultiline => _firstHelper.isMultiline;
+
+  @override
+  bool get isRaw => false;
+
+  @override
+  bool get isSingleQuoted => _firstHelper.isSingleQuoted;
+
+  StringLexemeHelper get _firstHelper {
+    InterpolationString lastString = _elements.first;
+    String lexeme = lastString.contents.lexeme;
+    return new StringLexemeHelper(lexeme, true, false);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitStringInterpolation(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _elements.accept(visitor);
+  }
+
+  @override
+  void _appendStringValue(StringBuffer buffer) {
+    throw new IllegalArgumentException();
+  }
+}
+
+/**
+ * A helper for analyzing string lexemes.
+ */
+class StringLexemeHelper {
+  final String lexeme;
+  final bool isFirst;
+  final bool isLast;
+
+  bool isRaw = false;
+  bool isSingleQuoted = false;
+  bool isMultiline = false;
+  int start = 0;
+  int end;
+
+  StringLexemeHelper(this.lexeme, this.isFirst, this.isLast) {
+    if (isFirst) {
+      isRaw = StringUtilities.startsWithChar(lexeme, 0x72);
+      if (isRaw) {
+        start++;
+      }
+      if (StringUtilities.startsWith3(lexeme, start, 0x27, 0x27, 0x27)) {
+        isSingleQuoted = true;
+        isMultiline = true;
+        start += 3;
+        start = _trimInitialWhitespace(start);
+      } else if (StringUtilities.startsWith3(lexeme, start, 0x22, 0x22, 0x22)) {
+        isSingleQuoted = false;
+        isMultiline = true;
+        start += 3;
+        start = _trimInitialWhitespace(start);
+      } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x27) {
+        isSingleQuoted = true;
+        isMultiline = false;
+        start++;
+      } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x22) {
+        isSingleQuoted = false;
+        isMultiline = false;
+        start++;
+      }
+    }
+    end = lexeme.length;
+    if (isLast) {
+      if (start + 3 <= end &&
+          (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) ||
+              StringUtilities.endsWith3(lexeme, 0x27, 0x27, 0x27))) {
+        end -= 3;
+      } else if (start + 1 <= end &&
+          (StringUtilities.endsWithChar(lexeme, 0x22) ||
+              StringUtilities.endsWithChar(lexeme, 0x27))) {
+        end -= 1;
+      }
+    }
+  }
+
+  /**
+   * Given the [lexeme] for a multi-line string whose content begins at the
+   * given [start] index, return the index of the first character that is
+   * included in the value of the string. According to the specification:
+   *
+   * If the first line of a multiline string consists solely of the whitespace
+   * characters defined by the production WHITESPACE 20.1), possibly prefixed
+   * by \, then that line is ignored, including the new line at its end.
+   */
+  int _trimInitialWhitespace(int start) {
+    int length = lexeme.length;
+    int index = start;
+    while (index < length) {
+      int currentChar = lexeme.codeUnitAt(index);
+      if (currentChar == 0x0D) {
+        if (index + 1 < length && lexeme.codeUnitAt(index + 1) == 0x0A) {
+          return index + 2;
+        }
+        return index + 1;
+      } else if (currentChar == 0x0A) {
+        return index + 1;
+      } else if (currentChar == 0x5C) {
+        if (index + 1 >= length) {
+          return start;
+        }
+        currentChar = lexeme.codeUnitAt(index + 1);
+        if (currentChar != 0x0D &&
+            currentChar != 0x0A &&
+            currentChar != 0x09 &&
+            currentChar != 0x20) {
+          return start;
+        }
+      } else if (currentChar != 0x09 && currentChar != 0x20) {
+        return start;
+      }
+      index++;
+    }
+    return start;
+  }
+}
+
+/**
+ * A string literal expression.
+ *
+ * > stringLiteral ::=
+ * >     [SimpleStringLiteral]
+ * >   | [AdjacentStrings]
+ * >   | [StringInterpolation]
+ */
+abstract class StringLiteralImpl extends LiteralImpl implements StringLiteral {
+  @override
+  String get stringValue {
+    StringBuffer buffer = new StringBuffer();
+    try {
+      _appendStringValue(buffer);
+    } on IllegalArgumentException {
+      return null;
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Append the value of this string literal to the given [buffer]. Throw an
+   * [IllegalArgumentException] if the string is not a constant string without
+   * any string interpolation.
+   */
+  void _appendStringValue(StringBuffer buffer);
+}
+
+/**
+ * The invocation of a superclass' constructor from within a constructor's
+ * initialization list.
+ *
+ * > superInvocation ::=
+ * >     'super' ('.' [SimpleIdentifier])? [ArgumentList]
+ */
+class SuperConstructorInvocationImpl extends ConstructorInitializerImpl
+    implements SuperConstructorInvocation {
+  /**
+   * The token for the 'super' keyword.
+   */
+  Token superKeyword;
+
+  /**
+   * The token for the period before the name of the constructor that is being
+   * invoked, or `null` if the unnamed constructor is being invoked.
+   */
+  Token period;
+
+  /**
+   * The name of the constructor that is being invoked, or `null` if the unnamed
+   * constructor is being invoked.
+   */
+  SimpleIdentifier _constructorName;
+
+  /**
+   * The list of arguments to the constructor.
+   */
+  ArgumentList _argumentList;
+
+  /**
+   * The element associated with the constructor based on static type
+   * information, or `null` if the AST structure has not been resolved or if the
+   * constructor could not be resolved.
+   */
+  ConstructorElement staticElement;
+
+  /**
+   * Initialize a newly created super invocation to invoke the inherited
+   * constructor with the given name with the given arguments. The [period] and
+   * [constructorName] can be `null` if the constructor being invoked is the
+   * unnamed constructor.
+   */
+  SuperConstructorInvocationImpl(this.superKeyword, this.period,
+      SimpleIdentifier constructorName, ArgumentList argumentList) {
+    _constructorName = _becomeParentOf(constructorName);
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  ArgumentList get argumentList => _argumentList;
+
+  @override
+  void set argumentList(ArgumentList argumentList) {
+    _argumentList = _becomeParentOf(argumentList);
+  }
+
+  @override
+  Token get beginToken => superKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(superKeyword)
+    ..add(period)
+    ..add(_constructorName)
+    ..add(_argumentList);
+
+  @override
+  SimpleIdentifier get constructorName => _constructorName;
+
+  @override
+  void set constructorName(SimpleIdentifier identifier) {
+    _constructorName = _becomeParentOf(identifier);
+  }
+
+  @override
+  Token get endToken => _argumentList.endToken;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSuperConstructorInvocation(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_constructorName, visitor);
+    _safelyVisitChild(_argumentList, visitor);
+  }
+}
+
+/**
+ * A super expression.
+ *
+ * > superExpression ::=
+ * >     'super'
+ */
+class SuperExpressionImpl extends ExpressionImpl implements SuperExpression {
+  /**
+   * The token representing the 'super' keyword.
+   */
+  Token superKeyword;
+
+  /**
+   * Initialize a newly created super expression.
+   */
+  SuperExpressionImpl(this.superKeyword);
+
+  @override
+  Token get beginToken => superKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(superKeyword);
+
+  @override
+  Token get endToken => superKeyword;
+
+  @override
+  int get precedence => 16;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSuperExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A case in a switch statement.
+ *
+ * > switchCase ::=
+ * >     [SimpleIdentifier]* 'case' [Expression] ':' [Statement]*
+ */
+class SwitchCaseImpl extends SwitchMemberImpl implements SwitchCase {
+  /**
+   * The expression controlling whether the statements will be executed.
+   */
+  Expression _expression;
+
+  /**
+   * Initialize a newly created switch case. The list of [labels] can be `null`
+   * if there are no labels.
+   */
+  SwitchCaseImpl(List<Label> labels, Token keyword, Expression expression,
+      Token colon, List<Statement> statements)
+      : super(labels, keyword, colon, statements) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..addAll(labels)
+    ..add(keyword)
+    ..add(_expression)
+    ..add(colon)
+    ..addAll(statements);
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSwitchCase(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    labels.accept(visitor);
+    _safelyVisitChild(_expression, visitor);
+    statements.accept(visitor);
+  }
+}
+
+/**
+ * The default case in a switch statement.
+ *
+ * > switchDefault ::=
+ * >     [SimpleIdentifier]* 'default' ':' [Statement]*
+ */
+class SwitchDefaultImpl extends SwitchMemberImpl implements SwitchDefault {
+  /**
+   * Initialize a newly created switch default. The list of [labels] can be
+   * `null` if there are no labels.
+   */
+  SwitchDefaultImpl(List<Label> labels, Token keyword, Token colon,
+      List<Statement> statements)
+      : super(labels, keyword, colon, statements);
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..addAll(labels)
+    ..add(keyword)
+    ..add(colon)
+    ..addAll(statements);
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSwitchDefault(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    labels.accept(visitor);
+    statements.accept(visitor);
+  }
+}
+
+/**
+ * An element within a switch statement.
+ *
+ * > switchMember ::=
+ * >     switchCase
+ * >   | switchDefault
+ */
+abstract class SwitchMemberImpl extends AstNodeImpl implements SwitchMember {
+  /**
+   * The labels associated with the switch member.
+   */
+  NodeList<Label> _labels;
+
+  /**
+   * The token representing the 'case' or 'default' keyword.
+   */
+  Token keyword;
+
+  /**
+   * The colon separating the keyword or the expression from the statements.
+   */
+  Token colon;
+
+  /**
+   * The statements that will be executed if this switch member is selected.
+   */
+  NodeList<Statement> _statements;
+
+  /**
+   * Initialize a newly created switch member. The list of [labels] can be
+   * `null` if there are no labels.
+   */
+  SwitchMemberImpl(List<Label> labels, this.keyword, this.colon,
+      List<Statement> statements) {
+    _labels = new NodeList<Label>(this, labels);
+    _statements = new NodeList<Statement>(this, statements);
+  }
+
+  @override
+  Token get beginToken {
+    if (!_labels.isEmpty) {
+      return _labels.beginToken;
+    }
+    return keyword;
+  }
+
+  @override
+  Token get endToken {
+    if (!_statements.isEmpty) {
+      return _statements.endToken;
+    }
+    return colon;
+  }
+
+  @override
+  NodeList<Label> get labels => _labels;
+
+  @override
+  NodeList<Statement> get statements => _statements;
+}
+
+/**
+ * A switch statement.
+ *
+ * > switchStatement ::=
+ * >     'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}'
+ */
+class SwitchStatementImpl extends StatementImpl implements SwitchStatement {
+  /**
+   * The token representing the 'switch' keyword.
+   */
+  Token switchKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The expression used to determine which of the switch members will be
+   * selected.
+   */
+  Expression _expression;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The left curly bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The switch members that can be selected by the expression.
+   */
+  NodeList<SwitchMember> _members;
+
+  /**
+   * The right curly bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created switch statement. The list of [members] can be
+   * `null` if there are no switch members.
+   */
+  SwitchStatementImpl(
+      this.switchKeyword,
+      this.leftParenthesis,
+      Expression expression,
+      this.rightParenthesis,
+      this.leftBracket,
+      List<SwitchMember> members,
+      this.rightBracket) {
+    _expression = _becomeParentOf(expression);
+    _members = new NodeList<SwitchMember>(this, members);
+  }
+
+  @override
+  Token get beginToken => switchKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(switchKeyword)
+    ..add(leftParenthesis)
+    ..add(_expression)
+    ..add(rightParenthesis)
+    ..add(leftBracket)
+    ..addAll(_members)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  NodeList<SwitchMember> get members => _members;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSwitchStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+    _members.accept(visitor);
+  }
+}
+
+/**
+ * A symbol literal expression.
+ *
+ * > symbolLiteral ::=
+ * >     '#' (operator | (identifier ('.' identifier)*))
+ */
+class SymbolLiteralImpl extends LiteralImpl implements SymbolLiteral {
+  /**
+   * The token introducing the literal.
+   */
+  Token poundSign;
+
+  /**
+   * The components of the literal.
+   */
+  final List<Token> components;
+
+  /**
+   * Initialize a newly created symbol literal.
+   */
+  SymbolLiteralImpl(this.poundSign, this.components);
+
+  @override
+  Token get beginToken => poundSign;
+
+  @override
+  // TODO(paulberry): add "." tokens.
+  Iterable get childEntities => new ChildEntities()
+    ..add(poundSign)
+    ..addAll(components);
+
+  @override
+  Token get endToken => components[components.length - 1];
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitSymbolLiteral(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A this expression.
+ *
+ * > thisExpression ::=
+ * >     'this'
+ */
+class ThisExpressionImpl extends ExpressionImpl implements ThisExpression {
+  /**
+   * The token representing the 'this' keyword.
+   */
+  Token thisKeyword;
+
+  /**
+   * Initialize a newly created this expression.
+   */
+  ThisExpressionImpl(this.thisKeyword);
+
+  @override
+  Token get beginToken => thisKeyword;
+
+  @override
+  Iterable get childEntities => new ChildEntities()..add(thisKeyword);
+
+  @override
+  Token get endToken => thisKeyword;
+
+  @override
+  int get precedence => 16;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitThisExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    // There are no children to visit.
+  }
+}
+
+/**
+ * A throw expression.
+ *
+ * > throwExpression ::=
+ * >     'throw' [Expression]
+ */
+class ThrowExpressionImpl extends ExpressionImpl implements ThrowExpression {
+  /**
+   * The token representing the 'throw' keyword.
+   */
+  Token throwKeyword;
+
+  /**
+   * The expression computing the exception to be thrown.
+   */
+  Expression _expression;
+
+  /**
+   * Initialize a newly created throw expression.
+   */
+  ThrowExpressionImpl(this.throwKeyword, Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken => throwKeyword;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(throwKeyword)..add(_expression);
+
+  @override
+  Token get endToken {
+    if (_expression != null) {
+      return _expression.endToken;
+    }
+    return throwKeyword;
+  }
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  int get precedence => 0;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitThrowExpression(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
+
+/**
+ * The declaration of one or more top-level variables of the same type.
+ *
+ * > topLevelVariableDeclaration ::=
+ * >     ('final' | 'const') type? staticFinalDeclarationList ';'
+ * >   | variableDeclaration ';'
+ */
+class TopLevelVariableDeclarationImpl extends CompilationUnitMemberImpl
+    implements TopLevelVariableDeclaration {
+  /**
+   * The top-level variables being declared.
+   */
+  VariableDeclarationList _variableList;
+
+  /**
+   * The semicolon terminating the declaration.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created top-level variable declaration. Either or both
+   * of the [comment] and [metadata] can be `null` if the variable does not have
+   * the corresponding attribute.
+   */
+  TopLevelVariableDeclarationImpl(Comment comment, List<Annotation> metadata,
+      VariableDeclarationList variableList, this.semicolon)
+      : super(comment, metadata) {
+    _variableList = _becomeParentOf(variableList);
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(_variableList)..add(semicolon);
+
+  @override
+  Element get element => null;
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => _variableList.beginToken;
+
+  @override
+  VariableDeclarationList get variables => _variableList;
+
+  @override
+  void set variables(VariableDeclarationList variables) {
+    _variableList = _becomeParentOf(variables);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitTopLevelVariableDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_variableList, visitor);
+  }
+}
+
+/**
+ * A try statement.
+ *
+ * > tryStatement ::=
+ * >     'try' [Block] ([CatchClause]+ finallyClause? | finallyClause)
+ * >
+ * > finallyClause ::=
+ * >     'finally' [Block]
+ */
+class TryStatementImpl extends StatementImpl implements TryStatement {
+  /**
+   * The token representing the 'try' keyword.
+   */
+  Token tryKeyword;
+
+  /**
+   * The body of the statement.
+   */
+  Block _body;
+
+  /**
+   * The catch clauses contained in the try statement.
+   */
+  NodeList<CatchClause> _catchClauses;
+
+  /**
+   * The token representing the 'finally' keyword, or `null` if the statement
+   * does not contain a finally clause.
+   */
+  Token finallyKeyword;
+
+  /**
+   * The finally block contained in the try statement, or `null` if the
+   * statement does not contain a finally clause.
+   */
+  Block _finallyBlock;
+
+  /**
+   * Initialize a newly created try statement. The list of [catchClauses] can be
+   * `null` if there are no catch clauses. The [finallyKeyword] and
+   * [finallyBlock] can be `null` if there is no finally clause.
+   */
+  TryStatementImpl(this.tryKeyword, Block body, List<CatchClause> catchClauses,
+      this.finallyKeyword, Block finallyBlock) {
+    _body = _becomeParentOf(body);
+    _catchClauses = new NodeList<CatchClause>(this, catchClauses);
+    _finallyBlock = _becomeParentOf(finallyBlock);
+  }
+
+  @override
+  Token get beginToken => tryKeyword;
+
+  @override
+  Block get body => _body;
+
+  @override
+  void set body(Block block) {
+    _body = _becomeParentOf(block);
+  }
+
+  @override
+  NodeList<CatchClause> get catchClauses => _catchClauses;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(tryKeyword)
+    ..add(_body)
+    ..addAll(_catchClauses)
+    ..add(finallyKeyword)
+    ..add(_finallyBlock);
+
+  @override
+  Token get endToken {
+    if (_finallyBlock != null) {
+      return _finallyBlock.endToken;
+    } else if (finallyKeyword != null) {
+      return finallyKeyword;
+    } else if (!_catchClauses.isEmpty) {
+      return _catchClauses.endToken;
+    }
+    return _body.endToken;
+  }
+
+  @override
+  Block get finallyBlock => _finallyBlock;
+
+  @override
+  void set finallyBlock(Block block) {
+    _finallyBlock = _becomeParentOf(block);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitTryStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_body, visitor);
+    _catchClauses.accept(visitor);
+    _safelyVisitChild(_finallyBlock, visitor);
+  }
+}
+
+/**
+ * The declaration of a type alias.
+ *
+ * > typeAlias ::=
+ * >     'typedef' typeAliasBody
+ * >
+ * > typeAliasBody ::=
+ * >     classTypeAlias
+ * >   | functionTypeAlias
+ */
+abstract class TypeAliasImpl extends NamedCompilationUnitMemberImpl
+    implements TypeAlias {
+  /**
+   * The token representing the 'typedef' keyword.
+   */
+  Token typedefKeyword;
+
+  /**
+   * The semicolon terminating the declaration.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created type alias. Either or both of the [comment] and
+   * [metadata] can be `null` if the declaration does not have the corresponding
+   * attribute.
+   */
+  TypeAliasImpl(Comment comment, List<Annotation> metadata, this.typedefKeyword,
+      SimpleIdentifier name, this.semicolon)
+      : super(comment, metadata, name);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => typedefKeyword;
+}
+
+/**
+ * A list of type arguments.
+ *
+ * > typeArguments ::=
+ * >     '<' typeName (',' typeName)* '>'
+ */
+class TypeArgumentListImpl extends AstNodeImpl implements TypeArgumentList {
+  /**
+   * The left bracket.
+   */
+  Token leftBracket;
+
+  /**
+   * The type arguments associated with the type.
+   */
+  NodeList<TypeName> _arguments;
+
+  /**
+   * The right bracket.
+   */
+  Token rightBracket;
+
+  /**
+   * Initialize a newly created list of type arguments.
+   */
+  TypeArgumentListImpl(
+      this.leftBracket, List<TypeName> arguments, this.rightBracket) {
+    _arguments = new NodeList<TypeName>(this, arguments);
+  }
+
+  @override
+  NodeList<TypeName> get arguments => _arguments;
+
+  @override
+  Token get beginToken => leftBracket;
+
+  @override
+  // TODO(paulberry): Add commas.
+  Iterable get childEntities => new ChildEntities()
+    ..add(leftBracket)
+    ..addAll(_arguments)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitTypeArgumentList(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _arguments.accept(visitor);
+  }
+}
+
+/**
+ * A literal that has a type associated with it.
+ *
+ * > typedLiteral ::=
+ * >     [ListLiteral]
+ * >   | [MapLiteral]
+ */
+abstract class TypedLiteralImpl extends LiteralImpl implements TypedLiteral {
+  /**
+   * The token representing the 'const' keyword, or `null` if the literal is not
+   * a constant.
+   */
+  Token constKeyword;
+
+  /**
+   * The type argument associated with this literal, or `null` if no type
+   * arguments were declared.
+   */
+  TypeArgumentList _typeArguments;
+
+  /**
+   * Initialize a newly created typed literal. The [constKeyword] can be `null`\
+   * if the literal is not a constant. The [typeArguments] can be `null` if no
+   * type arguments were declared.
+   */
+  TypedLiteralImpl(this.constKeyword, TypeArgumentList typeArguments) {
+    _typeArguments = _becomeParentOf(typeArguments);
+  }
+
+  @override
+  TypeArgumentList get typeArguments => _typeArguments;
+
+  @override
+  void set typeArguments(TypeArgumentList typeArguments) {
+    _typeArguments = _becomeParentOf(typeArguments);
+  }
+
+  ChildEntities get _childEntities =>
+      new ChildEntities()..add(constKeyword)..add(_typeArguments);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_typeArguments, visitor);
+  }
+}
+
+/**
+ * The name of a type, which can optionally include type arguments.
+ *
+ * > typeName ::=
+ * >     [Identifier] typeArguments?
+ */
+class TypeNameImpl extends AstNodeImpl implements TypeName {
+  /**
+   * The name of the type.
+   */
+  Identifier _name;
+
+  /**
+   * The type arguments associated with the type, or `null` if there are no type
+   * arguments.
+   */
+  TypeArgumentList _typeArguments;
+
+  /**
+   * The type being named, or `null` if the AST structure has not been resolved.
+   */
+  DartType type;
+
+  /**
+   * Initialize a newly created type name. The [typeArguments] can be `null` if
+   * there are no type arguments.
+   */
+  TypeNameImpl(Identifier name, TypeArgumentList typeArguments) {
+    _name = _becomeParentOf(name);
+    _typeArguments = _becomeParentOf(typeArguments);
+  }
+
+  @override
+  Token get beginToken => _name.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_name)..add(_typeArguments);
+
+  @override
+  Token get endToken {
+    if (_typeArguments != null) {
+      return _typeArguments.endToken;
+    }
+    return _name.endToken;
+  }
+
+  @override
+  bool get isDeferred {
+    Identifier identifier = name;
+    if (identifier is! PrefixedIdentifier) {
+      return false;
+    }
+    return (identifier as PrefixedIdentifier).isDeferred;
+  }
+
+  @override
+  bool get isSynthetic => _name.isSynthetic && _typeArguments == null;
+
+  @override
+  Identifier get name => _name;
+
+  @override
+  void set name(Identifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+
+  @override
+  TypeArgumentList get typeArguments => _typeArguments;
+
+  @override
+  void set typeArguments(TypeArgumentList typeArguments) {
+    _typeArguments = _becomeParentOf(typeArguments);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitTypeName(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_typeArguments, visitor);
+  }
+}
+
+/**
+ * A type parameter.
+ *
+ * > typeParameter ::=
+ * >     [SimpleIdentifier] ('extends' [TypeName])?
+ */
+class TypeParameterImpl extends DeclarationImpl implements TypeParameter {
+  /**
+   * The name of the type parameter.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * The token representing the 'extends' keyword, or `null` if there is no
+   * explicit upper bound.
+   */
+  Token extendsKeyword;
+
+  /**
+   * The name of the upper bound for legal arguments, or `null` if there is no
+   * explicit upper bound.
+   */
+  TypeName _bound;
+
+  /**
+   * Initialize a newly created type parameter. Either or both of the [comment]
+   * and [metadata] can be `null` if the parameter does not have the
+   * corresponding attribute. The [extendsKeyword] and [bound] can be `null` if
+   * the parameter does not have an upper bound.
+   */
+  TypeParameterImpl(Comment comment, List<Annotation> metadata,
+      SimpleIdentifier name, this.extendsKeyword, TypeName bound)
+      : super(comment, metadata) {
+    _name = _becomeParentOf(name);
+    _bound = _becomeParentOf(bound);
+  }
+
+  @override
+  TypeName get bound => _bound;
+
+  @override
+  void set bound(TypeName typeName) {
+    _bound = _becomeParentOf(typeName);
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(_name)..add(extendsKeyword)..add(_bound);
+
+  @override
+  TypeParameterElement get element =>
+      _name != null ? (_name.staticElement as TypeParameterElement) : null;
+
+  @override
+  Token get endToken {
+    if (_bound == null) {
+      return _name.endToken;
+    }
+    return _bound.endToken;
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitTypeParameter(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_bound, visitor);
+  }
+}
+
+/**
+ * Type parameters within a declaration.
+ *
+ * > typeParameterList ::=
+ * >     '<' [TypeParameter] (',' [TypeParameter])* '>'
+ */
+class TypeParameterListImpl extends AstNodeImpl implements TypeParameterList {
+  /**
+   * The left angle bracket.
+   */
+  final Token leftBracket;
+
+  /**
+   * The type parameters in the list.
+   */
+  NodeList<TypeParameter> _typeParameters;
+
+  /**
+   * The right angle bracket.
+   */
+  final Token rightBracket;
+
+  /**
+   * Initialize a newly created list of type parameters.
+   */
+  TypeParameterListImpl(
+      this.leftBracket, List<TypeParameter> typeParameters, this.rightBracket) {
+    _typeParameters = new NodeList<TypeParameter>(this, typeParameters);
+  }
+
+  @override
+  Token get beginToken => leftBracket;
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(leftBracket)
+    ..addAll(_typeParameters)
+    ..add(rightBracket);
+
+  @override
+  Token get endToken => rightBracket;
+
+  @override
+  NodeList<TypeParameter> get typeParameters => _typeParameters;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitTypeParameterList(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _typeParameters.accept(visitor);
+  }
+}
+
+/**
+ * A directive that references a URI.
+ *
+ * > uriBasedDirective ::=
+ * >     [ExportDirective]
+ * >   | [ImportDirective]
+ * >   | [PartDirective]
+ */
+abstract class UriBasedDirectiveImpl extends DirectiveImpl
+    implements UriBasedDirective {
+  /**
+   * The prefix of a URI using the `dart-ext` scheme to reference a native code
+   * library.
+   */
+  static String _DART_EXT_SCHEME = "dart-ext:";
+
+  /**
+   * The URI referenced by this directive.
+   */
+  StringLiteral _uri;
+
+  /**
+   * The content of the URI.
+   */
+  String uriContent;
+
+  /**
+   * The source to which the URI was resolved.
+   */
+  Source source;
+
+  /**
+   * Initialize a newly create URI-based directive. Either or both of the
+   * [comment] and [metadata] can be `null` if the directive does not have the
+   * corresponding attribute.
+   */
+  UriBasedDirectiveImpl(
+      Comment comment, List<Annotation> metadata, StringLiteral uri)
+      : super(comment, metadata) {
+    _uri = _becomeParentOf(uri);
+  }
+
+  @override
+  StringLiteral get uri => _uri;
+
+  @override
+  void set uri(StringLiteral uri) {
+    _uri = _becomeParentOf(uri);
+  }
+
+  @override
+  UriValidationCode validate() {
+    StringLiteral uriLiteral = uri;
+    if (uriLiteral is StringInterpolation) {
+      return UriValidationCode.URI_WITH_INTERPOLATION;
+    }
+    String uriContent = this.uriContent;
+    if (uriContent == null) {
+      return UriValidationCode.INVALID_URI;
+    }
+    if (this is ImportDirective && uriContent.startsWith(_DART_EXT_SCHEME)) {
+      return UriValidationCode.URI_WITH_DART_EXT_SCHEME;
+    }
+    try {
+      parseUriWithException(Uri.encodeFull(uriContent));
+    } on URISyntaxException {
+      return UriValidationCode.INVALID_URI;
+    }
+    return null;
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_uri, visitor);
+  }
+}
+
+/**
+ * Validation codes returned by [UriBasedDirective.validate].
+ */
+class UriValidationCodeImpl implements UriValidationCode {
+  static const UriValidationCode INVALID_URI =
+      const UriValidationCodeImpl('INVALID_URI');
+
+  static const UriValidationCode URI_WITH_INTERPOLATION =
+      const UriValidationCodeImpl('URI_WITH_INTERPOLATION');
+
+  static const UriValidationCode URI_WITH_DART_EXT_SCHEME =
+      const UriValidationCodeImpl('URI_WITH_DART_EXT_SCHEME');
+
+  /**
+   * The name of the validation code.
+   */
+  final String name;
+
+  /**
+   * Initialize a newly created validation code to have the given [name].
+   */
+  const UriValidationCodeImpl(this.name);
+
+  @override
+  String toString() => name;
+}
+
+/**
+ * An identifier that has an initial value associated with it. Instances of this
+ * class are always children of the class [VariableDeclarationList].
+ *
+ * > variableDeclaration ::=
+ * >     [SimpleIdentifier] ('=' [Expression])?
+ *
+ * TODO(paulberry): the grammar does not allow metadata to be associated with
+ * a VariableDeclaration, and currently we don't record comments for it either.
+ * Consider changing the class hierarchy so that [VariableDeclaration] does not
+ * extend [Declaration].
+ */
+class VariableDeclarationImpl extends DeclarationImpl
+    implements VariableDeclaration {
+  /**
+   * The name of the variable being declared.
+   */
+  SimpleIdentifier _name;
+
+  /**
+   * The equal sign separating the variable name from the initial value, or
+   * `null` if the initial value was not specified.
+   */
+  Token equals;
+
+  /**
+   * The expression used to compute the initial value for the variable, or
+   * `null` if the initial value was not specified.
+   */
+  Expression _initializer;
+
+  /**
+   * Initialize a newly created variable declaration. The [equals] and
+   * [initializer] can be `null` if there is no initializer.
+   */
+  VariableDeclarationImpl(
+      SimpleIdentifier name, this.equals, Expression initializer)
+      : super(null, null) {
+    _name = _becomeParentOf(name);
+    _initializer = _becomeParentOf(initializer);
+  }
+
+  @override
+  Iterable get childEntities =>
+      super._childEntities..add(_name)..add(equals)..add(_initializer);
+
+  /**
+   * This overridden implementation of getDocumentationComment() looks in the
+   * grandparent node for Dartdoc comments if no documentation is specifically
+   * available on the node.
+   */
+  @override
+  Comment get documentationComment {
+    Comment comment = super.documentationComment;
+    if (comment == null) {
+      if (parent != null && parent.parent != null) {
+        AstNode node = parent.parent;
+        if (node is AnnotatedNode) {
+          return node.documentationComment;
+        }
+      }
+    }
+    return comment;
+  }
+
+  @override
+  VariableElement get element =>
+      _name != null ? (_name.staticElement as VariableElement) : null;
+
+  @override
+  Token get endToken {
+    if (_initializer != null) {
+      return _initializer.endToken;
+    }
+    return _name.endToken;
+  }
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
+
+  @override
+  Expression get initializer => _initializer;
+
+  @override
+  void set initializer(Expression expression) {
+    _initializer = _becomeParentOf(expression);
+  }
+
+  @override
+  bool get isConst {
+    AstNode parent = this.parent;
+    return parent is VariableDeclarationList && parent.isConst;
+  }
+
+  @override
+  bool get isFinal {
+    AstNode parent = this.parent;
+    return parent is VariableDeclarationList && parent.isFinal;
+  }
+
+  @override
+  SimpleIdentifier get name => _name;
+
+  @override
+  void set name(SimpleIdentifier identifier) {
+    _name = _becomeParentOf(identifier);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitVariableDeclaration(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_name, visitor);
+    _safelyVisitChild(_initializer, visitor);
+  }
+}
+
+/**
+ * The declaration of one or more variables of the same type.
+ *
+ * > variableDeclarationList ::=
+ * >     finalConstVarOrType [VariableDeclaration] (',' [VariableDeclaration])*
+ * >
+ * > finalConstVarOrType ::=
+ * >   | 'final' [TypeName]?
+ * >   | 'const' [TypeName]?
+ * >   | 'var'
+ * >   | [TypeName]
+ */
+class VariableDeclarationListImpl extends AnnotatedNodeImpl
+    implements VariableDeclarationList {
+  /**
+   * The token representing the 'final', 'const' or 'var' keyword, or `null` if
+   * no keyword was included.
+   */
+  Token keyword;
+
+  /**
+   * The type of the variables being declared, or `null` if no type was provided.
+   */
+  TypeName _type;
+
+  /**
+   * A list containing the individual variables being declared.
+   */
+  NodeList<VariableDeclaration> _variables;
+
+  /**
+   * Initialize a newly created variable declaration list. Either or both of the
+   * [comment] and [metadata] can be `null` if the variable list does not have
+   * the corresponding attribute. The [keyword] can be `null` if a type was
+   * specified. The [type] must be `null` if the keyword is 'var'.
+   */
+  VariableDeclarationListImpl(Comment comment, List<Annotation> metadata,
+      this.keyword, TypeName type, List<VariableDeclaration> variables)
+      : super(comment, metadata) {
+    _type = _becomeParentOf(type);
+    _variables = new NodeList<VariableDeclaration>(this, variables);
+  }
+
+  @override
+  // TODO(paulberry): include commas.
+  Iterable get childEntities => super._childEntities
+    ..add(keyword)
+    ..add(_type)
+    ..addAll(_variables);
+
+  @override
+  Token get endToken => _variables.endToken;
+
+  @override
+  Token get firstTokenAfterCommentAndMetadata {
+    if (keyword != null) {
+      return keyword;
+    } else if (_type != null) {
+      return _type.beginToken;
+    }
+    return _variables.beginToken;
+  }
+
+  @override
+  bool get isConst =>
+      keyword is KeywordToken &&
+      (keyword as KeywordToken).keyword == Keyword.CONST;
+
+  @override
+  bool get isFinal =>
+      keyword is KeywordToken &&
+      (keyword as KeywordToken).keyword == Keyword.FINAL;
+
+  @override
+  TypeName get type => _type;
+
+  @override
+  void set type(TypeName typeName) {
+    _type = _becomeParentOf(typeName);
+  }
+
+  @override
+  NodeList<VariableDeclaration> get variables => _variables;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitVariableDeclarationList(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _safelyVisitChild(_type, visitor);
+    _variables.accept(visitor);
+  }
+}
+
+/**
+ * A list of variables that are being declared in a context where a statement is
+ * required.
+ *
+ * > variableDeclarationStatement ::=
+ * >     [VariableDeclarationList] ';'
+ */
+class VariableDeclarationStatementImpl extends StatementImpl
+    implements VariableDeclarationStatement {
+  /**
+   * The variables being declared.
+   */
+  VariableDeclarationList _variableList;
+
+  /**
+   * The semicolon terminating the statement.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created variable declaration statement.
+   */
+  VariableDeclarationStatementImpl(
+      VariableDeclarationList variableList, this.semicolon) {
+    _variableList = _becomeParentOf(variableList);
+  }
+
+  @override
+  Token get beginToken => _variableList.beginToken;
+
+  @override
+  Iterable get childEntities =>
+      new ChildEntities()..add(_variableList)..add(semicolon);
+
+  @override
+  Token get endToken => semicolon;
+
+  @override
+  VariableDeclarationList get variables => _variableList;
+
+  @override
+  void set variables(VariableDeclarationList variables) {
+    _variableList = _becomeParentOf(variables);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitVariableDeclarationStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_variableList, visitor);
+  }
+}
+
+/**
+ * A while statement.
+ *
+ * > whileStatement ::=
+ * >     'while' '(' [Expression] ')' [Statement]
+ */
+class WhileStatementImpl extends StatementImpl implements WhileStatement {
+  /**
+   * The token representing the 'while' keyword.
+   */
+  Token whileKeyword;
+
+  /**
+   * The left parenthesis.
+   */
+  Token leftParenthesis;
+
+  /**
+   * The expression used to determine whether to execute the body of the loop.
+   */
+  Expression _condition;
+
+  /**
+   * The right parenthesis.
+   */
+  Token rightParenthesis;
+
+  /**
+   * The body of the loop.
+   */
+  Statement _body;
+
+  /**
+   * Initialize a newly created while statement.
+   */
+  WhileStatementImpl(this.whileKeyword, this.leftParenthesis,
+      Expression condition, this.rightParenthesis, Statement body) {
+    _condition = _becomeParentOf(condition);
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  Token get beginToken => whileKeyword;
+
+  @override
+  Statement get body => _body;
+
+  @override
+  void set body(Statement statement) {
+    _body = _becomeParentOf(statement);
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(whileKeyword)
+    ..add(leftParenthesis)
+    ..add(_condition)
+    ..add(rightParenthesis)
+    ..add(_body);
+
+  @override
+  Expression get condition => _condition;
+
+  @override
+  void set condition(Expression expression) {
+    _condition = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get endToken => _body.endToken;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitWhileStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_condition, visitor);
+    _safelyVisitChild(_body, visitor);
+  }
+}
+
+/**
+ * The with clause in a class declaration.
+ *
+ * > withClause ::=
+ * >     'with' [TypeName] (',' [TypeName])*
+ */
+class WithClauseImpl extends AstNodeImpl implements WithClause {
+  /**
+   * The token representing the 'with' keyword.
+   */
+  Token withKeyword;
+
+  /**
+   * The names of the mixins that were specified.
+   */
+  NodeList<TypeName> _mixinTypes;
+
+  /**
+   * Initialize a newly created with clause.
+   */
+  WithClauseImpl(this.withKeyword, List<TypeName> mixinTypes) {
+    _mixinTypes = new NodeList<TypeName>(this, mixinTypes);
+  }
+
+  @override
+  Token get beginToken => withKeyword;
+
+  @override
+  // TODO(paulberry): add commas.
+  Iterable get childEntities => new ChildEntities()
+    ..add(withKeyword)
+    ..addAll(_mixinTypes);
+
+  @override
+  Token get endToken => _mixinTypes.endToken;
+
+  @override
+  NodeList<TypeName> get mixinTypes => _mixinTypes;
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitWithClause(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _mixinTypes.accept(visitor);
+  }
+}
+
+/**
+ * A yield statement.
+ *
+ * > yieldStatement ::=
+ * >     'yield' '*'? [Expression] ‘;’
+ */
+class YieldStatementImpl extends StatementImpl implements YieldStatement {
+  /**
+   * The 'yield' keyword.
+   */
+  Token yieldKeyword;
+
+  /**
+   * The star optionally following the 'yield' keyword.
+   */
+  Token star;
+
+  /**
+   * The expression whose value will be yielded.
+   */
+  Expression _expression;
+
+  /**
+   * The semicolon following the expression.
+   */
+  Token semicolon;
+
+  /**
+   * Initialize a newly created yield expression. The [star] can be `null` if no
+   * star was provided.
+   */
+  YieldStatementImpl(
+      this.yieldKeyword, this.star, Expression expression, this.semicolon) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  Token get beginToken {
+    if (yieldKeyword != null) {
+      return yieldKeyword;
+    }
+    return _expression.beginToken;
+  }
+
+  @override
+  Iterable get childEntities => new ChildEntities()
+    ..add(yieldKeyword)
+    ..add(star)
+    ..add(_expression)
+    ..add(semicolon);
+
+  @override
+  Token get endToken {
+    if (semicolon != null) {
+      return semicolon;
+    }
+    return _expression.endToken;
+  }
+
+  @override
+  Expression get expression => _expression;
+
+  @override
+  void set expression(Expression expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
+  accept(AstVisitor visitor) => visitor.visitYieldStatement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _safelyVisitChild(_expression, visitor);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index f0435eb..1a21746 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.src.generated.ast;
+library analyzer.src.dart.ast.utilities;
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 71030e7..e319acf 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -7,11 +7,12 @@
 import 'dart:collection';
 import 'dart:math' show min;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart'
     show DartObject, EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
@@ -335,7 +336,22 @@
   }
 
   @override
-  bool get isValidMixin => hasModifier(Modifier.MIXIN);
+  bool get isValidMixin {
+    if (!context.analysisOptions.enableSuperMixins) {
+      if (hasReferenceToSuper) {
+        return false;
+      }
+      if (!supertype.isObject) {
+        return false;
+      }
+    }
+    for (ConstructorElement constructor in constructors) {
+      if (!constructor.isSynthetic && !constructor.isFactory) {
+        return false;
+      }
+    }
+    return true;
+  }
 
   @override
   ElementKind get kind => ElementKind.CLASS;
@@ -385,13 +401,6 @@
     return null;
   }
 
-  /**
-   * Set whether this class is a valid mixin.
-   */
-  void set validMixin(bool isValidMixin) {
-    setModifier(Modifier.MIXIN, isValidMixin);
-  }
-
   @override
   accept(ElementVisitor visitor) => visitor.visitClassElement(this);
 
@@ -2511,6 +2520,13 @@
    */
   FieldFormalParameterElementImpl(Identifier name) : super.forNode(name);
 
+  /**
+   * Initialize a newly created parameter element to have the given [name] and
+   * [offset].
+   */
+  FieldFormalParameterElementImpl.forNameAndOffset(String name, int nameOffset)
+      : super(name, nameOffset);
+
   @override
   bool get isInitializingFormal => true;
 
@@ -3095,6 +3111,9 @@
       entryPoint != null && isOrImportsBrowserLibrary;
 
   @override
+  bool get isDartAsync => name == "dart.async";
+
+  @override
   bool get isDartCore => name == "dart.core";
 
   @override
@@ -3641,6 +3660,148 @@
 }
 
 /**
+ * The enumeration `Modifier` defines constants for all of the modifiers defined
+ * by the Dart language and for a few additional flags that are useful.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class Modifier extends Enum<Modifier> {
+  /**
+   * Indicates that the modifier 'abstract' was applied to the element.
+   */
+  static const Modifier ABSTRACT = const Modifier('ABSTRACT', 0);
+
+  /**
+   * Indicates that an executable element has a body marked as being
+   * asynchronous.
+   */
+  static const Modifier ASYNCHRONOUS = const Modifier('ASYNCHRONOUS', 1);
+
+  /**
+   * Indicates that the modifier 'const' was applied to the element.
+   */
+  static const Modifier CONST = const Modifier('CONST', 2);
+
+  /**
+   * Indicates that the import element represents a deferred library.
+   */
+  static const Modifier DEFERRED = const Modifier('DEFERRED', 3);
+
+  /**
+   * Indicates that a class element was defined by an enum declaration.
+   */
+  static const Modifier ENUM = const Modifier('ENUM', 4);
+
+  /**
+   * Indicates that a class element was defined by an enum declaration.
+   */
+  static const Modifier EXTERNAL = const Modifier('EXTERNAL', 5);
+
+  /**
+   * Indicates that the modifier 'factory' was applied to the element.
+   */
+  static const Modifier FACTORY = const Modifier('FACTORY', 6);
+
+  /**
+   * Indicates that the modifier 'final' was applied to the element.
+   */
+  static const Modifier FINAL = const Modifier('FINAL', 7);
+
+  /**
+   * Indicates that an executable element has a body marked as being a
+   * generator.
+   */
+  static const Modifier GENERATOR = const Modifier('GENERATOR', 8);
+
+  /**
+   * Indicates that the pseudo-modifier 'get' was applied to the element.
+   */
+  static const Modifier GETTER = const Modifier('GETTER', 9);
+
+  /**
+   * A flag used for libraries indicating that the defining compilation unit
+   * contains at least one import directive whose URI uses the "dart-ext"
+   * scheme.
+   */
+  static const Modifier HAS_EXT_URI = const Modifier('HAS_EXT_URI', 10);
+
+  /**
+   * Indicates that the associated element did not have an explicit type
+   * associated with it. If the element is an [ExecutableElement], then the
+   * type being referred to is the return type.
+   */
+  static const Modifier IMPLICIT_TYPE = const Modifier('IMPLICIT_TYPE', 11);
+
+  /**
+   * Indicates that a class is a mixin application.
+   */
+  static const Modifier MIXIN_APPLICATION =
+      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);
+
+  /**
+   * Indicates that the pseudo-modifier 'set' was applied to the element.
+   */
+  static const Modifier SETTER = const Modifier('SETTER', 16);
+
+  /**
+   * Indicates that the modifier 'static' was applied to the element.
+   */
+  static const Modifier STATIC = const Modifier('STATIC', 17);
+
+  /**
+   * Indicates that the element does not appear in the source code but was
+   * implicitly created. For example, if a class does not define any
+   * 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 List<Modifier> values = const [
+    ABSTRACT,
+    ASYNCHRONOUS,
+    CONST,
+    DEFERRED,
+    ENUM,
+    EXTERNAL,
+    FACTORY,
+    FINAL,
+    GENERATOR,
+    GETTER,
+    HAS_EXT_URI,
+    IMPLICIT_TYPE,
+    MIXIN_APPLICATION,
+    POTENTIALLY_MUTATED_IN_CONTEXT,
+    POTENTIALLY_MUTATED_IN_SCOPE,
+    REFERENCES_SUPER,
+    SETTER,
+    STATIC,
+    SYNTHETIC
+  ];
+
+  const Modifier(String name, int ordinal) : super(name, ordinal);
+}
+
+/**
  * A concrete implementation of a [MultiplyDefinedElement].
  */
 class MultiplyDefinedElementImpl implements MultiplyDefinedElement {
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 75dcee6..bc073d8 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -4,11 +4,11 @@
 
 library analyzer.src.dart.element.member;
 
+import 'package:analyzer/dart/ast/ast.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/ast.dart';
 import 'package:analyzer/src/generated/constant.dart'
     show DartObject, EvaluationResultImpl;
 import 'package:analyzer/src/generated/engine.dart'
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index b804339..0f8ec27 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -14,6 +14,7 @@
     show AnalysisContext, AnalysisEngine, AnalysisException;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/scanner.dart' show Keyword;
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -234,15 +235,6 @@
   List<TypeParameterElement> get boundTypeParameters => typeFormals;
 
   @override
-  List<TypeParameterElement> get typeFormals {
-    if (_isInstantiated) {
-      return TypeParameterElement.EMPTY_LIST;
-    } else {
-      return element?.typeParameters ?? TypeParameterElement.EMPTY_LIST;
-    }
-  }
-
-  @override
   String get displayName {
     String name = this.name;
     if (name == null || name.length == 0) {
@@ -496,6 +488,15 @@
   }
 
   @override
+  List<TypeParameterElement> get typeFormals {
+    if (_isInstantiated) {
+      return TypeParameterElement.EMPTY_LIST;
+    } else {
+      return element?.typeParameters ?? TypeParameterElement.EMPTY_LIST;
+    }
+  }
+
+  @override
   List<TypeParameterElement> get typeParameters {
     if (_typeParameters == null) {
       // Combine the generic type variables from all enclosing contexts, except
@@ -1194,6 +1195,15 @@
   }
 
   @override
+  bool get isDartAsyncFuture {
+    ClassElement element = this.element;
+    if (element == null) {
+      return false;
+    }
+    return element.name == "Future" && element.library.isDartAsync;
+  }
+
+  @override
   bool get isDartCoreFunction {
     ClassElement element = this.element;
     if (element == null) {
@@ -1280,6 +1290,35 @@
   }
 
   @override
+  DartType flattenFutures(TypeSystem typeSystem) {
+    // Implement the case: "If T = Future<S> then flatten(T) = flatten(S)."
+    if (isDartAsyncFuture && typeArguments.isNotEmpty) {
+      return typeArguments[0].flattenFutures(typeSystem);
+    }
+
+    // Implement the case: "Otherwise if T <: Future then let S be a type
+    // such that T << Future<S> and for all R, if T << Future<R> then S << R.
+    // Then flatten(T) = S."
+    //
+    // In other words, given the set of all types R such that T << Future<R>,
+    // let S be the most specific of those types, if any such S exists.
+    //
+    // Since we only care about the most specific type, it is sufficent to
+    // look at the types appearing as a parameter to Future in the type
+    // hierarchy of T.  We don't need to consider the supertypes of those
+    // types, since they are by definition less specific.
+    List<DartType> candidateTypes =
+        _searchTypeHierarchyForFutureTypeParameters();
+    DartType flattenResult = _findMostSpecificType(candidateTypes, typeSystem);
+    if (flattenResult != null) {
+      return flattenResult;
+    }
+
+    // Implement the case: "In any other circumstance, flatten(T) = T."
+    return this;
+  }
+
+  @override
   PropertyAccessorElement getGetter(String getterName) =>
       PropertyAccessorMember.from(element.getGetter(getterName), this);
 
@@ -1678,6 +1717,34 @@
     if (JavaArrays.equals(newTypeArguments, typeArguments)) {
       return this;
     }
+
+    if (isDartAsyncFuture && newTypeArguments.isNotEmpty) {
+      //
+      // In strong mode interpret Future< T > as Future< flatten(T) >
+      //
+      // For example, Future<Future<T>> will flatten to Future<T>.
+      //
+      // In the Dart 3rd edition spec, this flatten operation is used for
+      // `async` and `await`. In strong mode, we extend it to all Future<T>
+      // instantiations. This allows typing of Future-related operations
+      // in dart:async in a way that matches their runtime behavior and provides
+      // precise return types for users of these APIs.
+      //
+      // For example:
+      //
+      //     abstract class Future<T> {
+      //       Future<S> then<S>(S onValue(T value), ...);
+      //     }
+      //
+      // Given a call where S <: Future<R> for some R, we will need to flatten
+      // the return type so it is Future< flatten(S) >, yielding Future<R>.
+      //
+      if (element.library.context.analysisOptions.strongMode) {
+        TypeImpl t = newTypeArguments[0];
+        newTypeArguments[0] = t.flattenFutures(new StrongTypeSystemImpl());
+      }
+    }
+
     InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune);
     newType.typeArguments = newTypeArguments;
     return newType;
@@ -1688,6 +1755,31 @@
       substitute2(argumentTypes, typeArguments);
 
   /**
+   * Starting from this type, search its class hierarchy for types of the form
+   * Future<R>, and return a list of the resulting R's.
+   */
+  List<DartType> _searchTypeHierarchyForFutureTypeParameters() {
+    List<DartType> result = <DartType>[];
+    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
+    void recurse(InterfaceTypeImpl type) {
+      if (type.isDartAsyncFuture && type.typeArguments.isNotEmpty) {
+        result.add(type.typeArguments[0]);
+      }
+      if (visitedClasses.add(type.element)) {
+        if (type.superclass != null) {
+          recurse(type.superclass);
+        }
+        for (InterfaceType interface in type.interfaces) {
+          recurse(interface);
+        }
+        visitedClasses.remove(type.element);
+      }
+    }
+    recurse(this);
+    return result;
+  }
+
+  /**
    * Compute the least upper bound of types [i] and [j], both of which are
    * known to be interface types.
    *
@@ -1846,6 +1938,61 @@
   }
 
   /**
+   * If there is a single type which is at least as specific as all of the
+   * types in [types], return it.  Otherwise return `null`.
+   */
+  static DartType _findMostSpecificType(List<DartType> types, TypeSystem typeSystem) {
+    // The << relation ("more specific than") is a partial ordering on types,
+    // so to find the most specific type of a set, we keep a bucket of the most
+    // specific types seen so far such that no type in the bucket is more
+    // specific than any other type in the bucket.
+    List<DartType> bucket = <DartType>[];
+
+    // Then we consider each type in turn.
+    for (DartType type in types) {
+      // If any existing type in the bucket is more specific than this type,
+      // then we can ignore this type.
+      if (bucket.any((DartType t) => typeSystem.isMoreSpecificThan(t, type))) {
+        continue;
+      }
+      // Otherwise, we need to add this type to the bucket and remove any types
+      // that are less specific than it.
+      bool added = false;
+      int i = 0;
+      while (i < bucket.length) {
+        if (typeSystem.isMoreSpecificThan(type, bucket[i])) {
+          if (added) {
+            if (i < bucket.length - 1) {
+              bucket[i] = bucket.removeLast();
+            } else {
+              bucket.removeLast();
+            }
+          } else {
+            bucket[i] = type;
+            i++;
+            added = true;
+          }
+        } else {
+          i++;
+        }
+      }
+      if (!added) {
+        bucket.add(type);
+      }
+    }
+
+    // Now that we are finished, if there is exactly one type left in the
+    // bucket, it is the most specific type.
+    if (bucket.length == 1) {
+      return bucket[0];
+    }
+
+    // Otherwise, there is no single type that is more specific than the
+    // others.
+    return null;
+  }
+
+  /**
    * Return the intersection of the [first] and [second] sets of types, where
    * intersection is based on the equality of the types themselves.
    */
@@ -1986,6 +2133,9 @@
   bool get isBottom => false;
 
   @override
+  bool get isDartAsyncFuture => false;
+
+  @override
   bool get isDartCoreFunction => false;
 
   @override
@@ -2012,6 +2162,9 @@
     }
   }
 
+  @override
+  DartType flattenFutures(TypeSystem typeSystem) => this;
+
   /**
    * Return `true` if this type is assignable to the given [type] (written in
    * the spec as "T <=> S", where T=[this] and S=[type]).
diff --git a/pkg/analyzer/lib/src/generated/ast.dart b/pkg/analyzer/lib/src/generated/ast.dart
index 3daca75..18c14d8 100644
--- a/pkg/analyzer/lib/src/generated/ast.dart
+++ b/pkg/analyzer/lib/src/generated/ast.dart
@@ -2,12331 +2,18 @@
 // 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.
 
+/**
+ * This library is deprecated. Please convert all references to this library to
+ * reference one of the following public libraries:
+ * * package:analyzer/dart/ast/ast.dart
+ * * package:analyzer/dart/ast/visitor.dart
+ *
+ * If your code is using APIs not available in these public libraries, please
+ * contact the analyzer team to either find an alternate API or have the API you
+ * depend on added to the public API.
+ */
 library analyzer.src.generated.ast;
 
-import 'dart:collection';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
-import 'package:analyzer/src/generated/utilities_dart.dart';
-
+export 'package:analyzer/dart/ast/ast.dart';
 export 'package:analyzer/dart/ast/visitor.dart';
 export 'package:analyzer/src/dart/ast/utilities.dart';
-
-/**
- * Two or more string literals that are implicitly concatenated because of being
- * adjacent (separated only by whitespace).
- *
- * While the grammar only allows adjacent strings when all of the strings are of
- * the same kind (single line or multi-line), this class doesn't enforce that
- * restriction.
- *
- * > adjacentStrings ::=
- * >     [StringLiteral] [StringLiteral]+
- */
-class AdjacentStrings extends StringLiteral {
-  /**
-   * The strings that are implicitly concatenated.
-   */
-  NodeList<StringLiteral> _strings;
-
-  /**
-   * Initialize a newly created list of adjacent strings. To be syntactically
-   * valid, the list of [strings] must contain at least two elements.
-   */
-  AdjacentStrings(List<StringLiteral> strings) {
-    _strings = new NodeList<StringLiteral>(this, strings);
-  }
-
-  @override
-  Token get beginToken => _strings.beginToken;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..addAll(_strings);
-
-  @override
-  Token get endToken => _strings.endToken;
-
-  /**
-   * Return the strings that are implicitly concatenated.
-   */
-  NodeList<StringLiteral> get strings => _strings;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitAdjacentStrings(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _strings.accept(visitor);
-  }
-
-  @override
-  void _appendStringValue(StringBuffer buffer) {
-    for (StringLiteral stringLiteral in strings) {
-      stringLiteral._appendStringValue(buffer);
-    }
-  }
-}
-
-/**
- * An AST node that can be annotated with both a documentation comment and a
- * list of annotations.
- */
-abstract class AnnotatedNode extends AstNode {
-  /**
-   * The documentation comment associated with this node, or `null` if this node
-   * does not have a documentation comment associated with it.
-   */
-  Comment _comment;
-
-  /**
-   * The annotations associated with this node.
-   */
-  NodeList<Annotation> _metadata;
-
-  /**
-   * Initialize a newly created annotated node. Either or both of the [comment]
-   * and [metadata] can be `null` if the node does not have the corresponding
-   * attribute.
-   */
-  AnnotatedNode(Comment comment, List<Annotation> metadata) {
-    _comment = _becomeParentOf(comment);
-    _metadata = new NodeList<Annotation>(this, metadata);
-  }
-
-  @override
-  Token get beginToken {
-    if (_comment == null) {
-      if (_metadata.isEmpty) {
-        return firstTokenAfterCommentAndMetadata;
-      }
-      return _metadata.beginToken;
-    } else if (_metadata.isEmpty) {
-      return _comment.beginToken;
-    }
-    Token commentToken = _comment.beginToken;
-    Token metadataToken = _metadata.beginToken;
-    if (commentToken.offset < metadataToken.offset) {
-      return commentToken;
-    }
-    return metadataToken;
-  }
-
-  /**
-   * Return the documentation comment associated with this node, or `null` if
-   * this node does not have a documentation comment associated with it.
-   */
-  Comment get documentationComment => _comment;
-
-  /**
-   * Set the documentation comment associated with this node to the given
-   * [comment].
-   */
-  void set documentationComment(Comment comment) {
-    _comment = _becomeParentOf(comment);
-  }
-
-  /**
-   * Return the first token following the comment and metadata.
-   */
-  Token get firstTokenAfterCommentAndMetadata;
-
-  /**
-   * Return the annotations associated with this node.
-   */
-  NodeList<Annotation> get metadata => _metadata;
-
-  /**
-   * Return a list containing the comment and annotations associated with this
-   * node, sorted in lexical order.
-   */
-  List<AstNode> get sortedCommentAndAnnotations {
-    return <AstNode>[]
-      ..add(_comment)
-      ..addAll(_metadata)
-      ..sort(AstNode.LEXICAL_ORDER);
-  }
-
-  /**
-   * Return a holder of child entities that subclasses can add to.
-   */
-  ChildEntities get _childEntities {
-    ChildEntities result = new ChildEntities();
-    if (_commentIsBeforeAnnotations()) {
-      result
-        ..add(_comment)
-        ..addAll(_metadata);
-    } else {
-      result.addAll(sortedCommentAndAnnotations);
-    }
-    return result;
-  }
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    if (_commentIsBeforeAnnotations()) {
-      _safelyVisitChild(_comment, visitor);
-      _metadata.accept(visitor);
-    } else {
-      for (AstNode child in sortedCommentAndAnnotations) {
-        child.accept(visitor);
-      }
-    }
-  }
-
-  /**
-   * Return `true` if there are no annotations before the comment. Note that a
-   * result of `true` does not imply that there is a comment, nor that there are
-   * annotations associated with this node.
-   */
-  bool _commentIsBeforeAnnotations() {
-    // TODO(brianwilkerson) Convert this to a getter.
-    if (_comment == null || _metadata.isEmpty) {
-      return true;
-    }
-    Annotation firstAnnotation = _metadata[0];
-    return _comment.offset < firstAnnotation.offset;
-  }
-}
-
-/**
- * An annotation that can be associated with an AST node.
- *
- * > metadata ::=
- * >     annotation*
- * >
- * > annotation ::=
- * >     '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
- */
-class Annotation extends AstNode {
-  /**
-   * The at sign that introduced the annotation.
-   */
-  Token atSign;
-
-  /**
-   * The name of the class defining the constructor that is being invoked or the
-   * name of the field that is being referenced.
-   */
-  Identifier _name;
-
-  /**
-   * The period before the constructor name, or `null` if this annotation is not
-   * the invocation of a named constructor.
-   */
-  Token period;
-
-  /**
-   * The name of the constructor being invoked, or `null` if this annotation is
-   * not the invocation of a named constructor.
-   */
-  SimpleIdentifier _constructorName;
-
-  /**
-   * The arguments to the constructor being invoked, or `null` if this
-   * annotation is not the invocation of a constructor.
-   */
-  ArgumentList _arguments;
-
-  /**
-   * The element associated with this annotation, or `null` if the AST structure
-   * has not been resolved or if this annotation could not be resolved.
-   */
-  Element _element;
-
-  /**
-   * The element annotation representing this annotation in the element model.
-   */
-  ElementAnnotation elementAnnotation;
-
-  /**
-   * Initialize a newly created annotation. Both the [period] and the
-   * [constructorName] can be `null` if the annotation is not referencing a
-   * named constructor. The [arguments] can be `null` if the annotation is not
-   * referencing a constructor.
-   */
-  Annotation(this.atSign, Identifier name, this.period,
-      SimpleIdentifier constructorName, ArgumentList arguments) {
-    _name = _becomeParentOf(name);
-    _constructorName = _becomeParentOf(constructorName);
-    _arguments = _becomeParentOf(arguments);
-  }
-
-  /**
-   * Return the arguments to the constructor being invoked, or `null` if this
-   * annotation is not the invocation of a constructor.
-   */
-  ArgumentList get arguments => _arguments;
-
-  /**
-   * Set the arguments to the constructor being invoked to the given arguments.
-   */
-  void set arguments(ArgumentList arguments) {
-    _arguments = _becomeParentOf(arguments);
-  }
-
-  @override
-  Token get beginToken => atSign;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(atSign)
-    ..add(_name)
-    ..add(period)
-    ..add(_constructorName)
-    ..add(_arguments);
-
-  /**
-   * Return the name of the constructor being invoked, or `null` if this
-   * annotation is not the invocation of a named constructor.
-   */
-  SimpleIdentifier get constructorName => _constructorName;
-
-  /**
-   * Set the name of the constructor being invoked to the given [name].
-   */
-  void set constructorName(SimpleIdentifier name) {
-    _constructorName = _becomeParentOf(name);
-  }
-
-  /**
-   * Return the element associated with this annotation, or `null` if the AST
-   * structure has not been resolved or if this annotation could not be
-   * resolved.
-   */
-  Element get element {
-    if (_element != null) {
-      return _element;
-    } else if (_name != null) {
-      return _name.staticElement;
-    }
-    return null;
-  }
-
-  /**
-   * Set the element associated with this annotation to the given [element].
-   */
-  void set element(Element element) {
-    _element = element;
-  }
-
-  @override
-  Token get endToken {
-    if (_arguments != null) {
-      return _arguments.endToken;
-    } else if (_constructorName != null) {
-      return _constructorName.endToken;
-    }
-    return _name.endToken;
-  }
-
-  /**
-   * Return the name of the class defining the constructor that is being invoked
-   * or the name of the field that is being referenced.
-   */
-  Identifier get name => _name;
-
-  /**
-   * Set the name of the class defining the constructor that is being invoked or
-   * the name of the field that is being referenced to the given [name].
-   */
-  void set name(Identifier name) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitAnnotation(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_arguments, visitor);
-  }
-}
-
-/**
- * A list of arguments in the invocation of an executable element (that is, a
- * function, method, or constructor).
- *
- * > argumentList ::=
- * >     '(' arguments? ')'
- * >
- * > arguments ::=
- * >     [NamedExpression] (',' [NamedExpression])*
- * >   | [Expression] (',' [Expression])* (',' [NamedExpression])*
- */
-class ArgumentList extends AstNode {
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The expressions producing the values of the arguments.
-   */
-  NodeList<Expression> _arguments;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * A list containing the elements representing the parameters corresponding to
-   * each of the arguments in this list, or `null` if the AST has not been
-   * resolved or if the function or method being invoked could not be determined
-   * based on static type information. The list must be the same length as the
-   * number of arguments, but can contain `null` entries if a given argument
-   * does not correspond to a formal parameter.
-   */
-  List<ParameterElement> _correspondingStaticParameters;
-
-  /**
-   * A list containing the elements representing the parameters corresponding to
-   * each of the arguments in this list, or `null` if the AST has not been
-   * resolved or if the function or method being invoked could not be determined
-   * based on propagated type information. The list must be the same length as
-   * the number of arguments, but can contain `null` entries if a given argument
-   * does not correspond to a formal parameter.
-   */
-  List<ParameterElement> _correspondingPropagatedParameters;
-
-  /**
-   * Initialize a newly created list of arguments. The list of [arguments] can
-   * be `null` if there are no arguments.
-   */
-  ArgumentList(
-      this.leftParenthesis, List<Expression> arguments, this.rightParenthesis) {
-    _arguments = new NodeList<Expression>(this, arguments);
-  }
-
-  /**
-   * Return the expressions producing the values of the arguments. Although the
-   * language requires that positional arguments appear before named arguments,
-   * this class allows them to be intermixed.
-   */
-  NodeList<Expression> get arguments => _arguments;
-
-  @override
-  Token get beginToken => leftParenthesis;
-
-  @override
-  // TODO(paulberry): Add commas.
-  Iterable get childEntities => new ChildEntities()
-    ..add(leftParenthesis)
-    ..addAll(_arguments)
-    ..add(rightParenthesis);
-
-  /**
-   * Set the parameter elements corresponding to each of the arguments in this
-   * list to the given list of [parameters]. The list of parameters must be the
-   * same length as the number of arguments, but can contain `null` entries if a
-   * given argument does not correspond to a formal parameter.
-   */
-  void set correspondingPropagatedParameters(
-      List<ParameterElement> parameters) {
-    if (parameters.length != _arguments.length) {
-      throw new IllegalArgumentException(
-          "Expected ${_arguments.length} parameters, not ${parameters.length}");
-    }
-    _correspondingPropagatedParameters = parameters;
-  }
-
-  /**
-   * Set the parameter elements corresponding to each of the arguments in this
-   * list to the given list of parameters. The list of parameters must be the
-   * same length as the number of arguments, but can contain `null` entries if a
-   * given argument does not correspond to a formal parameter.
-   */
-  void set correspondingStaticParameters(List<ParameterElement> parameters) {
-    if (parameters.length != _arguments.length) {
-      throw new IllegalArgumentException(
-          "Expected ${_arguments.length} parameters, not ${parameters.length}");
-    }
-    _correspondingStaticParameters = parameters;
-  }
-
-  @override
-  Token get endToken => rightParenthesis;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitArgumentList(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _arguments.accept(visitor);
-  }
-
-  /**
-   * If
-   * * the given [expression] is a child of this list,
-   * * the AST structure has been resolved,
-   * * the function being invoked is known based on propagated type information,
-   *   and
-   * * the expression corresponds to one of the parameters of the function being
-   *   invoked,
-   * then return the parameter element representing the parameter to which the
-   * value of the given expression will be bound. Otherwise, return `null`.
-   */
-  ParameterElement _getPropagatedParameterElementFor(Expression expression) {
-    if (_correspondingPropagatedParameters == null ||
-        _correspondingPropagatedParameters.length != _arguments.length) {
-      // Either the AST structure has not been resolved, the invocation of which
-      // this list is a part could not be resolved, or the argument list was
-      // modified after the parameters were set.
-      return null;
-    }
-    int index = _arguments.indexOf(expression);
-    if (index < 0) {
-      // The expression isn't a child of this node.
-      return null;
-    }
-    return _correspondingPropagatedParameters[index];
-  }
-
-  /**
-   * If
-   * * the given [expression] is a child of this list,
-   * * the AST structure has been resolved,
-   * * the function being invoked is known based on static type information, and
-   * * the expression corresponds to one of the parameters of the function being
-   *   invoked,
-   * then return the parameter element representing the parameter to which the
-   * value of the given expression will be bound. Otherwise, return `null`.
-   */
-  ParameterElement _getStaticParameterElementFor(Expression expression) {
-    if (_correspondingStaticParameters == null ||
-        _correspondingStaticParameters.length != _arguments.length) {
-      // Either the AST structure has not been resolved, the invocation of which
-      // this list is a part could not be resolved, or the argument list was
-      // modified after the parameters were set.
-      return null;
-    }
-    int index = _arguments.indexOf(expression);
-    if (index < 0) {
-      // The expression isn't a child of this node.
-      return null;
-    }
-    return _correspondingStaticParameters[index];
-  }
-}
-
-/**
- * An as expression.
- *
- * > asExpression ::=
- * >     [Expression] 'as' [TypeName]
- */
-class AsExpression extends Expression {
-  /**
-   * The expression used to compute the value being cast.
-   */
-  Expression _expression;
-
-  /**
-   * The 'as' operator.
-   */
-  Token asOperator;
-
-  /**
-   * The name of the type being cast to.
-   */
-  TypeName _type;
-
-  /**
-   * Initialize a newly created as expression.
-   */
-  AsExpression(Expression expression, this.asOperator, TypeName type) {
-    _expression = _becomeParentOf(expression);
-    _type = _becomeParentOf(type);
-  }
-
-  @override
-  Token get beginToken => _expression.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_expression)..add(asOperator)..add(_type);
-
-  @override
-  Token get endToken => _type.endToken;
-
-  /**
-   * Return the expression used to compute the value being cast.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression used to compute the value being cast to the given
-   * [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 7;
-
-  /**
-   * Return the name of the type being cast to.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the name of the type being cast to to the given [name].
-   */
-  void set type(TypeName name) {
-    _type = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitAsExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-    _safelyVisitChild(_type, visitor);
-  }
-}
-
-/**
- * An assert statement.
- *
- * > assertStatement ::=
- * >     'assert' '(' [Expression] ')' ';'
- */
-class AssertStatement extends Statement {
-  /**
-   * The token representing the 'assert' keyword.
-   */
-  Token assertKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The condition that is being asserted to be `true`.
-   */
-  Expression _condition;
-
-  /**
-   * The comma, if a message expression was supplied.  Otherwise `null`.
-   */
-  Token comma;
-
-  /**
-   * The message to report if the assertion fails.  `null` if no message was
-   * supplied.
-   */
-  Expression _message;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created assert statement.
-   */
-  AssertStatement(
-      this.assertKeyword,
-      this.leftParenthesis,
-      Expression condition,
-      this.comma,
-      Expression message,
-      this.rightParenthesis,
-      this.semicolon) {
-    _condition = _becomeParentOf(condition);
-    _message = _becomeParentOf(message);
-  }
-
-  @override
-  Token get beginToken => assertKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(assertKeyword)
-    ..add(leftParenthesis)
-    ..add(_condition)
-    ..add(comma)
-    ..add(_message)
-    ..add(rightParenthesis)
-    ..add(semicolon);
-
-  /**
-   * Return the condition that is being asserted to be `true`.
-   */
-  Expression get condition => _condition;
-
-  /**
-   * Set the condition that is being asserted to be `true` to the given
-   * [expression].
-   */
-  void set condition(Expression condition) {
-    _condition = _becomeParentOf(condition);
-  }
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the message to report if the assertion fails.
-   */
-  Expression get message => _message;
-
-  /**
-   * Set the message to report if the assertion fails to the given
-   * [expression].
-   */
-  void set message(Expression expression) {
-    _message = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitAssertStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(message, visitor);
-  }
-}
-
-/**
- * An assignment expression.
- *
- * > assignmentExpression ::=
- * >     [Expression] operator [Expression]
- */
-class AssignmentExpression extends Expression {
-  /**
-   * The expression used to compute the left hand side.
-   */
-  Expression _leftHandSide;
-
-  /**
-   * The assignment operator being applied.
-   */
-  Token operator;
-
-  /**
-   * The expression used to compute the right hand side.
-   */
-  Expression _rightHandSide;
-
-  /**
-   * The element associated with the operator based on the static type of the
-   * left-hand-side, or `null` if the AST structure has not been resolved, if
-   * the operator is not a compound operator, or if the operator could not be
-   * resolved.
-   */
-  MethodElement staticElement;
-
-  /**
-   * The element associated with the operator based on the propagated type of
-   * the left-hand-side, or `null` if the AST structure has not been resolved,
-   * if the operator is not a compound operator, or if the operator could not be
-   * resolved.
-   */
-  MethodElement propagatedElement;
-
-  /**
-   * Initialize a newly created assignment expression.
-   */
-  AssignmentExpression(
-      Expression leftHandSide, this.operator, Expression rightHandSide) {
-    if (leftHandSide == null || rightHandSide == null) {
-      String message;
-      if (leftHandSide == null) {
-        if (rightHandSide == null) {
-          message = "Both the left-hand and right-hand sides are null";
-        } else {
-          message = "The left-hand size is null";
-        }
-      } else {
-        message = "The right-hand size is null";
-      }
-      AnalysisEngine.instance.logger.logError(
-          message, new CaughtException(new AnalysisException(message), null));
-    }
-    _leftHandSide = _becomeParentOf(leftHandSide);
-    _rightHandSide = _becomeParentOf(rightHandSide);
-  }
-
-  @override
-  Token get beginToken => _leftHandSide.beginToken;
-
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   */
-  MethodElement get bestElement {
-    MethodElement element = propagatedElement;
-    if (element == null) {
-      element = staticElement;
-    }
-    return element;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(_leftHandSide)
-    ..add(operator)
-    ..add(_rightHandSide);
-
-  @override
-  Token get endToken => _rightHandSide.endToken;
-
-  /**
-   * Set the expression used to compute the left hand side to the given
-   * [expression].
-   */
-  Expression get leftHandSide => _leftHandSide;
-
-  /**
-   * Return the expression used to compute the left hand side.
-   */
-  void set leftHandSide(Expression expression) {
-    _leftHandSide = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 1;
-
-  /**
-   * Return the expression used to compute the right hand side.
-   */
-  Expression get rightHandSide => _rightHandSide;
-
-  /**
-   * Set the expression used to compute the left hand side to the given
-   * [expression].
-   */
-  void set rightHandSide(Expression expression) {
-    _rightHandSide = _becomeParentOf(expression);
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on propagated type information, then return the parameter
-   * element representing the parameter to which the value of the right operand
-   * will be bound. Otherwise, return `null`.
-   */
-  ParameterElement get _propagatedParameterElementForRightHandSide {
-    ExecutableElement executableElement = null;
-    if (propagatedElement != null) {
-      executableElement = propagatedElement;
-    } else {
-      if (_leftHandSide is Identifier) {
-        Identifier identifier = _leftHandSide as Identifier;
-        Element leftElement = identifier.propagatedElement;
-        if (leftElement is ExecutableElement) {
-          executableElement = leftElement;
-        }
-      }
-      if (_leftHandSide is PropertyAccess) {
-        SimpleIdentifier identifier =
-            (_leftHandSide as PropertyAccess).propertyName;
-        Element leftElement = identifier.propagatedElement;
-        if (leftElement is ExecutableElement) {
-          executableElement = leftElement;
-        }
-      }
-    }
-    if (executableElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = executableElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on static type information, then return the parameter element
-   * representing the parameter to which the value of the right operand will be
-   * bound. Otherwise, return `null`.
-   */
-  ParameterElement get _staticParameterElementForRightHandSide {
-    ExecutableElement executableElement = null;
-    if (staticElement != null) {
-      executableElement = staticElement;
-    } else {
-      if (_leftHandSide is Identifier) {
-        Element leftElement = (_leftHandSide as Identifier).staticElement;
-        if (leftElement is ExecutableElement) {
-          executableElement = leftElement;
-        }
-      }
-      if (_leftHandSide is PropertyAccess) {
-        Element leftElement =
-            (_leftHandSide as PropertyAccess).propertyName.staticElement;
-        if (leftElement is ExecutableElement) {
-          executableElement = leftElement;
-        }
-      }
-    }
-    if (executableElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = executableElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitAssignmentExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_leftHandSide, visitor);
-    _safelyVisitChild(_rightHandSide, visitor);
-  }
-}
-
-/**
- * A node in the AST structure for a Dart program.
- */
-abstract class AstNode {
-  /**
-   * An empty list of AST nodes.
-   */
-  static const List<AstNode> EMPTY_LIST = const <AstNode>[];
-
-  /**
-   * A comparator that can be used to sort AST nodes in lexical order. In other
-   * words, `compare` will return a negative value if the offset of the first
-   * node is less than the offset of the second node, zero (0) if the nodes have
-   * the same offset, and a positive value if the offset of the first node is
-   * greater than the offset of the second node.
-   */
-  static Comparator<AstNode> LEXICAL_ORDER =
-      (AstNode first, AstNode second) => first.offset - second.offset;
-
-  /**
-   * The parent of the node, or `null` if the node is the root of an AST
-   * structure.
-   */
-  AstNode _parent;
-
-  /**
-   * A table mapping the names of properties to their values, or `null` if this
-   * node does not have any properties associated with it.
-   */
-  Map<String, Object> _propertyMap;
-
-  /**
-   * Return the first token included in this node's source range.
-   */
-  Token get beginToken;
-
-  /**
-   * Iterate through all the entities (either AST nodes or tokens) which make
-   * up the contents of this node, including doc comments but excluding other
-   * comments.
-   */
-  Iterable /*<AstNode | Token>*/ get childEntities;
-
-  /**
-   * Return the offset of the character immediately following the last character
-   * of this node's source range. This is equivalent to
-   * `node.getOffset() + node.getLength()`. For a compilation unit this will be
-   * equal to the length of the unit's source. For synthetic nodes this will be
-   * equivalent to the node's offset (because the length is zero (0) by
-   * definition).
-   */
-  int get end => offset + length;
-
-  /**
-   * Return the last token included in this node's source range.
-   */
-  Token get endToken;
-
-  /**
-   * Return `true` if this node is a synthetic node. A synthetic node is a node
-   * that was introduced by the parser in order to recover from an error in the
-   * code. Synthetic nodes always have a length of zero (`0`).
-   */
-  bool get isSynthetic => false;
-
-  /**
-   * Return the number of characters in the node's source range.
-   */
-  int get length {
-    Token beginToken = this.beginToken;
-    Token endToken = this.endToken;
-    if (beginToken == null || endToken == null) {
-      return -1;
-    }
-    return endToken.offset + endToken.length - beginToken.offset;
-  }
-
-  /**
-   * Return the offset from the beginning of the file to the first character in
-   * the node's source range.
-   */
-  int get offset {
-    Token beginToken = this.beginToken;
-    if (beginToken == null) {
-      return -1;
-    }
-    return beginToken.offset;
-  }
-
-  /**
-   * Return this node's parent node, or `null` if this node is the root of an
-   * AST structure.
-   *
-   * Note that the relationship between an AST node and its parent node may
-   * change over the lifetime of a node.
-   */
-  AstNode get parent => _parent;
-
-  /**
-   * Return the node at the root of this node's AST structure. Note that this
-   * method's performance is linear with respect to the depth of the node in the
-   * AST structure (O(depth)).
-   */
-  AstNode get root {
-    AstNode root = this;
-    AstNode parent = this.parent;
-    while (parent != null) {
-      root = parent;
-      parent = root.parent;
-    }
-    return root;
-  }
-
-  /**
-   * 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);
-
-  /**
-   * Return the most immediate ancestor of this node for which the [predicate]
-   * returns `true`, or `null` if there is no such ancestor. Note that this node
-   * will never be returned.
-   */
-  AstNode getAncestor(Predicate<AstNode> predicate) {
-    // TODO(brianwilkerson) It is a bug that this method can return `this`.
-    AstNode node = this;
-    while (node != null && !predicate(node)) {
-      node = node.parent;
-    }
-    return node;
-  }
-
-  /**
-   * Return the value of the property with the given [name], or `null` if this
-   * node does not have a property with the given name.
-   */
-  Object getProperty(String name) {
-    if (_propertyMap == null) {
-      return null;
-    }
-    return _propertyMap[name];
-  }
-
-  /**
-   * Set the value of the property with the given [name] to the given [value].
-   * If the value is `null`, the property will effectively be removed.
-   */
-  void setProperty(String name, Object value) {
-    if (value == null) {
-      if (_propertyMap != null) {
-        _propertyMap.remove(name);
-        if (_propertyMap.isEmpty) {
-          _propertyMap = null;
-        }
-      }
-    } else {
-      if (_propertyMap == null) {
-        _propertyMap = new HashMap<String, Object>();
-      }
-      _propertyMap[name] = value;
-    }
-  }
-
-  /**
-   * Return a textual description of this node in a form approximating valid
-   * source. The returned string will not be valid source primarily in the case
-   * where the node itself is not well-formed.
-   */
-  String toSource() {
-    PrintStringWriter writer = new PrintStringWriter();
-    accept(new ToSourceVisitor(writer));
-    return writer.toString();
-  }
-
-  @override
-  String toString() => toSource();
-
-  /**
-   * Use the given [visitor] to visit all of the children of this node. The
-   * children will be visited in lexical order.
-   */
-  void visitChildren(AstVisitor visitor);
-
-  /**
-   * Make this node the parent of the given [child] node. Return the child node.
-   */
-  AstNode _becomeParentOf(AstNode child) {
-    if (child != null) {
-      child._parent = this;
-    }
-    return child;
-  }
-
-  /**
-   * If the given [child] is not `null`, use the given [visitor] to visit it.
-   */
-  void _safelyVisitChild(AstNode child, AstVisitor visitor) {
-    if (child != null) {
-      child.accept(visitor);
-    }
-  }
-}
-
-/**
- * An object that can be used to visit an AST structure.
- */
-abstract class AstVisitor<R> {
-  R visitAdjacentStrings(AdjacentStrings node);
-
-  R visitAnnotation(Annotation node);
-
-  R visitArgumentList(ArgumentList node);
-
-  R visitAsExpression(AsExpression node);
-
-  R visitAssertStatement(AssertStatement assertStatement);
-
-  R visitAssignmentExpression(AssignmentExpression node);
-
-  R visitAwaitExpression(AwaitExpression node);
-
-  R visitBinaryExpression(BinaryExpression node);
-
-  R visitBlock(Block node);
-
-  R visitBlockFunctionBody(BlockFunctionBody node);
-
-  R visitBooleanLiteral(BooleanLiteral node);
-
-  R visitBreakStatement(BreakStatement node);
-
-  R visitCascadeExpression(CascadeExpression node);
-
-  R visitCatchClause(CatchClause node);
-
-  R visitClassDeclaration(ClassDeclaration node);
-
-  R visitClassTypeAlias(ClassTypeAlias node);
-
-  R visitComment(Comment node);
-
-  R visitCommentReference(CommentReference node);
-
-  R visitCompilationUnit(CompilationUnit node);
-
-  R visitConditionalExpression(ConditionalExpression node);
-
-  R visitConfiguration(Configuration node);
-
-  R visitConstructorDeclaration(ConstructorDeclaration node);
-
-  R visitConstructorFieldInitializer(ConstructorFieldInitializer node);
-
-  R visitConstructorName(ConstructorName node);
-
-  R visitContinueStatement(ContinueStatement node);
-
-  R visitDeclaredIdentifier(DeclaredIdentifier node);
-
-  R visitDefaultFormalParameter(DefaultFormalParameter node);
-
-  R visitDoStatement(DoStatement node);
-
-  R visitDottedName(DottedName node);
-
-  R visitDoubleLiteral(DoubleLiteral node);
-
-  R visitEmptyFunctionBody(EmptyFunctionBody node);
-
-  R visitEmptyStatement(EmptyStatement node);
-
-  R visitEnumConstantDeclaration(EnumConstantDeclaration node);
-
-  R visitEnumDeclaration(EnumDeclaration node);
-
-  R visitExportDirective(ExportDirective node);
-
-  R visitExpressionFunctionBody(ExpressionFunctionBody node);
-
-  R visitExpressionStatement(ExpressionStatement node);
-
-  R visitExtendsClause(ExtendsClause node);
-
-  R visitFieldDeclaration(FieldDeclaration node);
-
-  R visitFieldFormalParameter(FieldFormalParameter node);
-
-  R visitForEachStatement(ForEachStatement node);
-
-  R visitFormalParameterList(FormalParameterList node);
-
-  R visitForStatement(ForStatement node);
-
-  R visitFunctionDeclaration(FunctionDeclaration node);
-
-  R visitFunctionDeclarationStatement(FunctionDeclarationStatement node);
-
-  R visitFunctionExpression(FunctionExpression node);
-
-  R visitFunctionExpressionInvocation(FunctionExpressionInvocation node);
-
-  R visitFunctionTypeAlias(FunctionTypeAlias functionTypeAlias);
-
-  R visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node);
-
-  R visitHideCombinator(HideCombinator node);
-
-  R visitIfStatement(IfStatement node);
-
-  R visitImplementsClause(ImplementsClause node);
-
-  R visitImportDirective(ImportDirective node);
-
-  R visitIndexExpression(IndexExpression node);
-
-  R visitInstanceCreationExpression(InstanceCreationExpression node);
-
-  R visitIntegerLiteral(IntegerLiteral node);
-
-  R visitInterpolationExpression(InterpolationExpression node);
-
-  R visitInterpolationString(InterpolationString node);
-
-  R visitIsExpression(IsExpression node);
-
-  R visitLabel(Label node);
-
-  R visitLabeledStatement(LabeledStatement node);
-
-  R visitLibraryDirective(LibraryDirective node);
-
-  R visitLibraryIdentifier(LibraryIdentifier node);
-
-  R visitListLiteral(ListLiteral node);
-
-  R visitMapLiteral(MapLiteral node);
-
-  R visitMapLiteralEntry(MapLiteralEntry node);
-
-  R visitMethodDeclaration(MethodDeclaration node);
-
-  R visitMethodInvocation(MethodInvocation node);
-
-  R visitNamedExpression(NamedExpression node);
-
-  R visitNativeClause(NativeClause node);
-
-  R visitNativeFunctionBody(NativeFunctionBody node);
-
-  R visitNullLiteral(NullLiteral node);
-
-  R visitParenthesizedExpression(ParenthesizedExpression node);
-
-  R visitPartDirective(PartDirective node);
-
-  R visitPartOfDirective(PartOfDirective node);
-
-  R visitPostfixExpression(PostfixExpression node);
-
-  R visitPrefixedIdentifier(PrefixedIdentifier node);
-
-  R visitPrefixExpression(PrefixExpression node);
-
-  R visitPropertyAccess(PropertyAccess node);
-
-  R visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node);
-
-  R visitRethrowExpression(RethrowExpression node);
-
-  R visitReturnStatement(ReturnStatement node);
-
-  R visitScriptTag(ScriptTag node);
-
-  R visitShowCombinator(ShowCombinator node);
-
-  R visitSimpleFormalParameter(SimpleFormalParameter node);
-
-  R visitSimpleIdentifier(SimpleIdentifier node);
-
-  R visitSimpleStringLiteral(SimpleStringLiteral node);
-
-  R visitStringInterpolation(StringInterpolation node);
-
-  R visitSuperConstructorInvocation(SuperConstructorInvocation node);
-
-  R visitSuperExpression(SuperExpression node);
-
-  R visitSwitchCase(SwitchCase node);
-
-  R visitSwitchDefault(SwitchDefault node);
-
-  R visitSwitchStatement(SwitchStatement node);
-
-  R visitSymbolLiteral(SymbolLiteral node);
-
-  R visitThisExpression(ThisExpression node);
-
-  R visitThrowExpression(ThrowExpression node);
-
-  R visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node);
-
-  R visitTryStatement(TryStatement node);
-
-  R visitTypeArgumentList(TypeArgumentList node);
-
-  R visitTypeName(TypeName node);
-
-  R visitTypeParameter(TypeParameter node);
-
-  R visitTypeParameterList(TypeParameterList node);
-
-  R visitVariableDeclaration(VariableDeclaration node);
-
-  R visitVariableDeclarationList(VariableDeclarationList node);
-
-  R visitVariableDeclarationStatement(VariableDeclarationStatement node);
-
-  R visitWhileStatement(WhileStatement node);
-
-  R visitWithClause(WithClause node);
-
-  R visitYieldStatement(YieldStatement node);
-}
-
-/**
- * An await expression.
- *
- * > awaitExpression ::=
- * >     'await' [Expression]
- */
-class AwaitExpression extends Expression {
-  /**
-   * The 'await' keyword.
-   */
-  Token awaitKeyword;
-
-  /**
-   * The expression whose value is being waited on.
-   */
-  Expression _expression;
-
-  /**
-   * Initialize a newly created await expression.
-   */
-  AwaitExpression(this.awaitKeyword, Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken {
-    if (awaitKeyword != null) {
-      return awaitKeyword;
-    }
-    return _expression.beginToken;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(awaitKeyword)..add(_expression);
-
-  @override
-  Token get endToken => _expression.endToken;
-
-  /**
-   * Return the expression whose value is being waited on.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression whose value is being waited on to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 0;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitAwaitExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * A binary (infix) expression.
- *
- * > binaryExpression ::=
- * >     [Expression] [Token] [Expression]
- */
-class BinaryExpression extends Expression {
-  /**
-   * The expression used to compute the left operand.
-   */
-  Expression _leftOperand;
-
-  /**
-   * The binary operator being applied.
-   */
-  Token operator;
-
-  /**
-   * The expression used to compute the right operand.
-   */
-  Expression _rightOperand;
-
-  /**
-   * The element associated with the operator based on the static type of the
-   * left operand, or `null` if the AST structure has not been resolved, if the
-   * operator is not user definable, or if the operator could not be resolved.
-   */
-  MethodElement staticElement;
-
-  /**
-   * The element associated with the operator based on the propagated type of
-   * the left operand, or `null` if the AST structure has not been resolved, if
-   * the operator is not user definable, or if the operator could not be
-   * resolved.
-   */
-  MethodElement propagatedElement;
-
-  /**
-   * Initialize a newly created binary expression.
-   */
-  BinaryExpression(
-      Expression leftOperand, this.operator, Expression rightOperand) {
-    _leftOperand = _becomeParentOf(leftOperand);
-    _rightOperand = _becomeParentOf(rightOperand);
-  }
-
-  @override
-  Token get beginToken => _leftOperand.beginToken;
-
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   */
-  MethodElement get bestElement {
-    MethodElement element = propagatedElement;
-    if (element == null) {
-      element = staticElement;
-    }
-    return element;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_leftOperand)..add(operator)..add(_rightOperand);
-
-  @override
-  Token get endToken => _rightOperand.endToken;
-
-  /**
-   * Return the expression used to compute the left operand.
-   */
-  Expression get leftOperand => _leftOperand;
-
-  /**
-   * Set the expression used to compute the left operand to the given
-   * [expression].
-   */
-  void set leftOperand(Expression expression) {
-    _leftOperand = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => operator.type.precedence;
-
-  /**
-   * Return the expression used to compute the right operand.
-   */
-  Expression get rightOperand => _rightOperand;
-
-  /**
-   * Set the expression used to compute the right operand to the given
-   * [expression].
-   */
-  void set rightOperand(Expression expression) {
-    _rightOperand = _becomeParentOf(expression);
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on propagated type information, then return the parameter
-   * element representing the parameter to which the value of the right operand
-   * will be bound. Otherwise, return `null`.
-   */
-  ParameterElement get _propagatedParameterElementForRightOperand {
-    if (propagatedElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = propagatedElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on static type information, then return the parameter element
-   * representing the parameter to which the value of the right operand will be
-   * bound. Otherwise, return `null`.
-   */
-  ParameterElement get _staticParameterElementForRightOperand {
-    if (staticElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = staticElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitBinaryExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_leftOperand, visitor);
-    _safelyVisitChild(_rightOperand, visitor);
-  }
-}
-
-/**
- * A sequence of statements.
- *
- * > block ::=
- * >     '{' statement* '}'
- */
-class Block extends Statement {
-  /**
-   * The left curly bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The statements contained in the block.
-   */
-  NodeList<Statement> _statements;
-
-  /**
-   * The right curly bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created block of code.
-   */
-  Block(this.leftBracket, List<Statement> statements, this.rightBracket) {
-    _statements = new NodeList<Statement>(this, statements);
-  }
-
-  @override
-  Token get beginToken => leftBracket;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(leftBracket)
-    ..addAll(_statements)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken => rightBracket;
-
-  /**
-   * Return the statements contained in the block.
-   */
-  NodeList<Statement> get statements => _statements;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitBlock(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _statements.accept(visitor);
-  }
-}
-
-/**
- * A function body that consists of a block of statements.
- *
- * > blockFunctionBody ::=
- * >     ('async' | 'async' '*' | 'sync' '*')? [Block]
- */
-class BlockFunctionBody extends FunctionBody {
-  /**
-   * The token representing the 'async' or 'sync' keyword, or `null` if there is
-   * no such keyword.
-   */
-  Token keyword;
-
-  /**
-   * The star optionally following the 'async' or 'sync' keyword, or `null` if
-   * there is wither no such keyword or no star.
-   */
-  Token star;
-
-  /**
-   * The block representing the body of the function.
-   */
-  Block _block;
-
-  /**
-   * Initialize a newly created function body consisting of a block of
-   * statements. The [keyword] can be `null` if there is no keyword specified
-   * for the block. The [star] can be `null` if there is no star following the
-   * keyword (and must be `null` if there is no keyword).
-   */
-  BlockFunctionBody(this.keyword, this.star, Block block) {
-    _block = _becomeParentOf(block);
-  }
-
-  @override
-  Token get beginToken {
-    if (keyword != null) {
-      return keyword;
-    }
-    return _block.beginToken;
-  }
-
-  /**
-   * Return the block representing the body of the function.
-   */
-  Block get block => _block;
-
-  /**
-   * Set the block representing the body of the function to the given [block].
-   */
-  void set block(Block block) {
-    _block = _becomeParentOf(block);
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(keyword)..add(star)..add(_block);
-
-  @override
-  Token get endToken => _block.endToken;
-
-  @override
-  bool get isAsynchronous => keyword != null && keyword.lexeme == Parser.ASYNC;
-
-  @override
-  bool get isGenerator => star != null;
-
-  @override
-  bool get isSynchronous => keyword == null || keyword.lexeme != Parser.ASYNC;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitBlockFunctionBody(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_block, visitor);
-  }
-}
-
-/**
- * A boolean literal expression.
- *
- * > booleanLiteral ::=
- * >     'false' | 'true'
- */
-class BooleanLiteral extends Literal {
-  /**
-   * The token representing the literal.
-   */
-  Token literal;
-
-  /**
-   * The value of the literal.
-   */
-  bool value = false;
-
-  /**
-   * Initialize a newly created boolean literal.
-   */
-  BooleanLiteral(this.literal, this.value);
-
-  @override
-  Token get beginToken => literal;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
-
-  @override
-  Token get endToken => literal;
-
-  @override
-  bool get isSynthetic => literal.isSynthetic;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitBooleanLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A break statement.
- *
- * > breakStatement ::=
- * >     'break' [SimpleIdentifier]? ';'
- */
-class BreakStatement extends Statement {
-  /**
-   * The token representing the 'break' keyword.
-   */
-  Token breakKeyword;
-
-  /**
-   * The label associated with the statement, or `null` if there is no label.
-   */
-  SimpleIdentifier _label;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * The AstNode which this break statement is breaking from.  This will be
-   * either a [Statement] (in the case of breaking out of a loop), a
-   * [SwitchMember] (in the case of a labeled break statement whose label
-   * matches a label on a switch case in an enclosing switch statement), or
-   * `null` if the AST has not yet been resolved or if the target could not be
-   * resolved. Note that if the source code has errors, the target might be
-   * invalid (e.g. trying to break to a switch case).
-   */
-  AstNode target;
-
-  /**
-   * Initialize a newly created break statement. The [label] can be `null` if
-   * there is no label associated with the statement.
-   */
-  BreakStatement(this.breakKeyword, SimpleIdentifier label, this.semicolon) {
-    _label = _becomeParentOf(label);
-  }
-
-  @override
-  Token get beginToken => breakKeyword;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(breakKeyword)..add(_label)..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the label associated with the statement, or `null` if there is no
-   * label.
-   */
-  SimpleIdentifier get label => _label;
-
-  /**
-   * Set the label associated with the statement to the given [identifier].
-   */
-  void set label(SimpleIdentifier identifier) {
-    _label = _becomeParentOf(identifier);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitBreakStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_label, visitor);
-  }
-}
-
-/**
- * A sequence of cascaded expressions: expressions that share a common target.
- * There are three kinds of expressions that can be used in a cascade
- * expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
- *
- * > cascadeExpression ::=
- * >     [Expression] cascadeSection*
- * >
- * > cascadeSection ::=
- * >     '..'  (cascadeSelector arguments*) (assignableSelector arguments*)*
- * >     (assignmentOperator expressionWithoutCascade)?
- * >
- * > cascadeSelector ::=
- * >     '[ ' expression '] '
- * >   | identifier
- */
-class CascadeExpression extends Expression {
-  /**
-   * The target of the cascade sections.
-   */
-  Expression _target;
-
-  /**
-   * The cascade sections sharing the common target.
-   */
-  NodeList<Expression> _cascadeSections;
-
-  /**
-   * Initialize a newly created cascade expression. The list of
-   * [cascadeSections] must contain at least one element.
-   */
-  CascadeExpression(Expression target, List<Expression> cascadeSections) {
-    _target = _becomeParentOf(target);
-    _cascadeSections = new NodeList<Expression>(this, cascadeSections);
-  }
-
-  @override
-  Token get beginToken => _target.beginToken;
-
-  /**
-   * Return the cascade sections sharing the common target.
-   */
-  NodeList<Expression> get cascadeSections => _cascadeSections;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(_target)
-    ..addAll(_cascadeSections);
-
-  @override
-  Token get endToken => _cascadeSections.endToken;
-
-  @override
-  int get precedence => 2;
-
-  /**
-   * Return the target of the cascade sections.
-   */
-  Expression get target => _target;
-
-  /**
-   * Set the target of the cascade sections to the given [expression].
-   */
-  void set target(Expression target) {
-    _target = _becomeParentOf(target);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitCascadeExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _cascadeSections.accept(visitor);
-  }
-}
-
-/**
- * A catch clause within a try statement.
- *
- * > onPart ::=
- * >     catchPart [Block]
- * >   | 'on' type catchPart? [Block]
- * >
- * > catchPart ::=
- * >     'catch' '(' [SimpleIdentifier] (',' [SimpleIdentifier])? ')'
- */
-class CatchClause extends AstNode {
-  /**
-   * The token representing the 'on' keyword, or `null` if there is no 'on'
-   * keyword.
-   */
-  Token onKeyword;
-
-  /**
-   * The type of exceptions caught by this catch clause, or `null` if this catch
-   * clause catches every type of exception.
-   */
-  TypeName _exceptionType;
-
-  /**
-   * The token representing the 'catch' keyword, or `null` if there is no
-   * 'catch' keyword.
-   */
-  Token catchKeyword;
-
-  /**
-   * The left parenthesis, or `null` if there is no 'catch' keyword.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The parameter whose value will be the exception that was thrown, or `null`
-   * if there is no 'catch' keyword.
-   */
-  SimpleIdentifier _exceptionParameter;
-
-  /**
-   * The comma separating the exception parameter from the stack trace
-   * parameter, or `null` if there is no stack trace parameter.
-   */
-  Token comma;
-
-  /**
-   * The parameter whose value will be the stack trace associated with the
-   * exception, or `null` if there is no stack trace parameter.
-   */
-  SimpleIdentifier _stackTraceParameter;
-
-  /**
-   * The right parenthesis, or `null` if there is no 'catch' keyword.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The body of the catch block.
-   */
-  Block _body;
-
-  /**
-   * Initialize a newly created catch clause. The [onKeyword] and
-   * [exceptionType] can be `null` if the clause will catch all exceptions. The
-   * [comma] and [stackTraceParameter] can be `null` if the stack trace is not
-   * referencable within the body.
-   */
-  CatchClause(
-      this.onKeyword,
-      TypeName exceptionType,
-      this.catchKeyword,
-      this.leftParenthesis,
-      SimpleIdentifier exceptionParameter,
-      this.comma,
-      SimpleIdentifier stackTraceParameter,
-      this.rightParenthesis,
-      Block body) {
-    _exceptionType = _becomeParentOf(exceptionType);
-    _exceptionParameter = _becomeParentOf(exceptionParameter);
-    _stackTraceParameter = _becomeParentOf(stackTraceParameter);
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  Token get beginToken {
-    if (onKeyword != null) {
-      return onKeyword;
-    }
-    return catchKeyword;
-  }
-
-  /**
-   * Return the body of the catch block.
-   */
-  Block get body => _body;
-
-  /**
-   * Set the body of the catch block to the given [block].
-   */
-  void set body(Block block) {
-    _body = _becomeParentOf(block);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(onKeyword)
-    ..add(_exceptionType)
-    ..add(catchKeyword)
-    ..add(leftParenthesis)
-    ..add(_exceptionParameter)
-    ..add(comma)
-    ..add(_stackTraceParameter)
-    ..add(rightParenthesis)
-    ..add(_body);
-
-  @override
-  Token get endToken => _body.endToken;
-
-  /**
-   * Return the parameter whose value will be the exception that was thrown, or
-   * `null` if there is no 'catch' keyword.
-   */
-  SimpleIdentifier get exceptionParameter => _exceptionParameter;
-
-  /**
-   * Set the parameter whose value will be the exception that was thrown to the
-   * given [parameter].
-   */
-  void set exceptionParameter(SimpleIdentifier parameter) {
-    _exceptionParameter = _becomeParentOf(parameter);
-  }
-
-  /**
-   * Return the type of exceptions caught by this catch clause, or `null` if
-   * this catch clause catches every type of exception.
-   */
-  TypeName get exceptionType => _exceptionType;
-
-  /**
-   * Set the type of exceptions caught by this catch clause to the given
-   * [exceptionType].
-   */
-  void set exceptionType(TypeName exceptionType) {
-    _exceptionType = _becomeParentOf(exceptionType);
-  }
-
-  /**
-   * Return the parameter whose value will be the stack trace associated with
-   * the exception, or `null` if there is no stack trace parameter.
-   */
-  SimpleIdentifier get stackTraceParameter => _stackTraceParameter;
-
-  /**
-   * Set the parameter whose value will be the stack trace associated with the
-   * exception to the given [parameter].
-   */
-  void set stackTraceParameter(SimpleIdentifier parameter) {
-    _stackTraceParameter = _becomeParentOf(parameter);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitCatchClause(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_exceptionType, visitor);
-    _safelyVisitChild(_exceptionParameter, visitor);
-    _safelyVisitChild(_stackTraceParameter, visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * Helper class to allow iteration of child entities of an AST node.
- */
-class ChildEntities extends Object with IterableMixin implements Iterable {
-  /**
-   * The list of child entities to be iterated over.
-   */
-  List _entities = [];
-
-  @override
-  Iterator get iterator => _entities.iterator;
-
-  /**
-   * Add an AST node or token as the next child entity, if it is not null.
-   */
-  void add(entity) {
-    if (entity != null) {
-      assert(entity is Token || entity is AstNode);
-      _entities.add(entity);
-    }
-  }
-
-  /**
-   * Add the given items as the next child entities, if [items] is not null.
-   */
-  void addAll(Iterable items) {
-    if (items != null) {
-      _entities.addAll(items);
-    }
-  }
-}
-
-/**
- * The declaration of a class.
- *
- * > classDeclaration ::=
- * >     'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]?
- * >     ([ExtendsClause] [WithClause]?)?
- * >     [ImplementsClause]?
- * >     '{' [ClassMember]* '}'
- */
-class ClassDeclaration extends NamedCompilationUnitMember {
-  /**
-   * The 'abstract' keyword, or `null` if the keyword was absent.
-   */
-  Token abstractKeyword;
-
-  /**
-   * The token representing the 'class' keyword.
-   */
-  Token classKeyword;
-
-  /**
-   * The type parameters for the class, or `null` if the class does not have any
-   * type parameters.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The extends clause for the class, or `null` if the class does not extend
-   * any other class.
-   */
-  ExtendsClause _extendsClause;
-
-  /**
-   * The with clause for the class, or `null` if the class does not have a with
-   * clause.
-   */
-  WithClause _withClause;
-
-  /**
-   * The implements clause for the class, or `null` if the class does not
-   * implement any interfaces.
-   */
-  ImplementsClause _implementsClause;
-
-  /**
-   * The native clause for the class, or `null` if the class does not have a
-   * native clause.
-   */
-  NativeClause _nativeClause;
-
-  /**
-   * The left curly bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The members defined by the class.
-   */
-  NodeList<ClassMember> _members;
-
-  /**
-   * The right curly bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created class declaration. Either or both of the
-   * [comment] and [metadata] can be `null` if the class does not have the
-   * corresponding attribute. The [abstractKeyword] can be `null` if the class
-   * is not abstract. The [typeParameters] can be `null` if the class does not
-   * have any type parameters. Any or all of the [extendsClause], [withClause],
-   * and [implementsClause] can be `null` if the class does not have the
-   * corresponding clause. The list of [members] can be `null` if the class does
-   * not have any members.
-   */
-  ClassDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      this.abstractKeyword,
-      this.classKeyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      ExtendsClause extendsClause,
-      WithClause withClause,
-      ImplementsClause implementsClause,
-      this.leftBracket,
-      List<ClassMember> members,
-      this.rightBracket)
-      : super(comment, metadata, name) {
-    _typeParameters = _becomeParentOf(typeParameters);
-    _extendsClause = _becomeParentOf(extendsClause);
-    _withClause = _becomeParentOf(withClause);
-    _implementsClause = _becomeParentOf(implementsClause);
-    _members = new NodeList<ClassMember>(this, members);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(abstractKeyword)
-    ..add(classKeyword)
-    ..add(_name)
-    ..add(_typeParameters)
-    ..add(_extendsClause)
-    ..add(_withClause)
-    ..add(_implementsClause)
-    ..add(_nativeClause)
-    ..add(leftBracket)
-    ..addAll(members)
-    ..add(rightBracket);
-
-  @override
-  ClassElement get element =>
-      _name != null ? (_name.staticElement as ClassElement) : null;
-
-  @override
-  Token get endToken => rightBracket;
-
-  /**
-   * Return the extends clause for this class, or `null` if the class does not
-   * extend any other class.
-   */
-  ExtendsClause get extendsClause => _extendsClause;
-
-  /**
-   * Set the extends clause for this class to the given [extendsClause].
-   */
-  void set extendsClause(ExtendsClause extendsClause) {
-    _extendsClause = _becomeParentOf(extendsClause);
-  }
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    if (abstractKeyword != null) {
-      return abstractKeyword;
-    }
-    return classKeyword;
-  }
-
-  /**
-   * Return the implements clause for the class, or `null` if the class does not
-   * implement any interfaces.
-   */
-  ImplementsClause get implementsClause => _implementsClause;
-
-  /**
-   * Set the implements clause for the class to the given [implementsClause].
-   */
-  void set implementsClause(ImplementsClause implementsClause) {
-    _implementsClause = _becomeParentOf(implementsClause);
-  }
-
-  /**
-   * Return `true` if this class is declared to be an abstract class.
-   */
-  bool get isAbstract => abstractKeyword != null;
-
-  /**
-   * Return the members defined by the class.
-   */
-  NodeList<ClassMember> get members => _members;
-
-  /**
-   * Return the native clause for this class, or `null` if the class does not
-   * have a native clause.
-   */
-  NativeClause get nativeClause => _nativeClause;
-
-  /**
-   * Set the native clause for this class to the given [nativeClause].
-   */
-  void set nativeClause(NativeClause nativeClause) {
-    _nativeClause = _becomeParentOf(nativeClause);
-  }
-
-  /**
-   * Return the type parameters for the class, or `null` if the class does not
-   * have any type parameters.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters for the class to the given list of [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  /**
-   * Return the with clause for the class, or `null` if the class does not have
-   * a with clause.
-   */
-  WithClause get withClause => _withClause;
-
-  /**
-   * Set the with clause for the class to the given [withClause].
-   */
-  void set withClause(WithClause withClause) {
-    _withClause = _becomeParentOf(withClause);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitClassDeclaration(this);
-
-  /**
-   * Return the constructor declared in the class with the given [name], or
-   * `null` if there is no such constructor. If the [name] is `null` then the
-   * default constructor will be searched for.
-   */
-  ConstructorDeclaration getConstructor(String name) {
-    for (ClassMember classMember in _members) {
-      if (classMember is ConstructorDeclaration) {
-        ConstructorDeclaration constructor = classMember;
-        SimpleIdentifier constructorName = constructor.name;
-        if (name == null && constructorName == null) {
-          return constructor;
-        }
-        if (constructorName != null && constructorName.name == name) {
-          return constructor;
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the field declared in the class with the given [name], or `null` if
-   * there is no such field.
-   */
-  VariableDeclaration getField(String name) {
-    for (ClassMember classMember in _members) {
-      if (classMember is FieldDeclaration) {
-        FieldDeclaration fieldDeclaration = classMember;
-        NodeList<VariableDeclaration> fields =
-            fieldDeclaration.fields.variables;
-        for (VariableDeclaration field in fields) {
-          SimpleIdentifier fieldName = field.name;
-          if (fieldName != null && name == fieldName.name) {
-            return field;
-          }
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the method declared in the class with the given [name], or `null` if
-   * there is no such method.
-   */
-  MethodDeclaration getMethod(String name) {
-    for (ClassMember classMember in _members) {
-      if (classMember is MethodDeclaration) {
-        MethodDeclaration method = classMember;
-        SimpleIdentifier methodName = method.name;
-        if (methodName != null && name == methodName.name) {
-          return method;
-        }
-      }
-    }
-    return null;
-  }
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_extendsClause, visitor);
-    _safelyVisitChild(_withClause, visitor);
-    _safelyVisitChild(_implementsClause, visitor);
-    _safelyVisitChild(_nativeClause, visitor);
-    members.accept(visitor);
-  }
-}
-
-/**
- * A node that declares a name within the scope of a class.
- */
-abstract class ClassMember extends Declaration {
-  /**
-   * Initialize a newly created member of a class. Either or both of the
-   * [comment] and [metadata] can be `null` if the member does not have the
-   * corresponding attribute.
-   */
-  ClassMember(Comment comment, List<Annotation> metadata)
-      : super(comment, metadata);
-}
-
-/**
- * A class type alias.
- *
- * > classTypeAlias ::=
- * >     [SimpleIdentifier] [TypeParameterList]? '=' 'abstract'? mixinApplication
- * >
- * > mixinApplication ::=
- * >     [TypeName] [WithClause] [ImplementsClause]? ';'
- */
-class ClassTypeAlias extends TypeAlias {
-  /**
-   * The type parameters for the class, or `null` if the class does not have any
-   * type parameters.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The token for the '=' separating the name from the definition.
-   */
-  Token equals;
-
-  /**
-   * The token for the 'abstract' keyword, or `null` if this is not defining an
-   * abstract class.
-   */
-  Token abstractKeyword;
-
-  /**
-   * The name of the superclass of the class being declared.
-   */
-  TypeName _superclass;
-
-  /**
-   * The with clause for this class.
-   */
-  WithClause _withClause;
-
-  /**
-   * The implements clause for this class, or `null` if there is no implements
-   * clause.
-   */
-  ImplementsClause _implementsClause;
-
-  /**
-   * Initialize a newly created class type alias. Either or both of the
-   * [comment] and [metadata] can be `null` if the class type alias does not
-   * have the corresponding attribute. The [typeParameters] can be `null` if the
-   * class does not have any type parameters. The [abstractKeyword] can be
-   * `null` if the class is not abstract. The [implementsClause] can be `null`
-   * if the class does not implement any interfaces.
-   */
-  ClassTypeAlias(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      this.equals,
-      this.abstractKeyword,
-      TypeName superclass,
-      WithClause withClause,
-      ImplementsClause implementsClause,
-      Token semicolon)
-      : super(comment, metadata, keyword, name, semicolon) {
-    _typeParameters = _becomeParentOf(typeParameters);
-    _superclass = _becomeParentOf(superclass);
-    _withClause = _becomeParentOf(withClause);
-    _implementsClause = _becomeParentOf(implementsClause);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(typedefKeyword)
-    ..add(_name)
-    ..add(_typeParameters)
-    ..add(equals)
-    ..add(abstractKeyword)
-    ..add(_superclass)
-    ..add(_withClause)
-    ..add(_implementsClause)
-    ..add(semicolon);
-
-  @override
-  ClassElement get element =>
-      _name != null ? (_name.staticElement as ClassElement) : null;
-
-  /**
-   * Return the implements clause for this class, or `null` if there is no
-   * implements clause.
-   */
-  ImplementsClause get implementsClause => _implementsClause;
-
-  /**
-   * Set the implements clause for this class to the given [implementsClause].
-   */
-  void set implementsClause(ImplementsClause implementsClause) {
-    _implementsClause = _becomeParentOf(implementsClause);
-  }
-
-  /**
-   * Return `true` if this class is declared to be an abstract class.
-   */
-  bool get isAbstract => abstractKeyword != null;
-
-  /**
-   * Return the name of the superclass of the class being declared.
-   */
-  TypeName get superclass => _superclass;
-
-  /**
-   * Set the name of the superclass of the class being declared to the given
-   * [superclass] name.
-   */
-  void set superclass(TypeName superclass) {
-    _superclass = _becomeParentOf(superclass);
-  }
-
-  /**
-   * Return the type parameters for the class, or `null` if the class does not
-   * have any type parameters.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters for the class to the given list of [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  /**
-   * Return the with clause for this class.
-   */
-  WithClause get withClause => _withClause;
-
-  /**
-   * Set the with clause for this class to the given with [withClause].
-   */
-  void set withClause(WithClause withClause) {
-    _withClause = _becomeParentOf(withClause);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitClassTypeAlias(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_superclass, visitor);
-    _safelyVisitChild(_withClause, visitor);
-    _safelyVisitChild(_implementsClause, visitor);
-  }
-}
-
-/**
- * A combinator associated with an import or export directive.
- *
- * > combinator ::=
- * >     [HideCombinator]
- * >   | [ShowCombinator]
- */
-abstract class Combinator extends AstNode {
-  /**
-   * The 'hide' or 'show' keyword specifying what kind of processing is to be
-   * done on the names.
-   */
-  Token keyword;
-
-  /**
-   * Initialize a newly created combinator.
-   */
-  Combinator(this.keyword);
-
-  @override
-  Token get beginToken => keyword;
-}
-
-/**
- * A comment within the source code.
- *
- * > comment ::=
- * >     endOfLineComment
- * >   | blockComment
- * >   | documentationComment
- * >
- * > endOfLineComment ::=
- * >     '//' (CHARACTER - EOL)* EOL
- * >
- * > blockComment ::=
- * >     '/ *' CHARACTER* '&#42;/'
- * >
- * > documentationComment ::=
- * >     '/ **' (CHARACTER | [CommentReference])* '&#42;/'
- * >   | ('///' (CHARACTER - EOL)* EOL)+
- */
-class Comment extends AstNode {
-  /**
-   * The tokens representing the comment.
-   */
-  final List<Token> tokens;
-
-  /**
-   * The type of the comment.
-   */
-  final CommentType _type;
-
-  /**
-   * The references embedded within the documentation comment. This list will be
-   * empty unless this is a documentation comment that has references embedded
-   * within it.
-   */
-  NodeList<CommentReference> _references;
-
-  /**
-   * Initialize a newly created comment. The list of [tokens] must contain at
-   * least one token. The [type] is the type of the comment. The list of
-   * [references] can be empty if the comment does not contain any embedded
-   * references.
-   */
-  Comment(this.tokens, this._type, List<CommentReference> references) {
-    _references = new NodeList<CommentReference>(this, references);
-  }
-
-  @override
-  Token get beginToken => tokens[0];
-
-  @override
-  Iterable get childEntities => new ChildEntities()..addAll(tokens);
-
-  @override
-  Token get endToken => tokens[tokens.length - 1];
-
-  /**
-   * Return `true` if this is a block comment.
-   */
-  bool get isBlock => _type == CommentType.BLOCK;
-
-  /**
-   * Return `true` if this is a documentation comment.
-   */
-  bool get isDocumentation => _type == CommentType.DOCUMENTATION;
-
-  /**
-   * Return `true` if this is an end-of-line comment.
-   */
-  bool get isEndOfLine => _type == CommentType.END_OF_LINE;
-
-  /**
-   * Return the references embedded within the documentation comment.
-   */
-  NodeList<CommentReference> get references => _references;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitComment(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _references.accept(visitor);
-  }
-
-  /**
-   * Create a block comment consisting of the given [tokens].
-   */
-  static Comment createBlockComment(List<Token> tokens) =>
-      new Comment(tokens, CommentType.BLOCK, null);
-
-  /**
-   * Create a documentation comment consisting of the given [tokens].
-   */
-  static Comment createDocumentationComment(List<Token> tokens) => new Comment(
-      tokens, CommentType.DOCUMENTATION, new List<CommentReference>());
-
-  /**
-   * Create a documentation comment consisting of the given [tokens] and having
-   * the given [references] embedded within it.
-   */
-  static Comment createDocumentationCommentWithReferences(
-          List<Token> tokens, List<CommentReference> references) =>
-      new Comment(tokens, CommentType.DOCUMENTATION, references);
-
-  /**
-   * Create an end-of-line comment consisting of the given [tokens].
-   */
-  static Comment createEndOfLineComment(List<Token> tokens) =>
-      new Comment(tokens, CommentType.END_OF_LINE, null);
-}
-
-/**
- * A reference to a Dart element that is found within a documentation comment.
- *
- * > commentReference ::=
- * >     '[' 'new'? [Identifier] ']'
- */
-class CommentReference extends AstNode {
-  /**
-   * The token representing the 'new' keyword, or `null` if there was no 'new'
-   * keyword.
-   */
-  Token newKeyword;
-
-  /**
-   * The identifier being referenced.
-   */
-  Identifier _identifier;
-
-  /**
-   * Initialize a newly created reference to a Dart element. The [newKeyword]
-   * can be `null` if the reference is not to a constructor.
-   */
-  CommentReference(this.newKeyword, Identifier identifier) {
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  @override
-  Token get beginToken => _identifier.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(newKeyword)..add(_identifier);
-
-  @override
-  Token get endToken => _identifier.endToken;
-
-  /**
-   * Return the identifier being referenced.
-   */
-  Identifier get identifier => _identifier;
-
-  /**
-   * Set the identifier being referenced to the given [identifier].
-   */
-  void set identifier(Identifier identifier) {
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitCommentReference(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_identifier, visitor);
-  }
-}
-
-/**
- * The possible types of comments that are recognized by the parser.
- */
-class CommentType {
-  /**
-   * A block comment.
-   */
-  static const CommentType BLOCK = const CommentType('BLOCK');
-
-  /**
-   * A documentation comment.
-   */
-  static const CommentType DOCUMENTATION = const CommentType('DOCUMENTATION');
-
-  /**
-   * An end-of-line comment.
-   */
-  static const CommentType END_OF_LINE = const CommentType('END_OF_LINE');
-
-  /**
-   * The name of the comment type.
-   */
-  final String name;
-
-  /**
-   * Initialize a newly created comment type to have the given [name].
-   */
-  const CommentType(this.name);
-
-  @override
-  String toString() => name;
-}
-
-/**
- * A compilation unit.
- *
- * While the grammar restricts the order of the directives and declarations
- * within a compilation unit, this class does not enforce those restrictions.
- * In particular, the children of a compilation unit will be visited in lexical
- * order even if lexical order does not conform to the restrictions of the
- * grammar.
- *
- * > compilationUnit ::=
- * >     directives declarations
- * >
- * > directives ::=
- * >     [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
- * >   | [PartOfDirective]
- * >
- * > namespaceDirective ::=
- * >     [ImportDirective]
- * >   | [ExportDirective]
- * >
- * > declarations ::=
- * >     [CompilationUnitMember]*
- */
-class CompilationUnit extends AstNode {
-  /**
-   * The first token in the token stream that was parsed to form this
-   * compilation unit.
-   */
-  Token beginToken;
-
-  /**
-   * The script tag at the beginning of the compilation unit, or `null` if there
-   * is no script tag in this compilation unit.
-   */
-  ScriptTag _scriptTag;
-
-  /**
-   * The directives contained in this compilation unit.
-   */
-  NodeList<Directive> _directives;
-
-  /**
-   * The declarations contained in this compilation unit.
-   */
-  NodeList<CompilationUnitMember> _declarations;
-
-  /**
-   * The last token in the token stream that was parsed to form this compilation
-   * unit. This token should always have a type of [TokenType.EOF].
-   */
-  Token endToken;
-
-  /**
-   * The element associated with this compilation unit, or `null` if the AST
-   * structure has not been resolved.
-   */
-  CompilationUnitElement element;
-
-  /**
-   * The line information for this compilation unit.
-   */
-  LineInfo lineInfo;
-
-  /**
-   * Initialize a newly created compilation unit to have the given directives
-   * and declarations. The [scriptTag] can be `null` if there is no script tag
-   * in the compilation unit. The list of [directives] can be `null` if there
-   * are no directives in the compilation unit. The list of [declarations] can
-   * be `null` if there are no declarations in the compilation unit.
-   */
-  CompilationUnit(
-      this.beginToken,
-      ScriptTag scriptTag,
-      List<Directive> directives,
-      List<CompilationUnitMember> declarations,
-      this.endToken) {
-    _scriptTag = _becomeParentOf(scriptTag);
-    _directives = new NodeList<Directive>(this, directives);
-    _declarations = new NodeList<CompilationUnitMember>(this, declarations);
-  }
-
-  @override
-  Iterable get childEntities {
-    ChildEntities result = new ChildEntities()..add(_scriptTag);
-    if (_directivesAreBeforeDeclarations) {
-      result..addAll(_directives)..addAll(_declarations);
-    } else {
-      result.addAll(sortedDirectivesAndDeclarations);
-    }
-    return result;
-  }
-
-  /**
-   * Return the declarations contained in this compilation unit.
-   */
-  NodeList<CompilationUnitMember> get declarations => _declarations;
-
-  /**
-   * Return the directives contained in this compilation unit.
-   */
-  NodeList<Directive> get directives => _directives;
-
-  @override
-  int get length {
-    Token endToken = this.endToken;
-    if (endToken == null) {
-      return 0;
-    }
-    return endToken.offset + endToken.length;
-  }
-
-  @override
-  int get offset => 0;
-
-  /**
-   * Return the script tag at the beginning of the compilation unit, or `null`
-   * if there is no script tag in this compilation unit.
-   */
-  ScriptTag get scriptTag => _scriptTag;
-
-  /**
-   * Set the script tag at the beginning of the compilation unit to the given
-   * [scriptTag].
-   */
-  void set scriptTag(ScriptTag scriptTag) {
-    _scriptTag = _becomeParentOf(scriptTag);
-  }
-
-  /**
-   * Return a list containing all of the directives and declarations in this
-   * compilation unit, sorted in lexical order.
-   */
-  List<AstNode> get sortedDirectivesAndDeclarations {
-    return <AstNode>[]
-      ..addAll(_directives)
-      ..addAll(_declarations)
-      ..sort(AstNode.LEXICAL_ORDER);
-  }
-
-  /**
-   * Return `true` if all of the directives are lexically before any
-   * declarations.
-   */
-  bool get _directivesAreBeforeDeclarations {
-    if (_directives.isEmpty || _declarations.isEmpty) {
-      return true;
-    }
-    Directive lastDirective = _directives[_directives.length - 1];
-    CompilationUnitMember firstDeclaration = _declarations[0];
-    return lastDirective.offset < firstDeclaration.offset;
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitCompilationUnit(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_scriptTag, visitor);
-    if (_directivesAreBeforeDeclarations) {
-      _directives.accept(visitor);
-      _declarations.accept(visitor);
-    } else {
-      for (AstNode child in sortedDirectivesAndDeclarations) {
-        child.accept(visitor);
-      }
-    }
-  }
-}
-
-/**
- * A node that declares one or more names within the scope of a compilation
- * unit.
- *
- * > compilationUnitMember ::=
- * >     [ClassDeclaration]
- * >   | [TypeAlias]
- * >   | [FunctionDeclaration]
- * >   | [MethodDeclaration]
- * >   | [VariableDeclaration]
- * >   | [VariableDeclaration]
- */
-abstract class CompilationUnitMember extends Declaration {
-  /**
-   * Initialize a newly created generic compilation unit member. Either or both
-   * of the [comment] and [metadata] can be `null` if the member does not have
-   * the corresponding attribute.
-   */
-  CompilationUnitMember(Comment comment, List<Annotation> metadata)
-      : super(comment, metadata);
-}
-
-/**
- * A conditional expression.
- *
- * > conditionalExpression ::=
- * >     [Expression] '?' [Expression] ':' [Expression]
- */
-class ConditionalExpression extends Expression {
-  /**
-   * The condition used to determine which of the expressions is executed next.
-   */
-  Expression _condition;
-
-  /**
-   * The token used to separate the condition from the then expression.
-   */
-  Token question;
-
-  /**
-   * The expression that is executed if the condition evaluates to `true`.
-   */
-  Expression _thenExpression;
-
-  /**
-   * The token used to separate the then expression from the else expression.
-   */
-  Token colon;
-
-  /**
-   * The expression that is executed if the condition evaluates to `false`.
-   */
-  Expression _elseExpression;
-
-  /**
-   * Initialize a newly created conditional expression.
-   */
-  ConditionalExpression(Expression condition, this.question,
-      Expression thenExpression, this.colon, Expression elseExpression) {
-    _condition = _becomeParentOf(condition);
-    _thenExpression = _becomeParentOf(thenExpression);
-    _elseExpression = _becomeParentOf(elseExpression);
-  }
-
-  @override
-  Token get beginToken => _condition.beginToken;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(_condition)
-    ..add(question)
-    ..add(_thenExpression)
-    ..add(colon)
-    ..add(_elseExpression);
-
-  /**
-   * Return the condition used to determine which of the expressions is executed
-   * next.
-   */
-  Expression get condition => _condition;
-
-  /**
-   * Set the condition used to determine which of the expressions is executed
-   * next to the given [expression].
-   */
-  void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the expression that is executed if the condition evaluates to
-   * `false`.
-   */
-  Expression get elseExpression => _elseExpression;
-
-  /**
-   * Set the expression that is executed if the condition evaluates to `false`
-   * to the given [expression].
-   */
-  void set elseExpression(Expression expression) {
-    _elseExpression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get endToken => _elseExpression.endToken;
-
-  @override
-  int get precedence => 3;
-
-  /**
-   * Return the expression that is executed if the condition evaluates to
-   * `true`.
-   */
-  Expression get thenExpression => _thenExpression;
-
-  /**
-   * Set the expression that is executed if the condition evaluates to `true` to
-   * the given [expression].
-   */
-  void set thenExpression(Expression expression) {
-    _thenExpression = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitConditionalExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(_thenExpression, visitor);
-    _safelyVisitChild(_elseExpression, visitor);
-  }
-}
-
-/**
- * A configuration in either an import or export directive.
- *
- *     configuration ::=
- *         'if' '(' test ')' uri
- *
- *     test ::=
- *         dottedName ('==' stringLiteral)?
- *
- *     dottedName ::=
- *         identifier ('.' identifier)*
- */
-class Configuration extends AstNode {
-  Token ifKeyword;
-  Token leftParenthesis;
-  DottedName _name;
-  Token equalToken;
-  StringLiteral _value;
-  Token rightParenthesis;
-  StringLiteral _libraryUri;
-
-  Configuration(
-      this.ifKeyword,
-      this.leftParenthesis,
-      DottedName name,
-      this.equalToken,
-      StringLiteral value,
-      this.rightParenthesis,
-      StringLiteral libraryUri) {
-    _name = _becomeParentOf(name);
-    _value = _becomeParentOf(value);
-    _libraryUri = _becomeParentOf(libraryUri);
-  }
-
-  @override
-  Token get beginToken => ifKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(ifKeyword)
-    ..add(leftParenthesis)
-    ..add(_name)
-    ..add(equalToken)
-    ..add(_value)
-    ..add(rightParenthesis)
-    ..add(_libraryUri);
-
-  @override
-  Token get endToken => _libraryUri.endToken;
-
-  StringLiteral get libraryUri => _libraryUri;
-
-  void set libraryUri(StringLiteral libraryUri) {
-    _libraryUri = _becomeParentOf(libraryUri);
-  }
-
-  DottedName get name => _name;
-
-  void set name(DottedName name) {
-    _name = _becomeParentOf(name);
-  }
-
-  StringLiteral get value => _value;
-
-  void set value(StringLiteral value) {
-    _value = _becomeParentOf(value);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitConfiguration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_value, visitor);
-    _safelyVisitChild(_libraryUri, visitor);
-  }
-}
-
-/**
- * A constructor declaration.
- *
- * > constructorDeclaration ::=
- * >     constructorSignature [FunctionBody]?
- * >   | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier])? arguments
- * >
- * > constructorSignature ::=
- * >     'external'? constructorName formalParameterList initializerList?
- * >   | 'external'? 'factory' factoryName formalParameterList initializerList?
- * >   | 'external'? 'const'  constructorName formalParameterList initializerList?
- * >
- * > constructorName ::=
- * >     [SimpleIdentifier] ('.' [SimpleIdentifier])?
- * >
- * > factoryName ::=
- * >     [Identifier] ('.' [SimpleIdentifier])?
- * >
- * > initializerList ::=
- * >     ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
- */
-class ConstructorDeclaration extends ClassMember {
-  /**
-   * The token for the 'external' keyword, or `null` if the constructor is not
-   * external.
-   */
-  Token externalKeyword;
-
-  /**
-   * The token for the 'const' keyword, or `null` if the constructor is not a
-   * const constructor.
-   */
-  Token constKeyword;
-
-  /**
-   * The token for the 'factory' keyword, or `null` if the constructor is not a
-   * factory constructor.
-   */
-  Token factoryKeyword;
-
-  /**
-   * The type of object being created. This can be different than the type in
-   * which the constructor is being declared if the constructor is the
-   * implementation of a factory constructor.
-   */
-  Identifier _returnType;
-
-  /**
-   * The token for the period before the constructor name, or `null` if the
-   * constructor being declared is unnamed.
-   */
-  Token period;
-
-  /**
-   * The name of the constructor, or `null` if the constructor being declared is
-   * unnamed.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * The parameters associated with the constructor.
-   */
-  FormalParameterList _parameters;
-
-  /**
-   * The token for the separator (colon or equals) before the initializer list
-   * or redirection, or `null` if there are no initializers.
-   */
-  Token separator;
-
-  /**
-   * The initializers associated with the constructor.
-   */
-  NodeList<ConstructorInitializer> _initializers;
-
-  /**
-   * The name of the constructor to which this constructor will be redirected,
-   * or `null` if this is not a redirecting factory constructor.
-   */
-  ConstructorName _redirectedConstructor;
-
-  /**
-   * The body of the constructor, or `null` if the constructor does not have a
-   * body.
-   */
-  FunctionBody _body;
-
-  /**
-   * The element associated with this constructor, or `null` if the AST
-   * structure has not been resolved or if this constructor could not be
-   * resolved.
-   */
-  ConstructorElement element;
-
-  /**
-   * Initialize a newly created constructor declaration. The [externalKeyword]
-   * can be `null` if the constructor is not external. Either or both of the
-   * [comment] and [metadata] can be `null` if the constructor does not have the
-   * corresponding attribute. The [constKeyword] can be `null` if the
-   * constructor cannot be used to create a constant. The [factoryKeyword] can
-   * be `null` if the constructor is not a factory. The [period] and [name] can
-   * both be `null` if the constructor is not a named constructor. The
-   * [separator] can be `null` if the constructor does not have any initializers
-   * and does not redirect to a different constructor. The list of
-   * [initializers] can be `null` if the constructor does not have any
-   * initializers. The [redirectedConstructor] can be `null` if the constructor
-   * does not redirect to a different constructor. The [body] can be `null` if
-   * the constructor does not have a body.
-   */
-  ConstructorDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      this.externalKeyword,
-      this.constKeyword,
-      this.factoryKeyword,
-      Identifier returnType,
-      this.period,
-      SimpleIdentifier name,
-      FormalParameterList parameters,
-      this.separator,
-      List<ConstructorInitializer> initializers,
-      ConstructorName redirectedConstructor,
-      FunctionBody body)
-      : super(comment, metadata) {
-    _returnType = _becomeParentOf(returnType);
-    _name = _becomeParentOf(name);
-    _parameters = _becomeParentOf(parameters);
-    _initializers = new NodeList<ConstructorInitializer>(this, initializers);
-    _redirectedConstructor = _becomeParentOf(redirectedConstructor);
-    _body = _becomeParentOf(body);
-  }
-
-  /**
-   * Return the body of the constructor, or `null` if the constructor does not
-   * have a body.
-   */
-  FunctionBody get body => _body;
-
-  /**
-   * Set the body of the constructor to the given [functionBody].
-   */
-  void set body(FunctionBody functionBody) {
-    _body = _becomeParentOf(functionBody);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(externalKeyword)
-    ..add(constKeyword)
-    ..add(factoryKeyword)
-    ..add(_returnType)
-    ..add(period)
-    ..add(_name)
-    ..add(_parameters)
-    ..add(separator)
-    ..addAll(initializers)
-    ..add(_redirectedConstructor)
-    ..add(_body);
-
-  @override
-  Token get endToken {
-    if (_body != null) {
-      return _body.endToken;
-    } else if (!_initializers.isEmpty) {
-      return _initializers.endToken;
-    }
-    return _parameters.endToken;
-  }
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    Token leftMost =
-        Token.lexicallyFirst([externalKeyword, constKeyword, factoryKeyword]);
-    if (leftMost != null) {
-      return leftMost;
-    }
-    return _returnType.beginToken;
-  }
-
-  /**
-   * Return the initializers associated with the constructor.
-   */
-  NodeList<ConstructorInitializer> get initializers => _initializers;
-
-  /**
-   * Return the name of the constructor, or `null` if the constructor being
-   * declared is unnamed.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the constructor to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return the parameters associated with the constructor.
-   */
-  FormalParameterList get parameters => _parameters;
-
-  /**
-   * Set the parameters associated with the constructor to the given list of
-   * [parameters].
-   */
-  void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  /**
-   * Return the name of the constructor to which this constructor will be
-   * redirected, or `null` if this is not a redirecting factory constructor.
-   */
-  ConstructorName get redirectedConstructor => _redirectedConstructor;
-
-  /**
-   * Set the name of the constructor to which this constructor will be
-   * redirected to the given [redirectedConstructor] name.
-   */
-  void set redirectedConstructor(ConstructorName redirectedConstructor) {
-    _redirectedConstructor = _becomeParentOf(redirectedConstructor);
-  }
-
-  /**
-   * Return the type of object being created. This can be different than the
-   * type in which the constructor is being declared if the constructor is the
-   * implementation of a factory constructor.
-   */
-  Identifier get returnType => _returnType;
-
-  /**
-   * Set the type of object being created to the given [typeName].
-   */
-  void set returnType(Identifier typeName) {
-    _returnType = _becomeParentOf(typeName);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitConstructorDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_parameters, visitor);
-    _initializers.accept(visitor);
-    _safelyVisitChild(_redirectedConstructor, visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * The initialization of a field within a constructor's initialization list.
- *
- * > fieldInitializer ::=
- * >     ('this' '.')? [SimpleIdentifier] '=' [Expression]
- */
-class ConstructorFieldInitializer extends ConstructorInitializer {
-  /**
-   * The token for the 'this' keyword, or `null` if there is no 'this' keyword.
-   */
-  Token thisKeyword;
-
-  /**
-   * The token for the period after the 'this' keyword, or `null` if there is no
-   * 'this' keyword.
-   */
-  Token period;
-
-  /**
-   * The name of the field being initialized.
-   */
-  SimpleIdentifier _fieldName;
-
-  /**
-   * The token for the equal sign between the field name and the expression.
-   */
-  Token equals;
-
-  /**
-   * The expression computing the value to which the field will be initialized.
-   */
-  Expression _expression;
-
-  /**
-   * Initialize a newly created field initializer to initialize the field with
-   * the given name to the value of the given expression. The [thisKeyword] and
-   * [period] can be `null` if the 'this' keyword was not specified.
-   */
-  ConstructorFieldInitializer(this.thisKeyword, this.period,
-      SimpleIdentifier fieldName, this.equals, Expression expression) {
-    _fieldName = _becomeParentOf(fieldName);
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken {
-    if (thisKeyword != null) {
-      return thisKeyword;
-    }
-    return _fieldName.beginToken;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(thisKeyword)
-    ..add(period)
-    ..add(_fieldName)
-    ..add(equals)
-    ..add(_expression);
-
-  @override
-  Token get endToken => _expression.endToken;
-
-  /**
-   * Return the expression computing the value to which the field will be
-   * initialized.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression computing the value to which the field will be
-   * initialized to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the name of the field being initialized.
-   */
-  SimpleIdentifier get fieldName => _fieldName;
-
-  /**
-   * Set the name of the field being initialized to the given [identifier].
-   */
-  void set fieldName(SimpleIdentifier identifier) {
-    _fieldName = _becomeParentOf(identifier);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitConstructorFieldInitializer(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_fieldName, visitor);
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * A node that can occur in the initializer list of a constructor declaration.
- *
- * > constructorInitializer ::=
- * >     [SuperConstructorInvocation]
- * >   | [ConstructorFieldInitializer]
- * >   | [RedirectingConstructorInvocation]
- */
-abstract class ConstructorInitializer extends AstNode {}
-
-/**
- * The name of the constructor.
- *
- * > constructorName ::=
- * >     type ('.' identifier)?
- */
-class ConstructorName extends AstNode {
-  /**
-   * The name of the type defining the constructor.
-   */
-  TypeName _type;
-
-  /**
-   * The token for the period before the constructor name, or `null` if the
-   * specified constructor is the unnamed constructor.
-   */
-  Token period;
-
-  /**
-   * The name of the constructor, or `null` if the specified constructor is the
-   * unnamed constructor.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * The element associated with this constructor name based on static type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this constructor name could not be resolved.
-   */
-  ConstructorElement staticElement;
-
-  /**
-   * Initialize a newly created constructor name. The [period] and [name] can be
-   * `null` if the constructor being named is the unnamed constructor.
-   */
-  ConstructorName(TypeName type, this.period, SimpleIdentifier name) {
-    _type = _becomeParentOf(type);
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  Token get beginToken => _type.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_type)..add(period)..add(_name);
-
-  @override
-  Token get endToken {
-    if (_name != null) {
-      return _name.endToken;
-    }
-    return _type.endToken;
-  }
-
-  /**
-   * Return the name of the constructor, or `null` if the specified constructor
-   * is the unnamed constructor.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the constructor to the given [name].
-   */
-  void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
-  }
-
-  /**
-   * Return the name of the type defining the constructor.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the name of the type defining the constructor to the given [type] name.
-   */
-  void set type(TypeName type) {
-    _type = _becomeParentOf(type);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitConstructorName(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(_name, visitor);
-  }
-}
-
-/**
- * A continue statement.
- *
- * > continueStatement ::=
- * >     'continue' [SimpleIdentifier]? ';'
- */
-class ContinueStatement extends Statement {
-  /**
-   * The token representing the 'continue' keyword.
-   */
-  Token continueKeyword;
-
-  /**
-   * The label associated with the statement, or `null` if there is no label.
-   */
-  SimpleIdentifier _label;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * The AstNode which this continue statement is continuing to.  This will be
-   * either a Statement (in the case of continuing a loop) or a SwitchMember
-   * (in the case of continuing from one switch case to another).  Null if the
-   * AST has not yet been resolved or if the target could not be resolved.
-   * Note that if the source code has errors, the target may be invalid (e.g.
-   * the target may be in an enclosing function).
-   */
-  AstNode target;
-
-  /**
-   * Initialize a newly created continue statement. The [label] can be `null` if
-   * there is no label associated with the statement.
-   */
-  ContinueStatement(
-      this.continueKeyword, SimpleIdentifier label, this.semicolon) {
-    _label = _becomeParentOf(label);
-  }
-
-  @override
-  Token get beginToken => continueKeyword;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(continueKeyword)..add(_label)..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the label associated with the statement, or `null` if there is no
-   * label.
-   */
-  SimpleIdentifier get label => _label;
-
-  /**
-   * Set the label associated with the statement to the given [identifier].
-   */
-  void set label(SimpleIdentifier identifier) {
-    _label = _becomeParentOf(identifier);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitContinueStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_label, visitor);
-  }
-}
-
-/**
- * A node that represents the declaration of one or more names. Each declared
- * name is visible within a name scope.
- */
-abstract class Declaration extends AnnotatedNode {
-  /**
-   * Initialize a newly created declaration. Either or both of the [comment] and
-   * [metadata] can be `null` if the declaration does not have the corresponding
-   * attribute.
-   */
-  Declaration(Comment comment, List<Annotation> metadata)
-      : super(comment, metadata);
-
-  /**
-   * Return the element associated with this declaration, or `null` if either
-   * this node corresponds to a list of declarations or if the AST structure has
-   * not been resolved.
-   */
-  Element get element;
-}
-
-/**
- * The declaration of a single identifier.
- *
- * > declaredIdentifier ::=
- * >     [Annotation] finalConstVarOrType [SimpleIdentifier]
- */
-class DeclaredIdentifier extends Declaration {
-  /**
-   * The token representing either the 'final', 'const' or 'var' keyword, or
-   * `null` if no keyword was used.
-   */
-  Token keyword;
-
-  /**
-   * The name of the declared type of the parameter, or `null` if the parameter
-   * does not have a declared type.
-   */
-  TypeName _type;
-
-  /**
-   * The name of the variable being declared.
-   */
-  SimpleIdentifier _identifier;
-
-  /**
-   * Initialize a newly created formal parameter. Either or both of the
-   * [comment] and [metadata] can be `null` if the declaration does not have the
-   * corresponding attribute. The [keyword] can be `null` if a type name is
-   * given. The [type] must be `null` if the keyword is 'var'.
-   */
-  DeclaredIdentifier(Comment comment, List<Annotation> metadata, this.keyword,
-      TypeName type, SimpleIdentifier identifier)
-      : super(comment, metadata) {
-    _type = _becomeParentOf(type);
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(keyword)..add(_type)..add(_identifier);
-
-  @override
-  LocalVariableElement get element {
-    if (_identifier == null) {
-      return null;
-    }
-    return _identifier.staticElement as LocalVariableElement;
-  }
-
-  @override
-  Token get endToken => _identifier.endToken;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    if (keyword != null) {
-      return keyword;
-    } else if (_type != null) {
-      return _type.beginToken;
-    }
-    return _identifier.beginToken;
-  }
-
-  /**
-   * Return the name of the variable being declared.
-   */
-  SimpleIdentifier get identifier => _identifier;
-
-  /**
-   * Set the name of the variable being declared to the given [identifier].
-   */
-  void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return `true` if this variable was declared with the 'const' modifier.
-   */
-  bool get isConst =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
-
-  /**
-   * Return `true` if this variable was declared with the 'final' modifier.
-   * Variables that are declared with the 'const' modifier will return `false`
-   * even though they are implicitly final.
-   */
-  bool get isFinal =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
-
-  /**
-   * Return the name of the declared type of the parameter, or `null` if the
-   * parameter does not have a declared type.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the name of the declared type of the parameter to the given [typeName].
-   */
-  void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitDeclaredIdentifier(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(_identifier, visitor);
-  }
-}
-
-/**
- * A formal parameter with a default value. There are two kinds of parameters
- * that are both represented by this class: named formal parameters and
- * positional formal parameters.
- *
- * > defaultFormalParameter ::=
- * >     [NormalFormalParameter] ('=' [Expression])?
- * >
- * > defaultNamedParameter ::=
- * >     [NormalFormalParameter] (':' [Expression])?
- */
-class DefaultFormalParameter extends FormalParameter {
-  /**
-   * The formal parameter with which the default value is associated.
-   */
-  NormalFormalParameter _parameter;
-
-  /**
-   * The kind of this parameter.
-   */
-  ParameterKind kind;
-
-  /**
-   * The token separating the parameter from the default value, or `null` if
-   * there is no default value.
-   */
-  Token separator;
-
-  /**
-   * The expression computing the default value for the parameter, or `null` if
-   * there is no default value.
-   */
-  Expression _defaultValue;
-
-  /**
-   * Initialize a newly created default formal parameter. The [separator] and
-   * [defaultValue] can be `null` if there is no default value.
-   */
-  DefaultFormalParameter(NormalFormalParameter parameter, this.kind,
-      this.separator, Expression defaultValue) {
-    _parameter = _becomeParentOf(parameter);
-    _defaultValue = _becomeParentOf(defaultValue);
-  }
-
-  @override
-  Token get beginToken => _parameter.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_parameter)..add(separator)..add(_defaultValue);
-
-  /**
-   * Return the expression computing the default value for the parameter, or
-   * `null` if there is no default value.
-   */
-  Expression get defaultValue => _defaultValue;
-
-  /**
-   * Set the expression computing the default value for the parameter to the
-   * given [expression].
-   */
-  void set defaultValue(Expression expression) {
-    _defaultValue = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get endToken {
-    if (_defaultValue != null) {
-      return _defaultValue.endToken;
-    }
-    return _parameter.endToken;
-  }
-
-  @override
-  SimpleIdentifier get identifier => _parameter.identifier;
-
-  @override
-  bool get isConst => _parameter != null && _parameter.isConst;
-
-  @override
-  bool get isFinal => _parameter != null && _parameter.isFinal;
-
-  @override
-  NodeList<Annotation> get metadata => _parameter.metadata;
-
-  /**
-   * Return the formal parameter with which the default value is associated.
-   */
-  NormalFormalParameter get parameter => _parameter;
-
-  /**
-   * Set the formal parameter with which the default value is associated to the
-   * given [formalParameter].
-   */
-  void set parameter(NormalFormalParameter formalParameter) {
-    _parameter = _becomeParentOf(formalParameter);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitDefaultFormalParameter(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_parameter, visitor);
-    _safelyVisitChild(_defaultValue, visitor);
-  }
-}
-
-/**
- * A node that represents a directive.
- *
- * > directive ::=
- * >     [ExportDirective]
- * >   | [ImportDirective]
- * >   | [LibraryDirective]
- * >   | [PartDirective]
- * >   | [PartOfDirective]
- */
-abstract class Directive extends AnnotatedNode {
-  /**
-   * The element associated with this directive, or `null` if the AST structure
-   * has not been resolved or if this directive could not be resolved.
-   */
-  Element element;
-
-  /**
-   * Initialize a newly create directive. Either or both of the [comment] and
-   * [metadata] can be `null` if the directive does not have the corresponding
-   * attribute.
-   */
-  Directive(Comment comment, List<Annotation> metadata)
-      : super(comment, metadata);
-
-  /**
-   * Return the token representing the keyword that introduces this directive
-   * ('import', 'export', 'library' or 'part').
-   */
-  Token get keyword;
-}
-
-/**
- * A do statement.
- *
- * > doStatement ::=
- * >     'do' [Statement] 'while' '(' [Expression] ')' ';'
- */
-class DoStatement extends Statement {
-  /**
-   * The token representing the 'do' keyword.
-   */
-  Token doKeyword;
-
-  /**
-   * The body of the loop.
-   */
-  Statement _body;
-
-  /**
-   * The token representing the 'while' keyword.
-   */
-  Token whileKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The condition that determines when the loop will terminate.
-   */
-  Expression _condition;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created do loop.
-   */
-  DoStatement(
-      this.doKeyword,
-      Statement body,
-      this.whileKeyword,
-      this.leftParenthesis,
-      Expression condition,
-      this.rightParenthesis,
-      this.semicolon) {
-    _body = _becomeParentOf(body);
-    _condition = _becomeParentOf(condition);
-  }
-
-  @override
-  Token get beginToken => doKeyword;
-
-  /**
-   * Return the body of the loop.
-   */
-  Statement get body => _body;
-
-  /**
-   * Set the body of the loop to the given [statement].
-   */
-  void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(doKeyword)
-    ..add(_body)
-    ..add(whileKeyword)
-    ..add(leftParenthesis)
-    ..add(_condition)
-    ..add(rightParenthesis)
-    ..add(semicolon);
-
-  /**
-   * Return the condition that determines when the loop will terminate.
-   */
-  Expression get condition => _condition;
-
-  /**
-   * Set the condition that determines when the loop will terminate to the given
-   * [expression].
-   */
-  void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitDoStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_body, visitor);
-    _safelyVisitChild(_condition, visitor);
-  }
-}
-
-/**
- * A dotted name, used in a configuration within an import or export directive.
- *
- * > dottedName ::=
- * >     [SimpleIdentifier] ('.' [SimpleIdentifier])*
- */
-class DottedName extends AstNode {
-  /**
-   * The components of the identifier.
-   */
-  NodeList<SimpleIdentifier> _components;
-
-  /**
-   * Initialize a newly created dotted name.
-   */
-  DottedName(List<SimpleIdentifier> components) {
-    _components = new NodeList<SimpleIdentifier>(this, components);
-  }
-
-  @override
-  Token get beginToken => _components.beginToken;
-
-  @override
-  // TODO(paulberry): add "." tokens.
-  Iterable get childEntities => new ChildEntities()..addAll(_components);
-
-  /**
-   * Return the components of the identifier.
-   */
-  NodeList<SimpleIdentifier> get components => _components;
-
-  @override
-  Token get endToken => _components.endToken;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitDottedName(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _components.accept(visitor);
-  }
-}
-
-/**
- * A floating point literal expression.
- *
- * > doubleLiteral ::=
- * >     decimalDigit+ ('.' decimalDigit*)? exponent?
- * >   | '.' decimalDigit+ exponent?
- * >
- * > exponent ::=
- * >     ('e' | 'E') ('+' | '-')? decimalDigit+
- */
-class DoubleLiteral extends Literal {
-  /**
-   * The token representing the literal.
-   */
-  Token literal;
-
-  /**
-   * The value of the literal.
-   */
-  double value;
-
-  /**
-   * Initialize a newly created floating point literal.
-   */
-  DoubleLiteral(this.literal, this.value);
-
-  @override
-  Token get beginToken => literal;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
-
-  @override
-  Token get endToken => literal;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitDoubleLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * An empty function body, which can only appear in constructors or abstract
- * methods.
- *
- * > emptyFunctionBody ::=
- * >     ';'
- */
-class EmptyFunctionBody extends FunctionBody {
-  /**
-   * The token representing the semicolon that marks the end of the function
-   * body.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created function body.
-   */
-  EmptyFunctionBody(this.semicolon);
-
-  @override
-  Token get beginToken => semicolon;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitEmptyFunctionBody(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // Empty function bodies have no children.
-  }
-}
-
-/**
- * An empty statement.
- *
- * > emptyStatement ::=
- * >     ';'
- */
-class EmptyStatement extends Statement {
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created empty statement.
-   */
-  EmptyStatement(this.semicolon);
-
-  @override
-  Token get beginToken => semicolon;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitEmptyStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * The declaration of an enum constant.
- */
-class EnumConstantDeclaration extends Declaration {
-  /**
-   * The name of the constant.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * Initialize a newly created enum constant declaration. Either or both of the
-   * [comment] and [metadata] can be `null` if the constant does not have the
-   * corresponding attribute. (Technically, enum constants cannot have metadata,
-   * but we allow it for consistency.)
-   */
-  EnumConstantDeclaration(
-      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
-      : super(comment, metadata) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities..add(_name);
-
-  @override
-  FieldElement get element =>
-      _name == null ? null : (_name.staticElement as FieldElement);
-
-  @override
-  Token get endToken => _name.endToken;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
-
-  /**
-   * Return the name of the constant.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the constant to the given [name].
-   */
-  void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitEnumConstantDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-  }
-}
-
-/**
- * The declaration of an enumeration.
- *
- * > enumType ::=
- * >     metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] (',' [SimpleIdentifier])* (',')? '}'
- */
-class EnumDeclaration extends NamedCompilationUnitMember {
-  /**
-   * The 'enum' keyword.
-   */
-  Token enumKeyword;
-
-  /**
-   * The left curly bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The enumeration constants being declared.
-   */
-  NodeList<EnumConstantDeclaration> _constants;
-
-  /**
-   * The right curly bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created enumeration declaration. Either or both of the
-   * [comment] and [metadata] can be `null` if the declaration does not have the
-   * corresponding attribute. The list of [constants] must contain at least one
-   * value.
-   */
-  EnumDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      this.enumKeyword,
-      SimpleIdentifier name,
-      this.leftBracket,
-      List<EnumConstantDeclaration> constants,
-      this.rightBracket)
-      : super(comment, metadata, name) {
-    _constants = new NodeList<EnumConstantDeclaration>(this, constants);
-  }
-
-  @override
-  // TODO(brianwilkerson) Add commas?
-  Iterable get childEntities => super._childEntities
-    ..add(enumKeyword)
-    ..add(_name)
-    ..add(leftBracket)
-    ..addAll(_constants)
-    ..add(rightBracket);
-
-  /**
-   * Return the enumeration constants being declared.
-   */
-  NodeList<EnumConstantDeclaration> get constants => _constants;
-
-  @override
-  ClassElement get element =>
-      _name != null ? (_name.staticElement as ClassElement) : null;
-
-  @override
-  Token get endToken => rightBracket;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => enumKeyword;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitEnumDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _constants.accept(visitor);
-  }
-}
-
-/**
- * Ephemeral identifiers are created as needed to mimic the presence of an empty
- * identifier.
- */
-class EphemeralIdentifier extends SimpleIdentifier {
-  EphemeralIdentifier(AstNode parent, int location)
-      : super(new StringToken(TokenType.IDENTIFIER, "", location)) {
-    parent._becomeParentOf(this);
-  }
-}
-
-/**
- * An export directive.
- *
- * > exportDirective ::=
- * >     [Annotation] 'export' [StringLiteral] [Combinator]* ';'
- */
-class ExportDirective extends NamespaceDirective {
-  /**
-   * Initialize a newly created export directive. Either or both of the
-   * [comment] and [metadata] can be `null` if the directive does not have the
-   * corresponding attribute. The list of [combinators] can be `null` if there
-   * are no combinators.
-   */
-  ExportDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      StringLiteral libraryUri,
-      List<Configuration> configurations,
-      List<Combinator> combinators,
-      Token semicolon)
-      : super(comment, metadata, keyword, libraryUri, configurations,
-            combinators, semicolon);
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(_uri)
-    ..addAll(combinators)
-    ..add(semicolon);
-
-  @override
-  ExportElement get element => super.element as ExportElement;
-
-  @override
-  LibraryElement get uriElement {
-    if (element != null) {
-      return element.exportedLibrary;
-    }
-    return null;
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitExportDirective(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    combinators.accept(visitor);
-  }
-}
-
-/**
- * A node that represents an expression.
- *
- * > expression ::=
- * >     [AssignmentExpression]
- * >   | [ConditionalExpression] cascadeSection*
- * >   | [ThrowExpression]
- */
-abstract class Expression extends AstNode {
-  /**
-   * An empty list of expressions.
-   */
-  static const List<Expression> EMPTY_LIST = const <Expression>[];
-
-  /**
-   * The static type of this expression, or `null` if the AST structure has not
-   * been resolved.
-   */
-  DartType staticType;
-
-  /**
-   * The propagated type of this expression, or `null` if type propagation has
-   * not been performed on the AST structure.
-   */
-  DartType propagatedType;
-
-  /**
-   * Return the best parameter element information available for this
-   * expression. If type propagation was able to find a better parameter element
-   * than static analysis, that type will be returned. Otherwise, the result of
-   * static analysis will be returned.
-   */
-  ParameterElement get bestParameterElement {
-    ParameterElement propagatedElement = propagatedParameterElement;
-    if (propagatedElement != null) {
-      return propagatedElement;
-    }
-    return staticParameterElement;
-  }
-
-  /**
-   * Return the best type information available for this expression. If type
-   * propagation was able to find a better type than static analysis, that type
-   * will be returned. Otherwise, the result of static analysis will be
-   * returned. If no type analysis has been performed, then the type 'dynamic'
-   * will be returned.
-   */
-  DartType get bestType {
-    if (propagatedType != null) {
-      return propagatedType;
-    } else if (staticType != null) {
-      return staticType;
-    }
-    return DynamicTypeImpl.instance;
-  }
-
-  /**
-   * Return `true` if this expression is syntactically valid for the LHS of an
-   * [AssignmentExpression].
-   */
-  bool get isAssignable => false;
-
-  /**
-   * Return the precedence of this expression. The precedence is a positive
-   * integer value that defines how the source code is parsed into an AST. For
-   * example `a * b + c` is parsed as `(a * b) + c` because the precedence of
-   * `*` is greater than the precedence of `+`.
-   *
-   * Clients should not assume that returned values will stay the same, they
-   * might change as result of specification change. Only relative order should
-   * be used.
-   */
-  int get precedence;
-
-  /**
-   * If this expression is an argument to an invocation, and the AST structure
-   * has been resolved, and the function being invoked is known based on
-   * propagated type information, and this expression corresponds to one of the
-   * parameters of the function being invoked, then return the parameter element
-   * representing the parameter to which the value of this expression will be
-   * bound. Otherwise, return `null`.
-   */
-  ParameterElement get propagatedParameterElement {
-    AstNode parent = this.parent;
-    if (parent is ArgumentList) {
-      return parent._getPropagatedParameterElementFor(this);
-    } else if (parent is IndexExpression) {
-      IndexExpression indexExpression = parent;
-      if (identical(indexExpression.index, this)) {
-        return indexExpression._propagatedParameterElementForIndex;
-      }
-    } else if (parent is BinaryExpression) {
-      BinaryExpression binaryExpression = parent;
-      if (identical(binaryExpression.rightOperand, this)) {
-        return binaryExpression._propagatedParameterElementForRightOperand;
-      }
-    } else if (parent is AssignmentExpression) {
-      AssignmentExpression assignmentExpression = parent;
-      if (identical(assignmentExpression.rightHandSide, this)) {
-        return assignmentExpression._propagatedParameterElementForRightHandSide;
-      }
-    } else if (parent is PrefixExpression) {
-      return parent._propagatedParameterElementForOperand;
-    } else if (parent is PostfixExpression) {
-      return parent._propagatedParameterElementForOperand;
-    }
-    return null;
-  }
-
-  /**
-   * If this expression is an argument to an invocation, and the AST structure
-   * has been resolved, and the function being invoked is known based on static
-   * type information, and this expression corresponds to one of the parameters
-   * of the function being invoked, then return the parameter element
-   * representing the parameter to which the value of this expression will be
-   * bound. Otherwise, return `null`.
-   */
-  ParameterElement get staticParameterElement {
-    AstNode parent = this.parent;
-    if (parent is ArgumentList) {
-      return parent._getStaticParameterElementFor(this);
-    } else if (parent is IndexExpression) {
-      IndexExpression indexExpression = parent;
-      if (identical(indexExpression.index, this)) {
-        return indexExpression._staticParameterElementForIndex;
-      }
-    } else if (parent is BinaryExpression) {
-      BinaryExpression binaryExpression = parent;
-      if (identical(binaryExpression.rightOperand, this)) {
-        return binaryExpression._staticParameterElementForRightOperand;
-      }
-    } else if (parent is AssignmentExpression) {
-      AssignmentExpression assignmentExpression = parent;
-      if (identical(assignmentExpression.rightHandSide, this)) {
-        return assignmentExpression._staticParameterElementForRightHandSide;
-      }
-    } else if (parent is PrefixExpression) {
-      return parent._staticParameterElementForOperand;
-    } else if (parent is PostfixExpression) {
-      return parent._staticParameterElementForOperand;
-    }
-    return null;
-  }
-}
-
-/**
- * A function body consisting of a single expression.
- *
- * > expressionFunctionBody ::=
- * >     'async'? '=>' [Expression] ';'
- */
-class ExpressionFunctionBody extends FunctionBody {
-  /**
-   * The token representing the 'async' keyword, or `null` if there is no such
-   * keyword.
-   */
-  Token keyword;
-
-  /**
-   * The token introducing the expression that represents the body of the
-   * function.
-   */
-  Token functionDefinition;
-
-  /**
-   * The expression representing the body of the function.
-   */
-  Expression _expression;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created function body consisting of a block of
-   * statements. The [keyword] can be `null` if the function body is not an
-   * async function body.
-   */
-  ExpressionFunctionBody(this.keyword, this.functionDefinition,
-      Expression expression, this.semicolon) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken {
-    if (keyword != null) {
-      return keyword;
-    }
-    return functionDefinition;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(keyword)
-    ..add(functionDefinition)
-    ..add(_expression)
-    ..add(semicolon);
-
-  @override
-  Token get endToken {
-    if (semicolon != null) {
-      return semicolon;
-    }
-    return _expression.endToken;
-  }
-
-  /**
-   * Return the expression representing the body of the function.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression representing the body of the function to the given
-   * [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  bool get isAsynchronous => keyword != null;
-
-  @override
-  bool get isSynchronous => keyword == null;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitExpressionFunctionBody(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * An expression used as a statement.
- *
- * > expressionStatement ::=
- * >     [Expression]? ';'
- */
-class ExpressionStatement extends Statement {
-  /**
-   * The expression that comprises the statement.
-   */
-  Expression _expression;
-
-  /**
-   * The semicolon terminating the statement, or `null` if the expression is a
-   * function expression and therefore isn't followed by a semicolon.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created expression statement.
-   */
-  ExpressionStatement(Expression expression, this.semicolon) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken => _expression.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_expression)..add(semicolon);
-
-  @override
-  Token get endToken {
-    if (semicolon != null) {
-      return semicolon;
-    }
-    return _expression.endToken;
-  }
-
-  /**
-   * Return the expression that comprises the statement.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression that comprises the statement to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  bool get isSynthetic => _expression.isSynthetic && semicolon.isSynthetic;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitExpressionStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * The "extends" clause in a class declaration.
- *
- * > extendsClause ::=
- * >     'extends' [TypeName]
- */
-class ExtendsClause extends AstNode {
-  /**
-   * The token representing the 'extends' keyword.
-   */
-  Token extendsKeyword;
-
-  /**
-   * The name of the class that is being extended.
-   */
-  TypeName _superclass;
-
-  /**
-   * Initialize a newly created extends clause.
-   */
-  ExtendsClause(this.extendsKeyword, TypeName superclass) {
-    _superclass = _becomeParentOf(superclass);
-  }
-
-  @override
-  Token get beginToken => extendsKeyword;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(extendsKeyword)..add(_superclass);
-
-  @override
-  Token get endToken => _superclass.endToken;
-
-  /**
-   * Return the name of the class that is being extended.
-   */
-  TypeName get superclass => _superclass;
-
-  /**
-   * Set the name of the class that is being extended to the given [name].
-   */
-  void set superclass(TypeName name) {
-    _superclass = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitExtendsClause(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_superclass, visitor);
-  }
-}
-
-/**
- * The declaration of one or more fields of the same type.
- *
- * > fieldDeclaration ::=
- * >     'static'? [VariableDeclarationList] ';'
- */
-class FieldDeclaration extends ClassMember {
-  /**
-   * The token representing the 'static' keyword, or `null` if the fields are
-   * not static.
-   */
-  Token staticKeyword;
-
-  /**
-   * The fields being declared.
-   */
-  VariableDeclarationList _fieldList;
-
-  /**
-   * The semicolon terminating the declaration.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created field declaration. Either or both of the
-   * [comment] and [metadata] can be `null` if the declaration does not have the
-   * corresponding attribute. The [staticKeyword] can be `null` if the field is
-   * not a static field.
-   */
-  FieldDeclaration(Comment comment, List<Annotation> metadata,
-      this.staticKeyword, VariableDeclarationList fieldList, this.semicolon)
-      : super(comment, metadata) {
-    _fieldList = _becomeParentOf(fieldList);
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(staticKeyword)..add(_fieldList)..add(semicolon);
-
-  @override
-  Element get element => null;
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the fields being declared.
-   */
-  VariableDeclarationList get fields => _fieldList;
-
-  /**
-   * Set the fields being declared to the given list of [fields].
-   */
-  void set fields(VariableDeclarationList fields) {
-    _fieldList = _becomeParentOf(fields);
-  }
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    if (staticKeyword != null) {
-      return staticKeyword;
-    }
-    return _fieldList.beginToken;
-  }
-
-  /**
-   * Return `true` if the fields are declared to be static.
-   */
-  bool get isStatic => staticKeyword != null;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFieldDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_fieldList, visitor);
-  }
-}
-
-/**
- * A field formal parameter.
- *
- * > fieldFormalParameter ::=
- * >     ('final' [TypeName] | 'const' [TypeName] | 'var' | [TypeName])?
- * >     'this' '.' [SimpleIdentifier] ([TypeParameterList]? [FormalParameterList])?
- */
-class FieldFormalParameter extends NormalFormalParameter {
-  /**
-   * The token representing either the 'final', 'const' or 'var' keyword, or
-   * `null` if no keyword was used.
-   */
-  Token keyword;
-
-  /**
-   * The name of the declared type of the parameter, or `null` if the parameter
-   * does not have a declared type.
-   */
-  TypeName _type;
-
-  /**
-   * The token representing the 'this' keyword.
-   */
-  Token thisKeyword;
-
-  /**
-   * The token representing the period.
-   */
-  Token period;
-
-  /**
-   * The type parameters associated with the method, or `null` if the method is
-   * not a generic method.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The parameters of the function-typed parameter, or `null` if this is not a
-   * function-typed field formal parameter.
-   */
-  FormalParameterList _parameters;
-
-  /**
-   * Initialize a newly created formal parameter. Either or both of the
-   * [comment] and [metadata] can be `null` if the parameter does not have the
-   * corresponding attribute. The [keyword] can be `null` if there is a type.
-   * The [type] must be `null` if the keyword is 'var'. The [thisKeyword] and
-   * [period] can be `null` if the keyword 'this' was not provided.  The
-   * [parameters] can be `null` if this is not a function-typed field formal
-   * parameter.
-   */
-  FieldFormalParameter(
-      Comment comment,
-      List<Annotation> metadata,
-      this.keyword,
-      TypeName type,
-      this.thisKeyword,
-      this.period,
-      SimpleIdentifier identifier,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters)
-      : super(comment, metadata, identifier) {
-    _type = _becomeParentOf(type);
-    _typeParameters = _becomeParentOf(typeParameters);
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  @override
-  Token get beginToken {
-    if (keyword != null) {
-      return keyword;
-    } else if (_type != null) {
-      return _type.beginToken;
-    }
-    return thisKeyword;
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(keyword)
-    ..add(_type)
-    ..add(thisKeyword)
-    ..add(period)
-    ..add(identifier)
-    ..add(_parameters);
-
-  @override
-  Token get endToken {
-    if (_parameters != null) {
-      return _parameters.endToken;
-    }
-    return identifier.endToken;
-  }
-
-  @override
-  bool get isConst =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
-
-  @override
-  bool get isFinal =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
-
-  /**
-   * Return the parameters of the function-typed parameter, or `null` if this is
-   * not a function-typed field formal parameter.
-   */
-  FormalParameterList get parameters => _parameters;
-
-  /**
-   * Set the parameters of the function-typed parameter to the given
-   * [parameters].
-   */
-  void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  /**
-   * Return the name of the declared type of the parameter, or `null` if the
-   * parameter does not have a declared type. Note that if this is a
-   * function-typed field formal parameter this is the return type of the
-   * function.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the name of the declared type of the parameter to the given [typeName].
-   */
-  void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
-  }
-
-  /**
-   * Return the type parameters associated with this method, or `null` if this
-   * method is not a generic method.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFieldFormalParameter(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(identifier, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-  }
-}
-
-/**
- * A for-each statement.
- *
- * > forEachStatement ::=
- * >     'await'? 'for' '(' [DeclaredIdentifier] 'in' [Expression] ')' [Block]
- * >   | 'await'? 'for' '(' [SimpleIdentifier] 'in' [Expression] ')' [Block]
- */
-class ForEachStatement extends Statement {
-  /**
-   * The token representing the 'await' keyword, or `null` if there is no
-   * 'await' keyword.
-   */
-  Token awaitKeyword;
-
-  /**
-   * The token representing the 'for' keyword.
-   */
-  Token forKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The declaration of the loop variable, or `null` if the loop variable is a
-   * simple identifier.
-   */
-  DeclaredIdentifier _loopVariable;
-
-  /**
-   * The loop variable, or `null` if the loop variable is declared in the 'for'.
-   */
-  SimpleIdentifier _identifier;
-
-  /**
-   * The token representing the 'in' keyword.
-   */
-  Token inKeyword;
-
-  /**
-   * The expression evaluated to produce the iterator.
-   */
-  Expression _iterable;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The body of the loop.
-   */
-  Statement _body;
-
-  /**
-   * Initialize a newly created for-each statement whose loop control variable
-   * is declared internally (in the for-loop part). The [awaitKeyword] can be
-   * `null` if this is not an asynchronous for loop.
-   */
-  ForEachStatement.withDeclaration(
-      this.awaitKeyword,
-      this.forKeyword,
-      this.leftParenthesis,
-      DeclaredIdentifier loopVariable,
-      this.inKeyword,
-      Expression iterator,
-      this.rightParenthesis,
-      Statement body) {
-    _loopVariable = _becomeParentOf(loopVariable);
-    _iterable = _becomeParentOf(iterator);
-    _body = _becomeParentOf(body);
-  }
-
-  /**
-   * Initialize a newly created for-each statement whose loop control variable
-   * is declared outside the for loop. The [awaitKeyword] can be `null` if this
-   * is not an asynchronous for loop.
-   */
-  ForEachStatement.withReference(
-      this.awaitKeyword,
-      this.forKeyword,
-      this.leftParenthesis,
-      SimpleIdentifier identifier,
-      this.inKeyword,
-      Expression iterator,
-      this.rightParenthesis,
-      Statement body) {
-    _identifier = _becomeParentOf(identifier);
-    _iterable = _becomeParentOf(iterator);
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  Token get beginToken => forKeyword;
-
-  /**
-   * Return the body of the loop.
-   */
-  Statement get body => _body;
-
-  /**
-   * Set the body of the loop to the given [statement].
-   */
-  void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(awaitKeyword)
-    ..add(forKeyword)
-    ..add(leftParenthesis)
-    ..add(_loopVariable)
-    ..add(_identifier)
-    ..add(inKeyword)
-    ..add(_iterable)
-    ..add(rightParenthesis)
-    ..add(_body);
-
-  @override
-  Token get endToken => _body.endToken;
-
-  /**
-   * Return the loop variable, or `null` if the loop variable is declared in the
-   * 'for'.
-   */
-  SimpleIdentifier get identifier => _identifier;
-
-  /**
-   * Set the loop variable to the given [identifier].
-   */
-  void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return the expression evaluated to produce the iterator.
-   */
-  Expression get iterable => _iterable;
-
-  /**
-   * Set the expression evaluated to produce the iterator to the given
-   * [expression].
-   */
-  void set iterable(Expression expression) {
-    _iterable = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the declaration of the loop variable, or `null` if the loop variable
-   * is a simple identifier.
-   */
-  DeclaredIdentifier get loopVariable => _loopVariable;
-
-  /**
-   * Set the declaration of the loop variable to the given [variable].
-   */
-  void set loopVariable(DeclaredIdentifier variable) {
-    _loopVariable = _becomeParentOf(variable);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitForEachStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_loopVariable, visitor);
-    _safelyVisitChild(_identifier, visitor);
-    _safelyVisitChild(_iterable, visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * A node representing a parameter to a function.
- *
- * > formalParameter ::=
- * >     [NormalFormalParameter]
- * >   | [DefaultFormalParameter]
- */
-abstract class FormalParameter extends AstNode {
-  /**
-   * Return the element representing this parameter, or `null` if this parameter
-   * has not been resolved.
-   */
-  ParameterElement get element {
-    SimpleIdentifier identifier = this.identifier;
-    if (identifier == null) {
-      return null;
-    }
-    return identifier.staticElement as ParameterElement;
-  }
-
-  /**
-   * Return the name of the parameter being declared.
-   */
-  SimpleIdentifier get identifier;
-
-  /**
-   * Return `true` if this parameter was declared with the 'const' modifier.
-   */
-  bool get isConst;
-
-  /**
-   * Return `true` if this parameter was declared with the 'final' modifier.
-   * Parameters that are declared with the 'const' modifier will return `false`
-   * even though they are implicitly final.
-   */
-  bool get isFinal;
-
-  /**
-   * Return the kind of this parameter.
-   */
-  ParameterKind get kind;
-
-  /**
-   * Return the annotations associated with this parameter.
-   */
-  NodeList<Annotation> get metadata;
-}
-
-/**
- * The formal parameter list of a method declaration, function declaration, or
- * function type alias.
- *
- * While the grammar requires all optional formal parameters to follow all of
- * the normal formal parameters and at most one grouping of optional formal
- * parameters, this class does not enforce those constraints. All parameters are
- * flattened into a single list, which can have any or all kinds of parameters
- * (normal, named, and positional) in any order.
- *
- * > formalParameterList ::=
- * >     '(' ')'
- * >   | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
- * >   | '(' optionalFormalParameters ')'
- * >
- * > normalFormalParameters ::=
- * >     [NormalFormalParameter] (',' [NormalFormalParameter])*
- * >
- * > optionalFormalParameters ::=
- * >     optionalPositionalFormalParameters
- * >   | namedFormalParameters
- * >
- * > optionalPositionalFormalParameters ::=
- * >     '[' [DefaultFormalParameter] (',' [DefaultFormalParameter])* ']'
- * >
- * > namedFormalParameters ::=
- * >     '{' [DefaultFormalParameter] (',' [DefaultFormalParameter])* '}'
- */
-class FormalParameterList extends AstNode {
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The parameters associated with the method.
-   */
-  NodeList<FormalParameter> _parameters;
-
-  /**
-   * The left square bracket ('[') or left curly brace ('{') introducing the
-   * optional parameters, or `null` if there are no optional parameters.
-   */
-  Token leftDelimiter;
-
-  /**
-   * The right square bracket (']') or right curly brace ('}') terminating the
-   * optional parameters, or `null` if there are no optional parameters.
-   */
-  Token rightDelimiter;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * Initialize a newly created parameter list. The list of [parameters] can be
-   * `null` if there are no parameters. The [leftDelimiter] and [rightDelimiter]
-   * can be `null` if there are no optional parameters.
-   */
-  FormalParameterList(this.leftParenthesis, List<FormalParameter> parameters,
-      this.leftDelimiter, this.rightDelimiter, this.rightParenthesis) {
-    _parameters = new NodeList<FormalParameter>(this, parameters);
-  }
-
-  @override
-  Token get beginToken => leftParenthesis;
-
-  @override
-  Iterable get childEntities {
-    // TODO(paulberry): include commas.
-    ChildEntities result = new ChildEntities()..add(leftParenthesis);
-    bool leftDelimiterNeeded = leftDelimiter != null;
-    for (FormalParameter parameter in _parameters) {
-      if (leftDelimiterNeeded && leftDelimiter.offset < parameter.offset) {
-        result.add(leftDelimiter);
-        leftDelimiterNeeded = false;
-      }
-      result.add(parameter);
-    }
-    return result..add(rightDelimiter)..add(rightParenthesis);
-  }
-
-  @override
-  Token get endToken => rightParenthesis;
-
-  /**
-   * Return a list containing the elements representing the parameters in this
-   * list. The list will contain `null`s if the parameters in this list have not
-   * been resolved.
-   */
-  List<ParameterElement> get parameterElements {
-    int count = _parameters.length;
-    List<ParameterElement> types = new List<ParameterElement>(count);
-    for (int i = 0; i < count; i++) {
-      types[i] = _parameters[i].element;
-    }
-    return types;
-  }
-
-  /**
-   * Return the parameters associated with the method.
-   */
-  NodeList<FormalParameter> get parameters => _parameters;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFormalParameterList(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _parameters.accept(visitor);
-  }
-}
-
-/**
- * A for statement.
- *
- * > forStatement ::=
- * >     'for' '(' forLoopParts ')' [Statement]
- * >
- * > forLoopParts ::=
- * >     forInitializerStatement ';' [Expression]? ';' [Expression]?
- * >
- * > forInitializerStatement ::=
- * >     [DefaultFormalParameter]
- * >   | [Expression]?
- */
-class ForStatement extends Statement {
-  /**
-   * The token representing the 'for' keyword.
-   */
-  Token forKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The declaration of the loop variables, or `null` if there are no variables.
-   * Note that a for statement cannot have both a variable list and an
-   * initialization expression, but can validly have neither.
-   */
-  VariableDeclarationList _variableList;
-
-  /**
-   * The initialization expression, or `null` if there is no initialization
-   * expression. Note that a for statement cannot have both a variable list and
-   * an initialization expression, but can validly have neither.
-   */
-  Expression _initialization;
-
-  /**
-   * The semicolon separating the initializer and the condition.
-   */
-  Token leftSeparator;
-
-  /**
-   * The condition used to determine when to terminate the loop, or `null` if
-   * there is no condition.
-   */
-  Expression _condition;
-
-  /**
-   * The semicolon separating the condition and the updater.
-   */
-  Token rightSeparator;
-
-  /**
-   * The list of expressions run after each execution of the loop body.
-   */
-  NodeList<Expression> _updaters;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The body of the loop.
-   */
-  Statement _body;
-
-  /**
-   * Initialize a newly created for statement. Either the [variableList] or the
-   * [initialization] must be `null`. Either the [condition] and the list of
-   * [updaters] can be `null` if the loop does not have the corresponding
-   * attribute.
-   */
-  ForStatement(
-      this.forKeyword,
-      this.leftParenthesis,
-      VariableDeclarationList variableList,
-      Expression initialization,
-      this.leftSeparator,
-      Expression condition,
-      this.rightSeparator,
-      List<Expression> updaters,
-      this.rightParenthesis,
-      Statement body) {
-    _variableList = _becomeParentOf(variableList);
-    _initialization = _becomeParentOf(initialization);
-    _condition = _becomeParentOf(condition);
-    _updaters = new NodeList<Expression>(this, updaters);
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  Token get beginToken => forKeyword;
-
-  /**
-   * Return the body of the loop.
-   */
-  Statement get body => _body;
-
-  /**
-   * Set the body of the loop to the given [statement].
-   */
-  void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(forKeyword)
-    ..add(leftParenthesis)
-    ..add(_variableList)
-    ..add(_initialization)
-    ..add(leftSeparator)
-    ..add(_condition)
-    ..add(rightSeparator)
-    ..addAll(_updaters)
-    ..add(rightParenthesis)
-    ..add(_body);
-
-  /**
-   * Return the condition used to determine when to terminate the loop, or
-   * `null` if there is no condition.
-   */
-  Expression get condition => _condition;
-
-  /**
-   * Set the condition used to determine when to terminate the loop to the given
-   * [expression].
-   */
-  void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get endToken => _body.endToken;
-
-  /**
-   * Return the initialization expression, or `null` if there is no
-   * initialization expression.
-   */
-  Expression get initialization => _initialization;
-
-  /**
-   * Set the initialization expression to the given [expression].
-   */
-  void set initialization(Expression initialization) {
-    _initialization = _becomeParentOf(initialization);
-  }
-
-  /**
-   * Return the list of expressions run after each execution of the loop body.
-   */
-  NodeList<Expression> get updaters => _updaters;
-
-  /**
-   * Return the declaration of the loop variables, or `null` if there are no
-   * variables.
-   */
-  VariableDeclarationList get variables => _variableList;
-
-  /**
-   * Set the declaration of the loop variables to the given [variableList].
-   */
-  void set variables(VariableDeclarationList variableList) {
-    _variableList = _becomeParentOf(variableList);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitForStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_variableList, visitor);
-    _safelyVisitChild(_initialization, visitor);
-    _safelyVisitChild(_condition, visitor);
-    _updaters.accept(visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * A node representing the body of a function or method.
- *
- * > functionBody ::=
- * >     [BlockFunctionBody]
- * >   | [EmptyFunctionBody]
- * >   | [ExpressionFunctionBody]
- */
-abstract class FunctionBody extends AstNode {
-  /**
-   * Return `true` if this function body is asynchronous.
-   */
-  bool get isAsynchronous => false;
-
-  /**
-   * Return `true` if this function body is a generator.
-   */
-  bool get isGenerator => false;
-
-  /**
-   * Return `true` if this function body is synchronous.
-   */
-  bool get isSynchronous => true;
-
-  /**
-   * Return the token representing the 'async' or 'sync' keyword, or `null` if
-   * there is no such keyword.
-   */
-  Token get keyword => null;
-
-  /**
-   * Return the star following the 'async' or 'sync' keyword, or `null` if there
-   * is no star.
-   */
-  Token get star => null;
-}
-
-/**
- * A top-level declaration.
- *
- * > functionDeclaration ::=
- * >     'external' functionSignature
- * >   | functionSignature [FunctionBody]
- * >
- * > functionSignature ::=
- * >     [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
- */
-class FunctionDeclaration extends NamedCompilationUnitMember {
-  /**
-   * The token representing the 'external' keyword, or `null` if this is not an
-   * external function.
-   */
-  Token externalKeyword;
-
-  /**
-   * The return type of the function, or `null` if no return type was declared.
-   */
-  TypeName _returnType;
-
-  /**
-   * The token representing the 'get' or 'set' keyword, or `null` if this is a
-   * function declaration rather than a property declaration.
-   */
-  Token propertyKeyword;
-
-  /**
-   * The function expression being wrapped.
-   */
-  FunctionExpression _functionExpression;
-
-  /**
-   * Initialize a newly created function declaration. Either or both of the
-   * [comment] and [metadata] can be `null` if the function does not have the
-   * corresponding attribute. The [externalKeyword] can be `null` if the
-   * function is not an external function. The [returnType] can be `null` if no
-   * return type was specified. The [propertyKeyword] can be `null` if the
-   * function is neither a getter or a setter.
-   */
-  FunctionDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      this.externalKeyword,
-      TypeName returnType,
-      this.propertyKeyword,
-      SimpleIdentifier name,
-      FunctionExpression functionExpression)
-      : super(comment, metadata, name) {
-    _returnType = _becomeParentOf(returnType);
-    _functionExpression = _becomeParentOf(functionExpression);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(externalKeyword)
-    ..add(_returnType)
-    ..add(propertyKeyword)
-    ..add(_name)
-    ..add(_functionExpression);
-
-  @override
-  ExecutableElement get element =>
-      _name != null ? (_name.staticElement as ExecutableElement) : null;
-
-  @override
-  Token get endToken => _functionExpression.endToken;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    if (externalKeyword != null) {
-      return externalKeyword;
-    } else if (_returnType != null) {
-      return _returnType.beginToken;
-    } else if (propertyKeyword != null) {
-      return propertyKeyword;
-    } else if (_name != null) {
-      return _name.beginToken;
-    }
-    return _functionExpression.beginToken;
-  }
-
-  /**
-   * Return the function expression being wrapped.
-   */
-  FunctionExpression get functionExpression => _functionExpression;
-
-  /**
-   * Set the function expression being wrapped to the given
-   * [functionExpression].
-   */
-  void set functionExpression(FunctionExpression functionExpression) {
-    _functionExpression = _becomeParentOf(functionExpression);
-  }
-
-  /**
-   * Return `true` if this function declares a getter.
-   */
-  bool get isGetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.GET;
-
-  /**
-   * Return `true` if this function declares a setter.
-   */
-  bool get isSetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.SET;
-
-  /**
-   * Return the return type of the function, or `null` if no return type was
-   * declared.
-   */
-  TypeName get returnType => _returnType;
-
-  /**
-   * Set the return type of the function to the given [returnType].
-   */
-  void set returnType(TypeName returnType) {
-    _returnType = _becomeParentOf(returnType);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFunctionDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_functionExpression, visitor);
-  }
-}
-
-/**
- * A [FunctionDeclaration] used as a statement.
- */
-class FunctionDeclarationStatement extends Statement {
-  /**
-   * The function declaration being wrapped.
-   */
-  FunctionDeclaration _functionDeclaration;
-
-  /**
-   * Initialize a newly created function declaration statement.
-   */
-  FunctionDeclarationStatement(FunctionDeclaration functionDeclaration) {
-    _functionDeclaration = _becomeParentOf(functionDeclaration);
-  }
-
-  @override
-  Token get beginToken => _functionDeclaration.beginToken;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(_functionDeclaration);
-
-  @override
-  Token get endToken => _functionDeclaration.endToken;
-
-  /**
-   * Return the function declaration being wrapped.
-   */
-  FunctionDeclaration get functionDeclaration => _functionDeclaration;
-
-  /**
-   * Set the function declaration being wrapped to the given
-   * [functionDeclaration].
-   */
-  void set functionDeclaration(FunctionDeclaration functionDeclaration) {
-    _functionDeclaration = _becomeParentOf(functionDeclaration);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFunctionDeclarationStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_functionDeclaration, visitor);
-  }
-}
-
-/**
- * A function expression.
- *
- * > functionExpression ::=
- * >     [TypeParameterList]? [FormalParameterList] [FunctionBody]
- */
-class FunctionExpression extends Expression {
-  /**
-   * The type parameters associated with the method, or `null` if the method is
-   * not a generic method.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The parameters associated with the function.
-   */
-  FormalParameterList _parameters;
-
-  /**
-   * The body of the function, or `null` if this is an external function.
-   */
-  FunctionBody _body;
-
-  /**
-   * The element associated with the function, or `null` if the AST structure
-   * has not been resolved.
-   */
-  ExecutableElement element;
-
-  /**
-   * Initialize a newly created function declaration.
-   */
-  FunctionExpression(TypeParameterList typeParameters,
-      FormalParameterList parameters, FunctionBody body) {
-    _typeParameters = _becomeParentOf(typeParameters);
-    _parameters = _becomeParentOf(parameters);
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  Token get beginToken {
-    if (_typeParameters != null) {
-      return _typeParameters.beginToken;
-    } else if (_parameters != null) {
-      return _parameters.beginToken;
-    } else if (_body != null) {
-      return _body.beginToken;
-    }
-    // This should never be reached because external functions must be named,
-    // hence either the body or the name should be non-null.
-    throw new IllegalStateException("Non-external functions must have a body");
-  }
-
-  /**
-   * Return the body of the function, or `null` if this is an external function.
-   */
-  FunctionBody get body => _body;
-
-  /**
-   * Set the body of the function to the given [functionBody].
-   */
-  void set body(FunctionBody functionBody) {
-    _body = _becomeParentOf(functionBody);
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_parameters)..add(_body);
-
-  @override
-  Token get endToken {
-    if (_body != null) {
-      return _body.endToken;
-    } else if (_parameters != null) {
-      return _parameters.endToken;
-    }
-    // This should never be reached because external functions must be named,
-    // hence either the body or the name should be non-null.
-    throw new IllegalStateException("Non-external functions must have a body");
-  }
-
-  /**
-   * Return the parameters associated with the function.
-   */
-  FormalParameterList get parameters => _parameters;
-
-  /**
-   * Set the parameters associated with the function to the given list of
-   * [parameters].
-   */
-  void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  @override
-  int get precedence => 16;
-
-  /**
-   * Return the type parameters associated with this method, or `null` if this
-   * method is not a generic method.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFunctionExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * The invocation of a function resulting from evaluating an expression.
- * Invocations of methods and other forms of functions are represented by
- * [MethodInvocation] nodes. Invocations of getters and setters are represented
- * by either [PrefixedIdentifier] or [PropertyAccess] nodes.
- *
- * > functionExpressionInvocation ::=
- * >     [Expression] [TypeArgumentList]? [ArgumentList]
- */
-class FunctionExpressionInvocation extends Expression {
-  /**
-   * The expression producing the function being invoked.
-   */
-  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.
-   */
-  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.
-   */
-  ExecutableElement propagatedElement;
-
-  /**
-   * Like [staticInvokeType], but reflects propagated type information.
-   */
-  DartType propagatedInvokeType;
-
-  /**
-   * Initialize a newly created function expression invocation.
-   */
-  FunctionExpressionInvocation(Expression function,
-      TypeArgumentList typeArguments, ArgumentList argumentList) {
-    _function = _becomeParentOf(function);
-    _typeArguments = _becomeParentOf(typeArguments);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  /**
-   * Return the list of arguments to the method.
-   */
-  ArgumentList get argumentList => _argumentList;
-
-  /**
-   * Set the list of arguments to the method to the given [argumentList].
-   */
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  Token get beginToken => _function.beginToken;
-
-  /**
-   * Return the best element available for the function being invoked. If
-   * resolution was able to find a better element based on type propagation,
-   * that element will be returned. Otherwise, the element found using the
-   * result of static analysis will be returned. If resolution has not been
-   * performed, then `null` will be returned.
-   */
-  ExecutableElement get bestElement {
-    ExecutableElement element = propagatedElement;
-    if (element == null) {
-      element = staticElement;
-    }
-    return element;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_function)..add(_argumentList);
-
-  @override
-  Token get endToken => _argumentList.endToken;
-
-  /**
-   * Return the expression producing the function being invoked.
-   */
-  Expression get function => _function;
-
-  /**
-   * Set the expression producing the function being invoked to the given
-   * [expression].
-   */
-  void set function(Expression expression) {
-    _function = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 15;
-
-  /**
-   * Return the type arguments to be applied to the method being invoked, or
-   * `null` if no type arguments were provided.
-   */
-  TypeArgumentList get typeArguments => _typeArguments;
-
-  /**
-   * Set the type arguments to be applied to the method being invoked to the
-   * given [typeArguments].
-   */
-  void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFunctionExpressionInvocation(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_function, visitor);
-    _safelyVisitChild(_typeArguments, visitor);
-    _safelyVisitChild(_argumentList, visitor);
-  }
-}
-
-/**
- * A function type alias.
- *
- * > functionTypeAlias ::=
- * >     functionPrefix [TypeParameterList]? [FormalParameterList] ';'
- * >
- * > functionPrefix ::=
- * >     [TypeName]? [SimpleIdentifier]
- */
-class FunctionTypeAlias extends TypeAlias {
-  /**
-   * The name of the return type of the function type being defined, or `null`
-   * if no return type was given.
-   */
-  TypeName _returnType;
-
-  /**
-   * The type parameters for the function type, or `null` if the function type
-   * does not have any type parameters.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The parameters associated with the function type.
-   */
-  FormalParameterList _parameters;
-
-  /**
-   * Initialize a newly created function type alias. Either or both of the
-   * [comment] and [metadata] can be `null` if the function does not have the
-   * corresponding attribute. The [returnType] can be `null` if no return type
-   * was specified. The [typeParameters] can be `null` if the function has no
-   * type parameters.
-   */
-  FunctionTypeAlias(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      TypeName returnType,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
-      Token semicolon)
-      : super(comment, metadata, keyword, name, semicolon) {
-    _returnType = _becomeParentOf(returnType);
-    _typeParameters = _becomeParentOf(typeParameters);
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(typedefKeyword)
-    ..add(_returnType)
-    ..add(_name)
-    ..add(_typeParameters)
-    ..add(_parameters)
-    ..add(semicolon);
-
-  @override
-  FunctionTypeAliasElement get element =>
-      _name != null ? (_name.staticElement as FunctionTypeAliasElement) : null;
-
-  /**
-   * Return the parameters associated with the function type.
-   */
-  FormalParameterList get parameters => _parameters;
-
-  /**
-   * Set the parameters associated with the function type to the given list of
-   * [parameters].
-   */
-  void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  /**
-   * Return the name of the return type of the function type being defined, or
-   * `null` if no return type was given.
-   */
-  TypeName get returnType => _returnType;
-
-  /**
-   * Set the name of the return type of the function type being defined to the
-   * given [typeName].
-   */
-  void set returnType(TypeName typeName) {
-    _returnType = _becomeParentOf(typeName);
-  }
-
-  /**
-   * Return the type parameters for the function type, or `null` if the function
-   * type does not have any type parameters.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters for the function type to the given list of
-   * [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFunctionTypeAlias(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-  }
-}
-
-/**
- * A function-typed formal parameter.
- *
- * > functionSignature ::=
- * >     [TypeName]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
- */
-class FunctionTypedFormalParameter extends NormalFormalParameter {
-  /**
-   * The return type of the function, or `null` if the function does not have a
-   * return type.
-   */
-  TypeName _returnType;
-
-  /**
-   * The type parameters associated with the function, or `null` if the function
-   * is not a generic function.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The parameters of the function-typed parameter.
-   */
-  FormalParameterList _parameters;
-
-  /**
-   * Initialize a newly created formal parameter. Either or both of the
-   * [comment] and [metadata] can be `null` if the parameter does not have the
-   * corresponding attribute. The [returnType] can be `null` if no return type
-   * was specified.
-   */
-  FunctionTypedFormalParameter(
-      Comment comment,
-      List<Annotation> metadata,
-      TypeName returnType,
-      SimpleIdentifier identifier,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters)
-      : super(comment, metadata, identifier) {
-    _returnType = _becomeParentOf(returnType);
-    _typeParameters = _becomeParentOf(typeParameters);
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  @override
-  Token get beginToken {
-    if (_returnType != null) {
-      return _returnType.beginToken;
-    }
-    return identifier.beginToken;
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(_returnType)..add(identifier)..add(parameters);
-
-  @override
-  Token get endToken => _parameters.endToken;
-
-  @override
-  bool get isConst => false;
-
-  @override
-  bool get isFinal => false;
-
-  /**
-   * Return the parameters of the function-typed parameter.
-   */
-  FormalParameterList get parameters => _parameters;
-
-  /**
-   * Set the parameters of the function-typed parameter to the given
-   * [parameters].
-   */
-  void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  /**
-   * Return the return type of the function, or `null` if the function does not
-   * have a return type.
-   */
-  TypeName get returnType => _returnType;
-
-  /**
-   * Set the return type of the function to the given [type].
-   */
-  void set returnType(TypeName type) {
-    _returnType = _becomeParentOf(type);
-  }
-
-  /**
-   * Return the type parameters associated with this function, or `null` if
-   * this function is not a generic function.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitFunctionTypedFormalParameter(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(identifier, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-  }
-}
-
-/**
- * A combinator that restricts the names being imported to those that are not in
- * a given list.
- *
- * > hideCombinator ::=
- * >     'hide' [SimpleIdentifier] (',' [SimpleIdentifier])*
- */
-class HideCombinator extends Combinator {
-  /**
-   * The list of names from the library that are hidden by this combinator.
-   */
-  NodeList<SimpleIdentifier> _hiddenNames;
-
-  /**
-   * Initialize a newly created import show combinator.
-   */
-  HideCombinator(Token keyword, List<SimpleIdentifier> hiddenNames)
-      : super(keyword) {
-    _hiddenNames = new NodeList<SimpleIdentifier>(this, hiddenNames);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(keyword)
-    ..addAll(_hiddenNames);
-
-  @override
-  Token get endToken => _hiddenNames.endToken;
-
-  /**
-   * Return the list of names from the library that are hidden by this
-   * combinator.
-   */
-  NodeList<SimpleIdentifier> get hiddenNames => _hiddenNames;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitHideCombinator(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _hiddenNames.accept(visitor);
-  }
-}
-
-/**
- * A node that represents an identifier.
- *
- * > identifier ::=
- * >     [SimpleIdentifier]
- * >   | [PrefixedIdentifier]
- */
-abstract class Identifier extends Expression {
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   */
-  Element get bestElement;
-
-  @override
-  bool get isAssignable => true;
-
-  /**
-   * Return the lexical representation of the identifier.
-   */
-  String get name;
-
-  /**
-   * Return the element associated with this identifier based on propagated type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this identifier could not be resolved. One example of the latter case is an
-   * identifier that is not defined within the scope in which it appears.
-   */
-  Element get propagatedElement;
-
-  /**
-   * Return the element associated with this identifier based on static type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this identifier could not be resolved. One example of the latter case is an
-   * identifier that is not defined within the scope in which it appears
-   */
-  Element get staticElement;
-
-  /**
-   * Return `true` if the given [name] is visible only within the library in
-   * which it is declared.
-   */
-  static bool isPrivateName(String name) =>
-      StringUtilities.startsWithChar(name, 0x5F);
-}
-
-/**
- * An if statement.
- *
- * > ifStatement ::=
- * >     'if' '(' [Expression] ')' [Statement] ('else' [Statement])?
- */
-class IfStatement extends Statement {
-  /**
-   * The token representing the 'if' keyword.
-   */
-  Token ifKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The condition used to determine which of the statements is executed next.
-   */
-  Expression _condition;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The statement that is executed if the condition evaluates to `true`.
-   */
-  Statement _thenStatement;
-
-  /**
-   * The token representing the 'else' keyword, or `null` if there is no else
-   * statement.
-   */
-  Token elseKeyword;
-
-  /**
-   * The statement that is executed if the condition evaluates to `false`, or
-   * `null` if there is no else statement.
-   */
-  Statement _elseStatement;
-
-  /**
-   * Initialize a newly created if statement. The [elseKeyword] and
-   * [elseStatement] can be `null` if there is no else clause.
-   */
-  IfStatement(
-      this.ifKeyword,
-      this.leftParenthesis,
-      Expression condition,
-      this.rightParenthesis,
-      Statement thenStatement,
-      this.elseKeyword,
-      Statement elseStatement) {
-    _condition = _becomeParentOf(condition);
-    _thenStatement = _becomeParentOf(thenStatement);
-    _elseStatement = _becomeParentOf(elseStatement);
-  }
-
-  @override
-  Token get beginToken => ifKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(ifKeyword)
-    ..add(leftParenthesis)
-    ..add(_condition)
-    ..add(rightParenthesis)
-    ..add(_thenStatement)
-    ..add(elseKeyword)
-    ..add(_elseStatement);
-
-  /**
-   * Return the condition used to determine which of the statements is executed
-   * next.
-   */
-  Expression get condition => _condition;
-
-  /**
-   * Set the condition used to determine which of the statements is executed
-   * next to the given [expression].
-   */
-  void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the statement that is executed if the condition evaluates to
-   * `false`, or `null` if there is no else statement.
-   */
-  Statement get elseStatement => _elseStatement;
-
-  /**
-   * Set the statement that is executed if the condition evaluates to `false`
-   * to the given [statement].
-   */
-  void set elseStatement(Statement statement) {
-    _elseStatement = _becomeParentOf(statement);
-  }
-
-  @override
-  Token get endToken {
-    if (_elseStatement != null) {
-      return _elseStatement.endToken;
-    }
-    return _thenStatement.endToken;
-  }
-
-  /**
-   * Return the statement that is executed if the condition evaluates to `true`.
-   */
-  Statement get thenStatement => _thenStatement;
-
-  /**
-   * Set the statement that is executed if the condition evaluates to `true` to
-   * the given [statement].
-   */
-  void set thenStatement(Statement statement) {
-    _thenStatement = _becomeParentOf(statement);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitIfStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(_thenStatement, visitor);
-    _safelyVisitChild(_elseStatement, visitor);
-  }
-}
-
-/**
- * The "implements" clause in an class declaration.
- *
- * > implementsClause ::=
- * >     'implements' [TypeName] (',' [TypeName])*
- */
-class ImplementsClause extends AstNode {
-  /**
-   * The token representing the 'implements' keyword.
-   */
-  Token implementsKeyword;
-
-  /**
-   * The interfaces that are being implemented.
-   */
-  NodeList<TypeName> _interfaces;
-
-  /**
-   * Initialize a newly created implements clause.
-   */
-  ImplementsClause(this.implementsKeyword, List<TypeName> interfaces) {
-    _interfaces = new NodeList<TypeName>(this, interfaces);
-  }
-
-  @override
-  Token get beginToken => implementsKeyword;
-
-  @override
-  // TODO(paulberry): add commas.
-  Iterable get childEntities => new ChildEntities()
-    ..add(implementsKeyword)
-    ..addAll(interfaces);
-
-  @override
-  Token get endToken => _interfaces.endToken;
-
-  /**
-   * Return the list of the interfaces that are being implemented.
-   */
-  NodeList<TypeName> get interfaces => _interfaces;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitImplementsClause(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _interfaces.accept(visitor);
-  }
-}
-
-/**
- * An import directive.
- *
- * > importDirective ::=
- * >     [Annotation] 'import' [StringLiteral] ('as' identifier)? [Combinator]* ';'
- * >   | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier [Combinator]* ';'
- */
-class ImportDirective extends NamespaceDirective {
-  static Comparator<ImportDirective> COMPARATOR =
-      (ImportDirective import1, ImportDirective import2) {
-    //
-    // uri
-    //
-    StringLiteral uri1 = import1.uri;
-    StringLiteral uri2 = import2.uri;
-    String uriStr1 = uri1.stringValue;
-    String uriStr2 = uri2.stringValue;
-    if (uriStr1 != null || uriStr2 != null) {
-      if (uriStr1 == null) {
-        return -1;
-      } else if (uriStr2 == null) {
-        return 1;
-      } else {
-        int compare = uriStr1.compareTo(uriStr2);
-        if (compare != 0) {
-          return compare;
-        }
-      }
-    }
-    //
-    // as
-    //
-    SimpleIdentifier prefix1 = import1.prefix;
-    SimpleIdentifier prefix2 = import2.prefix;
-    String prefixStr1 = prefix1 != null ? prefix1.name : null;
-    String prefixStr2 = prefix2 != null ? prefix2.name : null;
-    if (prefixStr1 != null || prefixStr2 != null) {
-      if (prefixStr1 == null) {
-        return -1;
-      } else if (prefixStr2 == null) {
-        return 1;
-      } else {
-        int compare = prefixStr1.compareTo(prefixStr2);
-        if (compare != 0) {
-          return compare;
-        }
-      }
-    }
-    //
-    // hides and shows
-    //
-    NodeList<Combinator> combinators1 = import1.combinators;
-    List<String> allHides1 = new List<String>();
-    List<String> allShows1 = new List<String>();
-    for (Combinator combinator in combinators1) {
-      if (combinator is HideCombinator) {
-        NodeList<SimpleIdentifier> hides = combinator.hiddenNames;
-        for (SimpleIdentifier simpleIdentifier in hides) {
-          allHides1.add(simpleIdentifier.name);
-        }
-      } else {
-        NodeList<SimpleIdentifier> shows =
-            (combinator as ShowCombinator).shownNames;
-        for (SimpleIdentifier simpleIdentifier in shows) {
-          allShows1.add(simpleIdentifier.name);
-        }
-      }
-    }
-    NodeList<Combinator> combinators2 = import2.combinators;
-    List<String> allHides2 = new List<String>();
-    List<String> allShows2 = new List<String>();
-    for (Combinator combinator in combinators2) {
-      if (combinator is HideCombinator) {
-        NodeList<SimpleIdentifier> hides = combinator.hiddenNames;
-        for (SimpleIdentifier simpleIdentifier in hides) {
-          allHides2.add(simpleIdentifier.name);
-        }
-      } else {
-        NodeList<SimpleIdentifier> shows =
-            (combinator as ShowCombinator).shownNames;
-        for (SimpleIdentifier simpleIdentifier in shows) {
-          allShows2.add(simpleIdentifier.name);
-        }
-      }
-    }
-    // test lengths of combinator lists first
-    if (allHides1.length != allHides2.length) {
-      return allHides1.length - allHides2.length;
-    }
-    if (allShows1.length != allShows2.length) {
-      return allShows1.length - allShows2.length;
-    }
-    // next ensure that the lists are equivalent
-    if (!javaCollectionContainsAll(allHides1, allHides2)) {
-      return -1;
-    }
-    if (!javaCollectionContainsAll(allShows1, allShows2)) {
-      return -1;
-    }
-    return 0;
-  };
-
-  /**
-   * The token representing the 'deferred' keyword, or `null` if the imported is
-   * not deferred.
-   */
-  Token deferredKeyword;
-
-  /**
-   * The token representing the 'as' keyword, or `null` if the imported names are
-   * not prefixed.
-   */
-  Token asKeyword;
-
-  /**
-   * The prefix to be used with the imported names, or `null` if the imported
-   * names are not prefixed.
-   */
-  SimpleIdentifier _prefix;
-
-  /**
-   * Initialize a newly created import directive. Either or both of the
-   * [comment] and [metadata] can be `null` if the function does not have the
-   * corresponding attribute. The [deferredKeyword] can be `null` if the import
-   * is not deferred. The [asKeyword] and [prefix] can be `null` if the import
-   * does not specify a prefix. The list of [combinators] can be `null` if there
-   * are no combinators.
-   */
-  ImportDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      StringLiteral libraryUri,
-      List<Configuration> configurations,
-      this.deferredKeyword,
-      this.asKeyword,
-      SimpleIdentifier prefix,
-      List<Combinator> combinators,
-      Token semicolon)
-      : super(comment, metadata, keyword, libraryUri, configurations,
-            combinators, semicolon) {
-    _prefix = _becomeParentOf(prefix);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(_uri)
-    ..add(deferredKeyword)
-    ..add(asKeyword)
-    ..add(_prefix)
-    ..addAll(combinators)
-    ..add(semicolon);
-
-  @override
-  ImportElement get element => super.element as ImportElement;
-
-  /**
-   * Return the prefix to be used with the imported names, or `null` if the
-   * imported names are not prefixed.
-   */
-  SimpleIdentifier get prefix => _prefix;
-
-  /**
-   * Set the prefix to be used with the imported names to the given [identifier].
-   */
-  void set prefix(SimpleIdentifier identifier) {
-    _prefix = _becomeParentOf(identifier);
-  }
-
-  @override
-  LibraryElement get uriElement {
-    ImportElement element = this.element;
-    if (element == null) {
-      return null;
-    }
-    return element.importedLibrary;
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitImportDirective(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_prefix, visitor);
-    combinators.accept(visitor);
-  }
-}
-
-/**
- * An index expression.
- *
- * > indexExpression ::=
- * >     [Expression] '[' [Expression] ']'
- */
-class IndexExpression extends Expression {
-  /**
-   * The expression used to compute the object being indexed, or `null` if this
-   * index expression is part of a cascade expression.
-   */
-  Expression _target;
-
-  /**
-   * The period ("..") before a cascaded index expression, or `null` if this
-   * index expression is not part of a cascade expression.
-   */
-  Token period;
-
-  /**
-   * The left square bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The expression used to compute the index.
-   */
-  Expression _index;
-
-  /**
-   * The right square bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * The element associated with the operator based on the static type of the
-   * target, or `null` if the AST structure has not been resolved or if the
-   * operator could not be resolved.
-   */
-  MethodElement staticElement;
-
-  /**
-   * The element associated with the operator based on the propagated type of
-   * the target, or `null` if the AST structure has not been resolved or if the
-   * operator could not be resolved.
-   */
-  MethodElement propagatedElement;
-
-  /**
-   * If this expression is both in a getter and setter context, the
-   * [AuxiliaryElements] will be set to hold onto the static and propagated
-   * information. The auxiliary element will hold onto the elements from the
-   * getter context.
-   */
-  AuxiliaryElements auxiliaryElements = null;
-
-  /**
-   * Initialize a newly created index expression.
-   */
-  IndexExpression.forCascade(
-      this.period, this.leftBracket, Expression index, this.rightBracket) {
-    _index = _becomeParentOf(index);
-  }
-
-  /**
-   * Initialize a newly created index expression.
-   */
-  IndexExpression.forTarget(Expression target, this.leftBracket,
-      Expression index, this.rightBracket) {
-    _target = _becomeParentOf(target);
-    _index = _becomeParentOf(index);
-  }
-
-  @override
-  Token get beginToken {
-    if (_target != null) {
-      return _target.beginToken;
-    }
-    return period;
-  }
-
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   */
-  MethodElement get bestElement {
-    MethodElement element = propagatedElement;
-    if (element == null) {
-      element = staticElement;
-    }
-    return element;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(_target)
-    ..add(period)
-    ..add(leftBracket)
-    ..add(_index)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken => rightBracket;
-
-  /**
-   * Return the expression used to compute the index.
-   */
-  Expression get index => _index;
-
-  /**
-   * Set the expression used to compute the index to the given [expression].
-   */
-  void set index(Expression expression) {
-    _index = _becomeParentOf(expression);
-  }
-
-  @override
-  bool get isAssignable => true;
-
-  /**
-   * Return `true` if this expression is cascaded. If it is, then the target of
-   * this expression is not stored locally but is stored in the nearest ancestor
-   * that is a [CascadeExpression].
-   */
-  bool get isCascaded => period != null;
-
-  @override
-  int get precedence => 15;
-
-  /**
-   * Return the expression used to compute the object being indexed. If this
-   * index expression is not part of a cascade expression, then this is the same
-   * as [target]. If this index expression is part of a cascade expression, then
-   * the target expression stored with the cascade expression is returned.
-   */
-  Expression get realTarget {
-    if (isCascaded) {
-      AstNode ancestor = parent;
-      while (ancestor is! CascadeExpression) {
-        if (ancestor == null) {
-          return _target;
-        }
-        ancestor = ancestor.parent;
-      }
-      return (ancestor as CascadeExpression).target;
-    }
-    return _target;
-  }
-
-  /**
-   * Return the expression used to compute the object being indexed, or `null`
-   * if this index expression is part of a cascade expression.
-   *
-   * Use [realTarget] to get the target independent of whether this is part of a
-   * cascade expression.
-   */
-  Expression get target => _target;
-
-  /**
-   * Set the expression used to compute the object being indexed to the given
-   * [expression].
-   */
-  void set target(Expression expression) {
-    _target = _becomeParentOf(expression);
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on propagated type information, then return the parameter
-   * element representing the parameter to which the value of the index
-   * expression will be bound. Otherwise, return `null`.
-   */
-  ParameterElement get _propagatedParameterElementForIndex {
-    if (propagatedElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = propagatedElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on static type information, then return the parameter element
-   * representing the parameter to which the value of the index expression will
-   * be bound. Otherwise, return `null`.
-   */
-  ParameterElement get _staticParameterElementForIndex {
-    if (staticElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = staticElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitIndexExpression(this);
-
-  /**
-   * Return `true` if this expression is computing a right-hand value (that is,
-   * if this expression is in a context where the operator '[]' will be
-   * invoked).
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
-  bool inGetterContext() {
-    // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
-    if (parent is AssignmentExpression) {
-      AssignmentExpression assignment = parent;
-      if (identical(assignment.leftHandSide, this) &&
-          assignment.operator.type == TokenType.EQ) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Return `true` if this expression is computing a left-hand value (that is,
-   * if this expression is in a context where the operator '[]=' will be
-   * invoked).
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
-  bool inSetterContext() {
-    // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
-    if (parent is PrefixExpression) {
-      return parent.operator.type.isIncrementOperator;
-    } else if (parent is PostfixExpression) {
-      return true;
-    } else if (parent is AssignmentExpression) {
-      return identical(parent.leftHandSide, this);
-    }
-    return false;
-  }
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _safelyVisitChild(_index, visitor);
-  }
-}
-
-/**
- * An instance creation expression.
- *
- * > newExpression ::=
- * >     ('new' | 'const') [TypeName] ('.' [SimpleIdentifier])? [ArgumentList]
- */
-class InstanceCreationExpression extends Expression {
-  /**
-   * The 'new' or 'const' keyword used to indicate how an object should be
-   * created.
-   */
-  Token keyword;
-
-  /**
-   * The name of the constructor to be invoked.
-   */
-  ConstructorName _constructorName;
-
-  /**
-   * The list of arguments to the constructor.
-   */
-  ArgumentList _argumentList;
-
-  /**
-   * The element associated with the constructor based on static type
-   * information, or `null` if the AST structure has not been resolved or if the
-   * constructor could not be resolved.
-   */
-  ConstructorElement staticElement;
-
-  /**
-   * Initialize a newly created instance creation expression.
-   */
-  InstanceCreationExpression(this.keyword, ConstructorName constructorName,
-      ArgumentList argumentList) {
-    _constructorName = _becomeParentOf(constructorName);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  /**
-   * Return the list of arguments to the constructor.
-   */
-  ArgumentList get argumentList => _argumentList;
-
-  /**
-   * Set the list of arguments to the constructor to the given [argumentList].
-   */
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  Token get beginToken => keyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(keyword)
-    ..add(_constructorName)
-    ..add(_argumentList);
-
-  /**
-   * Return the name of the constructor to be invoked.
-   */
-  ConstructorName get constructorName => _constructorName;
-
-  /**
-   * Set the name of the constructor to be invoked to the given [name].
-   */
-  void set constructorName(ConstructorName name) {
-    _constructorName = _becomeParentOf(name);
-  }
-
-  @override
-  Token get endToken => _argumentList.endToken;
-
-  /**
-   * Return `true` if this creation expression is used to invoke a constant
-   * constructor.
-   */
-  bool get isConst =>
-      keyword is KeywordToken &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
-
-  @override
-  int get precedence => 16;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitInstanceCreationExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_argumentList, visitor);
-  }
-}
-
-/**
- * An integer literal expression.
- *
- * > integerLiteral ::=
- * >     decimalIntegerLiteral
- * >   | hexadecimalIntegerLiteral
- * >
- * > decimalIntegerLiteral ::=
- * >     decimalDigit+
- * >
- * > hexadecimalIntegerLiteral ::=
- * >     '0x' hexadecimalDigit+
- * >   | '0X' hexadecimalDigit+
- */
-class IntegerLiteral extends Literal {
-  /**
-   * The token representing the literal.
-   */
-  Token literal;
-
-  /**
-   * The value of the literal.
-   */
-  int value = 0;
-
-  /**
-   * Initialize a newly created integer literal.
-   */
-  IntegerLiteral(this.literal, this.value);
-
-  @override
-  Token get beginToken => literal;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
-
-  @override
-  Token get endToken => literal;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitIntegerLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A node within a [StringInterpolation].
- *
- * > interpolationElement ::=
- * >     [InterpolationExpression]
- * >   | [InterpolationString]
- */
-abstract class InterpolationElement extends AstNode {}
-
-/**
- * An expression embedded in a string interpolation.
- *
- * > interpolationExpression ::=
- * >     '$' [SimpleIdentifier]
- * >   | '$' '{' [Expression] '}'
- */
-class InterpolationExpression extends InterpolationElement {
-  /**
-   * The token used to introduce the interpolation expression; either '$' if the
-   * expression is a simple identifier or '${' if the expression is a full
-   * expression.
-   */
-  Token leftBracket;
-
-  /**
-   * The expression to be evaluated for the value to be converted into a string.
-   */
-  Expression _expression;
-
-  /**
-   * The right curly bracket, or `null` if the expression is an identifier
-   * without brackets.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created interpolation expression.
-   */
-  InterpolationExpression(
-      this.leftBracket, Expression expression, this.rightBracket) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken => leftBracket;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(leftBracket)
-    ..add(_expression)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken {
-    if (rightBracket != null) {
-      return rightBracket;
-    }
-    return _expression.endToken;
-  }
-
-  /**
-   * Return the expression to be evaluated for the value to be converted into a
-   * string.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression to be evaluated for the value to be converted into a
-   * string to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitInterpolationExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * A non-empty substring of an interpolated string.
- *
- * > interpolationString ::=
- * >     characters
- */
-class InterpolationString extends InterpolationElement {
-  /**
-   * The characters that will be added to the string.
-   */
-  Token contents;
-
-  /**
-   * The value of the literal.
-   */
-  String value;
-
-  /**
-   * Initialize a newly created string of characters that are part of a string
-   * interpolation.
-   */
-  InterpolationString(this.contents, this.value);
-
-  @override
-  Token get beginToken => contents;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(contents);
-
-  /**
-   * Return the offset of the after-last contents character.
-   */
-  int get contentsEnd {
-    String lexeme = contents.lexeme;
-    return offset + new StringLexemeHelper(lexeme, true, true).end;
-  }
-
-  /**
-   * Return the offset of the first contents character.
-   */
-  int get contentsOffset {
-    int offset = contents.offset;
-    String lexeme = contents.lexeme;
-    return offset + new StringLexemeHelper(lexeme, true, true).start;
-  }
-
-  @override
-  Token get endToken => contents;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitInterpolationString(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {}
-}
-
-/**
- * An is expression.
- *
- * > isExpression ::=
- * >     [Expression] 'is' '!'? [TypeName]
- */
-class IsExpression extends Expression {
-  /**
-   * The expression used to compute the value whose type is being tested.
-   */
-  Expression _expression;
-
-  /**
-   * The is operator.
-   */
-  Token isOperator;
-
-  /**
-   * The not operator, or `null` if the sense of the test is not negated.
-   */
-  Token notOperator;
-
-  /**
-   * The name of the type being tested for.
-   */
-  TypeName _type;
-
-  /**
-   * Initialize a newly created is expression. The [notOperator] can be `null`
-   * if the sense of the test is not negated.
-   */
-  IsExpression(
-      Expression expression, this.isOperator, this.notOperator, TypeName type) {
-    _expression = _becomeParentOf(expression);
-    _type = _becomeParentOf(type);
-  }
-
-  @override
-  Token get beginToken => _expression.beginToken;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(_expression)
-    ..add(isOperator)
-    ..add(notOperator)
-    ..add(_type);
-
-  @override
-  Token get endToken => _type.endToken;
-
-  /**
-   * Return the expression used to compute the value whose type is being tested.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression used to compute the value whose type is being tested to
-   * the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 7;
-
-  /**
-   * Return the name of the type being tested for.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the name of the type being tested for to the given [name].
-   */
-  void set type(TypeName name) {
-    _type = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitIsExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-    _safelyVisitChild(_type, visitor);
-  }
-}
-
-/**
- * A label on either a [LabeledStatement] or a [NamedExpression].
- *
- * > label ::=
- * >     [SimpleIdentifier] ':'
- */
-class Label extends AstNode {
-  /**
-   * The label being associated with the statement.
-   */
-  SimpleIdentifier _label;
-
-  /**
-   * The colon that separates the label from the statement.
-   */
-  Token colon;
-
-  /**
-   * Initialize a newly created label.
-   */
-  Label(SimpleIdentifier label, this.colon) {
-    _label = _becomeParentOf(label);
-  }
-
-  @override
-  Token get beginToken => _label.beginToken;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(_label)..add(colon);
-
-  @override
-  Token get endToken => colon;
-
-  /**
-   * Return the label being associated with the statement.
-   */
-  SimpleIdentifier get label => _label;
-
-  /**
-   * Set the label being associated with the statement to the given [label].
-   */
-  void set label(SimpleIdentifier label) {
-    _label = _becomeParentOf(label);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitLabel(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_label, visitor);
-  }
-}
-
-/**
- * A statement that has a label associated with them.
- *
- * > labeledStatement ::=
- * >    [Label]+ [Statement]
- */
-class LabeledStatement extends Statement {
-  /**
-   * The labels being associated with the statement.
-   */
-  NodeList<Label> _labels;
-
-  /**
-   * The statement with which the labels are being associated.
-   */
-  Statement _statement;
-
-  /**
-   * Initialize a newly created labeled statement.
-   */
-  LabeledStatement(List<Label> labels, Statement statement) {
-    _labels = new NodeList<Label>(this, labels);
-    _statement = _becomeParentOf(statement);
-  }
-
-  @override
-  Token get beginToken {
-    if (!_labels.isEmpty) {
-      return _labels.beginToken;
-    }
-    return _statement.beginToken;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..addAll(_labels)
-    ..add(_statement);
-
-  @override
-  Token get endToken => _statement.endToken;
-
-  /**
-   * Return the labels being associated with the statement.
-   */
-  NodeList<Label> get labels => _labels;
-
-  /**
-   * Return the statement with which the labels are being associated.
-   */
-  Statement get statement => _statement;
-
-  /**
-   * Set the statement with which the labels are being associated to the given
-   * [statement].
-   */
-  void set statement(Statement statement) {
-    _statement = _becomeParentOf(statement);
-  }
-
-  @override
-  Statement get unlabeled => _statement.unlabeled;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitLabeledStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _labels.accept(visitor);
-    _safelyVisitChild(_statement, visitor);
-  }
-}
-
-/**
- * A library directive.
- *
- * > libraryDirective ::=
- * >     [Annotation] 'library' [Identifier] ';'
- */
-class LibraryDirective extends Directive {
-  /**
-   * The token representing the 'library' keyword.
-   */
-  Token libraryKeyword;
-
-  /**
-   * The name of the library being defined.
-   */
-  LibraryIdentifier _name;
-
-  /**
-   * The semicolon terminating the directive.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created library directive. Either or both of the
-   * [comment] and [metadata] can be `null` if the directive does not have the
-   * corresponding attribute.
-   */
-  LibraryDirective(Comment comment, List<Annotation> metadata,
-      this.libraryKeyword, LibraryIdentifier name, this.semicolon)
-      : super(comment, metadata) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(libraryKeyword)..add(_name)..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => libraryKeyword;
-
-  @override
-  Token get keyword => libraryKeyword;
-
-  /**
-   * Return the name of the library being defined.
-   */
-  LibraryIdentifier get name => _name;
-
-  /**
-   * Set the name of the library being defined to the given [name].
-   */
-  void set name(LibraryIdentifier name) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitLibraryDirective(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-  }
-}
-
-/**
- * The identifier for a library.
- *
- * > libraryIdentifier ::=
- * >     [SimpleIdentifier] ('.' [SimpleIdentifier])*
- */
-class LibraryIdentifier extends Identifier {
-  /**
-   * The components of the identifier.
-   */
-  NodeList<SimpleIdentifier> _components;
-
-  /**
-   * Initialize a newly created prefixed identifier.
-   */
-  LibraryIdentifier(List<SimpleIdentifier> components) {
-    _components = new NodeList<SimpleIdentifier>(this, components);
-  }
-
-  @override
-  Token get beginToken => _components.beginToken;
-
-  @override
-  Element get bestElement => staticElement;
-
-  @override
-  // TODO(paulberry): add "." tokens.
-  Iterable get childEntities => new ChildEntities()..addAll(_components);
-
-  /**
-   * Return the components of the identifier.
-   */
-  NodeList<SimpleIdentifier> get components => _components;
-
-  @override
-  Token get endToken => _components.endToken;
-
-  @override
-  String get name {
-    StringBuffer buffer = new StringBuffer();
-    bool needsPeriod = false;
-    for (SimpleIdentifier identifier in _components) {
-      if (needsPeriod) {
-        buffer.write(".");
-      } else {
-        needsPeriod = true;
-      }
-      buffer.write(identifier.name);
-    }
-    return buffer.toString();
-  }
-
-  @override
-  int get precedence => 15;
-
-  @override
-  Element get propagatedElement => null;
-
-  @override
-  Element get staticElement => null;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitLibraryIdentifier(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _components.accept(visitor);
-  }
-}
-
-/**
- * A list literal.
- *
- * > listLiteral ::=
- * >     'const'? ('<' [TypeName] '>')? '[' ([Expression] ','?)? ']'
- */
-class ListLiteral extends TypedLiteral {
-  /**
-   * The left square bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The expressions used to compute the elements of the list.
-   */
-  NodeList<Expression> _elements;
-
-  /**
-   * The right square bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created list literal. The [constKeyword] can be `null`
-   * if the literal is not a constant. The [typeArguments] can be `null` if no
-   * type arguments were declared. The list of [elements] can be `null` if the
-   * list is empty.
-   */
-  ListLiteral(Token constKeyword, TypeArgumentList typeArguments,
-      this.leftBracket, List<Expression> elements, this.rightBracket)
-      : super(constKeyword, typeArguments) {
-    _elements = new NodeList<Expression>(this, elements);
-  }
-
-  @override
-  Token get beginToken {
-    if (constKeyword != null) {
-      return constKeyword;
-    }
-    TypeArgumentList typeArguments = this.typeArguments;
-    if (typeArguments != null) {
-      return typeArguments.beginToken;
-    }
-    return leftBracket;
-  }
-
-  @override
-  // TODO(paulberry): add commas.
-  Iterable get childEntities => super._childEntities
-    ..add(leftBracket)
-    ..addAll(_elements)
-    ..add(rightBracket);
-
-  /**
-   * Return the expressions used to compute the elements of the list.
-   */
-  NodeList<Expression> get elements => _elements;
-
-  @override
-  Token get endToken => rightBracket;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitListLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _elements.accept(visitor);
-  }
-}
-
-/**
- * A node that represents a literal expression.
- *
- * > literal ::=
- * >     [BooleanLiteral]
- * >   | [DoubleLiteral]
- * >   | [IntegerLiteral]
- * >   | [ListLiteral]
- * >   | [MapLiteral]
- * >   | [NullLiteral]
- * >   | [StringLiteral]
- */
-abstract class Literal extends Expression {
-  @override
-  int get precedence => 16;
-}
-
-/**
- * A literal map.
- *
- * > mapLiteral ::=
- * >     'const'? ('<' [TypeName] (',' [TypeName])* '>')?
- * >     '{' ([MapLiteralEntry] (',' [MapLiteralEntry])* ','?)? '}'
- */
-class MapLiteral extends TypedLiteral {
-  /**
-   * The left curly bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The entries in the map.
-   */
-  NodeList<MapLiteralEntry> _entries;
-
-  /**
-   * The right curly bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created map literal. The [constKeyword] can be `null` if
-   * the literal is not a constant. The [typeArguments] can be `null` if no type
-   * arguments were declared. The [entries] can be `null` if the map is empty.
-   */
-  MapLiteral(Token constKeyword, TypeArgumentList typeArguments,
-      this.leftBracket, List<MapLiteralEntry> entries, this.rightBracket)
-      : super(constKeyword, typeArguments) {
-    _entries = new NodeList<MapLiteralEntry>(this, entries);
-  }
-
-  @override
-  Token get beginToken {
-    if (constKeyword != null) {
-      return constKeyword;
-    }
-    TypeArgumentList typeArguments = this.typeArguments;
-    if (typeArguments != null) {
-      return typeArguments.beginToken;
-    }
-    return leftBracket;
-  }
-
-  @override
-  // TODO(paulberry): add commas.
-  Iterable get childEntities => super._childEntities
-    ..add(leftBracket)
-    ..addAll(entries)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken => rightBracket;
-
-  /**
-   * Return the entries in the map.
-   */
-  NodeList<MapLiteralEntry> get entries => _entries;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitMapLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _entries.accept(visitor);
-  }
-}
-
-/**
- * A single key/value pair in a map literal.
- *
- * > mapLiteralEntry ::=
- * >     [Expression] ':' [Expression]
- */
-class MapLiteralEntry extends AstNode {
-  /**
-   * The expression computing the key with which the value will be associated.
-   */
-  Expression _key;
-
-  /**
-   * The colon that separates the key from the value.
-   */
-  Token separator;
-
-  /**
-   * The expression computing the value that will be associated with the key.
-   */
-  Expression _value;
-
-  /**
-   * Initialize a newly created map literal entry.
-   */
-  MapLiteralEntry(Expression key, this.separator, Expression value) {
-    _key = _becomeParentOf(key);
-    _value = _becomeParentOf(value);
-  }
-
-  @override
-  Token get beginToken => _key.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_key)..add(separator)..add(_value);
-
-  @override
-  Token get endToken => _value.endToken;
-
-  /**
-   * Return the expression computing the key with which the value will be
-   * associated.
-   */
-  Expression get key => _key;
-
-  /**
-   * Set the expression computing the key with which the value will be
-   * associated to the given [string].
-   */
-  void set key(Expression string) {
-    _key = _becomeParentOf(string);
-  }
-
-  /**
-   * Return the expression computing the value that will be associated with the
-   * key.
-   */
-  Expression get value => _value;
-
-  /**
-   * Set the expression computing the value that will be associated with the key
-   * to the given [expression].
-   */
-  void set value(Expression expression) {
-    _value = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitMapLiteralEntry(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_key, visitor);
-    _safelyVisitChild(_value, visitor);
-  }
-}
-
-/**
- * A method declaration.
- *
- * > methodDeclaration ::=
- * >     methodSignature [FunctionBody]
- * >
- * > methodSignature ::=
- * >     'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')?
- * >     methodName [TypeParameterList] [FormalParameterList]
- * >
- * > methodName ::=
- * >     [SimpleIdentifier]
- * >   | 'operator' [SimpleIdentifier]
- */
-class MethodDeclaration extends ClassMember {
-  /**
-   * The token for the 'external' keyword, or `null` if the constructor is not
-   * external.
-   */
-  Token externalKeyword;
-
-  /**
-   * The token representing the 'abstract' or 'static' keyword, or `null` if
-   * neither modifier was specified.
-   */
-  Token modifierKeyword;
-
-  /**
-   * The return type of the method, or `null` if no return type was declared.
-   */
-  TypeName _returnType;
-
-  /**
-   * The token representing the 'get' or 'set' keyword, or `null` if this is a
-   * method declaration rather than a property declaration.
-   */
-  Token propertyKeyword;
-
-  /**
-   * The token representing the 'operator' keyword, or `null` if this method
-   * does not declare an operator.
-   */
-  Token operatorKeyword;
-
-  /**
-   * The name of the method.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * The type parameters associated with the method, or `null` if the method is
-   * not a generic method.
-   */
-  TypeParameterList _typeParameters;
-
-  /**
-   * The parameters associated with the method, or `null` if this method
-   * declares a getter.
-   */
-  FormalParameterList _parameters;
-
-  /**
-   * The body of the method.
-   */
-  FunctionBody _body;
-
-  /**
-   * Initialize a newly created method declaration. Either or both of the
-   * [comment] and [metadata] can be `null` if the declaration does not have the
-   * corresponding attribute. The [externalKeyword] can be `null` if the method
-   * is not external. The [modifierKeyword] can be `null` if the method is
-   * neither abstract nor static. The [returnType] can be `null` if no return
-   * type was specified. The [propertyKeyword] can be `null` if the method is
-   * neither a getter or a setter. The [operatorKeyword] can be `null` if the
-   * method does not implement an operator. The [parameters] must be `null` if
-   * this method declares a getter.
-   */
-  MethodDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      this.externalKeyword,
-      this.modifierKeyword,
-      TypeName returnType,
-      this.propertyKeyword,
-      this.operatorKeyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
-      FunctionBody body)
-      : super(comment, metadata) {
-    _returnType = _becomeParentOf(returnType);
-    _name = _becomeParentOf(name);
-    _typeParameters = _becomeParentOf(typeParameters);
-    _parameters = _becomeParentOf(parameters);
-    _body = _becomeParentOf(body);
-  }
-
-  /**
-   * Return the body of the method.
-   */
-  FunctionBody get body => _body;
-
-  /**
-   * Set the body of the method to the given [functionBody].
-   */
-  void set body(FunctionBody functionBody) {
-    _body = _becomeParentOf(functionBody);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(externalKeyword)
-    ..add(modifierKeyword)
-    ..add(_returnType)
-    ..add(propertyKeyword)
-    ..add(operatorKeyword)
-    ..add(_name)
-    ..add(_parameters)
-    ..add(_body);
-
-  /**
-   * Return the element associated with this method, or `null` if the AST
-   * structure has not been resolved. The element can either be a
-   * [MethodElement], if this represents the declaration of a normal method, or
-   * a [PropertyAccessorElement] if this represents the declaration of either a
-   * getter or a setter.
-   */
-  @override
-  ExecutableElement get element =>
-      _name != null ? (_name.staticElement as ExecutableElement) : null;
-
-  @override
-  Token get endToken => _body.endToken;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    if (modifierKeyword != null) {
-      return modifierKeyword;
-    } else if (_returnType != null) {
-      return _returnType.beginToken;
-    } else if (propertyKeyword != null) {
-      return propertyKeyword;
-    } else if (operatorKeyword != null) {
-      return operatorKeyword;
-    }
-    return _name.beginToken;
-  }
-
-  /**
-   * Return `true` if this method is declared to be an abstract method.
-   */
-  bool get isAbstract {
-    FunctionBody body = _body;
-    return externalKeyword == null &&
-        (body is EmptyFunctionBody && !body.semicolon.isSynthetic);
-  }
-
-  /**
-   * Return `true` if this method declares a getter.
-   */
-  bool get isGetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.GET;
-
-  /**
-   * Return `true` if this method declares an operator.
-   */
-  bool get isOperator => operatorKeyword != null;
-
-  /**
-   * Return `true` if this method declares a setter.
-   */
-  bool get isSetter =>
-      propertyKeyword != null &&
-      (propertyKeyword as KeywordToken).keyword == Keyword.SET;
-
-  /**
-   * Return `true` if this method is declared to be a static method.
-   */
-  bool get isStatic =>
-      modifierKeyword != null &&
-      (modifierKeyword as KeywordToken).keyword == Keyword.STATIC;
-
-  /**
-   * Return the name of the method.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the method to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return the parameters associated with the method, or `null` if this method
-   * declares a getter.
-   */
-  FormalParameterList get parameters => _parameters;
-
-  /**
-   * Set the parameters associated with the method to the given list of
-   * [parameters].
-   */
-  void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
-  }
-
-  /**
-   * Return the return type of the method, or `null` if no return type was
-   * declared.
-   */
-  TypeName get returnType => _returnType;
-
-  /**
-   * Set the return type of the method to the given [typeName].
-   */
-  void set returnType(TypeName typeName) {
-    _returnType = _becomeParentOf(typeName);
-  }
-
-  /**
-   * Return the type parameters associated with this method, or `null` if this
-   * method is not a generic method.
-   */
-  TypeParameterList get typeParameters => _typeParameters;
-
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
-  void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitMethodDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_returnType, visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeParameters, visitor);
-    _safelyVisitChild(_parameters, visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * The invocation of either a function or a method. Invocations of functions
- * resulting from evaluating an expression are represented by
- * [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
- * represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
- *
- * > methodInvocation ::=
- * >     ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
- */
-class MethodInvocation extends Expression {
-  /**
-   * 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`).
-   */
-  Expression _target;
-
-  /**
-   * The operator that separates the target from the method name, or `null`
-   * if there is no target. In an ordinary method invocation this will be a
-   * period ('.'). In a cascade section this will be the cascade operator
-   * ('..').
-   */
-  Token operator;
-
-  /**
-   * The name of the method being invoked.
-   */
-  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.
-   */
-  MethodInvocation(
-      Expression target,
-      this.operator,
-      SimpleIdentifier methodName,
-      TypeArgumentList typeArguments,
-      ArgumentList argumentList) {
-    _target = _becomeParentOf(target);
-    _methodName = _becomeParentOf(methodName);
-    _typeArguments = _becomeParentOf(typeArguments);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  /**
-   * Return the list of arguments to the method.
-   */
-  ArgumentList get argumentList => _argumentList;
-
-  /**
-   * Set the list of arguments to the method to the given [argumentList].
-   */
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  Token get beginToken {
-    if (_target != null) {
-      return _target.beginToken;
-    } else if (operator != null) {
-      return operator;
-    }
-    return _methodName.beginToken;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(_target)
-    ..add(operator)
-    ..add(_methodName)
-    ..add(_argumentList);
-
-  @override
-  Token get endToken => _argumentList.endToken;
-
-  /**
-   * Return `true` if this expression is cascaded. If it is, then the target of
-   * this expression is not stored locally but is stored in the nearest ancestor
-   * that is a [CascadeExpression].
-   */
-  bool get isCascaded =>
-      operator != null && operator.type == TokenType.PERIOD_PERIOD;
-
-  /**
-   * Return the name of the method being invoked.
-   */
-  SimpleIdentifier get methodName => _methodName;
-
-  /**
-   * Set the name of the method being invoked to the given [identifier].
-   */
-  void set methodName(SimpleIdentifier identifier) {
-    _methodName = _becomeParentOf(identifier);
-  }
-
-  @override
-  int get precedence => 15;
-
-  /**
-   * Return the expression used to compute the receiver of the invocation. If
-   * this invocation is not part of a cascade expression, then this is the same
-   * as [target]. If this invocation is part of a cascade expression, then the
-   * target stored with the cascade expression is returned.
-   */
-  Expression get realTarget {
-    if (isCascaded) {
-      AstNode ancestor = parent;
-      while (ancestor is! CascadeExpression) {
-        if (ancestor == null) {
-          return _target;
-        }
-        ancestor = ancestor.parent;
-      }
-      return (ancestor as CascadeExpression).target;
-    }
-    return _target;
-  }
-
-  /**
-   * Return 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`)
-   * or if this method invocation is part of a cascade expression.
-   *
-   * Use [realTarget] to get the target independent of whether this is part of a
-   * cascade expression.
-   */
-  Expression get target => _target;
-
-  /**
-   * Set the expression producing the object on which the method is defined to
-   * the given [expression].
-   */
-  void set target(Expression expression) {
-    _target = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the type arguments to be applied to the method being invoked, or
-   * `null` if no type arguments were provided.
-   */
-  TypeArgumentList get typeArguments => _typeArguments;
-
-  /**
-   * Set the type arguments to be applied to the method being invoked to the
-   * given [typeArguments].
-   */
-  void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitMethodInvocation(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _safelyVisitChild(_methodName, visitor);
-    _safelyVisitChild(_typeArguments, visitor);
-    _safelyVisitChild(_argumentList, visitor);
-  }
-}
-
-/**
- * A node that declares a single name within the scope of a compilation unit.
- */
-abstract class NamedCompilationUnitMember extends CompilationUnitMember {
-  /**
-   * The name of the member being declared.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * Initialize a newly created compilation unit member with the given [name].
-   * Either or both of the [comment] and [metadata] can be `null` if the member
-   * does not have the corresponding attribute.
-   */
-  NamedCompilationUnitMember(
-      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
-      : super(comment, metadata) {
-    _name = _becomeParentOf(name);
-  }
-
-  /**
-   * Return the name of the member being declared.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the member being declared to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-}
-
-/**
- * An expression that has a name associated with it. They are used in method
- * invocations when there are named parameters.
- *
- * > namedExpression ::=
- * >     [Label] [Expression]
- */
-class NamedExpression extends Expression {
-  /**
-   * The name associated with the expression.
-   */
-  Label _name;
-
-  /**
-   * The expression with which the name is associated.
-   */
-  Expression _expression;
-
-  /**
-   * Initialize a newly created named expression..
-   */
-  NamedExpression(Label name, Expression expression) {
-    _name = _becomeParentOf(name);
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken => _name.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_name)..add(_expression);
-
-  /**
-   * Return the element representing the parameter being named by this
-   * expression, or `null` if the AST structure has not been resolved or if
-   * there is no parameter with the same name as this expression.
-   */
-  ParameterElement get element {
-    Element element = _name.label.staticElement;
-    if (element is ParameterElement) {
-      return element;
-    }
-    return null;
-  }
-
-  @override
-  Token get endToken => _expression.endToken;
-
-  /**
-   * Return the expression with which the name is associated.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression with which the name is associated to the given
-   * [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the name associated with the expression.
-   */
-  Label get name => _name;
-
-  /**
-   * Set the name associated with the expression to the given [identifier].
-   */
-  void set name(Label identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  @override
-  int get precedence => 0;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitNamedExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * A node that represents a directive that impacts the namespace of a library.
- *
- * > directive ::=
- * >     [ExportDirective]
- * >   | [ImportDirective]
- */
-abstract class NamespaceDirective extends UriBasedDirective {
-  /**
-   * The token representing the 'import' or 'export' keyword.
-   */
-  Token keyword;
-
-  /**
-   * The configurations used to control which library will actually be loaded at
-   * run-time.
-   */
-  NodeList<Configuration> _configurations;
-
-  /**
-   * The combinators used to control which names are imported or exported.
-   */
-  NodeList<Combinator> _combinators;
-
-  /**
-   * The semicolon terminating the directive.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created namespace directive. Either or both of the
-   * [comment] and [metadata] can be `null` if the directive does not have the
-   * corresponding attribute. The list of [combinators] can be `null` if there
-   * are no combinators.
-   */
-  NamespaceDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      this.keyword,
-      StringLiteral libraryUri,
-      List<Configuration> configurations,
-      List<Combinator> combinators,
-      this.semicolon)
-      : super(comment, metadata, libraryUri) {
-    _configurations = new NodeList<Configuration>(this, configurations);
-    _combinators = new NodeList<Combinator>(this, combinators);
-  }
-
-  /**
-   * Return the combinators used to control how names are imported or exported.
-   */
-  NodeList<Combinator> get combinators => _combinators;
-
-  /**
-   * Return the configurations used to control which library will actually be
-   * loaded at run-time.
-   */
-  NodeList<Configuration> get configurations => _configurations;
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => keyword;
-
-  @override
-  LibraryElement get uriElement;
-}
-
-/**
- * The "native" clause in an class declaration.
- *
- * > nativeClause ::=
- * >     'native' [StringLiteral]
- */
-class NativeClause extends AstNode {
-  /**
-   * The token representing the 'native' keyword.
-   */
-  Token nativeKeyword;
-
-  /**
-   * The name of the native object that implements the class.
-   */
-  StringLiteral _name;
-
-  /**
-   * Initialize a newly created native clause.
-   */
-  NativeClause(this.nativeKeyword, StringLiteral name) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  Token get beginToken => nativeKeyword;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(nativeKeyword)..add(_name);
-
-  @override
-  Token get endToken => _name.endToken;
-
-  /**
-   * Return the name of the native object that implements the class.
-   */
-  StringLiteral get name => _name;
-
-  /**
-   * Set the name of the native object that implements the class to the given
-   * [name].
-   */
-  void set name(StringLiteral name) {
-    _name = _becomeParentOf(name);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitNativeClause(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-  }
-}
-
-/**
- * A function body that consists of a native keyword followed by a string
- * literal.
- *
- * > nativeFunctionBody ::=
- * >     'native' [SimpleStringLiteral] ';'
- */
-class NativeFunctionBody extends FunctionBody {
-  /**
-   * The token representing 'native' that marks the start of the function body.
-   */
-  Token nativeKeyword;
-
-  /**
-   * The string literal, after the 'native' token.
-   */
-  StringLiteral _stringLiteral;
-
-  /**
-   * The token representing the semicolon that marks the end of the function
-   * body.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created function body consisting of the 'native' token,
-   * a string literal, and a semicolon.
-   */
-  NativeFunctionBody(
-      this.nativeKeyword, StringLiteral stringLiteral, this.semicolon) {
-    _stringLiteral = _becomeParentOf(stringLiteral);
-  }
-
-  @override
-  Token get beginToken => nativeKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(nativeKeyword)
-    ..add(_stringLiteral)
-    ..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the string literal representing the string after the 'native' token.
-   */
-  StringLiteral get stringLiteral => _stringLiteral;
-
-  /**
-   * Set the string literal representing the string after the 'native' token to
-   * the given [stringLiteral].
-   */
-  void set stringLiteral(StringLiteral stringLiteral) {
-    _stringLiteral = _becomeParentOf(stringLiteral);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitNativeFunctionBody(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_stringLiteral, visitor);
-  }
-}
-
-/**
- * A list of AST nodes that have a common parent.
- */
-class NodeList<E extends AstNode> extends Object with ListMixin<E> {
-  /**
-   * The node that is the parent of each of the elements in the list.
-   */
-  AstNode owner;
-
-  /**
-   * The elements contained in the list.
-   */
-  List<E> _elements = <E>[];
-
-  /**
-   * Initialize a newly created list of nodes such that all of the nodes that
-   * are added to the list will have their parent set to the given [owner]. The
-   * list will initially be populated with the given [elements].
-   */
-  NodeList(this.owner, [List<E> elements]) {
-    addAll(elements);
-  }
-
-  /**
-   * Return the first token included in this node list's source range, or `null`
-   * if the list is empty.
-   */
-  Token get beginToken {
-    if (_elements.length == 0) {
-      return null;
-    }
-    return _elements[0].beginToken;
-  }
-
-  /**
-   * Return the last token included in this node list's source range, or `null`
-   * if the list is empty.
-   */
-  Token get endToken {
-    int length = _elements.length;
-    if (length == 0) {
-      return null;
-    }
-    return _elements[length - 1].endToken;
-  }
-
-  int get length => _elements.length;
-
-  @deprecated // Never intended for public use.
-  @override
-  void set length(int newLength) {
-    throw new UnsupportedError("Cannot resize NodeList.");
-  }
-
-  E operator [](int index) {
-    if (index < 0 || index >= _elements.length) {
-      throw new RangeError("Index: $index, Size: ${_elements.length}");
-    }
-    return _elements[index];
-  }
-
-  void operator []=(int index, E node) {
-    if (index < 0 || index >= _elements.length) {
-      throw new RangeError("Index: $index, Size: ${_elements.length}");
-    }
-    owner._becomeParentOf(node);
-    _elements[index] = node;
-  }
-
-  /**
-   * Use the given [visitor] to visit each of the nodes in this list.
-   */
-  accept(AstVisitor visitor) {
-    int length = _elements.length;
-    for (var i = 0; i < length; i++) {
-      _elements[i].accept(visitor);
-    }
-  }
-
-  @override
-  void add(E node) {
-    insert(length, node);
-  }
-
-  @override
-  bool addAll(Iterable<E> nodes) {
-    if (nodes != null && !nodes.isEmpty) {
-      _elements.addAll(nodes);
-      for (E node in nodes) {
-        owner._becomeParentOf(node);
-      }
-      return true;
-    }
-    return false;
-  }
-
-  @override
-  void clear() {
-    _elements = <E>[];
-  }
-
-  @override
-  void insert(int index, E node) {
-    int length = _elements.length;
-    if (index < 0 || index > length) {
-      throw new RangeError("Index: $index, Size: ${_elements.length}");
-    }
-    owner._becomeParentOf(node);
-    if (length == 0) {
-      _elements.add(node);
-    } else {
-      _elements.insert(index, node);
-    }
-  }
-
-  @override
-  E removeAt(int index) {
-    if (index < 0 || index >= _elements.length) {
-      throw new RangeError("Index: $index, Size: ${_elements.length}");
-    }
-    E removedNode = _elements[index];
-    _elements.removeAt(index);
-    return removedNode;
-  }
-}
-
-/**
- * A formal parameter that is required (is not optional).
- *
- * > normalFormalParameter ::=
- * >     [FunctionTypedFormalParameter]
- * >   | [FieldFormalParameter]
- * >   | [SimpleFormalParameter]
- */
-abstract class NormalFormalParameter extends FormalParameter {
-  /**
-   * The documentation comment associated with this parameter, or `null` if this
-   * parameter does not have a documentation comment associated with it.
-   */
-  Comment _comment;
-
-  /**
-   * The annotations associated with this parameter.
-   */
-  NodeList<Annotation> _metadata;
-
-  /**
-   * The name of the parameter being declared.
-   */
-  SimpleIdentifier _identifier;
-
-  /**
-   * Initialize a newly created formal parameter. Either or both of the
-   * [comment] and [metadata] can be `null` if the parameter does not have the
-   * corresponding attribute.
-   */
-  NormalFormalParameter(
-      Comment comment, List<Annotation> metadata, SimpleIdentifier identifier) {
-    _comment = _becomeParentOf(comment);
-    _metadata = new NodeList<Annotation>(this, metadata);
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return the documentation comment associated with this parameter, or `null`
-   * if this parameter does not have a documentation comment associated with it.
-   */
-  Comment get documentationComment => _comment;
-
-  /**
-   * Set the documentation comment associated with this parameter to the given
-   * [comment].
-   */
-  void set documentationComment(Comment comment) {
-    _comment = _becomeParentOf(comment);
-  }
-
-  @override
-  SimpleIdentifier get identifier => _identifier;
-
-  /**
-   * Set the name of the parameter being declared to the given [identifier].
-   */
-  void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  @override
-  ParameterKind get kind {
-    AstNode parent = this.parent;
-    if (parent is DefaultFormalParameter) {
-      return parent.kind;
-    }
-    return ParameterKind.REQUIRED;
-  }
-
-  @override
-  NodeList<Annotation> get metadata => _metadata;
-
-  /**
-   * Set the metadata associated with this node to the given [metadata].
-   */
-  void set metadata(List<Annotation> metadata) {
-    _metadata.clear();
-    _metadata.addAll(metadata);
-  }
-
-  /**
-   * Return a list containing the comment and annotations associated with this
-   * parameter, sorted in lexical order.
-   */
-  List<AstNode> get sortedCommentAndAnnotations {
-    return <AstNode>[]
-      ..add(_comment)
-      ..addAll(_metadata)
-      ..sort(AstNode.LEXICAL_ORDER);
-  }
-
-  ChildEntities get _childEntities {
-    ChildEntities result = new ChildEntities();
-    if (_commentIsBeforeAnnotations()) {
-      result
-        ..add(_comment)
-        ..addAll(_metadata);
-    } else {
-      result.addAll(sortedCommentAndAnnotations);
-    }
-    return result;
-  }
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    //
-    // Note that subclasses are responsible for visiting the identifier because
-    // they often need to visit other nodes before visiting the identifier.
-    //
-    if (_commentIsBeforeAnnotations()) {
-      _safelyVisitChild(_comment, visitor);
-      _metadata.accept(visitor);
-    } else {
-      for (AstNode child in sortedCommentAndAnnotations) {
-        child.accept(visitor);
-      }
-    }
-  }
-
-  /**
-   * Return `true` if the comment is lexically before any annotations.
-   */
-  bool _commentIsBeforeAnnotations() {
-    if (_comment == null || _metadata.isEmpty) {
-      return true;
-    }
-    Annotation firstAnnotation = _metadata[0];
-    return _comment.offset < firstAnnotation.offset;
-  }
-}
-
-/**
- * A null literal expression.
- *
- * > nullLiteral ::=
- * >     'null'
- */
-class NullLiteral extends Literal {
-  /**
-   * The token representing the literal.
-   */
-  Token literal;
-
-  /**
-   * Initialize a newly created null literal.
-   */
-  NullLiteral(this.literal);
-
-  @override
-  Token get beginToken => literal;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
-
-  @override
-  Token get endToken => literal;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitNullLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A parenthesized expression.
- *
- * > parenthesizedExpression ::=
- * >     '(' [Expression] ')'
- */
-class ParenthesizedExpression extends Expression {
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The expression within the parentheses.
-   */
-  Expression _expression;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * Initialize a newly created parenthesized expression.
-   */
-  ParenthesizedExpression(
-      this.leftParenthesis, Expression expression, this.rightParenthesis) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken => leftParenthesis;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(leftParenthesis)
-    ..add(_expression)
-    ..add(rightParenthesis);
-
-  @override
-  Token get endToken => rightParenthesis;
-
-  /**
-   * Return the expression within the parentheses.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression within the parentheses to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 15;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitParenthesizedExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * A part directive.
- *
- * > partDirective ::=
- * >     [Annotation] 'part' [StringLiteral] ';'
- */
-class PartDirective extends UriBasedDirective {
-  /**
-   * The token representing the 'part' keyword.
-   */
-  Token partKeyword;
-
-  /**
-   * The semicolon terminating the directive.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created part directive. Either or both of the [comment]
-   * and [metadata] can be `null` if the directive does not have the
-   * corresponding attribute.
-   */
-  PartDirective(Comment comment, List<Annotation> metadata, this.partKeyword,
-      StringLiteral partUri, this.semicolon)
-      : super(comment, metadata, partUri);
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(partKeyword)..add(_uri)..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => partKeyword;
-
-  @override
-  Token get keyword => partKeyword;
-
-  @override
-  CompilationUnitElement get uriElement => element as CompilationUnitElement;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitPartDirective(this);
-}
-
-/**
- * A part-of directive.
- *
- * > partOfDirective ::=
- * >     [Annotation] 'part' 'of' [Identifier] ';'
- */
-class PartOfDirective extends Directive {
-  /**
-   * The token representing the 'part' keyword.
-   */
-  Token partKeyword;
-
-  /**
-   * The token representing the 'of' keyword.
-   */
-  Token ofKeyword;
-
-  /**
-   * The name of the library that the containing compilation unit is part of.
-   */
-  LibraryIdentifier _libraryName;
-
-  /**
-   * The semicolon terminating the directive.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created part-of directive. Either or both of the
-   * [comment] and [metadata] can be `null` if the directive does not have the
-   * corresponding attribute.
-   */
-  PartOfDirective(Comment comment, List<Annotation> metadata, this.partKeyword,
-      this.ofKeyword, LibraryIdentifier libraryName, this.semicolon)
-      : super(comment, metadata) {
-    _libraryName = _becomeParentOf(libraryName);
-  }
-
-  @override
-  Iterable get childEntities => super._childEntities
-    ..add(partKeyword)
-    ..add(ofKeyword)
-    ..add(_libraryName)
-    ..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => partKeyword;
-
-  @override
-  Token get keyword => partKeyword;
-
-  /**
-   * Return the name of the library that the containing compilation unit is part
-   * of.
-   */
-  LibraryIdentifier get libraryName => _libraryName;
-
-  /**
-   * Set the name of the library that the containing compilation unit is part of
-   * to the given [libraryName].
-   */
-  void set libraryName(LibraryIdentifier libraryName) {
-    _libraryName = _becomeParentOf(libraryName);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitPartOfDirective(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_libraryName, visitor);
-  }
-}
-
-/**
- * A postfix unary expression.
- *
- * > postfixExpression ::=
- * >     [Expression] [Token]
- */
-class PostfixExpression extends Expression {
-  /**
-   * The expression computing the operand for the operator.
-   */
-  Expression _operand;
-
-  /**
-   * The postfix operator being applied to the operand.
-   */
-  Token operator;
-
-  /**
-   * The element associated with this the operator based on the propagated type
-   * of the operand, or `null` if the AST structure has not been resolved, if
-   * the operator is not user definable, or if the operator could not be
-   * resolved.
-   */
-  MethodElement propagatedElement;
-
-  /**
-   * The element associated with the operator based on the static type of the
-   * operand, or `null` if the AST structure has not been resolved, if the
-   * operator is not user definable, or if the operator could not be resolved.
-   */
-  MethodElement staticElement;
-
-  /**
-   * Initialize a newly created postfix expression.
-   */
-  PostfixExpression(Expression operand, this.operator) {
-    _operand = _becomeParentOf(operand);
-  }
-
-  @override
-  Token get beginToken => _operand.beginToken;
-
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   */
-  MethodElement get bestElement {
-    MethodElement element = propagatedElement;
-    if (element == null) {
-      element = staticElement;
-    }
-    return element;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_operand)..add(operator);
-
-  @override
-  Token get endToken => operator;
-
-  /**
-   * Return the expression computing the operand for the operator.
-   */
-  Expression get operand => _operand;
-
-  /**
-   * Set the expression computing the operand for the operator to the given
-   * [expression].
-   */
-  void set operand(Expression expression) {
-    _operand = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 15;
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on propagated type information, then return the parameter
-   * element representing the parameter to which the value of the operand will
-   * be bound. Otherwise, return `null`.
-   */
-  ParameterElement get _propagatedParameterElementForOperand {
-    if (propagatedElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = propagatedElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on static type information, then return the parameter element
-   * representing the parameter to which the value of the operand will be bound.
-   * Otherwise, return `null`.
-   */
-  ParameterElement get _staticParameterElementForOperand {
-    if (staticElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = staticElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitPostfixExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_operand, visitor);
-  }
-}
-
-/**
- * An identifier that is prefixed or an access to an object property where the
- * target of the property access is a simple identifier.
- *
- * > prefixedIdentifier ::=
- * >     [SimpleIdentifier] '.' [SimpleIdentifier]
- */
-class PrefixedIdentifier extends Identifier {
-  /**
-   * The prefix associated with the library in which the identifier is defined.
-   */
-  SimpleIdentifier _prefix;
-
-  /**
-   * The period used to separate the prefix from the identifier.
-   */
-  Token period;
-
-  /**
-   * The identifier being prefixed.
-   */
-  SimpleIdentifier _identifier;
-
-  /**
-   * Initialize a newly created prefixed identifier.
-   */
-  PrefixedIdentifier(
-      SimpleIdentifier prefix, this.period, SimpleIdentifier identifier) {
-    _prefix = _becomeParentOf(prefix);
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  @override
-  Token get beginToken => _prefix.beginToken;
-
-  @override
-  Element get bestElement {
-    if (_identifier == null) {
-      return null;
-    }
-    return _identifier.bestElement;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_prefix)..add(period)..add(_identifier);
-
-  @override
-  Token get endToken => _identifier.endToken;
-
-  /**
-   * Return the identifier being prefixed.
-   */
-  SimpleIdentifier get identifier => _identifier;
-
-  /**
-   * Set the identifier being prefixed to the given [identifier].
-   */
-  void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return `true` if this type is a deferred type. If the AST structure has not
-   * been resolved, then return `false`.
-   *
-   * 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
-   * </i>p.T</i> where <i>p</i> is a deferred prefix.
-   */
-  bool get isDeferred {
-    Element element = _prefix.staticElement;
-    if (element is! PrefixElement) {
-      return false;
-    }
-    PrefixElement prefixElement = element as PrefixElement;
-    List<ImportElement> imports =
-        prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
-    if (imports.length != 1) {
-      return false;
-    }
-    return imports[0].isDeferred;
-  }
-
-  @override
-  String get name => "${_prefix.name}.${_identifier.name}";
-
-  @override
-  int get precedence => 15;
-
-  /**
-   * Return the prefix associated with the library in which the identifier is
-   * defined.
-   */
-  SimpleIdentifier get prefix => _prefix;
-
-  /**
-   * Set the prefix associated with the library in which the identifier is
-   * defined to the given [identifier].
-   */
-  void set prefix(SimpleIdentifier identifier) {
-    _prefix = _becomeParentOf(identifier);
-  }
-
-  @override
-  Element get propagatedElement {
-    if (_identifier == null) {
-      return null;
-    }
-    return _identifier.propagatedElement;
-  }
-
-  @override
-  Element get staticElement {
-    if (_identifier == null) {
-      return null;
-    }
-    return _identifier.staticElement;
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitPrefixedIdentifier(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_prefix, visitor);
-    _safelyVisitChild(_identifier, visitor);
-  }
-}
-
-/**
- * A prefix unary expression.
- *
- * > prefixExpression ::=
- * >     [Token] [Expression]
- */
-class PrefixExpression extends Expression {
-  /**
-   * The prefix operator being applied to the operand.
-   */
-  Token operator;
-
-  /**
-   * The expression computing the operand for the operator.
-   */
-  Expression _operand;
-
-  /**
-   * The element associated with the operator based on the static type of the
-   * operand, or `null` if the AST structure has not been resolved, if the
-   * operator is not user definable, or if the operator could not be resolved.
-   */
-  MethodElement staticElement;
-
-  /**
-   * The element associated with the operator based on the propagated type of
-   * the operand, or `null` if the AST structure has not been resolved, if the
-   * operator is not user definable, or if the operator could not be resolved.
-   */
-  MethodElement propagatedElement;
-
-  /**
-   * Initialize a newly created prefix expression.
-   */
-  PrefixExpression(this.operator, Expression operand) {
-    _operand = _becomeParentOf(operand);
-  }
-
-  @override
-  Token get beginToken => operator;
-
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   */
-  MethodElement get bestElement {
-    MethodElement element = propagatedElement;
-    if (element == null) {
-      element = staticElement;
-    }
-    return element;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(operator)..add(_operand);
-
-  @override
-  Token get endToken => _operand.endToken;
-
-  /**
-   * Return the expression computing the operand for the operator.
-   */
-  Expression get operand => _operand;
-
-  /**
-   * Set the expression computing the operand for the operator to the given
-   * [expression].
-   */
-  void set operand(Expression expression) {
-    _operand = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 14;
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on propagated type information, then return the parameter
-   * element representing the parameter to which the value of the operand will
-   * be bound. Otherwise, return `null`.
-   */
-  ParameterElement get _propagatedParameterElementForOperand {
-    if (propagatedElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = propagatedElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  /**
-   * If the AST structure has been resolved, and the function being invoked is
-   * known based on static type information, then return the parameter element
-   * representing the parameter to which the value of the operand will be bound.
-   * Otherwise, return `null`.
-   */
-  ParameterElement get _staticParameterElementForOperand {
-    if (staticElement == null) {
-      return null;
-    }
-    List<ParameterElement> parameters = staticElement.parameters;
-    if (parameters.length < 1) {
-      return null;
-    }
-    return parameters[0];
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitPrefixExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_operand, visitor);
-  }
-}
-
-/**
- * The access of a property of an object.
- *
- * Note, however, that accesses to properties of objects can also be represented
- * as [PrefixedIdentifier] nodes in cases where the target is also a simple
- * identifier.
- *
- * > propertyAccess ::=
- * >     [Expression] '.' [SimpleIdentifier]
- */
-class PropertyAccess extends Expression {
-  /**
-   * The expression computing the object defining the property being accessed.
-   */
-  Expression _target;
-
-  /**
-   * The property access operator.
-   */
-  Token operator;
-
-  /**
-   * The name of the property being accessed.
-   */
-  SimpleIdentifier _propertyName;
-
-  /**
-   * Initialize a newly created property access expression.
-   */
-  PropertyAccess(
-      Expression target, this.operator, SimpleIdentifier propertyName) {
-    _target = _becomeParentOf(target);
-    _propertyName = _becomeParentOf(propertyName);
-  }
-
-  @override
-  Token get beginToken {
-    if (_target != null) {
-      return _target.beginToken;
-    }
-    return operator;
-  }
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_target)..add(operator)..add(_propertyName);
-
-  @override
-  Token get endToken => _propertyName.endToken;
-
-  @override
-  bool get isAssignable => true;
-
-  /**
-   * Return `true` if this expression is cascaded. If it is, then the target of
-   * this expression is not stored locally but is stored in the nearest ancestor
-   * that is a [CascadeExpression].
-   */
-  bool get isCascaded =>
-      operator != null && operator.type == TokenType.PERIOD_PERIOD;
-
-  @override
-  int get precedence => 15;
-
-  /**
-   * Return the name of the property being accessed.
-   */
-  SimpleIdentifier get propertyName => _propertyName;
-
-  /**
-   * Set the name of the property being accessed to the given [identifier].
-   */
-  void set propertyName(SimpleIdentifier identifier) {
-    _propertyName = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return the expression used to compute the receiver of the invocation. If
-   * this invocation is not part of a cascade expression, then this is the same
-   * as [target]. If this invocation is part of a cascade expression, then the
-   * target stored with the cascade expression is returned.
-   */
-  Expression get realTarget {
-    if (isCascaded) {
-      AstNode ancestor = parent;
-      while (ancestor is! CascadeExpression) {
-        if (ancestor == null) {
-          return _target;
-        }
-        ancestor = ancestor.parent;
-      }
-      return (ancestor as CascadeExpression).target;
-    }
-    return _target;
-  }
-
-  /**
-   * Return the expression computing the object defining the property being
-   * accessed, or `null` if this property access is part of a cascade expression.
-   *
-   * Use [realTarget] to get the target independent of whether this is part of a
-   * cascade expression.
-   */
-  Expression get target => _target;
-
-  /**
-   * Set the expression computing the object defining the property being
-   * accessed to the given [expression].
-   */
-  void set target(Expression expression) {
-    _target = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitPropertyAccess(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_target, visitor);
-    _safelyVisitChild(_propertyName, visitor);
-  }
-}
-
-/**
- * The invocation of a constructor in the same class from within a constructor's
- * initialization list.
- *
- * > redirectingConstructorInvocation ::=
- * >     'this' ('.' identifier)? arguments
- */
-class RedirectingConstructorInvocation extends ConstructorInitializer {
-  /**
-   * The token for the 'this' keyword.
-   */
-  Token thisKeyword;
-
-  /**
-   * The token for the period before the name of the constructor that is being
-   * invoked, or `null` if the unnamed constructor is being invoked.
-   */
-  Token period;
-
-  /**
-   * The name of the constructor that is being invoked, or `null` if the unnamed
-   * constructor is being invoked.
-   */
-  SimpleIdentifier _constructorName;
-
-  /**
-   * The list of arguments to the constructor.
-   */
-  ArgumentList _argumentList;
-
-  /**
-   * The element associated with the constructor based on static type
-   * information, or `null` if the AST structure has not been resolved or if the
-   * constructor could not be resolved.
-   */
-  ConstructorElement staticElement;
-
-  /**
-   * Initialize a newly created redirecting invocation to invoke the constructor
-   * with the given name with the given arguments. The [constructorName] can be
-   * `null` if the constructor being invoked is the unnamed constructor.
-   */
-  RedirectingConstructorInvocation(this.thisKeyword, this.period,
-      SimpleIdentifier constructorName, ArgumentList argumentList) {
-    _constructorName = _becomeParentOf(constructorName);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  /**
-   * Return the list of arguments to the constructor.
-   */
-  ArgumentList get argumentList => _argumentList;
-
-  /**
-   * Set the list of arguments to the constructor to the given [argumentList].
-   */
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  Token get beginToken => thisKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(thisKeyword)
-    ..add(period)
-    ..add(_constructorName)
-    ..add(_argumentList);
-
-  /**
-   * Return the name of the constructor that is being invoked, or `null` if the
-   * unnamed constructor is being invoked.
-   */
-  SimpleIdentifier get constructorName => _constructorName;
-
-  /**
-   * Set the name of the constructor that is being invoked to the given
-   * [identifier].
-   */
-  void set constructorName(SimpleIdentifier identifier) {
-    _constructorName = _becomeParentOf(identifier);
-  }
-
-  @override
-  Token get endToken => _argumentList.endToken;
-
-  @override
-  accept(AstVisitor visitor) =>
-      visitor.visitRedirectingConstructorInvocation(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_argumentList, visitor);
-  }
-}
-
-/**
- * A rethrow expression.
- *
- * > rethrowExpression ::=
- * >     'rethrow'
- */
-class RethrowExpression extends Expression {
-  /**
-   * The token representing the 'rethrow' keyword.
-   */
-  Token rethrowKeyword;
-
-  /**
-   * Initialize a newly created rethrow expression.
-   */
-  RethrowExpression(this.rethrowKeyword);
-
-  @override
-  Token get beginToken => rethrowKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(rethrowKeyword);
-
-  @override
-  Token get endToken => rethrowKeyword;
-
-  @override
-  int get precedence => 0;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitRethrowExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A return statement.
- *
- * > returnStatement ::=
- * >     'return' [Expression]? ';'
- */
-class ReturnStatement extends Statement {
-  /**
-   * The token representing the 'return' keyword.
-   */
-  Token returnKeyword;
-
-  /**
-   * The expression computing the value to be returned, or `null` if no explicit
-   * value was provided.
-   */
-  Expression _expression;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created return statement. The [expression] can be `null`
-   * if no explicit value was provided.
-   */
-  ReturnStatement(this.returnKeyword, Expression expression, this.semicolon) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken => returnKeyword;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(returnKeyword)..add(_expression)..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the expression computing the value to be returned, or `null` if no
-   * explicit value was provided.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression computing the value to be returned to the given
-   * [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitReturnStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * A script tag that can optionally occur at the beginning of a compilation unit.
- *
- * > scriptTag ::=
- * >     '#!' (~NEWLINE)* NEWLINE
- */
-class ScriptTag extends AstNode {
-  /**
-   * The token representing this script tag.
-   */
-  Token scriptTag;
-
-  /**
-   * Initialize a newly created script tag.
-   */
-  ScriptTag(this.scriptTag);
-
-  @override
-  Token get beginToken => scriptTag;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(scriptTag);
-
-  @override
-  Token get endToken => scriptTag;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitScriptTag(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A combinator that restricts the names being imported to those in a given list.
- *
- * > showCombinator ::=
- * >     'show' [SimpleIdentifier] (',' [SimpleIdentifier])*
- */
-class ShowCombinator extends Combinator {
-  /**
-   * The list of names from the library that are made visible by this combinator.
-   */
-  NodeList<SimpleIdentifier> _shownNames;
-
-  /**
-   * Initialize a newly created import show combinator.
-   */
-  ShowCombinator(Token keyword, List<SimpleIdentifier> shownNames)
-      : super(keyword) {
-    _shownNames = new NodeList<SimpleIdentifier>(this, shownNames);
-  }
-
-  @override
-  // TODO(paulberry): add commas.
-  Iterable get childEntities => new ChildEntities()
-    ..add(keyword)
-    ..addAll(_shownNames);
-
-  @override
-  Token get endToken => _shownNames.endToken;
-
-  /**
-   * Return the list of names from the library that are made visible by this
-   * combinator.
-   */
-  NodeList<SimpleIdentifier> get shownNames => _shownNames;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitShowCombinator(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _shownNames.accept(visitor);
-  }
-}
-
-/**
- * A simple formal parameter.
- *
- * > simpleFormalParameter ::=
- * >     ('final' [TypeName] | 'var' | [TypeName])? [SimpleIdentifier]
- */
-class SimpleFormalParameter extends NormalFormalParameter {
-  /**
-   * The token representing either the 'final', 'const' or 'var' keyword, or
-   * `null` if no keyword was used.
-   */
-  Token keyword;
-
-  /**
-   * The name of the declared type of the parameter, or `null` if the parameter
-   * does not have a declared type.
-   */
-  TypeName _type;
-
-  /**
-   * Initialize a newly created formal parameter. Either or both of the
-   * [comment] and [metadata] can be `null` if the parameter does not have the
-   * corresponding attribute. The [keyword] can be `null` if a type was
-   * specified. The [type] must be `null` if the keyword is 'var'.
-   */
-  SimpleFormalParameter(Comment comment, List<Annotation> metadata,
-      this.keyword, TypeName type, SimpleIdentifier identifier)
-      : super(comment, metadata, identifier) {
-    _type = _becomeParentOf(type);
-  }
-
-  @override
-  Token get beginToken {
-    NodeList<Annotation> metadata = this.metadata;
-    if (!metadata.isEmpty) {
-      return metadata.beginToken;
-    } else if (keyword != null) {
-      return keyword;
-    } else if (_type != null) {
-      return _type.beginToken;
-    }
-    return identifier.beginToken;
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(keyword)..add(_type)..add(identifier);
-
-  @override
-  Token get endToken => identifier.endToken;
-
-  @override
-  bool get isConst =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
-
-  @override
-  bool get isFinal =>
-      (keyword is KeywordToken) &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
-
-  /**
-   * Return the name of the declared type of the parameter, or `null` if the
-   * parameter does not have a declared type.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the name of the declared type of the parameter to the given [typeName].
-   */
-  void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSimpleFormalParameter(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _safelyVisitChild(identifier, visitor);
-  }
-}
-
-/**
- * A simple identifier.
- *
- * > simpleIdentifier ::=
- * >     initialCharacter internalCharacter*
- * >
- * > initialCharacter ::= '_' | '$' | letter
- * >
- * > internalCharacter ::= '_' | '$' | letter | digit
- */
-class SimpleIdentifier extends Identifier {
-  /**
-   * The token representing the identifier.
-   */
-  Token token;
-
-  /**
-   * The element associated with this identifier based on static type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this identifier could not be resolved.
-   */
-  Element _staticElement;
-
-  /**
-   * The element associated with this identifier based on propagated type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this identifier could not be resolved.
-   */
-  Element _propagatedElement;
-
-  /**
-   * If this expression is both in a getter and setter context, the
-   * [AuxiliaryElements] will be set to hold onto the static and propagated
-   * information. The auxiliary element will hold onto the elements from the
-   * getter context.
-   */
-  AuxiliaryElements auxiliaryElements = null;
-
-  /**
-   * Initialize a newly created identifier.
-   */
-  SimpleIdentifier(this.token);
-
-  @override
-  Token get beginToken => token;
-
-  @override
-  Element get bestElement {
-    if (_propagatedElement == null) {
-      return _staticElement;
-    }
-    return _propagatedElement;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(token);
-
-  @override
-  Token get endToken => token;
-
-  /**
-   * Return `true` if this identifier is the "name" part of a prefixed
-   * identifier or a method invocation.
-   */
-  bool get isQualified {
-    AstNode parent = this.parent;
-    if (parent is PrefixedIdentifier) {
-      return identical(parent.identifier, this);
-    }
-    if (parent is PropertyAccess) {
-      return identical(parent.propertyName, this);
-    }
-    if (parent is MethodInvocation) {
-      MethodInvocation invocation = parent;
-      return identical(invocation.methodName, this) &&
-          invocation.realTarget != null;
-    }
-    return false;
-  }
-
-  @override
-  bool get isSynthetic => token.isSynthetic;
-
-  @override
-  String get name => token.lexeme;
-
-  @override
-  int get precedence => 16;
-
-  @override
-  Element get propagatedElement => _propagatedElement;
-
-  /**
-   * Set the element associated with this identifier based on propagated type
-   * information to the given [element].
-   */
-  void set propagatedElement(Element element) {
-    _propagatedElement = _validateElement(element);
-  }
-
-  @override
-  Element get staticElement => _staticElement;
-
-  /**
-   * Set the element associated with this identifier based on static type
-   * information to the given [element].
-   */
-  void set staticElement(Element element) {
-    _staticElement = _validateElement(element);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSimpleIdentifier(this);
-
-  /**
-   * Return `true` if this identifier is the name being declared in a
-   * declaration.
-   */
-  bool inDeclarationContext() {
-    // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
-    if (parent is CatchClause) {
-      CatchClause clause = parent;
-      return identical(this, clause.exceptionParameter) ||
-          identical(this, clause.stackTraceParameter);
-    } else if (parent is ClassDeclaration) {
-      return identical(this, parent.name);
-    } else if (parent is ClassTypeAlias) {
-      return identical(this, parent.name);
-    } else if (parent is ConstructorDeclaration) {
-      return identical(this, parent.name);
-    } else if (parent is DeclaredIdentifier) {
-      return identical(this, parent.identifier);
-    } else if (parent is EnumDeclaration) {
-      return identical(this, parent.name);
-    } else if (parent is EnumConstantDeclaration) {
-      return identical(this, parent.name);
-    } else if (parent is FunctionDeclaration) {
-      return identical(this, parent.name);
-    } else if (parent is FunctionTypeAlias) {
-      return identical(this, parent.name);
-    } else if (parent is ImportDirective) {
-      return identical(this, parent.prefix);
-    } else if (parent is Label) {
-      return identical(this, parent.label) &&
-          (parent.parent is LabeledStatement);
-    } else if (parent is MethodDeclaration) {
-      return identical(this, parent.name);
-    } else if (parent is FunctionTypedFormalParameter ||
-        parent is SimpleFormalParameter) {
-      return identical(this, (parent as NormalFormalParameter).identifier);
-    } else if (parent is TypeParameter) {
-      return identical(this, parent.name);
-    } else if (parent is VariableDeclaration) {
-      return identical(this, parent.name);
-    }
-    return false;
-  }
-
-  /**
-   * Return `true` if this expression is computing a right-hand value.
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
-  bool inGetterContext() {
-    // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
-    AstNode target = this;
-    // skip prefix
-    if (parent is PrefixedIdentifier) {
-      PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
-      if (identical(prefixed.prefix, this)) {
-        return true;
-      }
-      parent = prefixed.parent;
-      target = prefixed;
-    } else if (parent is PropertyAccess) {
-      PropertyAccess access = parent as PropertyAccess;
-      if (identical(access.target, this)) {
-        return true;
-      }
-      parent = access.parent;
-      target = access;
-    }
-    // skip label
-    if (parent is Label) {
-      return false;
-    }
-    // analyze usage
-    if (parent is AssignmentExpression) {
-      if (identical(parent.leftHandSide, target) &&
-          parent.operator.type == TokenType.EQ) {
-        return false;
-      }
-    }
-    if (parent is ForEachStatement) {
-      if (identical(parent.identifier, target)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Return `true` if this expression is computing a left-hand value.
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
-  bool inSetterContext() {
-    // TODO(brianwilkerson) Convert this to a getter.
-    AstNode parent = this.parent;
-    AstNode target = this;
-    // skip prefix
-    if (parent is PrefixedIdentifier) {
-      PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
-      // if this is the prefix, then return false
-      if (identical(prefixed.prefix, this)) {
-        return false;
-      }
-      parent = prefixed.parent;
-      target = prefixed;
-    } else if (parent is PropertyAccess) {
-      PropertyAccess access = parent as PropertyAccess;
-      if (identical(access.target, this)) {
-        return false;
-      }
-      parent = access.parent;
-      target = access;
-    }
-    // analyze usage
-    if (parent is PrefixExpression) {
-      return parent.operator.type.isIncrementOperator;
-    } else if (parent is PostfixExpression) {
-      return true;
-    } else if (parent is AssignmentExpression) {
-      return identical(parent.leftHandSide, target);
-    } else if (parent is ForEachStatement) {
-      return identical(parent.identifier, target);
-    }
-    return false;
-  }
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-
-  /**
-   * Return the given element if it is valid, or report the problem and return
-   * `null` if it is not appropriate.
-   *
-   * The [parent] is the parent of the element, used for reporting when there is
-   * a problem.
-   * The [isValid] is `true` if the element is appropriate.
-   * The [element] is the element to be associated with this identifier.
-   */
-  Element _returnOrReportElement(
-      AstNode parent, bool isValid, Element element) {
-    if (!isValid) {
-      AnalysisEngine.instance.logger.logInformation(
-          "Internal error: attempting to set the name of a ${parent.runtimeType} to a ${element.runtimeType}",
-          new CaughtException(new AnalysisException(), null));
-      return null;
-    }
-    return element;
-  }
-
-  /**
-   * Return the given [element] if it is an appropriate element based on the
-   * parent of this identifier, or `null` if it is not appropriate.
-   */
-  Element _validateElement(Element element) {
-    if (element == null) {
-      return null;
-    }
-    AstNode parent = this.parent;
-    if (parent is ClassDeclaration && identical(parent.name, this)) {
-      return _returnOrReportElement(parent, element is ClassElement, element);
-    } else if (parent is ClassTypeAlias && identical(parent.name, this)) {
-      return _returnOrReportElement(parent, element is ClassElement, element);
-    } else if (parent is DeclaredIdentifier &&
-        identical(parent.identifier, this)) {
-      return _returnOrReportElement(
-          parent, element is LocalVariableElement, element);
-    } else if (parent is FormalParameter &&
-        identical(parent.identifier, this)) {
-      return _returnOrReportElement(
-          parent, element is ParameterElement, element);
-    } else if (parent is FunctionDeclaration && identical(parent.name, this)) {
-      return _returnOrReportElement(
-          parent, element is ExecutableElement, element);
-    } else if (parent is FunctionTypeAlias && identical(parent.name, this)) {
-      return _returnOrReportElement(
-          parent, element is FunctionTypeAliasElement, element);
-    } else if (parent is MethodDeclaration && identical(parent.name, this)) {
-      return _returnOrReportElement(
-          parent, element is ExecutableElement, element);
-    } else if (parent is TypeParameter && identical(parent.name, this)) {
-      return _returnOrReportElement(
-          parent, element is TypeParameterElement, element);
-    } else if (parent is VariableDeclaration && identical(parent.name, this)) {
-      return _returnOrReportElement(
-          parent, element is VariableElement, element);
-    }
-    return element;
-  }
-}
-
-/**
- * A string literal expression that does not contain any interpolations.
- *
- * > simpleStringLiteral ::=
- * >     rawStringLiteral
- * >   | basicStringLiteral
- * >
- * > rawStringLiteral ::=
- * >     'r' basicStringLiteral
- * >
- * > simpleStringLiteral ::=
- * >     multiLineStringLiteral
- * >   | singleLineStringLiteral
- * >
- * > multiLineStringLiteral ::=
- * >     "'''" characters "'''"
- * >   | '"""' characters '"""'
- * >
- * > singleLineStringLiteral ::=
- * >     "'" characters "'"
- * >   | '"' characters '"'
- */
-class SimpleStringLiteral extends SingleStringLiteral {
-  /**
-   * The token representing the literal.
-   */
-  Token literal;
-
-  /**
-   * The value of the literal.
-   */
-  String _value;
-
-  /**
-   * Initialize a newly created simple string literal.
-   */
-  SimpleStringLiteral(this.literal, String value) {
-    _value = StringUtilities.intern(value);
-  }
-
-  @override
-  Token get beginToken => literal;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(literal);
-
-  @override
-  int get contentsEnd => offset + _helper.end;
-
-  @override
-  int get contentsOffset => offset + _helper.start;
-
-  @override
-  Token get endToken => literal;
-
-  @override
-  bool get isMultiline => _helper.isMultiline;
-
-  @override
-  bool get isRaw => _helper.isRaw;
-
-  @override
-  bool get isSingleQuoted => _helper.isSingleQuoted;
-
-  @override
-  bool get isSynthetic => literal.isSynthetic;
-
-  /**
-   * Return the value of the literal.
-   */
-  String get value => _value;
-
-  /**
-   * Set the value of the literal to the given [string].
-   */
-  void set value(String string) {
-    _value = StringUtilities.intern(_value);
-  }
-
-  StringLexemeHelper get _helper {
-    return new StringLexemeHelper(literal.lexeme, true, true);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSimpleStringLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-
-  @override
-  void _appendStringValue(StringBuffer buffer) {
-    buffer.write(value);
-  }
-}
-
-/**
- * A single string literal expression.
- *
- * > singleStringLiteral ::=
- * >     [SimpleStringLiteral]
- * >   | [StringInterpolation]
- */
-abstract class SingleStringLiteral extends StringLiteral {
-  /**
-   * Return the offset of the after-last contents character.
-   */
-  int get contentsEnd;
-
-  /**
-   * Return the offset of the first contents character.
-   * If the string is multiline, then leading whitespaces are skipped.
-   */
-  int get contentsOffset;
-
-  /**
-   * Return `true` if this string literal is a multi-line string.
-   */
-  bool get isMultiline;
-
-  /**
-   * Return `true` if this string literal is a raw string.
-   */
-  bool get isRaw;
-
-  /**
-   * Return `true` if this string literal uses single quotes (' or ''').
-   * Return `false` if this string literal uses double quotes (" or """).
-   */
-  bool get isSingleQuoted;
-}
-
-/**
- * A node that represents a statement.
- *
- * > statement ::=
- * >     [Block]
- * >   | [VariableDeclarationStatement]
- * >   | [ForStatement]
- * >   | [ForEachStatement]
- * >   | [WhileStatement]
- * >   | [DoStatement]
- * >   | [SwitchStatement]
- * >   | [IfStatement]
- * >   | [TryStatement]
- * >   | [BreakStatement]
- * >   | [ContinueStatement]
- * >   | [ReturnStatement]
- * >   | [ExpressionStatement]
- * >   | [FunctionDeclarationStatement]
- */
-abstract class Statement extends AstNode {
-  /**
-   * If this is a labeled statement, return the unlabeled portion of the
-   * statement.  Otherwise return the statement itself.
-   */
-  Statement get unlabeled => this;
-}
-
-/**
- * A string interpolation literal.
- *
- * > stringInterpolation ::=
- * >     ''' [InterpolationElement]* '''
- * >   | '"' [InterpolationElement]* '"'
- */
-class StringInterpolation extends SingleStringLiteral {
-  /**
-   * The elements that will be composed to produce the resulting string.
-   */
-  NodeList<InterpolationElement> _elements;
-
-  /**
-   * Initialize a newly created string interpolation expression.
-   */
-  StringInterpolation(List<InterpolationElement> elements) {
-    _elements = new NodeList<InterpolationElement>(this, elements);
-  }
-
-  @override
-  Token get beginToken => _elements.beginToken;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..addAll(_elements);
-
-  @override
-  int get contentsEnd {
-    InterpolationString element = _elements.last;
-    return element.contentsEnd;
-  }
-
-  @override
-  int get contentsOffset {
-    InterpolationString element = _elements.first;
-    return element.contentsOffset;
-  }
-
-  /**
-   * Return the elements that will be composed to produce the resulting string.
-   */
-  NodeList<InterpolationElement> get elements => _elements;
-
-  @override
-  Token get endToken => _elements.endToken;
-
-  @override
-  bool get isMultiline => _firstHelper.isMultiline;
-
-  @override
-  bool get isRaw => false;
-
-  @override
-  bool get isSingleQuoted => _firstHelper.isSingleQuoted;
-
-  StringLexemeHelper get _firstHelper {
-    InterpolationString lastString = _elements.first;
-    String lexeme = lastString.contents.lexeme;
-    return new StringLexemeHelper(lexeme, true, false);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitStringInterpolation(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _elements.accept(visitor);
-  }
-
-  @override
-  void _appendStringValue(StringBuffer buffer) {
-    throw new IllegalArgumentException();
-  }
-}
-
-/**
- * A helper for analyzing string lexemes.
- */
-class StringLexemeHelper {
-  final String lexeme;
-  final bool isFirst;
-  final bool isLast;
-
-  bool isRaw = false;
-  bool isSingleQuoted = false;
-  bool isMultiline = false;
-  int start = 0;
-  int end;
-
-  StringLexemeHelper(this.lexeme, this.isFirst, this.isLast) {
-    if (isFirst) {
-      isRaw = StringUtilities.startsWithChar(lexeme, 0x72);
-      if (isRaw) {
-        start++;
-      }
-      if (StringUtilities.startsWith3(lexeme, start, 0x27, 0x27, 0x27)) {
-        isSingleQuoted = true;
-        isMultiline = true;
-        start += 3;
-        start = _trimInitialWhitespace(start);
-      } else if (StringUtilities.startsWith3(lexeme, start, 0x22, 0x22, 0x22)) {
-        isSingleQuoted = false;
-        isMultiline = true;
-        start += 3;
-        start = _trimInitialWhitespace(start);
-      } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x27) {
-        isSingleQuoted = true;
-        isMultiline = false;
-        start++;
-      } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x22) {
-        isSingleQuoted = false;
-        isMultiline = false;
-        start++;
-      }
-    }
-    end = lexeme.length;
-    if (isLast) {
-      if (start + 3 <= end &&
-          (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) ||
-              StringUtilities.endsWith3(lexeme, 0x27, 0x27, 0x27))) {
-        end -= 3;
-      } else if (start + 1 <= end &&
-          (StringUtilities.endsWithChar(lexeme, 0x22) ||
-              StringUtilities.endsWithChar(lexeme, 0x27))) {
-        end -= 1;
-      }
-    }
-  }
-
-  /**
-   * Given the [lexeme] for a multi-line string whose content begins at the
-   * given [start] index, return the index of the first character that is
-   * included in the value of the string. According to the specification:
-   *
-   * If the first line of a multiline string consists solely of the whitespace
-   * characters defined by the production WHITESPACE 20.1), possibly prefixed
-   * by \, then that line is ignored, including the new line at its end.
-   */
-  int _trimInitialWhitespace(int start) {
-    int length = lexeme.length;
-    int index = start;
-    while (index < length) {
-      int currentChar = lexeme.codeUnitAt(index);
-      if (currentChar == 0x0D) {
-        if (index + 1 < length && lexeme.codeUnitAt(index + 1) == 0x0A) {
-          return index + 2;
-        }
-        return index + 1;
-      } else if (currentChar == 0x0A) {
-        return index + 1;
-      } else if (currentChar == 0x5C) {
-        if (index + 1 >= length) {
-          return start;
-        }
-        currentChar = lexeme.codeUnitAt(index + 1);
-        if (currentChar != 0x0D &&
-            currentChar != 0x0A &&
-            currentChar != 0x09 &&
-            currentChar != 0x20) {
-          return start;
-        }
-      } else if (currentChar != 0x09 && currentChar != 0x20) {
-        return start;
-      }
-      index++;
-    }
-    return start;
-  }
-}
-
-/**
- * A string literal expression.
- *
- * > stringLiteral ::=
- * >     [SimpleStringLiteral]
- * >   | [AdjacentStrings]
- * >   | [StringInterpolation]
- */
-abstract class StringLiteral extends Literal {
-  /**
-   * Return the value of the string literal, or `null` if the string is not a
-   * constant string without any string interpolation.
-   */
-  String get stringValue {
-    StringBuffer buffer = new StringBuffer();
-    try {
-      _appendStringValue(buffer);
-    } on IllegalArgumentException {
-      return null;
-    }
-    return buffer.toString();
-  }
-
-  /**
-   * Append the value of this string literal to the given [buffer]. Throw an
-   * [IllegalArgumentException] if the string is not a constant string without
-   * any string interpolation.
-   */
-  void _appendStringValue(StringBuffer buffer);
-}
-
-/**
- * The invocation of a superclass' constructor from within a constructor's
- * initialization list.
- *
- * > superInvocation ::=
- * >     'super' ('.' [SimpleIdentifier])? [ArgumentList]
- */
-class SuperConstructorInvocation extends ConstructorInitializer {
-  /**
-   * The token for the 'super' keyword.
-   */
-  Token superKeyword;
-
-  /**
-   * The token for the period before the name of the constructor that is being
-   * invoked, or `null` if the unnamed constructor is being invoked.
-   */
-  Token period;
-
-  /**
-   * The name of the constructor that is being invoked, or `null` if the unnamed
-   * constructor is being invoked.
-   */
-  SimpleIdentifier _constructorName;
-
-  /**
-   * The list of arguments to the constructor.
-   */
-  ArgumentList _argumentList;
-
-  /**
-   * The element associated with the constructor based on static type
-   * information, or `null` if the AST structure has not been resolved or if the
-   * constructor could not be resolved.
-   */
-  ConstructorElement staticElement;
-
-  /**
-   * Initialize a newly created super invocation to invoke the inherited
-   * constructor with the given name with the given arguments. The [period] and
-   * [constructorName] can be `null` if the constructor being invoked is the
-   * unnamed constructor.
-   */
-  SuperConstructorInvocation(this.superKeyword, this.period,
-      SimpleIdentifier constructorName, ArgumentList argumentList) {
-    _constructorName = _becomeParentOf(constructorName);
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  /**
-   * Return the list of arguments to the constructor.
-   */
-  ArgumentList get argumentList => _argumentList;
-
-  /**
-   * Set the list of arguments to the constructor to the given [argumentList].
-   */
-  void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
-  }
-
-  @override
-  Token get beginToken => superKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(superKeyword)
-    ..add(period)
-    ..add(_constructorName)
-    ..add(_argumentList);
-
-  /**
-   * Return the name of the constructor that is being invoked, or `null` if the
-   * unnamed constructor is being invoked.
-   */
-  SimpleIdentifier get constructorName => _constructorName;
-
-  /**
-   * Set the name of the constructor that is being invoked to the given
-   * [identifier].
-   */
-  void set constructorName(SimpleIdentifier identifier) {
-    _constructorName = _becomeParentOf(identifier);
-  }
-
-  @override
-  Token get endToken => _argumentList.endToken;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSuperConstructorInvocation(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_constructorName, visitor);
-    _safelyVisitChild(_argumentList, visitor);
-  }
-}
-
-/**
- * A super expression.
- *
- * > superExpression ::=
- * >     'super'
- */
-class SuperExpression extends Expression {
-  /**
-   * The token representing the 'super' keyword.
-   */
-  Token superKeyword;
-
-  /**
-   * Initialize a newly created super expression.
-   */
-  SuperExpression(this.superKeyword);
-
-  @override
-  Token get beginToken => superKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(superKeyword);
-
-  @override
-  Token get endToken => superKeyword;
-
-  @override
-  int get precedence => 16;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSuperExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A case in a switch statement.
- *
- * > switchCase ::=
- * >     [SimpleIdentifier]* 'case' [Expression] ':' [Statement]*
- */
-class SwitchCase extends SwitchMember {
-  /**
-   * The expression controlling whether the statements will be executed.
-   */
-  Expression _expression;
-
-  /**
-   * Initialize a newly created switch case. The list of [labels] can be `null`
-   * if there are no labels.
-   */
-  SwitchCase(List<Label> labels, Token keyword, Expression expression,
-      Token colon, List<Statement> statements)
-      : super(labels, keyword, colon, statements) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..addAll(labels)
-    ..add(keyword)
-    ..add(_expression)
-    ..add(colon)
-    ..addAll(statements);
-
-  /**
-   * Return the expression controlling whether the statements will be executed.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression controlling whether the statements will be executed to
-   * the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSwitchCase(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    labels.accept(visitor);
-    _safelyVisitChild(_expression, visitor);
-    statements.accept(visitor);
-  }
-}
-
-/**
- * The default case in a switch statement.
- *
- * > switchDefault ::=
- * >     [SimpleIdentifier]* 'default' ':' [Statement]*
- */
-class SwitchDefault extends SwitchMember {
-  /**
-   * Initialize a newly created switch default. The list of [labels] can be
-   * `null` if there are no labels.
-   */
-  SwitchDefault(List<Label> labels, Token keyword, Token colon,
-      List<Statement> statements)
-      : super(labels, keyword, colon, statements);
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..addAll(labels)
-    ..add(keyword)
-    ..add(colon)
-    ..addAll(statements);
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSwitchDefault(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    labels.accept(visitor);
-    statements.accept(visitor);
-  }
-}
-
-/**
- * An element within a switch statement.
- *
- * > switchMember ::=
- * >     switchCase
- * >   | switchDefault
- */
-abstract class SwitchMember extends AstNode {
-  /**
-   * The labels associated with the switch member.
-   */
-  NodeList<Label> _labels;
-
-  /**
-   * The token representing the 'case' or 'default' keyword.
-   */
-  Token keyword;
-
-  /**
-   * The colon separating the keyword or the expression from the statements.
-   */
-  Token colon;
-
-  /**
-   * The statements that will be executed if this switch member is selected.
-   */
-  NodeList<Statement> _statements;
-
-  /**
-   * Initialize a newly created switch member. The list of [labels] can be
-   * `null` if there are no labels.
-   */
-  SwitchMember(List<Label> labels, this.keyword, this.colon,
-      List<Statement> statements) {
-    _labels = new NodeList<Label>(this, labels);
-    _statements = new NodeList<Statement>(this, statements);
-  }
-
-  @override
-  Token get beginToken {
-    if (!_labels.isEmpty) {
-      return _labels.beginToken;
-    }
-    return keyword;
-  }
-
-  @override
-  Token get endToken {
-    if (!_statements.isEmpty) {
-      return _statements.endToken;
-    }
-    return colon;
-  }
-
-  /**
-   * Return the labels associated with the switch member.
-   */
-  NodeList<Label> get labels => _labels;
-
-  /**
-   * Return the statements that will be executed if this switch member is
-   * selected.
-   */
-  NodeList<Statement> get statements => _statements;
-}
-
-/**
- * A switch statement.
- *
- * > switchStatement ::=
- * >     'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}'
- */
-class SwitchStatement extends Statement {
-  /**
-   * The token representing the 'switch' keyword.
-   */
-  Token switchKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The expression used to determine which of the switch members will be
-   * selected.
-   */
-  Expression _expression;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The left curly bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The switch members that can be selected by the expression.
-   */
-  NodeList<SwitchMember> _members;
-
-  /**
-   * The right curly bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created switch statement. The list of [members] can be
-   * `null` if there are no switch members.
-   */
-  SwitchStatement(
-      this.switchKeyword,
-      this.leftParenthesis,
-      Expression expression,
-      this.rightParenthesis,
-      this.leftBracket,
-      List<SwitchMember> members,
-      this.rightBracket) {
-    _expression = _becomeParentOf(expression);
-    _members = new NodeList<SwitchMember>(this, members);
-  }
-
-  @override
-  Token get beginToken => switchKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(switchKeyword)
-    ..add(leftParenthesis)
-    ..add(_expression)
-    ..add(rightParenthesis)
-    ..add(leftBracket)
-    ..addAll(_members)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken => rightBracket;
-
-  /**
-   * Return the expression used to determine which of the switch members will be
-   * selected.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression used to determine which of the switch members will be
-   * selected to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return the switch members that can be selected by the expression.
-   */
-  NodeList<SwitchMember> get members => _members;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSwitchStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-    _members.accept(visitor);
-  }
-}
-
-/**
- * A symbol literal expression.
- *
- * > symbolLiteral ::=
- * >     '#' (operator | (identifier ('.' identifier)*))
- */
-class SymbolLiteral extends Literal {
-  /**
-   * The token introducing the literal.
-   */
-  Token poundSign;
-
-  /**
-   * The components of the literal.
-   */
-  final List<Token> components;
-
-  /**
-   * Initialize a newly created symbol literal.
-   */
-  SymbolLiteral(this.poundSign, this.components);
-
-  @override
-  Token get beginToken => poundSign;
-
-  @override
-  // TODO(paulberry): add "." tokens.
-  Iterable get childEntities => new ChildEntities()
-    ..add(poundSign)
-    ..addAll(components);
-
-  @override
-  Token get endToken => components[components.length - 1];
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitSymbolLiteral(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A this expression.
- *
- * > thisExpression ::=
- * >     'this'
- */
-class ThisExpression extends Expression {
-  /**
-   * The token representing the 'this' keyword.
-   */
-  Token thisKeyword;
-
-  /**
-   * Initialize a newly created this expression.
-   */
-  ThisExpression(this.thisKeyword);
-
-  @override
-  Token get beginToken => thisKeyword;
-
-  @override
-  Iterable get childEntities => new ChildEntities()..add(thisKeyword);
-
-  @override
-  Token get endToken => thisKeyword;
-
-  @override
-  int get precedence => 16;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitThisExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    // There are no children to visit.
-  }
-}
-
-/**
- * A throw expression.
- *
- * > throwExpression ::=
- * >     'throw' [Expression]
- */
-class ThrowExpression extends Expression {
-  /**
-   * The token representing the 'throw' keyword.
-   */
-  Token throwKeyword;
-
-  /**
-   * The expression computing the exception to be thrown.
-   */
-  Expression _expression;
-
-  /**
-   * Initialize a newly created throw expression.
-   */
-  ThrowExpression(this.throwKeyword, Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken => throwKeyword;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(throwKeyword)..add(_expression);
-
-  @override
-  Token get endToken {
-    if (_expression != null) {
-      return _expression.endToken;
-    }
-    return throwKeyword;
-  }
-
-  /**
-   * Return the expression computing the exception to be thrown.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression computing the exception to be thrown to the given
-   * [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  int get precedence => 0;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitThrowExpression(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
-
-/**
- * The declaration of one or more top-level variables of the same type.
- *
- * > topLevelVariableDeclaration ::=
- * >     ('final' | 'const') type? staticFinalDeclarationList ';'
- * >   | variableDeclaration ';'
- */
-class TopLevelVariableDeclaration extends CompilationUnitMember {
-  /**
-   * The top-level variables being declared.
-   */
-  VariableDeclarationList _variableList;
-
-  /**
-   * The semicolon terminating the declaration.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created top-level variable declaration. Either or both
-   * of the [comment] and [metadata] can be `null` if the variable does not have
-   * the corresponding attribute.
-   */
-  TopLevelVariableDeclaration(Comment comment, List<Annotation> metadata,
-      VariableDeclarationList variableList, this.semicolon)
-      : super(comment, metadata) {
-    _variableList = _becomeParentOf(variableList);
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(_variableList)..add(semicolon);
-
-  @override
-  Element get element => null;
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => _variableList.beginToken;
-
-  /**
-   * Return the top-level variables being declared.
-   */
-  VariableDeclarationList get variables => _variableList;
-
-  /**
-   * Set the top-level variables being declared to the given list of
-   * [variables].
-   */
-  void set variables(VariableDeclarationList variables) {
-    _variableList = _becomeParentOf(variables);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitTopLevelVariableDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_variableList, visitor);
-  }
-}
-
-/**
- * A try statement.
- *
- * > tryStatement ::=
- * >     'try' [Block] ([CatchClause]+ finallyClause? | finallyClause)
- * >
- * > finallyClause ::=
- * >     'finally' [Block]
- */
-class TryStatement extends Statement {
-  /**
-   * The token representing the 'try' keyword.
-   */
-  Token tryKeyword;
-
-  /**
-   * The body of the statement.
-   */
-  Block _body;
-
-  /**
-   * The catch clauses contained in the try statement.
-   */
-  NodeList<CatchClause> _catchClauses;
-
-  /**
-   * The token representing the 'finally' keyword, or `null` if the statement
-   * does not contain a finally clause.
-   */
-  Token finallyKeyword;
-
-  /**
-   * The finally block contained in the try statement, or `null` if the
-   * statement does not contain a finally clause.
-   */
-  Block _finallyBlock;
-
-  /**
-   * Initialize a newly created try statement. The list of [catchClauses] can be
-   * `null` if there are no catch clauses. The [finallyKeyword] and
-   * [finallyBlock] can be `null` if there is no finally clause.
-   */
-  TryStatement(this.tryKeyword, Block body, List<CatchClause> catchClauses,
-      this.finallyKeyword, Block finallyBlock) {
-    _body = _becomeParentOf(body);
-    _catchClauses = new NodeList<CatchClause>(this, catchClauses);
-    _finallyBlock = _becomeParentOf(finallyBlock);
-  }
-
-  @override
-  Token get beginToken => tryKeyword;
-
-  /**
-   * Return the body of the statement.
-   */
-  Block get body => _body;
-
-  /**
-   * Set the body of the statement to the given [block].
-   */
-  void set body(Block block) {
-    _body = _becomeParentOf(block);
-  }
-
-  /**
-   * Return the catch clauses contained in the try statement.
-   */
-  NodeList<CatchClause> get catchClauses => _catchClauses;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(tryKeyword)
-    ..add(_body)
-    ..addAll(_catchClauses)
-    ..add(finallyKeyword)
-    ..add(_finallyBlock);
-
-  @override
-  Token get endToken {
-    if (_finallyBlock != null) {
-      return _finallyBlock.endToken;
-    } else if (finallyKeyword != null) {
-      return finallyKeyword;
-    } else if (!_catchClauses.isEmpty) {
-      return _catchClauses.endToken;
-    }
-    return _body.endToken;
-  }
-
-  /**
-   * Return the finally block contained in the try statement, or `null` if the
-   * statement does not contain a finally clause.
-   */
-  Block get finallyBlock => _finallyBlock;
-
-  /**
-   * Set the finally block contained in the try statement to the given [block].
-   */
-  void set finallyBlock(Block block) {
-    _finallyBlock = _becomeParentOf(block);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitTryStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_body, visitor);
-    _catchClauses.accept(visitor);
-    _safelyVisitChild(_finallyBlock, visitor);
-  }
-}
-
-/**
- * The declaration of a type alias.
- *
- * > typeAlias ::=
- * >     'typedef' typeAliasBody
- * >
- * > typeAliasBody ::=
- * >     classTypeAlias
- * >   | functionTypeAlias
- */
-abstract class TypeAlias extends NamedCompilationUnitMember {
-  /**
-   * The token representing the 'typedef' keyword.
-   */
-  Token typedefKeyword;
-
-  /**
-   * The semicolon terminating the declaration.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created type alias. Either or both of the [comment] and
-   * [metadata] can be `null` if the declaration does not have the corresponding
-   * attribute.
-   */
-  TypeAlias(Comment comment, List<Annotation> metadata, this.typedefKeyword,
-      SimpleIdentifier name, this.semicolon)
-      : super(comment, metadata, name);
-
-  @override
-  Token get endToken => semicolon;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => typedefKeyword;
-}
-
-/**
- * A list of type arguments.
- *
- * > typeArguments ::=
- * >     '<' typeName (',' typeName)* '>'
- */
-class TypeArgumentList extends AstNode {
-  /**
-   * The left bracket.
-   */
-  Token leftBracket;
-
-  /**
-   * The type arguments associated with the type.
-   */
-  NodeList<TypeName> _arguments;
-
-  /**
-   * The right bracket.
-   */
-  Token rightBracket;
-
-  /**
-   * Initialize a newly created list of type arguments.
-   */
-  TypeArgumentList(
-      this.leftBracket, List<TypeName> arguments, this.rightBracket) {
-    _arguments = new NodeList<TypeName>(this, arguments);
-  }
-
-  /**
-   * Return the type arguments associated with the type.
-   */
-  NodeList<TypeName> get arguments => _arguments;
-
-  @override
-  Token get beginToken => leftBracket;
-
-  @override
-  // TODO(paulberry): Add commas.
-  Iterable get childEntities => new ChildEntities()
-    ..add(leftBracket)
-    ..addAll(_arguments)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken => rightBracket;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitTypeArgumentList(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _arguments.accept(visitor);
-  }
-}
-
-/**
- * A literal that has a type associated with it.
- *
- * > typedLiteral ::=
- * >     [ListLiteral]
- * >   | [MapLiteral]
- */
-abstract class TypedLiteral extends Literal {
-  /**
-   * The token representing the 'const' keyword, or `null` if the literal is not
-   * a constant.
-   */
-  Token constKeyword;
-
-  /**
-   * The type argument associated with this literal, or `null` if no type
-   * arguments were declared.
-   */
-  TypeArgumentList _typeArguments;
-
-  /**
-   * Initialize a newly created typed literal. The [constKeyword] can be `null`\
-   * if the literal is not a constant. The [typeArguments] can be `null` if no
-   * type arguments were declared.
-   */
-  TypedLiteral(this.constKeyword, TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  /**
-   * Return the type argument associated with this literal, or `null` if no type
-   * arguments were declared.
-   */
-  TypeArgumentList get typeArguments => _typeArguments;
-
-  /**
-   * Set the type argument associated with this literal to the given
-   * [typeArguments].
-   */
-  void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  ChildEntities get _childEntities =>
-      new ChildEntities()..add(constKeyword)..add(_typeArguments);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_typeArguments, visitor);
-  }
-}
-
-/**
- * The name of a type, which can optionally include type arguments.
- *
- * > typeName ::=
- * >     [Identifier] typeArguments?
- */
-class TypeName extends AstNode {
-  /**
-   * The name of the type.
-   */
-  Identifier _name;
-
-  /**
-   * The type arguments associated with the type, or `null` if there are no type
-   * arguments.
-   */
-  TypeArgumentList _typeArguments;
-
-  /**
-   * The type being named, or `null` if the AST structure has not been resolved.
-   */
-  DartType type;
-
-  /**
-   * Initialize a newly created type name. The [typeArguments] can be `null` if
-   * there are no type arguments.
-   */
-  TypeName(Identifier name, TypeArgumentList typeArguments) {
-    _name = _becomeParentOf(name);
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  @override
-  Token get beginToken => _name.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_name)..add(_typeArguments);
-
-  @override
-  Token get endToken {
-    if (_typeArguments != null) {
-      return _typeArguments.endToken;
-    }
-    return _name.endToken;
-  }
-
-  /**
-   * Return `true` if this type is a deferred type.
-   *
-   * 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
-   * </i>p.T</i> where <i>p</i> is a deferred prefix.
-   */
-  bool get isDeferred {
-    Identifier identifier = name;
-    if (identifier is! PrefixedIdentifier) {
-      return false;
-    }
-    return (identifier as PrefixedIdentifier).isDeferred;
-  }
-
-  @override
-  bool get isSynthetic => _name.isSynthetic && _typeArguments == null;
-
-  /**
-   * Return the name of the type.
-   */
-  Identifier get name => _name;
-
-  /**
-   * Set the name of the type to the given [identifier].
-   */
-  void set name(Identifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  /**
-   * Return the type arguments associated with the type, or `null` if there are
-   * no type arguments.
-   */
-  TypeArgumentList get typeArguments => _typeArguments;
-
-  /**
-   * Set the type arguments associated with the type to the given
-   * [typeArguments].
-   */
-  void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitTypeName(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_typeArguments, visitor);
-  }
-}
-
-/**
- * A type parameter.
- *
- * > typeParameter ::=
- * >     [SimpleIdentifier] ('extends' [TypeName])?
- */
-class TypeParameter extends Declaration {
-  /**
-   * The name of the type parameter.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * The token representing the 'extends' keyword, or `null` if there is no
-   * explicit upper bound.
-   */
-  Token extendsKeyword;
-
-  /**
-   * The name of the upper bound for legal arguments, or `null` if there is no
-   * explicit upper bound.
-   */
-  TypeName _bound;
-
-  /**
-   * Initialize a newly created type parameter. Either or both of the [comment]
-   * and [metadata] can be `null` if the parameter does not have the
-   * corresponding attribute. The [extendsKeyword] and [bound] can be `null` if
-   * the parameter does not have an upper bound.
-   */
-  TypeParameter(Comment comment, List<Annotation> metadata,
-      SimpleIdentifier name, this.extendsKeyword, TypeName bound)
-      : super(comment, metadata) {
-    _name = _becomeParentOf(name);
-    _bound = _becomeParentOf(bound);
-  }
-
-  /**
-   * Return the name of the upper bound for legal arguments, or `null` if there
-   * is no explicit upper bound.
-   */
-  TypeName get bound => _bound;
-
-  /**
-   * Set the name of the upper bound for legal arguments to the given
-   * [typeName].
-   */
-  void set bound(TypeName typeName) {
-    _bound = _becomeParentOf(typeName);
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(_name)..add(extendsKeyword)..add(_bound);
-
-  @override
-  TypeParameterElement get element =>
-      _name != null ? (_name.staticElement as TypeParameterElement) : null;
-
-  @override
-  Token get endToken {
-    if (_bound == null) {
-      return _name.endToken;
-    }
-    return _bound.endToken;
-  }
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
-
-  /**
-   * Return the name of the type parameter.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the type parameter to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitTypeParameter(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_bound, visitor);
-  }
-}
-
-/**
- * Type parameters within a declaration.
- *
- * > typeParameterList ::=
- * >     '<' [TypeParameter] (',' [TypeParameter])* '>'
- */
-class TypeParameterList extends AstNode {
-  /**
-   * The left angle bracket.
-   */
-  final Token leftBracket;
-
-  /**
-   * The type parameters in the list.
-   */
-  NodeList<TypeParameter> _typeParameters;
-
-  /**
-   * The right angle bracket.
-   */
-  final Token rightBracket;
-
-  /**
-   * Initialize a newly created list of type parameters.
-   */
-  TypeParameterList(
-      this.leftBracket, List<TypeParameter> typeParameters, this.rightBracket) {
-    _typeParameters = new NodeList<TypeParameter>(this, typeParameters);
-  }
-
-  @override
-  Token get beginToken => leftBracket;
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(leftBracket)
-    ..addAll(_typeParameters)
-    ..add(rightBracket);
-
-  @override
-  Token get endToken => rightBracket;
-
-  /**
-   * Return the type parameters for the type.
-   */
-  NodeList<TypeParameter> get typeParameters => _typeParameters;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitTypeParameterList(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _typeParameters.accept(visitor);
-  }
-}
-
-/**
- * A directive that references a URI.
- *
- * > uriBasedDirective ::=
- * >     [ExportDirective]
- * >   | [ImportDirective]
- * >   | [PartDirective]
- */
-abstract class UriBasedDirective extends Directive {
-  /**
-   * The prefix of a URI using the `dart-ext` scheme to reference a native code
-   * library.
-   */
-  static String _DART_EXT_SCHEME = "dart-ext:";
-
-  /**
-   * The URI referenced by this directive.
-   */
-  StringLiteral _uri;
-
-  /**
-   * The content of the URI.
-   */
-  String uriContent;
-
-  /**
-   * The source to which the URI was resolved.
-   */
-  Source source;
-
-  /**
-   * Initialize a newly create URI-based directive. Either or both of the
-   * [comment] and [metadata] can be `null` if the directive does not have the
-   * corresponding attribute.
-   */
-  UriBasedDirective(
-      Comment comment, List<Annotation> metadata, StringLiteral uri)
-      : super(comment, metadata) {
-    _uri = _becomeParentOf(uri);
-  }
-
-  /**
-   * Return the URI referenced by this directive.
-   */
-  StringLiteral get uri => _uri;
-
-  /**
-   * Set the URI referenced by this directive to the given [uri].
-   */
-  void set uri(StringLiteral uri) {
-    _uri = _becomeParentOf(uri);
-  }
-
-  /**
-   * Return the element associated with the URI of this directive, or `null` if
-   * the AST structure has not been resolved or if the URI could not be
-   * resolved. Examples of the latter case include a directive that contains an
-   * invalid URL or a URL that does not exist.
-   */
-  Element get uriElement;
-
-  /**
-   * Validate this directive, but do not check for existence. Return a code
-   * indicating the problem if there is one, or `null` no problem
-   */
-  UriValidationCode validate() {
-    StringLiteral uriLiteral = uri;
-    if (uriLiteral is StringInterpolation) {
-      return UriValidationCode.URI_WITH_INTERPOLATION;
-    }
-    String uriContent = this.uriContent;
-    if (uriContent == null) {
-      return UriValidationCode.INVALID_URI;
-    }
-    if (this is ImportDirective && uriContent.startsWith(_DART_EXT_SCHEME)) {
-      return UriValidationCode.URI_WITH_DART_EXT_SCHEME;
-    }
-    try {
-      parseUriWithException(Uri.encodeFull(uriContent));
-    } on URISyntaxException {
-      return UriValidationCode.INVALID_URI;
-    }
-    return null;
-  }
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_uri, visitor);
-  }
-}
-
-/**
- * Validation codes returned by [UriBasedDirective.validate].
- */
-class UriValidationCode {
-  static const UriValidationCode INVALID_URI =
-      const UriValidationCode('INVALID_URI');
-
-  static const UriValidationCode URI_WITH_INTERPOLATION =
-      const UriValidationCode('URI_WITH_INTERPOLATION');
-
-  static const UriValidationCode URI_WITH_DART_EXT_SCHEME =
-      const UriValidationCode('URI_WITH_DART_EXT_SCHEME');
-
-  /**
-   * The name of the validation code.
-   */
-  final String name;
-
-  /**
-   * Initialize a newly created validation code to have the given [name].
-   */
-  const UriValidationCode(this.name);
-
-  @override
-  String toString() => name;
-}
-
-/**
- * An identifier that has an initial value associated with it. Instances of this
- * class are always children of the class [VariableDeclarationList].
- *
- * > variableDeclaration ::=
- * >     [SimpleIdentifier] ('=' [Expression])?
- *
- * TODO(paulberry): the grammar does not allow metadata to be associated with
- * a VariableDeclaration, and currently we don't record comments for it either.
- * Consider changing the class hierarchy so that [VariableDeclaration] does not
- * extend [Declaration].
- */
-class VariableDeclaration extends Declaration {
-  /**
-   * The name of the variable being declared.
-   */
-  SimpleIdentifier _name;
-
-  /**
-   * The equal sign separating the variable name from the initial value, or
-   * `null` if the initial value was not specified.
-   */
-  Token equals;
-
-  /**
-   * The expression used to compute the initial value for the variable, or
-   * `null` if the initial value was not specified.
-   */
-  Expression _initializer;
-
-  /**
-   * Initialize a newly created variable declaration. The [equals] and
-   * [initializer] can be `null` if there is no initializer.
-   */
-  VariableDeclaration(
-      SimpleIdentifier name, this.equals, Expression initializer)
-      : super(null, null) {
-    _name = _becomeParentOf(name);
-    _initializer = _becomeParentOf(initializer);
-  }
-
-  @override
-  Iterable get childEntities =>
-      super._childEntities..add(_name)..add(equals)..add(_initializer);
-
-  /**
-   * This overridden implementation of getDocumentationComment() looks in the
-   * grandparent node for Dartdoc comments if no documentation is specifically
-   * available on the node.
-   */
-  @override
-  Comment get documentationComment {
-    Comment comment = super.documentationComment;
-    if (comment == null) {
-      if (parent != null && parent.parent != null) {
-        AstNode node = parent.parent;
-        if (node is AnnotatedNode) {
-          return node.documentationComment;
-        }
-      }
-    }
-    return comment;
-  }
-
-  @override
-  VariableElement get element =>
-      _name != null ? (_name.staticElement as VariableElement) : null;
-
-  @override
-  Token get endToken {
-    if (_initializer != null) {
-      return _initializer.endToken;
-    }
-    return _name.endToken;
-  }
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
-
-  /**
-   * Return the expression used to compute the initial value for the variable,
-   * or `null` if the initial value was not specified.
-   */
-  Expression get initializer => _initializer;
-
-  /**
-   * Set the expression used to compute the initial value for the variable to
-   * the given [expression].
-   */
-  void set initializer(Expression expression) {
-    _initializer = _becomeParentOf(expression);
-  }
-
-  /**
-   * Return `true` if this variable was declared with the 'const' modifier.
-   */
-  bool get isConst {
-    AstNode parent = this.parent;
-    return parent is VariableDeclarationList && parent.isConst;
-  }
-
-  /**
-   * Return `true` if this variable was declared with the 'final' modifier.
-   * Variables that are declared with the 'const' modifier will return `false`
-   * even though they are implicitly final.
-   */
-  bool get isFinal {
-    AstNode parent = this.parent;
-    return parent is VariableDeclarationList && parent.isFinal;
-  }
-
-  /**
-   * Return the name of the variable being declared.
-   */
-  SimpleIdentifier get name => _name;
-
-  /**
-   * Set the name of the variable being declared to the given [identifier].
-   */
-  void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitVariableDeclaration(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_name, visitor);
-    _safelyVisitChild(_initializer, visitor);
-  }
-}
-
-/**
- * The declaration of one or more variables of the same type.
- *
- * > variableDeclarationList ::=
- * >     finalConstVarOrType [VariableDeclaration] (',' [VariableDeclaration])*
- * >
- * > finalConstVarOrType ::=
- * >   | 'final' [TypeName]?
- * >   | 'const' [TypeName]?
- * >   | 'var'
- * >   | [TypeName]
- */
-class VariableDeclarationList extends AnnotatedNode {
-  /**
-   * The token representing the 'final', 'const' or 'var' keyword, or `null` if
-   * no keyword was included.
-   */
-  Token keyword;
-
-  /**
-   * The type of the variables being declared, or `null` if no type was provided.
-   */
-  TypeName _type;
-
-  /**
-   * A list containing the individual variables being declared.
-   */
-  NodeList<VariableDeclaration> _variables;
-
-  /**
-   * Initialize a newly created variable declaration list. Either or both of the
-   * [comment] and [metadata] can be `null` if the variable list does not have
-   * the corresponding attribute. The [keyword] can be `null` if a type was
-   * specified. The [type] must be `null` if the keyword is 'var'.
-   */
-  VariableDeclarationList(Comment comment, List<Annotation> metadata,
-      this.keyword, TypeName type, List<VariableDeclaration> variables)
-      : super(comment, metadata) {
-    _type = _becomeParentOf(type);
-    _variables = new NodeList<VariableDeclaration>(this, variables);
-  }
-
-  @override
-  // TODO(paulberry): include commas.
-  Iterable get childEntities => super._childEntities
-    ..add(keyword)
-    ..add(_type)
-    ..addAll(_variables);
-
-  @override
-  Token get endToken => _variables.endToken;
-
-  @override
-  Token get firstTokenAfterCommentAndMetadata {
-    if (keyword != null) {
-      return keyword;
-    } else if (_type != null) {
-      return _type.beginToken;
-    }
-    return _variables.beginToken;
-  }
-
-  /**
-   * Return `true` if the variables in this list were declared with the 'const'
-   * modifier.
-   */
-  bool get isConst =>
-      keyword is KeywordToken &&
-      (keyword as KeywordToken).keyword == Keyword.CONST;
-
-  /**
-   * Return `true` if the variables in this list were declared with the 'final'
-   * modifier. Variables that are declared with the 'const' modifier will return
-   * `false` even though they are implicitly final. (In other words, this is a
-   * syntactic check rather than a semantic check.)
-   */
-  bool get isFinal =>
-      keyword is KeywordToken &&
-      (keyword as KeywordToken).keyword == Keyword.FINAL;
-
-  /**
-   * Return the type of the variables being declared, or `null` if no type was
-   * provided.
-   */
-  TypeName get type => _type;
-
-  /**
-   * Set the type of the variables being declared to the given [typeName].
-   */
-  void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
-  }
-
-  /**
-   * Return a list containing the individual variables being declared.
-   */
-  NodeList<VariableDeclaration> get variables => _variables;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitVariableDeclarationList(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _safelyVisitChild(_type, visitor);
-    _variables.accept(visitor);
-  }
-}
-
-/**
- * A list of variables that are being declared in a context where a statement is
- * required.
- *
- * > variableDeclarationStatement ::=
- * >     [VariableDeclarationList] ';'
- */
-class VariableDeclarationStatement extends Statement {
-  /**
-   * The variables being declared.
-   */
-  VariableDeclarationList _variableList;
-
-  /**
-   * The semicolon terminating the statement.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created variable declaration statement.
-   */
-  VariableDeclarationStatement(
-      VariableDeclarationList variableList, this.semicolon) {
-    _variableList = _becomeParentOf(variableList);
-  }
-
-  @override
-  Token get beginToken => _variableList.beginToken;
-
-  @override
-  Iterable get childEntities =>
-      new ChildEntities()..add(_variableList)..add(semicolon);
-
-  @override
-  Token get endToken => semicolon;
-
-  /**
-   * Return the variables being declared.
-   */
-  VariableDeclarationList get variables => _variableList;
-
-  /**
-   * Set the variables being declared to the given list of [variables].
-   */
-  void set variables(VariableDeclarationList variables) {
-    _variableList = _becomeParentOf(variables);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitVariableDeclarationStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_variableList, visitor);
-  }
-}
-
-/**
- * A while statement.
- *
- * > whileStatement ::=
- * >     'while' '(' [Expression] ')' [Statement]
- */
-class WhileStatement extends Statement {
-  /**
-   * The token representing the 'while' keyword.
-   */
-  Token whileKeyword;
-
-  /**
-   * The left parenthesis.
-   */
-  Token leftParenthesis;
-
-  /**
-   * The expression used to determine whether to execute the body of the loop.
-   */
-  Expression _condition;
-
-  /**
-   * The right parenthesis.
-   */
-  Token rightParenthesis;
-
-  /**
-   * The body of the loop.
-   */
-  Statement _body;
-
-  /**
-   * Initialize a newly created while statement.
-   */
-  WhileStatement(this.whileKeyword, this.leftParenthesis, Expression condition,
-      this.rightParenthesis, Statement body) {
-    _condition = _becomeParentOf(condition);
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  Token get beginToken => whileKeyword;
-
-  /**
-   * Return the body of the loop.
-   */
-  Statement get body => _body;
-
-  /**
-   * Set the body of the loop to the given [statement].
-   */
-  void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(whileKeyword)
-    ..add(leftParenthesis)
-    ..add(_condition)
-    ..add(rightParenthesis)
-    ..add(_body);
-
-  /**
-   * Return the expression used to determine whether to execute the body of the
-   * loop.
-   */
-  Expression get condition => _condition;
-
-  /**
-   * Set the expression used to determine whether to execute the body of the
-   * loop to the given [expression].
-   */
-  void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get endToken => _body.endToken;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitWhileStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_condition, visitor);
-    _safelyVisitChild(_body, visitor);
-  }
-}
-
-/**
- * The with clause in a class declaration.
- *
- * > withClause ::=
- * >     'with' [TypeName] (',' [TypeName])*
- */
-class WithClause extends AstNode {
-  /**
-   * The token representing the 'with' keyword.
-   */
-  Token withKeyword;
-
-  /**
-   * The names of the mixins that were specified.
-   */
-  NodeList<TypeName> _mixinTypes;
-
-  /**
-   * Initialize a newly created with clause.
-   */
-  WithClause(this.withKeyword, List<TypeName> mixinTypes) {
-    _mixinTypes = new NodeList<TypeName>(this, mixinTypes);
-  }
-
-  @override
-  Token get beginToken => withKeyword;
-
-  @override
-  // TODO(paulberry): add commas.
-  Iterable get childEntities => new ChildEntities()
-    ..add(withKeyword)
-    ..addAll(_mixinTypes);
-
-  @override
-  Token get endToken => _mixinTypes.endToken;
-
-  /**
-   * Return the names of the mixins that were specified.
-   */
-  NodeList<TypeName> get mixinTypes => _mixinTypes;
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitWithClause(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _mixinTypes.accept(visitor);
-  }
-}
-
-/**
- * A yield statement.
- *
- * > yieldStatement ::=
- * >     'yield' '*'? [Expression] ‘;’
- */
-class YieldStatement extends Statement {
-  /**
-   * The 'yield' keyword.
-   */
-  Token yieldKeyword;
-
-  /**
-   * The star optionally following the 'yield' keyword.
-   */
-  Token star;
-
-  /**
-   * The expression whose value will be yielded.
-   */
-  Expression _expression;
-
-  /**
-   * The semicolon following the expression.
-   */
-  Token semicolon;
-
-  /**
-   * Initialize a newly created yield expression. The [star] can be `null` if no
-   * star was provided.
-   */
-  YieldStatement(
-      this.yieldKeyword, this.star, Expression expression, this.semicolon) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  Token get beginToken {
-    if (yieldKeyword != null) {
-      return yieldKeyword;
-    }
-    return _expression.beginToken;
-  }
-
-  @override
-  Iterable get childEntities => new ChildEntities()
-    ..add(yieldKeyword)
-    ..add(star)
-    ..add(_expression)
-    ..add(semicolon);
-
-  @override
-  Token get endToken {
-    if (semicolon != null) {
-      return semicolon;
-    }
-    return _expression.endToken;
-  }
-
-  /**
-   * Return the expression whose value will be yielded.
-   */
-  Expression get expression => _expression;
-
-  /**
-   * Set the expression whose value will be yielded to the given [expression].
-   */
-  void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
-  }
-
-  @override
-  accept(AstVisitor visitor) => visitor.visitYieldStatement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _safelyVisitChild(_expression, visitor);
-  }
-}
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index a561978..efb81e3 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -6,11 +6,13 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisEngine, RecordingErrorListener;
@@ -157,6 +159,13 @@
   ConstantAstCloner() : super(true);
 
   @override
+  ConstructorName visitConstructorName(ConstructorName node) {
+    ConstructorName name = super.visitConstructorName(node);
+    name.staticElement = node.staticElement;
+    return name;
+  }
+
+  @override
   InstanceCreationExpression visitInstanceCreationExpression(
       InstanceCreationExpression node) {
     InstanceCreationExpression expression =
@@ -441,13 +450,6 @@
    * Determine which constant elements need to have their values computed
    * prior to computing the value of [constant], and report them using
    * [callback].
-   *
-   * Note that it's possible (in erroneous code) for a constant to depend on a
-   * non-constant.  When this happens, we report the dependency anyhow so that
-   * if the non-constant changes to a constant, we will know to recompute the
-   * thing that depends on it.  [computeDependencies] and
-   * [computeConstantValue] are responsible for ignoring the request if they
-   * are asked to act on a non-constant target.
    */
   void computeDependencies(
       ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
@@ -1616,7 +1618,9 @@
     DartObjectImpl rightResult = node.rightOperand.accept(this);
     TokenType operatorType = node.operator.type;
     // 'null' is almost never good operand
-    if (operatorType != TokenType.BANG_EQ && operatorType != TokenType.EQ_EQ) {
+    if (operatorType != TokenType.BANG_EQ &&
+        operatorType != TokenType.EQ_EQ &&
+        operatorType != TokenType.QUESTION_QUESTION) {
       if (leftResult != null && leftResult.isNull ||
           rightResult != null && rightResult.isNull) {
         _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
@@ -1665,6 +1669,9 @@
         return _dartObjectComputer.divide(node, leftResult, rightResult);
       } else if (operatorType == TokenType.TILDE_SLASH) {
         return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
+      } else if (operatorType == TokenType.QUESTION_QUESTION) {
+        return _dartObjectComputer.questionQuestion(
+            node, leftResult, rightResult);
       } else {
         // TODO(brianwilkerson) Figure out which error to report.
         _error(node, null);
@@ -2461,6 +2468,17 @@
     return null;
   }
 
+  DartObjectImpl questionQuestion(Expression node, DartObjectImpl leftOperand,
+      DartObjectImpl rightOperand) {
+    if (leftOperand != null && rightOperand != null) {
+      if (leftOperand.isNull) {
+        return rightOperand;
+      }
+      return leftOperand;
+    }
+    return null;
+  }
+
   DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand,
       DartObjectImpl rightOperand) {
     if (leftOperand != null && rightOperand != null) {
@@ -5232,7 +5250,7 @@
     if (element is PropertyAccessorElement) {
       element = (element as PropertyAccessorElement).variable;
     }
-    if (element is VariableElement) {
+    if (element is VariableElement && element.isConst) {
       _callback(element);
     }
     return null;
diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart
index 968d797..4ff96d5 100644
--- a/pkg/analyzer/lib/src/generated/element.dart
+++ b/pkg/analyzer/lib/src/generated/element.dart
@@ -9,7 +9,7 @@
  * * package:analyzer/dart/element/type.dart
  * * package:analyzer/dart/element/visitor.dart
  *
- * If your code is using API's not available in these public libraries, please
+ * If your code is using APIs not available in these public libraries, please
  * contact the analyzer team to either find an alternate API or have the API you
  * depend on added to the public API.
  */
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
index 0a29cfb..03f9137 100644
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ b/pkg/analyzer/lib/src/generated/element_handle.dart
@@ -7,7 +7,7 @@
 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/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -754,6 +754,9 @@
   bool get isBrowserApplication => actualElement.isBrowserApplication;
 
   @override
+  bool get isDartAsync => actualElement.isDartAsync;
+
+  @override
   bool get isDartCore => actualElement.isDartCore;
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 368da2a..5bf9630 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -6,11 +6,14 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/ast/ast.dart'
+    show ChildEntities, IdentifierImpl;
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -427,9 +430,9 @@
   @override
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     Expression function = node.function;
-    DartType staticInvokeType =
-        _resolveGenericMethod(function.staticType, node.typeArguments, node);
-    DartType propagatedInvokeType = _resolveGenericMethod(
+    DartType staticInvokeType = _instantiateGenericMethod(
+        function.staticType, node.typeArguments, node);
+    DartType propagatedInvokeType = _instantiateGenericMethod(
         function.propagatedType, node.typeArguments, node);
 
     node.staticInvokeType = staticInvokeType;
@@ -616,7 +619,9 @@
             [(target as SimpleIdentifier).name]);
       }
       LibraryElement importedLibrary = _getImportedLibrary(target);
-      methodName.staticElement = importedLibrary.loadLibraryFunction;
+      FunctionElement loadLibraryFunction = importedLibrary.loadLibraryFunction;
+      methodName.staticElement = loadLibraryFunction;
+      node.staticInvokeType = loadLibraryFunction.type;
       return null;
     } else {
       //
@@ -650,9 +655,23 @@
     staticElement = _convertSetterToGetter(staticElement);
     propagatedElement = _convertSetterToGetter(propagatedElement);
 
-    DartType staticInvokeType = _computeMethodInvokeType(node, staticElement);
-    DartType propagatedInvokeType =
-        _computeMethodInvokeType(node, propagatedElement);
+    //
+    // Given the elements, determine the type of the function we are invoking
+    //
+    DartType staticInvokeType = _getInvokeType(staticElement);
+    methodName.staticType = staticInvokeType;
+
+    DartType propagatedInvokeType = _getInvokeType(propagatedElement);
+    methodName.propagatedType =
+        _propagatedInvokeTypeIfBetter(propagatedInvokeType, staticInvokeType);
+
+    //
+    // Instantiate generic function or method if needed.
+    //
+    staticInvokeType = _instantiateGenericMethod(
+        staticInvokeType, node.typeArguments, node.methodName);
+    propagatedInvokeType = _instantiateGenericMethod(
+        propagatedInvokeType, node.typeArguments, node.methodName);
 
     //
     // Record the results.
@@ -1336,30 +1355,6 @@
     return null;
   }
 
-  DartType _computeMethodInvokeType(MethodInvocation node, Element element) {
-    if (element == null) {
-      // TODO(jmesserly): should we return `dynamic` in this case?
-      // Otherwise we have to guard against `null` every time we use
-      // `staticInvokeType`.
-      // If we do return `dynamic` we need to be careful that this doesn't
-      // adversely affect propagatedType code path. But it shouldn't because
-      // we'll discard `dynamic` anyway (see _propagatedInvokeTypeIfBetter).
-      return null;
-    }
-
-    DartType invokeType;
-    if (element is PropertyAccessorElement) {
-      invokeType = element.returnType;
-    } else if (element is ExecutableElement) {
-      invokeType = element.type;
-    } else if (element is VariableElement) {
-      invokeType = _promoteManager.getStaticType(element);
-    }
-
-    return _resolveGenericMethod(
-        invokeType, node.typeArguments, node.methodName);
-  }
-
   /**
    * If the given [element] is a setter, return the getter associated with it.
    * Otherwise, return the element unchanged.
@@ -1437,6 +1432,28 @@
   }
 
   /**
+   * Given an element, computes the type of the invocation.
+   *
+   * For executable elements (like methods, functions) this is just their type.
+   *
+   * For variables it is their type taking into account any type promotion.
+   *
+   * For calls to getters in Dart, we invoke the function that is returned by
+   * the getter, so the invoke type is the getter's returnType.
+   */
+  DartType _getInvokeType(Element element) {
+    DartType invokeType;
+    if (element is PropertyAccessorElement) {
+      invokeType = element.returnType;
+    } else if (element is ExecutableElement) {
+      invokeType = element.type;
+    } else if (element is VariableElement) {
+      invokeType = _promoteManager.getStaticType(element);
+    }
+    return invokeType ?? DynamicTypeImpl.instance;
+  }
+
+  /**
    * Return the name of the method invoked by the given postfix [expression].
    */
   String _getPostfixOperator(PostfixExpression expression) =>
@@ -1497,6 +1514,36 @@
   }
 
   /**
+   * Check for a generic method & apply type arguments if any were passed.
+   */
+  DartType _instantiateGenericMethod(
+      DartType invokeType, TypeArgumentList typeArguments, AstNode node) {
+    // TODO(jmesserly): support generic "call" methods on InterfaceType.
+    if (invokeType is FunctionType) {
+      FunctionType type = invokeType;
+      List<TypeParameterElement> parameters = type.typeFormals;
+
+      NodeList<TypeName> arguments = typeArguments?.arguments;
+      if (arguments != null && arguments.length != parameters.length) {
+        // Wrong number of type arguments. Ignore them
+        arguments = null;
+        _resolver.reportErrorForNode(
+            StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+            node,
+            [type, parameters.length, arguments?.length ?? 0]);
+      }
+      if (parameters.isNotEmpty) {
+        if (arguments == null) {
+          invokeType = _resolver.typeSystem.instantiateToBounds(type);
+        } else {
+          invokeType = type.instantiate(arguments.map((n) => n.type).toList());
+        }
+      }
+    }
+    return invokeType;
+  }
+
+  /**
    * Return `true` if the given [expression] is a prefix for a deferred import.
    */
   bool _isDeferredPrefix(Expression expression) {
@@ -2081,36 +2128,6 @@
   }
 
   /**
-   * Check for a generic method & apply type arguments if any were passed.
-   */
-  DartType _resolveGenericMethod(
-      DartType invokeType, TypeArgumentList typeArguments, AstNode node) {
-    // TODO(jmesserly): support generic "call" methods on InterfaceType.
-    if (invokeType is FunctionType) {
-      FunctionType type = invokeType;
-      List<TypeParameterElement> parameters = type.typeFormals;
-
-      NodeList<TypeName> arguments = typeArguments?.arguments;
-      if (arguments != null && arguments.length != parameters.length) {
-        // Wrong number of type arguments. Ignore them
-        arguments = null;
-        _resolver.reportErrorForNode(
-            StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
-            node,
-            [type, parameters.length, arguments?.length ?? 0]);
-      }
-      if (parameters.isNotEmpty) {
-        if (arguments == null) {
-          invokeType = _resolver.typeSystem.instantiateToBounds(type);
-        } else {
-          invokeType = type.instantiate(arguments.map((n) => n.type).toList());
-        }
-      }
-    }
-    return invokeType;
-  }
-
-  /**
    * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the
    * element being invoked. If the returned element is a method, then the method
    * will be invoked. If the returned element is a getter, the getter will be
@@ -2559,7 +2576,7 @@
  * AST when the parser could not distinguish between a method invocation and an
  * invocation of a top-level function imported with a prefix.
  */
-class SyntheticIdentifier extends Identifier {
+class SyntheticIdentifier extends IdentifierImpl {
   /**
    * The name of the synthetic identifier.
    */
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 4f8d664..b27c42e 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -7,13 +7,14 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -312,8 +313,8 @@
    * Perform work until the given [result] has been computed for the given
    * [target]. Return the computed value.
    */
-  Object /*=V*/ computeResult /*<V>*/ (
-      AnalysisTarget target, ResultDescriptor /*<V>*/ result);
+  Object/*=V*/ computeResult/*<V>*/(
+      AnalysisTarget target, ResultDescriptor/*<V>*/ result);
 
   /**
    * Notifies the context that the client is going to stop using this context.
@@ -474,8 +475,8 @@
    * If the corresponding [target] does not exist, or the [result] is not
    * computed yet, then the default value is returned.
    */
-  Object /*=V*/ getResult /*<V>*/ (
-      AnalysisTarget target, ResultDescriptor /*<V>*/ result);
+  Object/*=V*/ getResult/*<V>*/(
+      AnalysisTarget target, ResultDescriptor/*<V>*/ result);
 
   /**
    * Return a list of the sources being analyzed in this context whose full path
@@ -1589,6 +1590,7 @@
   /**
    * A list containing the sources that have been deleted.
    */
+  @deprecated
   final List<Source> deletedSources = new List<Source>();
 
   /**
@@ -1651,6 +1653,7 @@
   /**
    * Record that the specified [source] has been deleted.
    */
+  @deprecated
   void deletedSource(Source source) {
     deletedSources.add(source);
   }
@@ -1850,6 +1853,11 @@
  */
 abstract class InternalAnalysisContext implements AnalysisContext {
   /**
+   * The result provider for [aboutToComputeResult].
+   */
+  ResultProvider resultProvider;
+
+  /**
    * A table mapping the sources known to the context to the information known
    * about the source.
    */
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index aa43a7e..777e5bc 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -6,10 +6,10 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart' show AstNode;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/source/error_processor.dart';
-import 'package:analyzer/src/generated/ast.dart' show AstNode;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/scanner.dart'
@@ -19,6 +19,8 @@
 import 'package:analyzer/task/model.dart';
 import 'package:source_span/source_span.dart';
 
+import 'generated/shared_messages.dart' as shared_messages;
+
 /**
  * The descriptor used to associate error processors with analysis contexts in
  * configuration data.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index d644fcd..20462bb 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -7,13 +7,14 @@
 import 'dart:collection';
 import "dart:math" as math;
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 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/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -23,7 +24,6 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/scanner.dart' as sc;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
-import 'package:analyzer/src/generated/static_type_analyzer.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
@@ -1285,27 +1285,27 @@
         }
       }
     });
+
     if (notInitFinalFields.isNotEmpty) {
       foundError = true;
       AnalysisErrorWithProperties analysisError;
-      if (notInitFinalFields.length == 1) {
+      List<String> names = notInitFinalFields.map((item) => item.name).toList();
+      names.sort();
+      if (names.length == 1) {
         analysisError = _errorReporter.newErrorWithProperties(
             StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
             constructor.returnType,
-            [notInitFinalFields[0].name]);
-      } else if (notInitFinalFields.length == 2) {
+            names);
+      } else if (names.length == 2) {
         analysisError = _errorReporter.newErrorWithProperties(
             StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2,
             constructor.returnType,
-            [notInitFinalFields[0].name, notInitFinalFields[1].name]);
+            names);
       } else {
         analysisError = _errorReporter.newErrorWithProperties(
             StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS,
-            constructor.returnType, [
-          notInitFinalFields[0].name,
-          notInitFinalFields[1].name,
-          notInitFinalFields.length - 2
-        ]);
+            constructor.returnType,
+            [names[0], names[1], names.length - 2]);
       }
       analysisError.setProperty(
           ErrorProperty.NOT_INITIALIZED_FIELDS, notInitFinalFields);
@@ -5771,9 +5771,8 @@
     }
     DartType staticReturnType = getStaticType(returnExpression);
     if (staticReturnType != null && _enclosingFunction.isAsynchronous) {
-      return _typeProvider.futureType.substitute4(<DartType>[
-        StaticTypeAnalyzer.flattenFutures(_typeProvider, staticReturnType)
-      ]);
+      return _typeProvider.futureType.substitute4(
+          <DartType>[staticReturnType.flattenFutures(_typeSystem)]);
     }
     return staticReturnType;
   }
diff --git a/pkg/analyzer/lib/src/generated/generated/shared_messages.dart b/pkg/analyzer/lib/src/generated/generated/shared_messages.dart
new file mode 100644
index 0000000..2c1465c
--- /dev/null
+++ b/pkg/analyzer/lib/src/generated/generated/shared_messages.dart
@@ -0,0 +1,17 @@
+// 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.
+/*
+DON'T EDIT. GENERATED. DON'T EDIT.
+This file has been generated by 'publish.dart' in the dart_messages package.
+
+Messages are maintained in `lib/shared_messages.dart` of that same package.
+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';
+
+const AnalysisOptionsErrorCode exampleMessage = const AnalysisOptionsErrorCode(
+    'exampleMessage',
+    "{2} {1} {0}",
+    "an explanation on how to fix things");  // Generated. Don't edit.
diff --git a/pkg/analyzer/lib/src/generated/incremental_logger.dart b/pkg/analyzer/lib/src/generated/incremental_logger.dart
index d942aba..1de2534 100644
--- a/pkg/analyzer/lib/src/generated/incremental_logger.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_logger.dart
@@ -40,6 +40,11 @@
   void log(Object obj);
 
   /**
+   * Logs the given [exception] and [stackTrace].
+   */
+  void logException(Object exception, [Object stackTrace]);
+
+  /**
    * Starts a new timer.
    */
   LoggingTimer startTimer();
@@ -102,6 +107,16 @@
   }
 
   @override
+  void logException(Object exception, [Object stackTrace]) {
+    if (exception != null) {
+      log(exception);
+    }
+    if (stackTrace != null) {
+      log(stackTrace);
+    }
+  }
+
+  @override
   LoggingTimer startTimer() {
     return new LoggingTimer(this);
   }
@@ -147,6 +162,9 @@
   void log(Object obj) {}
 
   @override
+  void logException(Object exception, [Object stackTrace]) {}
+
+  @override
   LoggingTimer startTimer() {
     return new LoggingTimer(this);
   }
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
index 36d8784..f0f7a4c7 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolution_validator.dart
@@ -4,11 +4,11 @@
 
 library analyzer.src.generated.incremental_resolution_validator;
 
+import 'package:analyzer/dart/ast/ast.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/member.dart';
-import 'package:analyzer/src/generated/ast.dart';
 
 /**
  * Validates that the [actual] and the [expected] units have the same structure
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index b67b905..542e721 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -7,12 +7,14 @@
 import 'dart:collection';
 import 'dart:math' as math;
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -474,7 +476,8 @@
   void _assertCompatibleParameter(
       FormalParameter node, ParameterElement element) {
     _assertEquals(node.kind, element.parameterKind);
-    if (node.kind == ParameterKind.NAMED) {
+    if (node.kind == ParameterKind.NAMED ||
+        element.enclosingElement is ConstructorElement) {
       _assertEquals(node.identifier.name, element.name);
     }
     // check parameter type specific properties
@@ -597,12 +600,12 @@
   }
 
   void _assertSameAnnotations(AnnotatedNode node, Element element) {
-    List<Annotation> nodeAnnotaitons = node.metadata;
+    List<Annotation> nodeAnnotations = node.metadata;
     List<ElementAnnotation> elementAnnotations = element.metadata;
-    int length = nodeAnnotaitons.length;
+    int length = nodeAnnotations.length;
     _assertEquals(elementAnnotations.length, length);
     for (int i = 0; i < length; i++) {
-      _assertSameAnnotation(nodeAnnotaitons[i], elementAnnotations[i]);
+      _assertSameAnnotation(nodeAnnotations[i], elementAnnotations[i]);
     }
   }
 
@@ -1468,37 +1471,67 @@
         {
           List<AstNode> oldParents = _getParents(oldNode);
           List<AstNode> newParents = _getParents(newNode);
+          // fail if an initializer change
+          if (oldParents.any((n) => n is ConstructorInitializer) ||
+              newParents.any((n) => n is ConstructorInitializer)) {
+            logger.log('Failure: a change in a constructor initializer');
+            return false;
+          }
+          // find matching methods / bodies
           int length = math.min(oldParents.length, newParents.length);
           bool found = false;
           for (int i = 0; i < length; i++) {
             AstNode oldParent = oldParents[i];
             AstNode newParent = newParents[i];
-            if (oldParent is ConstructorInitializer ||
-                newParent is ConstructorInitializer) {
-              logger.log('Failure: changes in constant constructor initializers'
-                  ' may cause external changes in constant objects.');
-              return false;
-            }
-            if (oldParent is FunctionDeclaration &&
+            if (oldParent is CompilationUnit && newParent is CompilationUnit) {
+              int oldLength = oldParent.declarations.length;
+              int newLength = newParent.declarations.length;
+              if (oldLength != newLength) {
+                logger.log(
+                    'Failure: unit declarations mismatch $oldLength vs. $newLength');
+                return false;
+              }
+            } else if (oldParent is ClassDeclaration &&
+                newParent is ClassDeclaration) {
+              int oldLength = oldParent.members.length;
+              int newLength = newParent.members.length;
+              if (oldLength != newLength) {
+                logger.log(
+                    'Failure: class declarations mismatch $oldLength vs. $newLength');
+                return false;
+              }
+            } else if (oldParent is FunctionDeclaration &&
                     newParent is FunctionDeclaration ||
-                oldParent is MethodDeclaration &&
-                    newParent is MethodDeclaration ||
                 oldParent is ConstructorDeclaration &&
-                    newParent is ConstructorDeclaration) {
+                    newParent is ConstructorDeclaration ||
+                oldParent is MethodDeclaration &&
+                    newParent is MethodDeclaration) {
               Element oldElement = (oldParent as Declaration).element;
               if (new DeclarationMatcher().matches(newParent, oldElement) ==
                   DeclarationMatchKind.MATCH) {
                 oldNode = oldParent;
                 newNode = newParent;
                 found = true;
+              } else {
+                return false;
               }
-            }
-            if (oldParent is BlockFunctionBody &&
-                newParent is BlockFunctionBody) {
-              oldNode = oldParent;
-              newNode = newParent;
-              found = true;
-              break;
+            } else if (oldParent is FunctionBody && newParent is FunctionBody) {
+              if (oldParent is BlockFunctionBody &&
+                  newParent is BlockFunctionBody) {
+                oldNode = oldParent;
+                newNode = newParent;
+                found = true;
+                break;
+              }
+              logger.log('Failure: not a block function body.');
+              return false;
+            } else if (oldParent is FunctionExpression &&
+                newParent is FunctionExpression) {
+              // skip
+            } else {
+              logger.log('Failure: old and new parent mismatch'
+                  ' ${oldParent.runtimeType} vs. ${newParent.runtimeType}');
+              return false;
             }
           }
           if (!found) {
@@ -1555,9 +1588,12 @@
         return true;
       }
     } catch (e, st) {
-      logger.log(e);
-      logger.log(st);
+      logger.logException(e, st);
       logger.log('Failure: exception.');
+      // The incremental resolver log is usually turned off,
+      // so also log the exception to the instrumentation log.
+      AnalysisEngine.instance.logger.logError(
+          'Failure in incremental resolver', new CaughtException(e, st));
     } finally {
       logger.exit();
     }
@@ -1595,8 +1631,13 @@
     // find nodes
     int offset = oldComments.offset;
     logger.log('offset: $offset');
-    Comment oldComment = _findNodeCovering(_oldUnit, offset, offset);
-    Comment newComment = _findNodeCovering(newUnit, offset, offset);
+    AstNode oldNode = _findNodeCovering(_oldUnit, offset, offset);
+    AstNode newNode = _findNodeCovering(newUnit, offset, offset);
+    if (oldNode is! Comment || newNode is! Comment) {
+      return false;
+    }
+    Comment oldComment = oldNode;
+    Comment newComment = newNode;
     logger.log('oldComment.beginToken: ${oldComment.beginToken}');
     logger.log('newComment.beginToken: ${newComment.beginToken}');
     _updateOffset = oldToken.offset - 1;
@@ -1733,7 +1774,7 @@
         Token newComment = newToken.precedingComments;
         if (_compareToken(oldComment, newComment, 0, true) != null) {
           _TokenDifferenceKind diffKind = _TokenDifferenceKind.COMMENT;
-          if (oldComment is DocumentationCommentToken ||
+          if (oldComment is DocumentationCommentToken &&
               newComment is DocumentationCommentToken) {
             diffKind = _TokenDifferenceKind.COMMENT_DOC;
           }
@@ -1769,7 +1810,7 @@
         Token newComment = newToken.precedingComments;
         if (_compareToken(oldComment, newComment, delta, true) != null) {
           _TokenDifferenceKind diffKind = _TokenDifferenceKind.COMMENT;
-          if (oldComment is DocumentationCommentToken ||
+          if (oldComment is DocumentationCommentToken &&
               newComment is DocumentationCommentToken) {
             diffKind = _TokenDifferenceKind.COMMENT_DOC;
           }
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index de0306f..4f249be 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -7,7 +7,10 @@
 import 'dart:collection';
 import "dart:math" as math;
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisEngine, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/error.dart';
@@ -3798,8 +3801,7 @@
 
   /**
    * If the current token has the type [TokenType.GT], return it after advancing
-   * to the next token. Otherwise report an error and return the current token
-   * without advancing.
+   * to the next token. Otherwise report an error and create a synthetic token.
    */
   Token _expectGt() {
     if (_matchesGt()) {
@@ -3807,7 +3809,7 @@
     }
     _reportErrorForCurrentToken(
         ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]);
-    return _currentToken;
+    return _createSyntheticToken(TokenType.GT);
   }
 
   /**
@@ -5369,12 +5371,13 @@
    */
   Expression _parseConstExpression() {
     Token keyword = _expectKeyword(Keyword.CONST);
-    if (_matches(TokenType.OPEN_SQUARE_BRACKET) || _matches(TokenType.INDEX)) {
+    if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) {
+      return _parseListOrMapLiteral(keyword);
+    } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
+        _matches(TokenType.INDEX)) {
       return _parseListLiteral(keyword, null);
     } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
       return _parseMapLiteral(keyword, null);
-    } else if (_matches(TokenType.LT)) {
-      return _parseListOrMapLiteral(keyword);
     }
     return _parseInstanceCreationExpression(keyword);
   }
@@ -7394,11 +7397,6 @@
       return new IntegerLiteral(token, value);
     } else if (_matches(TokenType.STRING)) {
       return parseStringLiteral();
-    } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      return _parseMapLiteral(null, null);
-    } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
-        _matches(TokenType.INDEX)) {
-      return _parseListLiteral(null, null);
     } else if (_matchesIdentifier()) {
       // TODO(brianwilkerson) The code below was an attempt to recover from an
       // error case, but it needs to be applied as a recovery only after we
@@ -7431,8 +7429,13 @@
       } finally {
         _inInitializer = wasInInitializer;
       }
-    } else if (_matches(TokenType.LT)) {
+    } else if (_matches(TokenType.LT) || _injectGenericCommentTypeList()) {
       return _parseListOrMapLiteral(null);
+    } else if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
+      return _parseMapLiteral(null, null);
+    } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
+        _matches(TokenType.INDEX)) {
+      return _parseListLiteral(null, null);
     } else if (_matches(TokenType.QUESTION) &&
         _tokenMatches(_peek(), TokenType.IDENTIFIER)) {
       _reportErrorForCurrentToken(
@@ -9381,9 +9384,9 @@
   /**
    * Some environments, such as Fletch, do not support async.
    */
-  static const CompileTimeErrorCode ASYNC_NOT_SUPPORTED =
-      const CompileTimeErrorCode('ASYNC_NOT_SUPPORTED',
-          "Async and sync are not supported in this environment.");
+  static const ParserErrorCode ASYNC_NOT_SUPPORTED = const ParserErrorCode(
+      'ASYNC_NOT_SUPPORTED',
+      "Async and sync are not supported in this environment.");
 
   static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = const ParserErrorCode(
       'BREAK_OUTSIDE_OF_LOOP',
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 0d856c8..4ed3deb 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -6,13 +6,15 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -517,6 +519,8 @@
     }
     AstNode parent = identifier.parent;
     if ((parent is ConstructorName && identical(identifier, parent.name)) ||
+        (parent is ConstructorDeclaration &&
+            identical(identifier, parent.returnType)) ||
         (parent is SuperConstructorInvocation &&
             identical(identifier, parent.constructorName)) ||
         parent is HideCombinator) {
@@ -906,6 +910,63 @@
 }
 
 /**
+ * Utilities for [LibraryElementImpl] building.
+ */
+class BuildLibraryElementUtils {
+  /**
+   * Look through all of the compilation units defined for the given [library],
+   * looking for getters and setters that are defined in different compilation
+   * units but that have the same names. If any are found, make sure that they
+   * have the same variable element.
+   */
+  static void patchTopLevelAccessors(LibraryElementImpl library) {
+    // Without parts getters/setters already share the same variable element.
+    if (library.parts.isEmpty) {
+      return;
+    }
+    // Collect getters and setters.
+    HashMap<String, PropertyAccessorElement> getters =
+        new HashMap<String, PropertyAccessorElement>();
+    List<PropertyAccessorElement> setters = <PropertyAccessorElement>[];
+    _collectAccessors(getters, setters, library.definingCompilationUnit);
+    for (CompilationUnitElement unit in library.parts) {
+      _collectAccessors(getters, setters, unit);
+    }
+    // Move every setter to the corresponding getter's variable (if exists).
+    for (PropertyAccessorElement setter in setters) {
+      PropertyAccessorElement getter = getters[setter.displayName];
+      if (getter != null) {
+        TopLevelVariableElementImpl variable = getter.variable;
+        TopLevelVariableElementImpl setterVariable = setter.variable;
+        CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement;
+        setterUnit.replaceTopLevelVariable(setterVariable, variable);
+        variable.setter = setter;
+        (setter as PropertyAccessorElementImpl).variable = variable;
+      }
+    }
+  }
+
+  /**
+   * Add all of the non-synthetic [getters] and [setters] defined in the given
+   * [unit] that have no corresponding accessor to one of the given collections.
+   */
+  static void _collectAccessors(Map<String, PropertyAccessorElement> getters,
+      List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
+    for (PropertyAccessorElement accessor in unit.accessors) {
+      if (accessor.isGetter) {
+        if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
+          getters[accessor.displayName] = accessor;
+        }
+      } else {
+        if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
+          setters.add(accessor);
+        }
+      }
+    }
+  }
+}
+
+/**
  * Instances of the class `ClassScope` implement the scope defined by a class.
  */
 class ClassScope extends EnclosedScope {
@@ -2610,11 +2671,6 @@
   bool _inFunction = false;
 
   /**
-   * A flag indicating whether the class currently being visited can be used as a mixin.
-   */
-  bool _isValidMixin = false;
-
-  /**
    * A collection holding the elements defined in a class that need to have
    * their function type fixed to take into account type parameters of the
    * enclosing class, or `null` if we are not currently processing nodes within
@@ -2676,7 +2732,6 @@
   @override
   Object visitClassDeclaration(ClassDeclaration node) {
     ElementHolder holder = new ElementHolder();
-    _isValidMixin = true;
     _functionTypesToFix = new List<ExecutableElementImpl>();
     //
     // Process field declarations before constructors and methods so that field
@@ -2714,7 +2769,6 @@
     element.constructors = constructors;
     element.fields = holder.fields;
     element.methods = holder.methods;
-    element.validMixin = _isValidMixin;
     // Function types must be initialized after the enclosing element has been
     // set, for them to pick up the type parameters.
     for (ExecutableElementImpl e in _functionTypesToFix) {
@@ -2764,7 +2818,6 @@
 
   @override
   Object visitConstructorDeclaration(ConstructorDeclaration node) {
-    _isValidMixin = false;
     ElementHolder holder = new ElementHolder();
     bool wasInFunction = _inFunction;
     _inFunction = true;
@@ -3337,12 +3390,6 @@
   }
 
   @override
-  Object visitSuperExpression(SuperExpression node) {
-    _isValidMixin = false;
-    return super.visitSuperExpression(node);
-  }
-
-  @override
   Object visitSwitchCase(SwitchCase node) {
     for (Label label in node.labels) {
       SimpleIdentifier labelName = label.label;
@@ -6938,16 +6985,6 @@
 }
 
 /**
- * Instances of the class `LibraryResolver` are used to resolve one or more mutually dependent
- * libraries within a single context.
- */
-
-/**
- * Instances of the class `LibraryResolver` are used to resolve one or more mutually dependent
- * libraries within a single context.
- */
-
-/**
  * Instances of the class `LibraryScope` implement a scope containing all of the names defined
  * in a given library.
  */
@@ -8380,11 +8417,10 @@
   Object visitAwaitExpression(AwaitExpression node) {
     // TODO(leafp): Handle the implicit union type here
     // https://github.com/dart-lang/sdk/issues/25322
-    DartType contextType = StaticTypeAnalyzer.flattenFutures(
-        typeProvider, InferenceContext.getType(node));
+    DartType contextType = InferenceContext.getType(node);
     if (contextType != null) {
-      InterfaceType futureT =
-          typeProvider.futureType.substitute4([contextType]);
+      InterfaceType futureT = typeProvider.futureType
+          .substitute4([contextType.flattenFutures(typeSystem)]);
       InferenceContext.setType(node.expression, futureT);
     }
     return super.visitAwaitExpression(node);
@@ -9165,105 +9201,6 @@
     return null;
   }
 
-  /**
-   * Given an [argumentList] and the [parameters] related to the element that
-   * will be invoked using those arguments, compute the list of parameters that
-   * correspond to the list of arguments.
-   *
-   * An error will be reported to [onError] if any of the arguments cannot be
-   * matched to a parameter. onError can be null to ignore the error.
-   *
-   * The flag [reportAsError] should be `true` if a compile-time error should be
-   * reported; or `false` if a compile-time warning should be reported
-   *
-   * Returns the parameters that correspond to the arguments.
-   */
-  static List<ParameterElement> resolveArgumentsToParameters(
-      ArgumentList argumentList,
-      List<ParameterElement> parameters,
-      void onError(ErrorCode errorCode, AstNode node, [List<Object> arguments]),
-      {bool reportAsError: false}) {
-    List<ParameterElement> requiredParameters = new List<ParameterElement>();
-    List<ParameterElement> positionalParameters = new List<ParameterElement>();
-    HashMap<String, ParameterElement> namedParameters =
-        new HashMap<String, ParameterElement>();
-    for (ParameterElement parameter in parameters) {
-      ParameterKind kind = parameter.parameterKind;
-      if (kind == ParameterKind.REQUIRED) {
-        requiredParameters.add(parameter);
-      } else if (kind == ParameterKind.POSITIONAL) {
-        positionalParameters.add(parameter);
-      } else {
-        namedParameters[parameter.name] = parameter;
-      }
-    }
-    List<ParameterElement> unnamedParameters =
-        new List<ParameterElement>.from(requiredParameters);
-    unnamedParameters.addAll(positionalParameters);
-    int unnamedParameterCount = unnamedParameters.length;
-    int unnamedIndex = 0;
-    NodeList<Expression> arguments = argumentList.arguments;
-    int argumentCount = arguments.length;
-    List<ParameterElement> resolvedParameters =
-        new List<ParameterElement>(argumentCount);
-    int positionalArgumentCount = 0;
-    HashSet<String> usedNames = new HashSet<String>();
-    bool noBlankArguments = true;
-    for (int i = 0; i < argumentCount; i++) {
-      Expression argument = arguments[i];
-      if (argument is NamedExpression) {
-        SimpleIdentifier nameNode = argument.name.label;
-        String name = nameNode.name;
-        ParameterElement element = namedParameters[name];
-        if (element == null) {
-          ErrorCode errorCode = (reportAsError
-              ? CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER
-              : StaticWarningCode.UNDEFINED_NAMED_PARAMETER);
-          if (onError != null) {
-            onError(errorCode, nameNode, [name]);
-          }
-        } else {
-          resolvedParameters[i] = element;
-          nameNode.staticElement = element;
-        }
-        if (!usedNames.add(name)) {
-          if (onError != null) {
-            onError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode,
-                [name]);
-          }
-        }
-      } else {
-        if (argument is SimpleIdentifier && argument.name.isEmpty) {
-          noBlankArguments = false;
-        }
-        positionalArgumentCount++;
-        if (unnamedIndex < unnamedParameterCount) {
-          resolvedParameters[i] = unnamedParameters[unnamedIndex++];
-        }
-      }
-    }
-    if (positionalArgumentCount < requiredParameters.length &&
-        noBlankArguments) {
-      ErrorCode errorCode = (reportAsError
-          ? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS
-          : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS);
-      if (onError != null) {
-        onError(errorCode, argumentList,
-            [requiredParameters.length, positionalArgumentCount]);
-      }
-    } else if (positionalArgumentCount > unnamedParameterCount &&
-        noBlankArguments) {
-      ErrorCode errorCode = (reportAsError
-          ? CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS
-          : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS);
-      if (onError != null) {
-        onError(errorCode, argumentList,
-            [unnamedParameterCount, positionalArgumentCount]);
-      }
-    }
-    return resolvedParameters;
-  }
-
   @override
   Object visitNamedExpression(NamedExpression node) {
     InferenceContext.setType(node.expression, InferenceContext.getType(node));
@@ -9409,7 +9346,8 @@
     return null;
   }
 
-  @override visitVariableDeclarationList(VariableDeclarationList node) {
+  @override
+  visitVariableDeclarationList(VariableDeclarationList node) {
     for (VariableDeclaration decl in node.variables) {
       InferenceContext.setType(decl, node.type?.type);
     }
@@ -9525,7 +9463,7 @@
       return (typeArgs?.length == 1) ? typeArgs[0] : null;
     }
     // Must be asynchronous to reach here, so strip off any layers of Future
-    return StaticTypeAnalyzer.flattenFutures(typeProvider, declaredType);
+    return declaredType.flattenFutures(typeSystem);
   }
 
   /**
@@ -9775,24 +9713,17 @@
         return;
       }
       // prepare current variable type
-      DartType type = _promoteManager.getType(element);
-      if (type == null) {
-        type = expression.staticType;
+      DartType type = _promoteManager.getType(element) ??
+          expression.staticType ??
+          DynamicTypeImpl.instance;
+
+      potentialType ??= DynamicTypeImpl.instance;
+
+      // Check if we can promote to potentialType from type.
+      if (typeSystem.canPromoteToType(potentialType, type)) {
+        // Do promote type of variable.
+        _promoteManager.setType(element, potentialType);
       }
-      // Declared type should not be "dynamic".
-      if (type == null || type.isDynamic) {
-        return;
-      }
-      // Promoted type should not be "dynamic".
-      if (potentialType == null || potentialType.isDynamic) {
-        return;
-      }
-      // Promoted type should be more specific than declared.
-      if (!potentialType.isMoreSpecificThan(type)) {
-        return;
-      }
-      // Do promote type of variable.
-      _promoteManager.setType(element, potentialType);
     }
   }
 
@@ -9890,6 +9821,106 @@
       _propagateTrueState(condition.expression);
     }
   }
+
+  /**
+   * Given an [argumentList] and the [parameters] related to the element that
+   * will be invoked using those arguments, compute the list of parameters that
+   * correspond to the list of arguments.
+   *
+   * An error will be reported to [onError] if any of the arguments cannot be
+   * matched to a parameter. onError can be null to ignore the error.
+   *
+   * The flag [reportAsError] should be `true` if a compile-time error should be
+   * reported; or `false` if a compile-time warning should be reported.
+   *
+   * Returns the parameters that correspond to the arguments. If no parameter
+   * matched an argument, that position will be `null` in the list.
+   */
+  static List<ParameterElement> resolveArgumentsToParameters(
+      ArgumentList argumentList,
+      List<ParameterElement> parameters,
+      void onError(ErrorCode errorCode, AstNode node, [List<Object> arguments]),
+      {bool reportAsError: false}) {
+    List<ParameterElement> requiredParameters = new List<ParameterElement>();
+    List<ParameterElement> positionalParameters = new List<ParameterElement>();
+    HashMap<String, ParameterElement> namedParameters =
+        new HashMap<String, ParameterElement>();
+    for (ParameterElement parameter in parameters) {
+      ParameterKind kind = parameter.parameterKind;
+      if (kind == ParameterKind.REQUIRED) {
+        requiredParameters.add(parameter);
+      } else if (kind == ParameterKind.POSITIONAL) {
+        positionalParameters.add(parameter);
+      } else {
+        namedParameters[parameter.name] = parameter;
+      }
+    }
+    List<ParameterElement> unnamedParameters =
+        new List<ParameterElement>.from(requiredParameters);
+    unnamedParameters.addAll(positionalParameters);
+    int unnamedParameterCount = unnamedParameters.length;
+    int unnamedIndex = 0;
+    NodeList<Expression> arguments = argumentList.arguments;
+    int argumentCount = arguments.length;
+    List<ParameterElement> resolvedParameters =
+        new List<ParameterElement>(argumentCount);
+    int positionalArgumentCount = 0;
+    HashSet<String> usedNames = new HashSet<String>();
+    bool noBlankArguments = true;
+    for (int i = 0; i < argumentCount; i++) {
+      Expression argument = arguments[i];
+      if (argument is NamedExpression) {
+        SimpleIdentifier nameNode = argument.name.label;
+        String name = nameNode.name;
+        ParameterElement element = namedParameters[name];
+        if (element == null) {
+          ErrorCode errorCode = (reportAsError
+              ? CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER
+              : StaticWarningCode.UNDEFINED_NAMED_PARAMETER);
+          if (onError != null) {
+            onError(errorCode, nameNode, [name]);
+          }
+        } else {
+          resolvedParameters[i] = element;
+          nameNode.staticElement = element;
+        }
+        if (!usedNames.add(name)) {
+          if (onError != null) {
+            onError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode,
+                [name]);
+          }
+        }
+      } else {
+        if (argument is SimpleIdentifier && argument.name.isEmpty) {
+          noBlankArguments = false;
+        }
+        positionalArgumentCount++;
+        if (unnamedIndex < unnamedParameterCount) {
+          resolvedParameters[i] = unnamedParameters[unnamedIndex++];
+        }
+      }
+    }
+    if (positionalArgumentCount < requiredParameters.length &&
+        noBlankArguments) {
+      ErrorCode errorCode = (reportAsError
+          ? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS
+          : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS);
+      if (onError != null) {
+        onError(errorCode, argumentList,
+            [requiredParameters.length, positionalArgumentCount]);
+      }
+    } else if (positionalArgumentCount > unnamedParameterCount &&
+        noBlankArguments) {
+      ErrorCode errorCode = (reportAsError
+          ? CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS
+          : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS);
+      if (onError != null) {
+        onError(errorCode, argumentList,
+            [unnamedParameterCount, positionalArgumentCount]);
+      }
+    }
+    return resolvedParameters;
+  }
 }
 
 /**
@@ -11981,9 +12012,6 @@
           : CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS);
       superclassType = _resolveType(extendsClause.superclass, errorCode,
           CompileTimeErrorCode.EXTENDS_ENUM, errorCode);
-      if (!identical(superclassType, typeProvider.objectType)) {
-        classElement.validMixin = false;
-      }
     }
     if (classElement != null) {
       if (superclassType == null) {
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index 4c756e2..a2b6325 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -6,7 +6,8 @@
 
 import 'dart:collection';
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart'
     show ContentCache, Source, UriKind;
@@ -184,16 +185,20 @@
    */
   LibraryMap get librariesMap => _librariesMap;
 
-
   // To be backwards-compatible the new categories field is translated to
   // an old approximation.
   String convertCategories(String categories) {
     switch (categories) {
-      case "": return "Internal";
-      case "Client": return "Client";
-      case "Server": return "Server";
-      case "Client,Server": return "Shared";
-      case "Client,Server,Embedded": return "Shared";
+      case "":
+        return "Internal";
+      case "Client":
+        return "Client";
+      case "Server":
+        return "Server";
+      case "Client,Server":
+        return "Shared";
+      case "Client,Server,Embedded":
+        return "Shared";
     }
     return "Shared";
   }
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 863a3d4..a50eb95 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -7,8 +7,8 @@
 import 'dart:collection';
 import 'dart:io';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -255,20 +255,15 @@
   @override
   AnalysisContext get context {
     if (_analysisContext == null) {
-      SdkBundle sdkBundle = _getSummarySdkBundle();
-      if (sdkBundle != null) {
-        _analysisContext = new SummarySdkAnalysisContext(sdkBundle);
-      } else {
-        _analysisContext = new SdkAnalysisContext();
-      }
+      _analysisContext = new SdkAnalysisContext();
       SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
       _analysisContext.sourceFactory = factory;
-      List<String> uris = this.uris;
-      ChangeSet changeSet = new ChangeSet();
-      for (String uri in uris) {
-        changeSet.addedSource(factory.forUri(uri));
+      // Try to use summaries.
+      SdkBundle sdkBundle = _getSummarySdkBundle();
+      if (sdkBundle != null) {
+        _analysisContext.resultProvider =
+            new SdkSummaryResultProvider(_analysisContext, sdkBundle);
       }
-      _analysisContext.applyChanges(changeSet);
     }
     return _analysisContext;
   }
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 950f36e0..a3662f9 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -178,12 +178,12 @@
 }
 
 /**
- * Instances of the class `LineInfo` encapsulate information about line and column information
- * within a source file.
+ * Information about line and column information within a source file.
  */
 class LineInfo {
   /**
-   * An array containing the offsets of the first character of each line in the source code.
+   * A list containing the offsets of the first character of each line in the
+   * source code.
    */
   final List<int> _lineStarts;
 
@@ -194,12 +194,23 @@
   int _previousLine = 0;
 
   /**
-   * Initialize a newly created set of line information to represent the data encoded in the given
-   * array.
-   *
-   * @param lineStarts the offsets of the first character of each line in the source code
+   * Initialize a newly created set of line information to represent the data
+   * encoded in the given list of [_lineStarts].
    */
-  LineInfo(this._lineStarts) {
+  factory LineInfo(List<int> _lineStarts) => new LineInfoWithCount(_lineStarts);
+
+  /**
+   * Initialize a newly created set of line information corresponding to the
+   * given file [content].
+   */
+  factory LineInfo.fromContent(String content) =>
+      new LineInfoWithCount(StringUtilities.computeLineStarts(content));
+
+  /**
+   * Initialize a newly created set of line information to represent the data
+   * encoded in the given list of [_lineStarts].
+   */
+  LineInfo._(this._lineStarts) {
     if (_lineStarts == null) {
       throw new IllegalArgumentException("lineStarts must be non-null");
     } else if (_lineStarts.length < 1) {
@@ -208,10 +219,7 @@
   }
 
   /**
-   * Return the location information for the character at the given offset.
-   *
-   * @param offset the offset of the character for which location information is to be returned
-   * @return the location information for the character at the given offset
+   * Return the location information for the character at the given [offset].
    */
   LineInfo_Location getLocation(int offset) {
     var min = 0;
@@ -288,6 +296,26 @@
 }
 
 /**
+ * Information about line and column information within a source file,
+ * including a count of the total number of lines.
+ *
+ * TODO(paulberry): in the next major version roll of analyzer, merge this
+ * class into [LineInfo].
+ */
+class LineInfoWithCount extends LineInfo {
+  /**
+   * Initialize a newly created set of line information to represent the data
+   * encoded in the given list of [_lineStarts].
+   */
+  LineInfoWithCount(List<int> _lineStarts) : super._(_lineStarts);
+
+  /**
+   * Return the number of lines in the file.
+   */
+  int get lineCount => _lineStarts.length;
+}
+
+/**
  * Instances of interface `LocalSourcePredicate` are used to determine if the given
  * [Source] is "local" in some sense, so can be updated.
  */
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 28f42f7..e67d096 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -6,11 +6,12 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/ast.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/scanner.dart';
@@ -281,11 +282,11 @@
       // TODO(brianwilkerson) Determine whether this can still happen.
       staticExpressionType = _dynamicType;
     }
-    DartType staticType = flattenFutures(_typeProvider, staticExpressionType);
+    DartType staticType = staticExpressionType.flattenFutures(_typeSystem);
     _recordStaticType(node, staticType);
     DartType propagatedExpressionType = node.expression.propagatedType;
     DartType propagatedType =
-        flattenFutures(_typeProvider, propagatedExpressionType);
+        propagatedExpressionType?.flattenFutures(_typeSystem);
     _resolver.recordPropagatedTypeIfBetter(node, propagatedType);
     return null;
   }
@@ -495,6 +496,9 @@
    */
   @override
   Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    if (_strongMode) {
+      _inferFunctionInvocationGeneric(node);
+    }
     DartType staticType = _computeInvokeReturnType(node.staticInvokeType);
     _recordStaticType(node, staticType);
     DartType functionPropagatedType = node.propagatedInvokeType;
@@ -713,12 +717,12 @@
   Object visitMethodInvocation(MethodInvocation node) {
     SimpleIdentifier methodNameNode = node.methodName;
     Element staticMethodElement = methodNameNode.staticElement;
+    if (_strongMode) {
+      _inferMethodInvocation(node);
+    }
     // Record types of the variable invoked as a function.
     if (staticMethodElement is VariableElement) {
-      VariableElement variable = staticMethodElement;
-      DartType staticType = variable.type;
-      _recordStaticType(methodNameNode, staticType);
-      DartType propagatedType = _overrideManager.getType(variable);
+      DartType propagatedType = _overrideManager.getType(staticMethodElement);
       _resolver.recordPropagatedTypeIfBetter(methodNameNode, propagatedType);
     }
     // Record static return type of the static element.
@@ -731,10 +735,7 @@
     // Check for special cases.
     bool needPropagatedType = true;
     String methodName = methodNameNode.name;
-    if (_strongMode) {
-      _inferMethodInvocation(node);
-    }
-    if (methodName == "then") {
+    if (!_strongMode && methodName == "then") {
       Expression target = node.realTarget;
       if (target != null) {
         DartType targetType = target.bestType;
@@ -753,16 +754,10 @@
                   _computePropagatedReturnType(closureExpr.element);
               if (returnType != null) {
                 // prepare the type of the returned Future
-                InterfaceTypeImpl newFutureType;
-                if (_isAsyncFutureType(returnType)) {
-                  newFutureType = returnType as InterfaceTypeImpl;
-                } else {
-                  InterfaceType futureType = targetType as InterfaceType;
-                  newFutureType = new InterfaceTypeImpl(futureType.element);
-                  newFutureType.typeArguments = <DartType>[returnType];
-                }
+                InterfaceType newFutureType = _typeProvider.futureType
+                    .substitute4([returnType.flattenFutures(_typeSystem)]);
                 // set the 'then' invocation type
-                _recordPropagatedType(node, newFutureType);
+                _resolver.recordPropagatedTypeIfBetter(node, newFutureType);
                 needPropagatedType = false;
                 return null;
               }
@@ -873,16 +868,21 @@
     }
     if (needPropagatedType) {
       Element propagatedElement = methodNameNode.propagatedElement;
+      DartType propagatedInvokeType = node.propagatedInvokeType;
       // HACK: special case for object methods ([toString]) on dynamic
       // expressions. More special cases in [visitPrefixedIdentfier].
       if (propagatedElement == null) {
-        propagatedElement =
+        MethodElement objMethod =
             _typeProvider.objectType.getMethod(methodNameNode.name);
+        if (objMethod != null) {
+          propagatedElement = objMethod;
+          propagatedInvokeType = objMethod.type;
+        }
       }
       if (!identical(propagatedElement, staticMethodElement)) {
         // Record static return type of the propagated element.
         DartType propagatedStaticType =
-            _computeStaticReturnType(propagatedElement);
+            _computeInvokeReturnType(propagatedInvokeType);
         _resolver.recordPropagatedTypeIfBetter(
             node, propagatedStaticType, true);
         // Record propagated return type of the propagated element.
@@ -1379,6 +1379,21 @@
   }
 
   /**
+   * Compute the return type of the method or function represented by the given
+   * type that is being invoked.
+   */
+  DartType _computeInvokeReturnType(DartType type) {
+    if (type is InterfaceType) {
+      MethodElement callMethod = type.lookUpMethod(
+          FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
+      return callMethod?.type?.returnType ?? _dynamicType;
+    } else if (type is FunctionType) {
+      return type.returnType ?? _dynamicType;
+    }
+    return _dynamicType;
+  }
+
+  /**
    * Compute the propagated return type of the method or function represented by the given element.
    *
    * @param element the element representing the method or function invoked by the given node
@@ -1440,21 +1455,6 @@
   }
 
   /**
-   * Compute the return type of the method or function represented by the given
-   * type that is being invoked.
-   */
-  DartType _computeInvokeReturnType(DartType type) {
-    if (type is InterfaceType) {
-      MethodElement callMethod = type.lookUpMethod(
-          FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
-      return callMethod?.type?.returnType ?? _dynamicType;
-    } else if (type is FunctionType) {
-      return type.returnType ?? _dynamicType;
-    }
-    return _dynamicType;
-  }
-
-  /**
    * Given a function declaration, compute the return static type of the function. The return type
    * of functions with a block body is `dynamicType`, with an expression body it is the type
    * of the expression.
@@ -1497,7 +1497,7 @@
     }
     if (body.isAsynchronous) {
       return _typeProvider.futureType
-          .substitute4(<DartType>[flattenFutures(_typeProvider, type)]);
+          .substitute4(<DartType>[type.flattenFutures(_typeSystem)]);
     } else {
       return type;
     }
@@ -1769,6 +1769,63 @@
   }
 
   /**
+   * 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;
+  }
+
+  FunctionType _inferGenericInvoke(FunctionType invokeType, FunctionType fnType,
+      TypeArgumentList typeArguments, ArgumentList argumentList) {
+    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);
+
+        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;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
    * Given a local variable declaration and its initializer, attempt to infer
    * a type for the local variable declaration based on the initializer.
    * Inference is only done if an explicit type is not present, and if
@@ -1802,42 +1859,17 @@
    * type variables, using the actual types of the arguments.
    */
   bool _inferMethodInvocationGeneric(MethodInvocation node) {
-    Element element = node.methodName.staticElement;
-    DartType invokeType = node.staticInvokeType;
-
-    TypeSystem ts = _typeSystem;
-    if (node.typeArguments == null &&
-        element is ExecutableElement &&
-        ts is StrongTypeSystemImpl) {
-      FunctionType fnType = element.type;
-      if (fnType.typeFormals.isNotEmpty &&
-          ts.instantiateToBounds(fnType) == invokeType) {
-        // Get the parameters that correspond to the uninstantiated generic.
-        List<ParameterElement> genericParameters =
-            ResolverVisitor.resolveArgumentsToParameters(
-                node.argumentList, fnType.parameters, null);
-
-        int length = genericParameters.length;
-        List<DartType> argTypes = new List<DartType>(length);
-        List<DartType> paramTypes = new List<DartType>(length);
-        for (int i = 0; i < length; i++) {
-          argTypes[i] = node.argumentList.arguments[i].staticType;
-          paramTypes[i] = genericParameters[i].type;
-        }
-
-        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(
-                  node.argumentList, inferred.parameters, null);
-          node.argumentList.correspondingStaticParameters = inferredParameters;
-          node.staticInvokeType = inferred;
-          _recordStaticType(node, inferred.returnType);
-          return true;
-        }
+    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;
@@ -1890,7 +1922,7 @@
       return false;
     }
     DartType inferredType = inferredElement.type;
-    DartType nodeType = node.staticType;
+    DartType nodeType = node.staticInvokeType;
     if (nodeType != null &&
         nodeType.isDynamic &&
         inferredType is FunctionType &&
@@ -2082,47 +2114,6 @@
   }
 
   /**
-   * Implements the function "flatten" defined in the spec:
-   *
-   *   If T = Future<S> then flatten(T) = flatten(S).
-   *
-   *   Otherwise if T <: Future then let S be a type such that T << Future<S>
-   *   and for all R, if T << Future<R> then S << R.  Then flatten(T) = S.
-   *
-   *   In any other circumstance, flatten(T) = T.
-   */
-  static DartType flattenFutures(TypeProvider typeProvider, DartType type) {
-    if (type is InterfaceType) {
-      // Implement the case: "If T = Future<S> then flatten(T) = flatten(S)."
-      if (type.element == typeProvider.futureType.element &&
-          type.typeArguments.length > 0) {
-        return flattenFutures(typeProvider, type.typeArguments[0]);
-      }
-
-      // Implement the case: "Otherwise if T <: Future then let S be a type
-      // such that T << Future<S> and for all R, if T << Future<R> then S << R.
-      // Then flatten(T) = S."
-      //
-      // In other words, given the set of all types R such that T << Future<R>,
-      // let S be the most specific of those types, if any such S exists.
-      //
-      // Since we only care about the most specific type, it is sufficent to
-      // look at the types appearing as a parameter to Future in the type
-      // hierarchy of T.  We don't need to consider the supertypes of those
-      // types, since they are by definition less specific.
-      List<DartType> candidateTypes =
-          _searchTypeHierarchyForFutureParameters(typeProvider, type);
-      DartType flattenResult = _findMostSpecificType(candidateTypes);
-      if (flattenResult != null) {
-        return flattenResult;
-      }
-    }
-
-    // Implement the case: "In any other circumstance, flatten(T) = T."
-    return type;
-  }
-
-  /**
    * Create a table mapping HTML tag names to the names of the classes (in 'dart:html') that
    * implement those tags.
    *
@@ -2190,88 +2181,6 @@
     map["video"] = "VideoElement";
     return map;
   }
-
-  /**
-   * If there is a single type which is at least as specific as all of the
-   * types in [types], return it.  Otherwise return `null`.
-   */
-  static DartType _findMostSpecificType(List<DartType> types) {
-    // The << relation ("more specific than") is a partial ordering on types,
-    // so to find the most specific type of a set, we keep a bucket of the most
-    // specific types seen so far such that no type in the bucket is more
-    // specific than any other type in the bucket.
-    List<DartType> bucket = <DartType>[];
-
-    // Then we consider each type in turn.
-    for (DartType type in types) {
-      // If any existing type in the bucket is more specific than this type,
-      // then we can ignore this type.
-      if (bucket.any((DartType t) => t.isMoreSpecificThan(type))) {
-        continue;
-      }
-      // Otherwise, we need to add this type to the bucket and remove any types
-      // that are less specific than it.
-      bool added = false;
-      int i = 0;
-      while (i < bucket.length) {
-        if (type.isMoreSpecificThan(bucket[i])) {
-          if (added) {
-            if (i < bucket.length - 1) {
-              bucket[i] = bucket.removeLast();
-            } else {
-              bucket.removeLast();
-            }
-          } else {
-            bucket[i] = type;
-            i++;
-            added = true;
-          }
-        } else {
-          i++;
-        }
-      }
-      if (!added) {
-        bucket.add(type);
-      }
-    }
-
-    // Now that we are finished, if there is exactly one type left in the
-    // bucket, it is the most specific type.
-    if (bucket.length == 1) {
-      return bucket[0];
-    }
-
-    // Otherwise, there is no single type that is more specific than the
-    // others.
-    return null;
-  }
-
-  /**
-   * Given a seed type [type], search its class hierarchy for types of the form
-   * Future<R>, and return a list of the resulting R's.
-   */
-  static List<DartType> _searchTypeHierarchyForFutureParameters(
-      TypeProvider typeProvider, InterfaceType type) {
-    List<DartType> result = <DartType>[];
-    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
-    void recurse(InterfaceType type) {
-      if (type.element == typeProvider.futureType.element &&
-          type.typeArguments.length > 0) {
-        result.add(type.typeArguments[0]);
-      }
-      if (visitedClasses.add(type.element)) {
-        if (type.superclass != null) {
-          recurse(type.superclass);
-        }
-        for (InterfaceType interface in type.interfaces) {
-          recurse(interface);
-        }
-        visitedClasses.remove(type.element);
-      }
-    }
-    recurse(type);
-    return result;
-  }
 }
 
 class _StaticTypeAnalyzer_computePropagatedReturnTypeOfFunction
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
index c6892c2..c77192c 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
@@ -4,8 +4,9 @@
 
 library analyzer.src.generated.testing.ast_factory;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 0dc3c7b..38c322e 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -6,11 +6,11 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.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/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -100,6 +100,7 @@
     ConstructorElementImpl constructor = name == null
         ? new ConstructorElementImpl("", -1)
         : new ConstructorElementImpl(name, 0);
+    constructor.synthetic = name == null;
     constructor.const2 = isConst;
     if (argumentTypes != null) {
       int count = argumentTypes.length;
@@ -405,11 +406,12 @@
     field.type = type;
     field.final2 = true;
     PropertyAccessorElementImpl getter =
-        new PropertyAccessorElementImpl.forVariable(field);
+        new PropertyAccessorElementImpl(name, 0);
     getter.synthetic = false;
     getter.getter = true;
     getter.variable = field;
     getter.returnType = type;
+    getter.static = isStatic;
     field.getter = getter;
     FunctionTypeImpl getterType = new FunctionTypeImpl(getter);
     getter.type = getterType;
@@ -559,8 +561,14 @@
     if (isConst) {
       ConstTopLevelVariableElementImpl constant =
           new ConstTopLevelVariableElementImpl(AstFactory.identifier3(name));
-      constant.constantInitializer = AstFactory.instanceCreationExpression2(
+      InstanceCreationExpression initializer = AstFactory.instanceCreationExpression2(
           Keyword.CONST, AstFactory.typeName(type.element));
+      if (type is InterfaceType) {
+        ConstructorElement element = type.element.unnamedConstructor;
+        initializer.staticElement = element;
+        initializer.constructorName.staticElement = element;
+      }
+      constant.constantInitializer = initializer;
       variable = constant;
     } else {
       variable = new TopLevelVariableElementImpl(name, -1);
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 5f1a49b..4bf5cc9 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -4,14 +4,17 @@
 
 library analyzer.src.generated.testing.test_type_provider;
 
+import 'package:analyzer/dart/ast/ast.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/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
+import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/generated/testing/ast_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 
@@ -150,6 +153,14 @@
    */
   DartType _undefinedType;
 
+  /**
+   * The analysis context, if any. Used to create an appropriate 'dart:async'
+   * library to back `Future<T>`.
+   */
+  AnalysisContext _context;
+
+  TestTypeProvider([this._context]);
+
   @override
   InterfaceType get boolType {
     if (_boolType == null) {
@@ -181,8 +192,8 @@
     if (_deprecatedType == null) {
       ClassElementImpl deprecatedElement =
           ElementFactory.classElement2("Deprecated");
-      ConstructorElementImpl constructor = ElementFactory.constructorElement(
-          deprecatedElement, null, true, [stringType]);
+      ConstructorElementImpl constructor = ElementFactory
+          .constructorElement(deprecatedElement, '', true, [stringType]);
       constructor.constantInitializers = <ConstructorInitializer>[
         AstFactory.constructorFieldInitializer(
             true, 'expires', AstFactory.identifier3('expires'))
@@ -240,7 +251,18 @@
   @override
   InterfaceType get futureType {
     if (_futureType == null) {
-      _futureType = ElementFactory.classElement2("Future", ["T"]).type;
+      Source asyncSource = _context.sourceFactory.forUri(DartSdk.DART_ASYNC);
+      _context.setContents(asyncSource, "");
+      CompilationUnitElementImpl asyncUnit =
+          new CompilationUnitElementImpl("async.dart");
+      LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
+          _context, AstFactory.libraryIdentifier2(["dart.async"]));
+      asyncLibrary.definingCompilationUnit = asyncUnit;
+      asyncUnit.librarySource = asyncUnit.source = asyncSource;
+
+      ClassElementImpl future = ElementFactory.classElement2("Future", ["T"]);
+      _futureType = future.type;
+      asyncUnit.types = <ClassElement>[future];
     }
     return _futureType;
   }
@@ -274,7 +296,7 @@
         ElementFactory.getterElement("last", false, eType)
       ]);
       iterableElement.constructors = <ConstructorElement>[
-        ElementFactory.constructorElement(iterableElement, null, true)
+        ElementFactory.constructorElement(iterableElement, '', true)
           ..isCycleFree = true
       ];
       _propagateTypeArguments(iterableElement);
@@ -317,8 +339,8 @@
       ]);
       listElement.methods = <MethodElement>[
         ElementFactory.methodElement("[]", eType, [intType]),
-        ElementFactory.methodElement(
-            "[]=", VoidTypeImpl.instance, [intType, eType]),
+        ElementFactory
+            .methodElement("[]=", VoidTypeImpl.instance, [intType, eType]),
         ElementFactory.methodElement("add", VoidTypeImpl.instance, [eType])
       ];
       _propagateTypeArguments(listElement);
@@ -339,11 +361,11 @@
       ]);
       mapElement.methods = <MethodElement>[
         ElementFactory.methodElement("[]", vType, [objectType]),
-        ElementFactory.methodElement(
-            "[]=", VoidTypeImpl.instance, [kType, vType])
+        ElementFactory
+            .methodElement("[]=", VoidTypeImpl.instance, [kType, vType])
       ];
       mapElement.constructors = <ConstructorElement>[
-        ElementFactory.constructorElement(mapElement, null, false)
+        ElementFactory.constructorElement(mapElement, '', false)
           ..external = true
           ..factory = true
       ];
@@ -397,7 +419,7 @@
       ClassElementImpl objectElement = ElementFactory.object;
       _objectType = objectElement.type;
       ConstructorElementImpl constructor =
-          ElementFactory.constructorElement(objectElement, null, true);
+          ElementFactory.constructorElement(objectElement, '', true);
       constructor.constantInitializers = <ConstructorInitializer>[];
       objectElement.constructors = <ConstructorElement>[constructor];
       objectElement.methods = <MethodElement>[
@@ -475,8 +497,8 @@
   InterfaceType get symbolType {
     if (_symbolType == null) {
       ClassElementImpl symbolClass = ElementFactory.classElement2("Symbol");
-      ConstructorElementImpl constructor = ElementFactory.constructorElement(
-          symbolClass, null, true, [stringType]);
+      ConstructorElementImpl constructor = ElementFactory
+          .constructorElement(symbolClass, '', true, [stringType]);
       constructor.factory = true;
       constructor.isCycleFree = true;
       symbolClass.constructors = <ConstructorElement>[constructor];
@@ -555,10 +577,10 @@
       ElementFactory.methodElement("toInt", _intType),
       ElementFactory.methodElement("toDouble", _doubleType),
       ElementFactory.methodElement("toStringAsFixed", _stringType, [_intType]),
-      ElementFactory.methodElement(
-          "toStringAsExponential", _stringType, [_intType]),
-      ElementFactory.methodElement(
-          "toStringAsPrecision", _stringType, [_intType]),
+      ElementFactory
+          .methodElement("toStringAsExponential", _stringType, [_intType]),
+      ElementFactory
+          .methodElement("toStringAsPrecision", _stringType, [_intType]),
       ElementFactory.methodElement("toRadixString", _stringType, [_intType])
     ];
     intElement.methods = <MethodElement>[
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 911dfa9..b85205c 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -29,6 +29,12 @@
     return ft.parameters.any((p) => predicate(p.type));
   }
 
+  @override
+  bool canPromoteToType(DartType to, DartType from) => isSubtypeOf(to, from);
+
+  @override
+  bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf(t1, t2);
+
   /**
    * Given a type t, if t is an interface type with a call method
    * defined, return the function type for the call method, otherwise
@@ -563,6 +569,25 @@
  */
 abstract class TypeSystem {
   /**
+   * Returns `true` if we can promote to the first type from the second type.
+   *
+   * In the standard Dart type system, it is not possible to promote from or to
+   * `dynamic`, and we must be promoting to a more specific type, see
+   * [isMoreSpecificThan].
+   *
+   * In strong mode, this is equivalent to [isSubtypeOf].
+   */
+  bool canPromoteToType(DartType to, DartType from);
+
+  /**
+   * Return `true` if the [leftType] is more specific than the [rightType]
+   * (that is, if leftType << rightType), as defined in the Dart language spec.
+   *
+   * In strong mode, this is equivalent to [isSubtypeOf].
+   */
+  bool isMoreSpecificThan(DartType leftType, DartType rightType);
+
+  /**
    * Compute the least upper bound of two types.
    */
   DartType getLeastUpperBound(
@@ -606,6 +631,18 @@
   TypeSystemImpl();
 
   @override
+  bool isMoreSpecificThan(DartType t1, DartType t2) =>
+      t1.isMoreSpecificThan(t2);
+
+  @override
+  bool canPromoteToType(DartType to, DartType from) {
+    // Declared type should not be "dynamic".
+    // Promoted type should not be "dynamic".
+    // Promoted type should be more specific than declared.
+    return !from.isDynamic && !to.isDynamic && to.isMoreSpecificThan(from);
+  }
+
+  @override
   DartType getLeastUpperBound(
       TypeProvider typeProvider, DartType type1, DartType type2) {
     // The least upper bound relation is reflexive.
diff --git a/pkg/analyzer/lib/src/generated/visitors.dart b/pkg/analyzer/lib/src/generated/visitors.dart
index 46e2a41..31e5ddc 100644
--- a/pkg/analyzer/lib/src/generated/visitors.dart
+++ b/pkg/analyzer/lib/src/generated/visitors.dart
@@ -4,7 +4,7 @@
 
 library analyzer.src.generated.visitors;
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
 
 /// An [AstVisitor] that delegates calls to visit methods to all [delegates]
 /// before calling [visitChildren].
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
index 07b0def..c2ad576 100644
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/task/html.dart';
 import 'package:analyzer/src/task/html_work_manager.dart';
 import 'package:analyzer/src/task/options_work_manager.dart';
+import 'package:analyzer/src/task/yaml.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:plugin/plugin.dart';
 
@@ -240,6 +241,10 @@
     registerExtension(taskId, DartScriptsTask.DESCRIPTOR);
     registerExtension(taskId, HtmlErrorsTask.DESCRIPTOR);
     registerExtension(taskId, ParseHtmlTask.DESCRIPTOR);
+    //
+    // Register YAML tasks.
+    //
+    registerExtension(taskId, ParseYamlTask.DESCRIPTOR);
   }
 
   void _registerWorkManagerFactoryExtensions(
diff --git a/pkg/analyzer/lib/src/services/lint.dart b/pkg/analyzer/lib/src/services/lint.dart
index 91d72a2..953741b 100644
--- a/pkg/analyzer/lib/src/services/lint.dart
+++ b/pkg/analyzer/lib/src/services/lint.dart
@@ -4,7 +4,7 @@
 
 library analyzer.src.services.lint;
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index 3c7de13..c56b298 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -49,6 +49,9 @@
     return new BufferPointer._(_buffer, _offset + delta);
   }
 
+  double _getFloat64([int delta = 0]) =>
+      _buffer.getFloat64(_offset + delta, Endianness.LITTLE_ENDIAN);
+
   int _getInt32([int delta = 0]) =>
       _buffer.getInt32(_offset + delta, Endianness.LITTLE_ENDIAN);
 
@@ -175,6 +178,22 @@
   }
 
   /**
+   * Add the [field] with the given 32-bit unsigned integer [value].  The field
+   * is not added if the [value] is equal to [def].
+   */
+  void addUint32(int field, int value, [int def]) {
+    if (_currentVTable == null) {
+      throw new StateError('Start a table before adding values.');
+    }
+    if (value != null && value != def) {
+      int size = 4;
+      _prepare(size, 1);
+      _trackField(field);
+      _setUint32AtTail(_buf, _tail, value);
+    }
+  }
+
+  /**
    * End the current table and return its offset.
    */
   Offset endTable() {
@@ -299,6 +318,26 @@
   }
 
   /**
+   * Write the given list of 64-bit float [values].
+   */
+  Offset writeListFloat64(List<double> values) {
+    if (_currentVTable != null) {
+      throw new StateError(
+          'Cannot write a non-scalar value while writing a table.');
+    }
+    _prepare(8, 1 + values.length);
+    Offset result = new Offset(_tail);
+    int tail = _tail;
+    _setUint32AtTail(_buf, tail, values.length);
+    tail -= 8;
+    for (double value in values) {
+      _setFloat64AtTail(_buf, tail, value);
+      tail -= 8;
+    }
+    return result;
+  }
+
+  /**
    * Write the given list of signed 32-bit integer [values].
    */
   Offset writeListInt32(List<int> values) {
@@ -319,6 +358,26 @@
   }
 
   /**
+   * Write the given list of unsigned 32-bit integer [values].
+   */
+  Offset writeListUint32(List<int> values) {
+    if (_currentVTable != null) {
+      throw new StateError(
+          'Cannot write a non-scalar value while writing a table.');
+    }
+    _prepare(4, 1 + values.length);
+    Offset result = new Offset(_tail);
+    int tail = _tail;
+    _setUint32AtTail(_buf, tail, values.length);
+    tail -= 4;
+    for (int value in values) {
+      _setUint32AtTail(_buf, tail, value);
+      tail -= 4;
+    }
+    return result;
+  }
+
+  /**
    * Write the given string [value] and return its [Offset], or `null` if
    * the [value] is equal to [def].
    */
@@ -383,6 +442,10 @@
     _currentVTable.addField(field, _tail);
   }
 
+  static void _setFloat64AtTail(ByteData _buf, int tail, double x) {
+    _buf.setFloat64(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
+  }
+
   static void _setInt32AtTail(ByteData _buf, int tail, int x) {
     _buf.setInt32(_buf.lengthInBytes - tail, x, Endianness.LITTLE_ENDIAN);
   }
@@ -393,7 +456,22 @@
 }
 
 /**
- * The reader of 32-bit signed integers.
+ * The reader of lists of 64-bit float values.
+ *
+ * The returned unmodifiable lists lazily read values on access.
+ */
+class Float64ListReader extends Reader<List<double>> {
+  const Float64ListReader();
+
+  @override
+  int get size => 4;
+
+  @override
+  List<double> read(BufferPointer bp) => new _FbFloat64List(bp.derefObject());
+}
+
+/**
+ * The reader of signed 32-bit integers.
  */
 class Int32Reader extends Reader<int> {
   const Int32Reader() : super();
@@ -433,7 +511,7 @@
 
   @override
   List<E> read(BufferPointer bp) =>
-      new _FbList<E>(_elementReader, bp.derefObject());
+      new _FbInt32List<E>(_elementReader, bp.derefObject());
 }
 
 /**
@@ -519,14 +597,29 @@
   }
 }
 
-class _FbList<E> extends Object with ListMixin<E> implements List<E> {
-  final Reader<E> elementReader;
+/**
+ * The reader of unsigned 32-bit integers.
+ */
+class Uint32Reader extends Reader<int> {
+  const Uint32Reader() : super();
+
+  @override
+  int get size => 4;
+
+  @override
+  int read(BufferPointer bp) => bp._getUint32();
+}
+
+/**
+ * The list backed by 64-bit values - Uint64 length and Float64.
+ */
+class _FbFloat64List extends _FbList<double> {
   final BufferPointer bp;
 
   int _length;
-  List<E> _items;
+  List<double> _items;
 
-  _FbList(this.elementReader, this.bp);
+  _FbFloat64List(this.bp);
 
   @override
   int get length {
@@ -535,20 +628,56 @@
   }
 
   @override
-  void set length(int i) =>
-      throw new StateError('Attempt to modify immutable list');
+  double operator [](int i) {
+    _items ??= new List<double>(length);
+    double item = _items[i];
+    if (item == null) {
+      BufferPointer ref = bp._advance(8 + 8 * i);
+      item = ref._getFloat64();
+      _items[i] = item;
+    }
+    return item;
+  }
+}
+
+/**
+ * The list backed by 32-bit values - offsets or integers.
+ */
+class _FbInt32List<E> extends _FbList<E> {
+  final Reader<E> elementReader;
+  final BufferPointer bp;
+
+  int _length;
+  List<E> _items;
+
+  _FbInt32List(this.elementReader, this.bp);
+
+  @override
+  int get length {
+    _length ??= bp._getUint32();
+    return _length;
+  }
 
   @override
   E operator [](int i) {
     _items ??= new List<E>(length);
     E item = _items[i];
     if (item == null) {
-      BufferPointer ref = bp._advance(4 + elementReader.size * i);
+      BufferPointer ref = bp._advance(4 + 4 * i);
       item = elementReader.read(ref);
       _items[i] = item;
     }
     return item;
   }
+}
+
+/**
+ * The base class for immutable lists read from flat buffers.
+ */
+abstract class _FbList<E> extends Object with ListMixin<E> implements List<E> {
+  @override
+  void set length(int i) =>
+      throw new StateError('Attempt to modify immutable list');
 
   @override
   void operator []=(int i, E e) =>
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 97f9db6..4a0424b 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -12,42 +12,661 @@
 
 /**
  * Enum used to indicate the kind of entity referred to by a
- * [PrelinkedReference].
+ * [LinkedReference].
  */
-enum PrelinkedReferenceKind {
+enum ReferenceKind {
+  /**
+   * The entity is a class or enum.
+   */
   classOrEnum,
+
+  /**
+   * The entity is a constructor.
+   */
+  constructor,
+
+  /**
+   * The entity is a static const field.
+   */
+  constField,
+
+  /**
+   * The entity is a static method.
+   */
+  staticMethod,
+
+  /**
+   * The `length` property access.
+   */
+  length,
+
+  /**
+   * The entity is a typedef.
+   */
   typedef,
-  other,
+
+  /**
+   * The entity is a top level function.
+   */
+  topLevelFunction,
+
+  /**
+   * The entity is a top level getter or setter.
+   */
+  topLevelPropertyAccessor,
+
+  /**
+   * The entity is a prefix.
+   */
   prefix,
-  unresolved,
+
+  /**
+   * The entity being referred to does not exist.
+   */
+  unresolved
+}
+
+class _ReferenceKindReader extends fb.Reader<ReferenceKind> {
+  const _ReferenceKindReader() : super();
+
+  @override
+  int get size => 4;
+
+  @override
+  ReferenceKind read(fb.BufferPointer bp) {
+    int index = const fb.Uint32Reader().read(bp);
+    return ReferenceKind.values[index];
+  }
+}
+
+/**
+ * Enum representing the various kinds of operations which may be performed to
+ * produce a constant value.  These options are assumed to execute in the
+ * context of a stack which is initially empty.
+ */
+enum UnlinkedConstOperation {
+  /**
+   * Push the value of the n-th constructor argument (where n is obtained from
+   * [UnlinkedConst.ints]) onto the stack.
+   */
+  pushArgument,
+
+  /**
+   * Push the next value from [UnlinkedConst.ints] (a 32-bit unsigned integer)
+   * onto the stack.
+   *
+   * Note that Dart supports integers larger than 32 bits; these are
+   * represented by composing 32 bit values using the [shiftOr] operation.
+   */
+  pushInt,
+
+  /**
+   * Pop the top value off the stack, which should be an integer.  Multiply it
+   * by 2^32, "or" in the next value from [UnlinkedConst.ints] (which is
+   * interpreted as a 32-bit unsigned integer), and push the result back onto
+   * the stack.
+   */
+  shiftOr,
+
+  /**
+   * Push the next value from [UnlinkedConst.doubles] (a double precision
+   * floating point value) onto the stack.
+   */
+  pushDouble,
+
+  /**
+   * Push the constant `true` onto the stack.
+   */
+  pushTrue,
+
+  /**
+   * Push the constant `false` onto the stack.
+   */
+  pushFalse,
+
+  /**
+   * Push the next value from [UnlinkedConst.strings] onto the stack.
+   */
+  pushString,
+
+  /**
+   * Pop the top n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), convert them to strings (if they aren't already),
+   * concatenate them into a single string, and push it back onto the stack.
+   *
+   * This operation is used to represent constants whose value is a literal
+   * string containing string interpolations.
+   */
+  concatenate,
+
+  /**
+   * Pop the top value from the stack which should be string, convert it to
+   * a symbol, and push it back onto the stack.
+   */
+  makeSymbol,
+
+  /**
+   * Push the constant `null` onto the stack.
+   */
+  pushNull,
+
+  /**
+   * Evaluate a (potentially qualified) identifier expression and push the
+   * resulting value onto the stack.  The identifier to be evaluated is
+   * obtained from [UnlinkedConst.references].
+   *
+   * This operation is used to represent the following kinds of constants
+   * (which are indistinguishable from an unresolved AST alone):
+   *
+   * - A qualified reference to a static constant variable (e.g. `C.v`, where
+   *   C is a class and `v` is a constant static variable in `C`).
+   * - An identifier expression referring to a constant variable.
+   * - A simple or qualified identifier denoting a class or type alias.
+   * - A simple or qualified identifier denoting a top-level function or a
+   *   static method.
+   */
+  pushReference,
+
+  /**
+   * Pop the top `n` values from the stack (where `n` is obtained from
+   * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
+   * `n` values from [UnlinkedConst.strings] and use the lists of names and
+   * values to create named arguments.  Then pop the top `m` values from the
+   * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
+   * from the end) and use them as positional arguments.  Use the lists of
+   * positional and names arguments to invoke a constant constructor obtained
+   * from [UnlinkedConst.references], and push the resulting value back onto the
+   * stack.
+   *
+   * Note that for an invocation of the form `const a.b(...)` (where no type
+   * arguments are specified), it is impossible to tell from the unresolved AST
+   * alone whether `a` is a class name and `b` is a constructor name, or `a` is
+   * a prefix name and `b` is a class name.  For consistency between AST based
+   * and elements based summaries, references to default constructors are always
+   * recorded as references to corresponding classes.
+   */
+  invokeConstructor,
+
+  /**
+   * Pop the top n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), place them in a [List], and push the result back
+   * onto the stack.  The type parameter for the [List] is implicitly `dynamic`.
+   */
+  makeUntypedList,
+
+  /**
+   * Pop the top 2*n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
+   * [Map], and push the result back onto the stack.  The two type parameters
+   * for the [Map] are implicitly `dynamic`.
+   */
+  makeUntypedMap,
+
+  /**
+   * Pop the top n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), place them in a [List], and push the result back
+   * onto the stack.  The type parameter for the [List] is obtained from
+   * [UnlinkedConst.references].
+   */
+  makeTypedList,
+
+  /**
+   * Pop the top 2*n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
+   * [Map], and push the result back onto the stack.  The two type parameters for
+   * the [Map] are obtained from [UnlinkedConst.references].
+   */
+  makeTypedMap,
+
+  /**
+   * Pop the top 2 values from the stack, pass them to the predefined Dart
+   * function `identical`, and push the result back onto the stack.
+   */
+  identical,
+
+  /**
+   * Pop the top 2 values from the stack, evaluate `v1 == v2`, and push the
+   * result back onto the stack.
+   *
+   * This is also used to represent `v1 != v2`, by composition with [not].
+   */
+  equal,
+
+  /**
+   * Pop the top value from the stack, compute its boolean negation, and push
+   * the result back onto the stack.
+   */
+  not,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 && v2`, and push the
+   * result back onto the stack.
+   */
+  and,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 || v2`, and push the
+   * result back onto the stack.
+   */
+  or,
+
+  /**
+   * Pop the top value from the stack, compute its integer complement, and push
+   * the result back onto the stack.
+   */
+  complement,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 ^ v2`, and push the
+   * result back onto the stack.
+   */
+  bitXor,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 & v2`, and push the
+   * result back onto the stack.
+   */
+  bitAnd,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 | v2`, and push the
+   * result back onto the stack.
+   */
+  bitOr,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 >> v2`, and push the
+   * result back onto the stack.
+   */
+  bitShiftRight,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 << v2`, and push the
+   * result back onto the stack.
+   */
+  bitShiftLeft,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 + v2`, and push the
+   * result back onto the stack.
+   */
+  add,
+
+  /**
+   * Pop the top value from the stack, compute its integer negation, and push
+   * the result back onto the stack.
+   */
+  negate,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 - v2`, and push the
+   * result back onto the stack.
+   */
+  subtract,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 * v2`, and push the
+   * result back onto the stack.
+   */
+  multiply,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 / v2`, and push the
+   * result back onto the stack.
+   */
+  divide,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 ~/ v2`, and push the
+   * result back onto the stack.
+   */
+  floorDivide,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 > v2`, and push the
+   * result back onto the stack.
+   */
+  greater,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 < v2`, and push the
+   * result back onto the stack.
+   */
+  less,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 >= v2`, and push the
+   * result back onto the stack.
+   */
+  greaterEqual,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 <= v2`, and push the
+   * result back onto the stack.
+   */
+  lessEqual,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 % v2`, and push the
+   * result back onto the stack.
+   */
+  modulo,
+
+  /**
+   * Pop the top 3 values from the stack, compute `v1 ? v2 : v3`, and push the
+   * result back onto the stack.
+   */
+  conditional,
+
+  /**
+   * Pop the top value from the stack, evaluate `v.length`, and push the result
+   * back onto the stack.
+   */
+  length
+}
+
+class _UnlinkedConstOperationReader extends fb.Reader<UnlinkedConstOperation> {
+  const _UnlinkedConstOperationReader() : super();
+
+  @override
+  int get size => 4;
+
+  @override
+  UnlinkedConstOperation read(fb.BufferPointer bp) {
+    int index = const fb.Uint32Reader().read(bp);
+    return UnlinkedConstOperation.values[index];
+  }
 }
 
 /**
  * Enum used to indicate the kind of an executable.
  */
 enum UnlinkedExecutableKind {
+  /**
+   * Executable is a function or method.
+   */
   functionOrMethod,
+
+  /**
+   * Executable is a getter.
+   */
   getter,
+
+  /**
+   * Executable is a setter.
+   */
   setter,
-  constructor,
+
+  /**
+   * Executable is a constructor.
+   */
+  constructor
+}
+
+class _UnlinkedExecutableKindReader extends fb.Reader<UnlinkedExecutableKind> {
+  const _UnlinkedExecutableKindReader() : super();
+
+  @override
+  int get size => 4;
+
+  @override
+  UnlinkedExecutableKind read(fb.BufferPointer bp) {
+    int index = const fb.Uint32Reader().read(bp);
+    return UnlinkedExecutableKind.values[index];
+  }
 }
 
 /**
  * Enum used to indicate the kind of a parameter.
  */
 enum UnlinkedParamKind {
+  /**
+   * Parameter is required.
+   */
   required,
+
+  /**
+   * Parameter is positional optional (enclosed in `[]`)
+   */
   positional,
-  named,
+
+  /**
+   * Parameter is named optional (enclosed in `{}`)
+   */
+  named
 }
 
-class PrelinkedDependencyBuilder {
+class _UnlinkedParamKindReader extends fb.Reader<UnlinkedParamKind> {
+  const _UnlinkedParamKindReader() : super();
+
+  @override
+  int get size => 4;
+
+  @override
+  UnlinkedParamKind read(fb.BufferPointer bp) {
+    int index = const fb.Uint32Reader().read(bp);
+    return UnlinkedParamKind.values[index];
+  }
+}
+
+class EntityRefBuilder extends Object with _EntityRefMixin implements EntityRef {
+  bool _finished = false;
+
+  int _slot;
+  int _reference;
+  int _paramReference;
+  List<EntityRefBuilder> _typeArguments;
+
+  @override
+  int get slot => _slot ??= 0;
+
+  /**
+   * If this [EntityRef] is contained within [LinkedUnit.types], slot id (which
+   * is unique within the compilation unit) identifying the target of type
+   * propagation or type inference with which this [EntityRef] is associated.
+   *
+   * Otherwise zero.
+   */
+  void set slot(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _slot = _value;
+  }
+
+  @override
+  int get reference => _reference ??= 0;
+
+  /**
+   * Index into [UnlinkedUnit.references] for the entity being referred to, or
+   * zero if this is a reference to a type parameter.
+   */
+  void set reference(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _reference = _value;
+  }
+
+  @override
+  int get paramReference => _paramReference ??= 0;
+
+  /**
+   * If this is a reference to a type parameter, one-based index into the list
+   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
+   * Bruijn index conventions; that is, innermost parameters come first, and
+   * if a class or method has multiple parameters, they are indexed from right
+   * to left.  So for instance, if the enclosing declaration is
+   *
+   *     class C<T,U> {
+   *       m<V,W> {
+   *         ...
+   *       }
+   *     }
+   *
+   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+   * respectively.
+   *
+   * If the type being referred to is not a type parameter, [paramReference] is
+   * zero.
+   */
+  void set paramReference(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _paramReference = _value;
+  }
+
+  @override
+  List<EntityRefBuilder> get typeArguments => _typeArguments ??= <EntityRefBuilder>[];
+
+  /**
+   * If this is an instantiation of a generic type or generic executable, the
+   * type arguments used to instantiate it.  Trailing type arguments of type
+   * `dynamic` are omitted.
+   */
+  void set typeArguments(List<EntityRefBuilder> _value) {
+    assert(!_finished);
+    _typeArguments = _value;
+  }
+
+  EntityRefBuilder({int slot, int reference, int paramReference, List<EntityRefBuilder> typeArguments})
+    : _slot = slot,
+      _reference = reference,
+      _paramReference = paramReference,
+      _typeArguments = typeArguments;
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    assert(!_finished);
+    _finished = true;
+    fb.Offset offset_typeArguments;
+    if (!(_typeArguments == null || _typeArguments.isEmpty)) {
+      offset_typeArguments = fbBuilder.writeList(_typeArguments.map((b) => b.finish(fbBuilder)).toList());
+    }
+    fbBuilder.startTable();
+    if (_slot != null && _slot != 0) {
+      fbBuilder.addUint32(0, _slot);
+    }
+    if (_reference != null && _reference != 0) {
+      fbBuilder.addUint32(1, _reference);
+    }
+    if (_paramReference != null && _paramReference != 0) {
+      fbBuilder.addUint32(2, _paramReference);
+    }
+    if (offset_typeArguments != null) {
+      fbBuilder.addOffset(3, offset_typeArguments);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+/**
+ * Summary information about a reference to a an entity such as a type, top
+ * level executable, or executable within a class.
+ */
+abstract class EntityRef extends base.SummaryClass {
+
+  /**
+   * If this [EntityRef] is contained within [LinkedUnit.types], slot id (which
+   * is unique within the compilation unit) identifying the target of type
+   * propagation or type inference with which this [EntityRef] is associated.
+   *
+   * Otherwise zero.
+   */
+  int get slot;
+
+  /**
+   * Index into [UnlinkedUnit.references] for the entity being referred to, or
+   * zero if this is a reference to a type parameter.
+   */
+  int get reference;
+
+  /**
+   * If this is a reference to a type parameter, one-based index into the list
+   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
+   * Bruijn index conventions; that is, innermost parameters come first, and
+   * if a class or method has multiple parameters, they are indexed from right
+   * to left.  So for instance, if the enclosing declaration is
+   *
+   *     class C<T,U> {
+   *       m<V,W> {
+   *         ...
+   *       }
+   *     }
+   *
+   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+   * respectively.
+   *
+   * If the type being referred to is not a type parameter, [paramReference] is
+   * zero.
+   */
+  int get paramReference;
+
+  /**
+   * If this is an instantiation of a generic type or generic executable, the
+   * type arguments used to instantiate it.  Trailing type arguments of type
+   * `dynamic` are omitted.
+   */
+  List<EntityRef> get typeArguments;
+}
+
+class _EntityRefReader extends fb.TableReader<_EntityRefImpl> {
+  const _EntityRefReader();
+
+  @override
+  _EntityRefImpl createObject(fb.BufferPointer bp) => new _EntityRefImpl(bp);
+}
+
+class _EntityRefImpl extends Object with _EntityRefMixin implements EntityRef {
+  final fb.BufferPointer _bp;
+
+  _EntityRefImpl(this._bp);
+
+  int _slot;
+  int _reference;
+  int _paramReference;
+  List<EntityRef> _typeArguments;
+
+  @override
+  int get slot {
+    _slot ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
+    return _slot;
+  }
+
+  @override
+  int get reference {
+    _reference ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    return _reference;
+  }
+
+  @override
+  int get paramReference {
+    _paramReference ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    return _paramReference;
+  }
+
+  @override
+  List<EntityRef> get typeArguments {
+    _typeArguments ??= const fb.ListReader<EntityRef>(const _EntityRefReader()).vTableGet(_bp, 3, const <EntityRef>[]);
+    return _typeArguments;
+  }
+}
+
+abstract class _EntityRefMixin implements EntityRef {
+  @override
+  Map<String, Object> toMap() => {
+    "slot": slot,
+    "reference": reference,
+    "paramReference": paramReference,
+    "typeArguments": typeArguments,
+  };
+}
+
+class LinkedDependencyBuilder extends Object with _LinkedDependencyMixin implements LinkedDependency {
   bool _finished = false;
 
   String _uri;
   List<String> _parts;
 
-  PrelinkedDependencyBuilder();
+  @override
+  String get uri => _uri ??= '';
 
   /**
    * The relative URI of the dependent library.  This URI is relative to the
@@ -61,6 +680,9 @@
     _uri = _value;
   }
 
+  @override
+  List<String> get parts => _parts ??= <String>[];
+
   /**
    * URI for the compilation units listed in the library's `part` declarations.
    * These URIs are relative to the importing library.
@@ -70,6 +692,10 @@
     _parts = _value;
   }
 
+  LinkedDependencyBuilder({String uri, List<String> parts})
+    : _uri = uri,
+      _parts = parts;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -92,18 +718,11 @@
   }
 }
 
-PrelinkedDependencyBuilder encodePrelinkedDependency({String uri, List<String> parts}) {
-  PrelinkedDependencyBuilder builder = new PrelinkedDependencyBuilder();
-  builder.uri = uri;
-  builder.parts = parts;
-  return builder;
-}
-
 /**
  * Information about a dependency that exists between one library and another
  * due to an "import" declaration.
  */
-abstract class PrelinkedDependency extends base.SummaryClass {
+abstract class LinkedDependency extends base.SummaryClass {
 
   /**
    * The relative URI of the dependent library.  This URI is relative to the
@@ -121,28 +740,22 @@
   List<String> get parts;
 }
 
-class _PrelinkedDependencyReader extends fb.TableReader<_PrelinkedDependencyImpl> {
-  const _PrelinkedDependencyReader();
+class _LinkedDependencyReader extends fb.TableReader<_LinkedDependencyImpl> {
+  const _LinkedDependencyReader();
 
   @override
-  _PrelinkedDependencyImpl createObject(fb.BufferPointer bp) => new _PrelinkedDependencyImpl(bp);
+  _LinkedDependencyImpl createObject(fb.BufferPointer bp) => new _LinkedDependencyImpl(bp);
 }
 
-class _PrelinkedDependencyImpl implements PrelinkedDependency {
+class _LinkedDependencyImpl extends Object with _LinkedDependencyMixin implements LinkedDependency {
   final fb.BufferPointer _bp;
 
-  _PrelinkedDependencyImpl(this._bp);
+  _LinkedDependencyImpl(this._bp);
 
   String _uri;
   List<String> _parts;
 
   @override
-  Map<String, Object> toMap() => {
-    "uri": uri,
-    "parts": parts,
-  };
-
-  @override
   String get uri {
     _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _uri;
@@ -155,52 +768,283 @@
   }
 }
 
-class PrelinkedLibraryBuilder {
+abstract class _LinkedDependencyMixin implements LinkedDependency {
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+    "parts": parts,
+  };
+}
+
+class LinkedExportNameBuilder extends Object with _LinkedExportNameMixin implements LinkedExportName {
   bool _finished = false;
 
-  List<PrelinkedUnitBuilder> _units;
-  List<PrelinkedDependencyBuilder> _dependencies;
-  List<int> _importDependencies;
+  String _name;
+  int _dependency;
+  int _unit;
+  ReferenceKind _kind;
 
-  PrelinkedLibraryBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
-   * The pre-linked summary of all the compilation units constituting the
+   * Name of the exported entity.  TODO(paulberry): do we include the trailing
+   * '=' for a setter?
+   */
+  void set name(String _value) {
+    assert(!_finished);
+    _name = _value;
+  }
+
+  @override
+  int get dependency => _dependency ??= 0;
+
+  /**
+   * Index into [LinkedLibrary.dependencies] for the library in which the
+   * entity is defined.
+   */
+  void set dependency(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _dependency = _value;
+  }
+
+  @override
+  int get unit => _unit ??= 0;
+
+  /**
+   * Integer index indicating which unit in the exported library contains the
+   * definition of the entity.  As with indices into [LinkedLibrary.units],
+   * zero represents the defining compilation unit, and nonzero values
+   * represent parts in the order of the corresponding `part` declarations.
+   */
+  void set unit(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _unit = _value;
+  }
+
+  @override
+  ReferenceKind get kind => _kind ??= ReferenceKind.classOrEnum;
+
+  /**
+   * The kind of the entity being referred to.
+   */
+  void set kind(ReferenceKind _value) {
+    assert(!_finished);
+    _kind = _value;
+  }
+
+  LinkedExportNameBuilder({String name, int dependency, int unit, ReferenceKind kind})
+    : _name = name,
+      _dependency = dependency,
+      _unit = unit,
+      _kind = kind;
+
+  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 (offset_name != null) {
+      fbBuilder.addOffset(0, offset_name);
+    }
+    if (_dependency != null && _dependency != 0) {
+      fbBuilder.addUint32(1, _dependency);
+    }
+    if (_unit != null && _unit != 0) {
+      fbBuilder.addUint32(2, _unit);
+    }
+    if (_kind != null && _kind != ReferenceKind.classOrEnum) {
+      fbBuilder.addUint32(3, _kind.index);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+/**
+ * Information about a single name in the export namespace of the library that
+ * is not in the public namespace.
+ */
+abstract class LinkedExportName extends base.SummaryClass {
+
+  /**
+   * Name of the exported entity.  TODO(paulberry): do we include the trailing
+   * '=' for a setter?
+   */
+  String get name;
+
+  /**
+   * Index into [LinkedLibrary.dependencies] for the library in which the
+   * entity is defined.
+   */
+  int get dependency;
+
+  /**
+   * Integer index indicating which unit in the exported library contains the
+   * definition of the entity.  As with indices into [LinkedLibrary.units],
+   * zero represents the defining compilation unit, and nonzero values
+   * represent parts in the order of the corresponding `part` declarations.
+   */
+  int get unit;
+
+  /**
+   * The kind of the entity being referred to.
+   */
+  ReferenceKind get kind;
+}
+
+class _LinkedExportNameReader extends fb.TableReader<_LinkedExportNameImpl> {
+  const _LinkedExportNameReader();
+
+  @override
+  _LinkedExportNameImpl createObject(fb.BufferPointer bp) => new _LinkedExportNameImpl(bp);
+}
+
+class _LinkedExportNameImpl extends Object with _LinkedExportNameMixin implements LinkedExportName {
+  final fb.BufferPointer _bp;
+
+  _LinkedExportNameImpl(this._bp);
+
+  String _name;
+  int _dependency;
+  int _unit;
+  ReferenceKind _kind;
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
+    return _name;
+  }
+
+  @override
+  int get dependency {
+    _dependency ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
+    return _dependency;
+  }
+
+  @override
+  int get unit {
+    _unit ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    return _unit;
+  }
+
+  @override
+  ReferenceKind get kind {
+    _kind ??= const _ReferenceKindReader().vTableGet(_bp, 3, ReferenceKind.classOrEnum);
+    return _kind;
+  }
+}
+
+abstract class _LinkedExportNameMixin implements LinkedExportName {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "dependency": dependency,
+    "unit": unit,
+    "kind": kind,
+  };
+}
+
+class LinkedLibraryBuilder extends Object with _LinkedLibraryMixin implements LinkedLibrary {
+  bool _finished = false;
+
+  List<LinkedUnitBuilder> _units;
+  List<LinkedDependencyBuilder> _dependencies;
+  List<int> _importDependencies;
+  List<LinkedExportNameBuilder> _exportNames;
+  int _numPrelinkedDependencies;
+
+  @override
+  List<LinkedUnitBuilder> get units => _units ??= <LinkedUnitBuilder>[];
+
+  /**
+   * The linked summary of all the compilation units constituting the
    * library.  The summary of the defining compilation unit is listed first,
    * followed by the summary of each part, in the order of the `part`
    * declarations in the defining compilation unit.
    */
-  void set units(List<PrelinkedUnitBuilder> _value) {
+  void set units(List<LinkedUnitBuilder> _value) {
     assert(!_finished);
     _units = _value;
   }
 
+  @override
+  List<LinkedDependencyBuilder> get dependencies => _dependencies ??= <LinkedDependencyBuilder>[];
+
   /**
    * The libraries that this library depends on (either via an explicit import
    * statement or via the implicit dependencies on `dart:core` and
    * `dart:async`).  The first element of this array is a pseudo-dependency
-   * representing the library itself (it is also used for "dynamic").
+   * representing the library itself (it is also used for `dynamic` and
+   * `void`).  This is followed by elements representing "prelinked"
+   * dependencies (direct imports and the transitive closure of exports).
+   * After the prelinked dependencies are elements representing "linked"
+   * dependencies.
    *
-   * TODO(paulberry): consider removing this entirely and just using
-   * [UnlinkedLibrary.imports].
+   * A library is only included as a "linked" dependency if it is a true
+   * dependency (e.g. a propagated or inferred type or constant value
+   * implicitly refers to an element declared in the library) or
+   * anti-dependency (e.g. the result of type propagation or type inference
+   * depends on the lack of a certain declaration in the library).
    */
-  void set dependencies(List<PrelinkedDependencyBuilder> _value) {
+  void set dependencies(List<LinkedDependencyBuilder> _value) {
     assert(!_finished);
     _dependencies = _value;
   }
 
+  @override
+  List<int> get importDependencies => _importDependencies ??= <int>[];
+
   /**
    * For each import in [UnlinkedUnit.imports], an index into [dependencies]
    * of the library being imported.
-   *
-   * TODO(paulberry): if [dependencies] is removed, this can be removed as
-   * well, since there will effectively be a one-to-one mapping.
    */
   void set importDependencies(List<int> _value) {
     assert(!_finished);
+    assert(_value == null || _value.every((e) => e >= 0));
     _importDependencies = _value;
   }
 
+  @override
+  List<LinkedExportNameBuilder> get exportNames => _exportNames ??= <LinkedExportNameBuilder>[];
+
+  /**
+   * Information about entities in the export namespace of the library that are
+   * not in the public namespace of the library (that is, entities that are
+   * brought into the namespace via `export` directives).
+   *
+   * Sorted by name.
+   */
+  void set exportNames(List<LinkedExportNameBuilder> _value) {
+    assert(!_finished);
+    _exportNames = _value;
+  }
+
+  @override
+  int get numPrelinkedDependencies => _numPrelinkedDependencies ??= 0;
+
+  /**
+   * The number of elements in [dependencies] which are not "linked"
+   * dependencies (that is, the number of libraries in the direct imports plus
+   * the transitive closure of exports, plus the library itself).
+   */
+  void set numPrelinkedDependencies(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _numPrelinkedDependencies = _value;
+  }
+
+  LinkedLibraryBuilder({List<LinkedUnitBuilder> units, List<LinkedDependencyBuilder> dependencies, List<int> importDependencies, List<LinkedExportNameBuilder> exportNames, int numPrelinkedDependencies})
+    : _units = units,
+      _dependencies = dependencies,
+      _importDependencies = importDependencies,
+      _exportNames = exportNames,
+      _numPrelinkedDependencies = numPrelinkedDependencies;
+
   List<int> toBuffer() {
     fb.Builder fbBuilder = new fb.Builder();
     return fbBuilder.finish(finish(fbBuilder));
@@ -212,6 +1056,7 @@
     fb.Offset offset_units;
     fb.Offset offset_dependencies;
     fb.Offset offset_importDependencies;
+    fb.Offset offset_exportNames;
     if (!(_units == null || _units.isEmpty)) {
       offset_units = fbBuilder.writeList(_units.map((b) => b.finish(fbBuilder)).toList());
     }
@@ -219,7 +1064,10 @@
       offset_dependencies = fbBuilder.writeList(_dependencies.map((b) => b.finish(fbBuilder)).toList());
     }
     if (!(_importDependencies == null || _importDependencies.isEmpty)) {
-      offset_importDependencies = fbBuilder.writeListInt32(_importDependencies);
+      offset_importDependencies = fbBuilder.writeListUint32(_importDependencies);
+    }
+    if (!(_exportNames == null || _exportNames.isEmpty)) {
+      offset_exportNames = fbBuilder.writeList(_exportNames.map((b) => b.finish(fbBuilder)).toList());
     }
     fbBuilder.startTable();
     if (offset_units != null) {
@@ -231,195 +1079,263 @@
     if (offset_importDependencies != null) {
       fbBuilder.addOffset(2, offset_importDependencies);
     }
+    if (offset_exportNames != null) {
+      fbBuilder.addOffset(3, offset_exportNames);
+    }
+    if (_numPrelinkedDependencies != null && _numPrelinkedDependencies != 0) {
+      fbBuilder.addUint32(4, _numPrelinkedDependencies);
+    }
     return fbBuilder.endTable();
   }
 }
 
-PrelinkedLibraryBuilder encodePrelinkedLibrary({List<PrelinkedUnitBuilder> units, List<PrelinkedDependencyBuilder> dependencies, List<int> importDependencies}) {
-  PrelinkedLibraryBuilder builder = new PrelinkedLibraryBuilder();
-  builder.units = units;
-  builder.dependencies = dependencies;
-  builder.importDependencies = importDependencies;
-  return builder;
-}
-
 /**
- * Pre-linked summary of a library.
+ * Linked summary of a library.
  */
-abstract class PrelinkedLibrary extends base.SummaryClass {
-  factory PrelinkedLibrary.fromBuffer(List<int> buffer) {
+abstract class LinkedLibrary extends base.SummaryClass {
+  factory LinkedLibrary.fromBuffer(List<int> buffer) {
     fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer);
-    return const _PrelinkedLibraryReader().read(rootRef);
+    return const _LinkedLibraryReader().read(rootRef);
   }
 
   /**
-   * The pre-linked summary of all the compilation units constituting the
+   * The linked summary of all the compilation units constituting the
    * library.  The summary of the defining compilation unit is listed first,
    * followed by the summary of each part, in the order of the `part`
    * declarations in the defining compilation unit.
    */
-  List<PrelinkedUnit> get units;
+  List<LinkedUnit> get units;
 
   /**
    * The libraries that this library depends on (either via an explicit import
    * statement or via the implicit dependencies on `dart:core` and
    * `dart:async`).  The first element of this array is a pseudo-dependency
-   * representing the library itself (it is also used for "dynamic").
+   * representing the library itself (it is also used for `dynamic` and
+   * `void`).  This is followed by elements representing "prelinked"
+   * dependencies (direct imports and the transitive closure of exports).
+   * After the prelinked dependencies are elements representing "linked"
+   * dependencies.
    *
-   * TODO(paulberry): consider removing this entirely and just using
-   * [UnlinkedLibrary.imports].
+   * A library is only included as a "linked" dependency if it is a true
+   * dependency (e.g. a propagated or inferred type or constant value
+   * implicitly refers to an element declared in the library) or
+   * anti-dependency (e.g. the result of type propagation or type inference
+   * depends on the lack of a certain declaration in the library).
    */
-  List<PrelinkedDependency> get dependencies;
+  List<LinkedDependency> get dependencies;
 
   /**
    * For each import in [UnlinkedUnit.imports], an index into [dependencies]
    * of the library being imported.
-   *
-   * TODO(paulberry): if [dependencies] is removed, this can be removed as
-   * well, since there will effectively be a one-to-one mapping.
    */
   List<int> get importDependencies;
+
+  /**
+   * Information about entities in the export namespace of the library that are
+   * not in the public namespace of the library (that is, entities that are
+   * brought into the namespace via `export` directives).
+   *
+   * Sorted by name.
+   */
+  List<LinkedExportName> get exportNames;
+
+  /**
+   * The number of elements in [dependencies] which are not "linked"
+   * dependencies (that is, the number of libraries in the direct imports plus
+   * the transitive closure of exports, plus the library itself).
+   */
+  int get numPrelinkedDependencies;
 }
 
-class _PrelinkedLibraryReader extends fb.TableReader<_PrelinkedLibraryImpl> {
-  const _PrelinkedLibraryReader();
+class _LinkedLibraryReader extends fb.TableReader<_LinkedLibraryImpl> {
+  const _LinkedLibraryReader();
 
   @override
-  _PrelinkedLibraryImpl createObject(fb.BufferPointer bp) => new _PrelinkedLibraryImpl(bp);
+  _LinkedLibraryImpl createObject(fb.BufferPointer bp) => new _LinkedLibraryImpl(bp);
 }
 
-class _PrelinkedLibraryImpl implements PrelinkedLibrary {
+class _LinkedLibraryImpl extends Object with _LinkedLibraryMixin implements LinkedLibrary {
   final fb.BufferPointer _bp;
 
-  _PrelinkedLibraryImpl(this._bp);
+  _LinkedLibraryImpl(this._bp);
 
-  List<PrelinkedUnit> _units;
-  List<PrelinkedDependency> _dependencies;
+  List<LinkedUnit> _units;
+  List<LinkedDependency> _dependencies;
   List<int> _importDependencies;
+  List<LinkedExportName> _exportNames;
+  int _numPrelinkedDependencies;
 
   @override
-  Map<String, Object> toMap() => {
-    "units": units,
-    "dependencies": dependencies,
-    "importDependencies": importDependencies,
-  };
-
-  @override
-  List<PrelinkedUnit> get units {
-    _units ??= const fb.ListReader<PrelinkedUnit>(const _PrelinkedUnitReader()).vTableGet(_bp, 0, const <PrelinkedUnit>[]);
+  List<LinkedUnit> get units {
+    _units ??= const fb.ListReader<LinkedUnit>(const _LinkedUnitReader()).vTableGet(_bp, 0, const <LinkedUnit>[]);
     return _units;
   }
 
   @override
-  List<PrelinkedDependency> get dependencies {
-    _dependencies ??= const fb.ListReader<PrelinkedDependency>(const _PrelinkedDependencyReader()).vTableGet(_bp, 1, const <PrelinkedDependency>[]);
+  List<LinkedDependency> get dependencies {
+    _dependencies ??= const fb.ListReader<LinkedDependency>(const _LinkedDependencyReader()).vTableGet(_bp, 1, const <LinkedDependency>[]);
     return _dependencies;
   }
 
   @override
   List<int> get importDependencies {
-    _importDependencies ??= const fb.ListReader<int>(const fb.Int32Reader()).vTableGet(_bp, 2, const <int>[]);
+    _importDependencies ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 2, const <int>[]);
     return _importDependencies;
   }
+
+  @override
+  List<LinkedExportName> get exportNames {
+    _exportNames ??= const fb.ListReader<LinkedExportName>(const _LinkedExportNameReader()).vTableGet(_bp, 3, const <LinkedExportName>[]);
+    return _exportNames;
+  }
+
+  @override
+  int get numPrelinkedDependencies {
+    _numPrelinkedDependencies ??= const fb.Uint32Reader().vTableGet(_bp, 4, 0);
+    return _numPrelinkedDependencies;
+  }
 }
 
-class PrelinkedReferenceBuilder {
+abstract class _LinkedLibraryMixin implements LinkedLibrary {
+  @override
+  Map<String, Object> toMap() => {
+    "units": units,
+    "dependencies": dependencies,
+    "importDependencies": importDependencies,
+    "exportNames": exportNames,
+    "numPrelinkedDependencies": numPrelinkedDependencies,
+  };
+}
+
+class LinkedReferenceBuilder extends Object with _LinkedReferenceMixin implements LinkedReference {
   bool _finished = false;
 
   int _dependency;
-  PrelinkedReferenceKind _kind;
+  ReferenceKind _kind;
   int _unit;
   int _numTypeParameters;
+  String _name;
 
-  PrelinkedReferenceBuilder();
+  @override
+  int get dependency => _dependency ??= 0;
 
   /**
-   * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+   * Index into [LinkedLibrary.dependencies] indicating which imported library
    * declares the entity being referred to.
    */
   void set dependency(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _dependency = _value;
   }
 
+  @override
+  ReferenceKind get kind => _kind ??= ReferenceKind.classOrEnum;
+
   /**
-   * The kind of the entity being referred to.  For the pseudo-type `dynamic`,
-   * the kind is [PrelinkedReferenceKind.classOrEnum].
+   * The kind of the entity being referred to.  For the pseudo-types `dynamic`
+   * and `void`, the kind is [ReferenceKind.classOrEnum].
    */
-  void set kind(PrelinkedReferenceKind _value) {
+  void set kind(ReferenceKind _value) {
     assert(!_finished);
     _kind = _value;
   }
 
+  @override
+  int get unit => _unit ??= 0;
+
   /**
    * Integer index indicating which unit in the imported library contains the
-   * definition of the entity.  As with indices into [PrelinkedLibrary.units],
+   * definition of the entity.  As with indices into [LinkedLibrary.units],
    * zero represents the defining compilation unit, and nonzero values
    * represent parts in the order of the corresponding `part` declarations.
    */
   void set unit(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _unit = _value;
   }
 
+  @override
+  int get numTypeParameters => _numTypeParameters ??= 0;
+
   /**
    * If the entity being referred to is generic, the number of type parameters
    * it accepts.  Otherwise zero.
    */
   void set numTypeParameters(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _numTypeParameters = _value;
   }
 
+  @override
+  String get name => _name ??= '';
+
+  /**
+   * 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".
+   */
+  void set name(String _value) {
+    assert(!_finished);
+    _name = _value;
+  }
+
+  LinkedReferenceBuilder({int dependency, ReferenceKind kind, int unit, int numTypeParameters, String name})
+    : _dependency = dependency,
+      _kind = kind,
+      _unit = unit,
+      _numTypeParameters = numTypeParameters,
+      _name = name;
+
   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 (_dependency != null && _dependency != 0) {
-      fbBuilder.addInt32(0, _dependency);
+      fbBuilder.addUint32(0, _dependency);
     }
-    if (_kind != null && _kind != PrelinkedReferenceKind.classOrEnum) {
-      fbBuilder.addInt32(1, _kind.index);
+    if (_kind != null && _kind != ReferenceKind.classOrEnum) {
+      fbBuilder.addUint32(1, _kind.index);
     }
     if (_unit != null && _unit != 0) {
-      fbBuilder.addInt32(2, _unit);
+      fbBuilder.addUint32(2, _unit);
     }
     if (_numTypeParameters != null && _numTypeParameters != 0) {
-      fbBuilder.addInt32(3, _numTypeParameters);
+      fbBuilder.addUint32(3, _numTypeParameters);
+    }
+    if (offset_name != null) {
+      fbBuilder.addOffset(4, offset_name);
     }
     return fbBuilder.endTable();
   }
 }
 
-PrelinkedReferenceBuilder encodePrelinkedReference({int dependency, PrelinkedReferenceKind kind, int unit, int numTypeParameters}) {
-  PrelinkedReferenceBuilder builder = new PrelinkedReferenceBuilder();
-  builder.dependency = dependency;
-  builder.kind = kind;
-  builder.unit = unit;
-  builder.numTypeParameters = numTypeParameters;
-  return builder;
-}
-
 /**
  * Information about the resolution of an [UnlinkedReference].
  */
-abstract class PrelinkedReference extends base.SummaryClass {
+abstract class LinkedReference extends base.SummaryClass {
 
   /**
-   * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+   * Index into [LinkedLibrary.dependencies] indicating which imported library
    * declares the entity being referred to.
    */
   int get dependency;
 
   /**
-   * The kind of the entity being referred to.  For the pseudo-type `dynamic`,
-   * the kind is [PrelinkedReferenceKind.classOrEnum].
+   * The kind of the entity being referred to.  For the pseudo-types `dynamic`
+   * and `void`, the kind is [ReferenceKind.classOrEnum].
    */
-  PrelinkedReferenceKind get kind;
+  ReferenceKind get kind;
 
   /**
    * Integer index indicating which unit in the imported library contains the
-   * definition of the entity.  As with indices into [PrelinkedLibrary.units],
+   * definition of the entity.  As with indices into [LinkedLibrary.units],
    * zero represents the defining compilation unit, and nonzero values
    * represent parts in the order of the corresponding `part` declarations.
    */
@@ -430,159 +1346,226 @@
    * it accepts.  Otherwise zero.
    */
   int get numTypeParameters;
+
+  /**
+   * 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".
+   */
+  String get name;
 }
 
-class _PrelinkedReferenceReader extends fb.TableReader<_PrelinkedReferenceImpl> {
-  const _PrelinkedReferenceReader();
+class _LinkedReferenceReader extends fb.TableReader<_LinkedReferenceImpl> {
+  const _LinkedReferenceReader();
 
   @override
-  _PrelinkedReferenceImpl createObject(fb.BufferPointer bp) => new _PrelinkedReferenceImpl(bp);
+  _LinkedReferenceImpl createObject(fb.BufferPointer bp) => new _LinkedReferenceImpl(bp);
 }
 
-class _PrelinkedReferenceImpl implements PrelinkedReference {
+class _LinkedReferenceImpl extends Object with _LinkedReferenceMixin implements LinkedReference {
   final fb.BufferPointer _bp;
 
-  _PrelinkedReferenceImpl(this._bp);
+  _LinkedReferenceImpl(this._bp);
 
   int _dependency;
-  PrelinkedReferenceKind _kind;
+  ReferenceKind _kind;
   int _unit;
   int _numTypeParameters;
+  String _name;
 
   @override
+  int get dependency {
+    _dependency ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
+    return _dependency;
+  }
+
+  @override
+  ReferenceKind get kind {
+    _kind ??= const _ReferenceKindReader().vTableGet(_bp, 1, ReferenceKind.classOrEnum);
+    return _kind;
+  }
+
+  @override
+  int get unit {
+    _unit ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
+    return _unit;
+  }
+
+  @override
+  int get numTypeParameters {
+    _numTypeParameters ??= const fb.Uint32Reader().vTableGet(_bp, 3, 0);
+    return _numTypeParameters;
+  }
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bp, 4, '');
+    return _name;
+  }
+}
+
+abstract class _LinkedReferenceMixin implements LinkedReference {
+  @override
   Map<String, Object> toMap() => {
     "dependency": dependency,
     "kind": kind,
     "unit": unit,
     "numTypeParameters": numTypeParameters,
+    "name": name,
   };
-
-  @override
-  int get dependency {
-    _dependency ??= const fb.Int32Reader().vTableGet(_bp, 0, 0);
-    return _dependency;
-  }
-
-  @override
-  PrelinkedReferenceKind get kind {
-    _kind ??= PrelinkedReferenceKind.values[const fb.Int32Reader().vTableGet(_bp, 1, 0)];
-    return _kind;
-  }
-
-  @override
-  int get unit {
-    _unit ??= const fb.Int32Reader().vTableGet(_bp, 2, 0);
-    return _unit;
-  }
-
-  @override
-  int get numTypeParameters {
-    _numTypeParameters ??= const fb.Int32Reader().vTableGet(_bp, 3, 0);
-    return _numTypeParameters;
-  }
 }
 
-class PrelinkedUnitBuilder {
+class LinkedUnitBuilder extends Object with _LinkedUnitMixin implements LinkedUnit {
   bool _finished = false;
 
-  List<PrelinkedReferenceBuilder> _references;
+  List<LinkedReferenceBuilder> _references;
+  List<EntityRefBuilder> _types;
 
-  PrelinkedUnitBuilder();
+  @override
+  List<LinkedReferenceBuilder> get references => _references ??= <LinkedReferenceBuilder>[];
 
   /**
-   * For each reference in [UnlinkedUnit.references], information about how
-   * that reference is resolved.
+   * Information about the resolution of references within the compilation
+   * unit.  Each element of [UnlinkedUnit.references] has a corresponding
+   * element in this list (at the same index).  If this list has additional
+   * elements beyond the number of elements in [UnlinkedUnit.references], those
+   * additional elements are references that are only referred to implicitly
+   * (e.g. elements involved in inferred or propagated types).
    */
-  void set references(List<PrelinkedReferenceBuilder> _value) {
+  void set references(List<LinkedReferenceBuilder> _value) {
     assert(!_finished);
     _references = _value;
   }
 
+  @override
+  List<EntityRefBuilder> get types => _types ??= <EntityRefBuilder>[];
+
+  /**
+   * List associating slot ids found inside the unlinked summary for the
+   * compilation unit with propagated and inferred types.
+   */
+  void set types(List<EntityRefBuilder> _value) {
+    assert(!_finished);
+    _types = _value;
+  }
+
+  LinkedUnitBuilder({List<LinkedReferenceBuilder> references, List<EntityRefBuilder> types})
+    : _references = references,
+      _types = types;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
     fb.Offset offset_references;
+    fb.Offset offset_types;
     if (!(_references == null || _references.isEmpty)) {
       offset_references = fbBuilder.writeList(_references.map((b) => b.finish(fbBuilder)).toList());
     }
+    if (!(_types == null || _types.isEmpty)) {
+      offset_types = fbBuilder.writeList(_types.map((b) => b.finish(fbBuilder)).toList());
+    }
     fbBuilder.startTable();
     if (offset_references != null) {
       fbBuilder.addOffset(0, offset_references);
     }
+    if (offset_types != null) {
+      fbBuilder.addOffset(1, offset_types);
+    }
     return fbBuilder.endTable();
   }
 }
 
-PrelinkedUnitBuilder encodePrelinkedUnit({List<PrelinkedReferenceBuilder> references}) {
-  PrelinkedUnitBuilder builder = new PrelinkedUnitBuilder();
-  builder.references = references;
-  return builder;
-}
-
 /**
- * Pre-linked summary of a compilation unit.
+ * Linked summary of a compilation unit.
  */
-abstract class PrelinkedUnit extends base.SummaryClass {
+abstract class LinkedUnit extends base.SummaryClass {
 
   /**
-   * For each reference in [UnlinkedUnit.references], information about how
-   * that reference is resolved.
+   * Information about the resolution of references within the compilation
+   * unit.  Each element of [UnlinkedUnit.references] has a corresponding
+   * element in this list (at the same index).  If this list has additional
+   * elements beyond the number of elements in [UnlinkedUnit.references], those
+   * additional elements are references that are only referred to implicitly
+   * (e.g. elements involved in inferred or propagated types).
    */
-  List<PrelinkedReference> get references;
+  List<LinkedReference> get references;
+
+  /**
+   * List associating slot ids found inside the unlinked summary for the
+   * compilation unit with propagated and inferred types.
+   */
+  List<EntityRef> get types;
 }
 
-class _PrelinkedUnitReader extends fb.TableReader<_PrelinkedUnitImpl> {
-  const _PrelinkedUnitReader();
+class _LinkedUnitReader extends fb.TableReader<_LinkedUnitImpl> {
+  const _LinkedUnitReader();
 
   @override
-  _PrelinkedUnitImpl createObject(fb.BufferPointer bp) => new _PrelinkedUnitImpl(bp);
+  _LinkedUnitImpl createObject(fb.BufferPointer bp) => new _LinkedUnitImpl(bp);
 }
 
-class _PrelinkedUnitImpl implements PrelinkedUnit {
+class _LinkedUnitImpl extends Object with _LinkedUnitMixin implements LinkedUnit {
   final fb.BufferPointer _bp;
 
-  _PrelinkedUnitImpl(this._bp);
+  _LinkedUnitImpl(this._bp);
 
-  List<PrelinkedReference> _references;
+  List<LinkedReference> _references;
+  List<EntityRef> _types;
 
   @override
+  List<LinkedReference> get references {
+    _references ??= const fb.ListReader<LinkedReference>(const _LinkedReferenceReader()).vTableGet(_bp, 0, const <LinkedReference>[]);
+    return _references;
+  }
+
+  @override
+  List<EntityRef> get types {
+    _types ??= const fb.ListReader<EntityRef>(const _EntityRefReader()).vTableGet(_bp, 1, const <EntityRef>[]);
+    return _types;
+  }
+}
+
+abstract class _LinkedUnitMixin implements LinkedUnit {
+  @override
   Map<String, Object> toMap() => {
     "references": references,
+    "types": types,
   };
-
-  @override
-  List<PrelinkedReference> get references {
-    _references ??= const fb.ListReader<PrelinkedReference>(const _PrelinkedReferenceReader()).vTableGet(_bp, 0, const <PrelinkedReference>[]);
-    return _references;
-  }
 }
 
-class SdkBundleBuilder {
+class SdkBundleBuilder extends Object with _SdkBundleMixin implements SdkBundle {
   bool _finished = false;
 
-  List<String> _prelinkedLibraryUris;
-  List<PrelinkedLibraryBuilder> _prelinkedLibraries;
+  List<String> _linkedLibraryUris;
+  List<LinkedLibraryBuilder> _linkedLibraries;
   List<String> _unlinkedUnitUris;
   List<UnlinkedUnitBuilder> _unlinkedUnits;
 
-  SdkBundleBuilder();
+  @override
+  List<String> get linkedLibraryUris => _linkedLibraryUris ??= <String>[];
 
   /**
-   * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+   * The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
    */
-  void set prelinkedLibraryUris(List<String> _value) {
+  void set linkedLibraryUris(List<String> _value) {
     assert(!_finished);
-    _prelinkedLibraryUris = _value;
+    _linkedLibraryUris = _value;
   }
 
+  @override
+  List<LinkedLibraryBuilder> get linkedLibraries => _linkedLibraries ??= <LinkedLibraryBuilder>[];
+
   /**
-   * Pre-linked libraries.
+   * Linked libraries.
    */
-  void set prelinkedLibraries(List<PrelinkedLibraryBuilder> _value) {
+  void set linkedLibraries(List<LinkedLibraryBuilder> _value) {
     assert(!_finished);
-    _prelinkedLibraries = _value;
+    _linkedLibraries = _value;
   }
 
+  @override
+  List<String> get unlinkedUnitUris => _unlinkedUnitUris ??= <String>[];
+
   /**
    * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
    */
@@ -591,6 +1574,9 @@
     _unlinkedUnitUris = _value;
   }
 
+  @override
+  List<UnlinkedUnitBuilder> get unlinkedUnits => _unlinkedUnits ??= <UnlinkedUnitBuilder>[];
+
   /**
    * Unlinked information for the compilation units constituting the SDK.
    */
@@ -599,6 +1585,12 @@
     _unlinkedUnits = _value;
   }
 
+  SdkBundleBuilder({List<String> linkedLibraryUris, List<LinkedLibraryBuilder> linkedLibraries, List<String> unlinkedUnitUris, List<UnlinkedUnitBuilder> unlinkedUnits})
+    : _linkedLibraryUris = linkedLibraryUris,
+      _linkedLibraries = linkedLibraries,
+      _unlinkedUnitUris = unlinkedUnitUris,
+      _unlinkedUnits = unlinkedUnits;
+
   List<int> toBuffer() {
     fb.Builder fbBuilder = new fb.Builder();
     return fbBuilder.finish(finish(fbBuilder));
@@ -607,15 +1599,15 @@
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
-    fb.Offset offset_prelinkedLibraryUris;
-    fb.Offset offset_prelinkedLibraries;
+    fb.Offset offset_linkedLibraryUris;
+    fb.Offset offset_linkedLibraries;
     fb.Offset offset_unlinkedUnitUris;
     fb.Offset offset_unlinkedUnits;
-    if (!(_prelinkedLibraryUris == null || _prelinkedLibraryUris.isEmpty)) {
-      offset_prelinkedLibraryUris = fbBuilder.writeList(_prelinkedLibraryUris.map((b) => fbBuilder.writeString(b)).toList());
+    if (!(_linkedLibraryUris == null || _linkedLibraryUris.isEmpty)) {
+      offset_linkedLibraryUris = fbBuilder.writeList(_linkedLibraryUris.map((b) => fbBuilder.writeString(b)).toList());
     }
-    if (!(_prelinkedLibraries == null || _prelinkedLibraries.isEmpty)) {
-      offset_prelinkedLibraries = fbBuilder.writeList(_prelinkedLibraries.map((b) => b.finish(fbBuilder)).toList());
+    if (!(_linkedLibraries == null || _linkedLibraries.isEmpty)) {
+      offset_linkedLibraries = fbBuilder.writeList(_linkedLibraries.map((b) => b.finish(fbBuilder)).toList());
     }
     if (!(_unlinkedUnitUris == null || _unlinkedUnitUris.isEmpty)) {
       offset_unlinkedUnitUris = fbBuilder.writeList(_unlinkedUnitUris.map((b) => fbBuilder.writeString(b)).toList());
@@ -624,11 +1616,11 @@
       offset_unlinkedUnits = fbBuilder.writeList(_unlinkedUnits.map((b) => b.finish(fbBuilder)).toList());
     }
     fbBuilder.startTable();
-    if (offset_prelinkedLibraryUris != null) {
-      fbBuilder.addOffset(0, offset_prelinkedLibraryUris);
+    if (offset_linkedLibraryUris != null) {
+      fbBuilder.addOffset(0, offset_linkedLibraryUris);
     }
-    if (offset_prelinkedLibraries != null) {
-      fbBuilder.addOffset(1, offset_prelinkedLibraries);
+    if (offset_linkedLibraries != null) {
+      fbBuilder.addOffset(1, offset_linkedLibraries);
     }
     if (offset_unlinkedUnitUris != null) {
       fbBuilder.addOffset(2, offset_unlinkedUnitUris);
@@ -640,15 +1632,6 @@
   }
 }
 
-SdkBundleBuilder encodeSdkBundle({List<String> prelinkedLibraryUris, List<PrelinkedLibraryBuilder> prelinkedLibraries, List<String> unlinkedUnitUris, List<UnlinkedUnitBuilder> unlinkedUnits}) {
-  SdkBundleBuilder builder = new SdkBundleBuilder();
-  builder.prelinkedLibraryUris = prelinkedLibraryUris;
-  builder.prelinkedLibraries = prelinkedLibraries;
-  builder.unlinkedUnitUris = unlinkedUnitUris;
-  builder.unlinkedUnits = unlinkedUnits;
-  return builder;
-}
-
 /**
  * Information about SDK.
  */
@@ -659,14 +1642,14 @@
   }
 
   /**
-   * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+   * The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
    */
-  List<String> get prelinkedLibraryUris;
+  List<String> get linkedLibraryUris;
 
   /**
-   * Pre-linked libraries.
+   * Linked libraries.
    */
-  List<PrelinkedLibrary> get prelinkedLibraries;
+  List<LinkedLibrary> get linkedLibraries;
 
   /**
    * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
@@ -686,34 +1669,26 @@
   _SdkBundleImpl createObject(fb.BufferPointer bp) => new _SdkBundleImpl(bp);
 }
 
-class _SdkBundleImpl implements SdkBundle {
+class _SdkBundleImpl extends Object with _SdkBundleMixin implements SdkBundle {
   final fb.BufferPointer _bp;
 
   _SdkBundleImpl(this._bp);
 
-  List<String> _prelinkedLibraryUris;
-  List<PrelinkedLibrary> _prelinkedLibraries;
+  List<String> _linkedLibraryUris;
+  List<LinkedLibrary> _linkedLibraries;
   List<String> _unlinkedUnitUris;
   List<UnlinkedUnit> _unlinkedUnits;
 
   @override
-  Map<String, Object> toMap() => {
-    "prelinkedLibraryUris": prelinkedLibraryUris,
-    "prelinkedLibraries": prelinkedLibraries,
-    "unlinkedUnitUris": unlinkedUnitUris,
-    "unlinkedUnits": unlinkedUnits,
-  };
-
-  @override
-  List<String> get prelinkedLibraryUris {
-    _prelinkedLibraryUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
-    return _prelinkedLibraryUris;
+  List<String> get linkedLibraryUris {
+    _linkedLibraryUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
+    return _linkedLibraryUris;
   }
 
   @override
-  List<PrelinkedLibrary> get prelinkedLibraries {
-    _prelinkedLibraries ??= const fb.ListReader<PrelinkedLibrary>(const _PrelinkedLibraryReader()).vTableGet(_bp, 1, const <PrelinkedLibrary>[]);
-    return _prelinkedLibraries;
+  List<LinkedLibrary> get linkedLibraries {
+    _linkedLibraries ??= const fb.ListReader<LinkedLibrary>(const _LinkedLibraryReader()).vTableGet(_bp, 1, const <LinkedLibrary>[]);
+    return _linkedLibraries;
   }
 
   @override
@@ -729,23 +1704,34 @@
   }
 }
 
-class UnlinkedClassBuilder {
+abstract class _SdkBundleMixin implements SdkBundle {
+  @override
+  Map<String, Object> toMap() => {
+    "linkedLibraryUris": linkedLibraryUris,
+    "linkedLibraries": linkedLibraries,
+    "unlinkedUnitUris": unlinkedUnitUris,
+    "unlinkedUnits": unlinkedUnits,
+  };
+}
+
+class UnlinkedClassBuilder extends Object with _UnlinkedClassMixin implements UnlinkedClass {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
   UnlinkedDocumentationCommentBuilder _documentationComment;
   List<UnlinkedTypeParamBuilder> _typeParameters;
-  UnlinkedTypeRefBuilder _supertype;
-  List<UnlinkedTypeRefBuilder> _mixins;
-  List<UnlinkedTypeRefBuilder> _interfaces;
+  EntityRefBuilder _supertype;
+  List<EntityRefBuilder> _mixins;
+  List<EntityRefBuilder> _interfaces;
   List<UnlinkedVariableBuilder> _fields;
   List<UnlinkedExecutableBuilder> _executables;
   bool _isAbstract;
   bool _isMixinApplication;
   bool _hasNoSupertype;
 
-  UnlinkedClassBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the class.
@@ -755,14 +1741,21 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the class name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get documentationComment => _documentationComment;
+
   /**
    * Documentation comment for the class, or `null` if there is no
    * documentation comment.
@@ -772,6 +1765,9 @@
     _documentationComment = _value;
   }
 
+  @override
+  List<UnlinkedTypeParamBuilder> get typeParameters => _typeParameters ??= <UnlinkedTypeParamBuilder>[];
+
   /**
    * Type parameters of the class, if any.
    */
@@ -780,32 +1776,44 @@
     _typeParameters = _value;
   }
 
+  @override
+  EntityRefBuilder get supertype => _supertype;
+
   /**
    * Supertype of the class, or `null` if either (a) the class doesn't
    * explicitly declare a supertype (and hence has supertype `Object`), or (b)
    * the class *is* `Object` (and hence has no supertype).
    */
-  void set supertype(UnlinkedTypeRefBuilder _value) {
+  void set supertype(EntityRefBuilder _value) {
     assert(!_finished);
     _supertype = _value;
   }
 
+  @override
+  List<EntityRefBuilder> get mixins => _mixins ??= <EntityRefBuilder>[];
+
   /**
    * Mixins appearing in a `with` clause, if any.
    */
-  void set mixins(List<UnlinkedTypeRefBuilder> _value) {
+  void set mixins(List<EntityRefBuilder> _value) {
     assert(!_finished);
     _mixins = _value;
   }
 
+  @override
+  List<EntityRefBuilder> get interfaces => _interfaces ??= <EntityRefBuilder>[];
+
   /**
    * Interfaces appearing in an `implements` clause, if any.
    */
-  void set interfaces(List<UnlinkedTypeRefBuilder> _value) {
+  void set interfaces(List<EntityRefBuilder> _value) {
     assert(!_finished);
     _interfaces = _value;
   }
 
+  @override
+  List<UnlinkedVariableBuilder> get fields => _fields ??= <UnlinkedVariableBuilder>[];
+
   /**
    * Field declarations contained in the class.
    */
@@ -814,6 +1822,9 @@
     _fields = _value;
   }
 
+  @override
+  List<UnlinkedExecutableBuilder> get executables => _executables ??= <UnlinkedExecutableBuilder>[];
+
   /**
    * Executable objects (methods, getters, and setters) contained in the class.
    */
@@ -822,6 +1833,9 @@
     _executables = _value;
   }
 
+  @override
+  bool get isAbstract => _isAbstract ??= false;
+
   /**
    * Indicates whether the class is declared with the `abstract` keyword.
    */
@@ -830,6 +1844,9 @@
     _isAbstract = _value;
   }
 
+  @override
+  bool get isMixinApplication => _isMixinApplication ??= false;
+
   /**
    * Indicates whether the class is declared using mixin application syntax.
    */
@@ -838,6 +1855,9 @@
     _isMixinApplication = _value;
   }
 
+  @override
+  bool get hasNoSupertype => _hasNoSupertype ??= false;
+
   /**
    * Indicates whether this class is the core "Object" class (and hence has no
    * supertype)
@@ -847,6 +1867,20 @@
     _hasNoSupertype = _value;
   }
 
+  UnlinkedClassBuilder({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedTypeParamBuilder> typeParameters, EntityRefBuilder supertype, List<EntityRefBuilder> mixins, List<EntityRefBuilder> interfaces, List<UnlinkedVariableBuilder> fields, List<UnlinkedExecutableBuilder> executables, bool isAbstract, bool isMixinApplication, bool hasNoSupertype})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _documentationComment = documentationComment,
+      _typeParameters = typeParameters,
+      _supertype = supertype,
+      _mixins = mixins,
+      _interfaces = interfaces,
+      _fields = fields,
+      _executables = executables,
+      _isAbstract = isAbstract,
+      _isMixinApplication = isMixinApplication,
+      _hasNoSupertype = hasNoSupertype;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -887,7 +1921,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
@@ -923,23 +1957,6 @@
   }
 }
 
-UnlinkedClassBuilder encodeUnlinkedClass({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder supertype, List<UnlinkedTypeRefBuilder> mixins, List<UnlinkedTypeRefBuilder> interfaces, List<UnlinkedVariableBuilder> fields, List<UnlinkedExecutableBuilder> executables, bool isAbstract, bool isMixinApplication, bool hasNoSupertype}) {
-  UnlinkedClassBuilder builder = new UnlinkedClassBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.documentationComment = documentationComment;
-  builder.typeParameters = typeParameters;
-  builder.supertype = supertype;
-  builder.mixins = mixins;
-  builder.interfaces = interfaces;
-  builder.fields = fields;
-  builder.executables = executables;
-  builder.isAbstract = isAbstract;
-  builder.isMixinApplication = isMixinApplication;
-  builder.hasNoSupertype = hasNoSupertype;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a class declaration.
  */
@@ -971,17 +1988,17 @@
    * explicitly declare a supertype (and hence has supertype `Object`), or (b)
    * the class *is* `Object` (and hence has no supertype).
    */
-  UnlinkedTypeRef get supertype;
+  EntityRef get supertype;
 
   /**
    * Mixins appearing in a `with` clause, if any.
    */
-  List<UnlinkedTypeRef> get mixins;
+  List<EntityRef> get mixins;
 
   /**
    * Interfaces appearing in an `implements` clause, if any.
    */
-  List<UnlinkedTypeRef> get interfaces;
+  List<EntityRef> get interfaces;
 
   /**
    * Field declarations contained in the class.
@@ -1017,7 +2034,7 @@
   _UnlinkedClassImpl createObject(fb.BufferPointer bp) => new _UnlinkedClassImpl(bp);
 }
 
-class _UnlinkedClassImpl implements UnlinkedClass {
+class _UnlinkedClassImpl extends Object with _UnlinkedClassMixin implements UnlinkedClass {
   final fb.BufferPointer _bp;
 
   _UnlinkedClassImpl(this._bp);
@@ -1026,9 +2043,9 @@
   int _nameOffset;
   UnlinkedDocumentationComment _documentationComment;
   List<UnlinkedTypeParam> _typeParameters;
-  UnlinkedTypeRef _supertype;
-  List<UnlinkedTypeRef> _mixins;
-  List<UnlinkedTypeRef> _interfaces;
+  EntityRef _supertype;
+  List<EntityRef> _mixins;
+  List<EntityRef> _interfaces;
   List<UnlinkedVariable> _fields;
   List<UnlinkedExecutable> _executables;
   bool _isAbstract;
@@ -1036,22 +2053,6 @@
   bool _hasNoSupertype;
 
   @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "documentationComment": documentationComment,
-    "typeParameters": typeParameters,
-    "supertype": supertype,
-    "mixins": mixins,
-    "interfaces": interfaces,
-    "fields": fields,
-    "executables": executables,
-    "isAbstract": isAbstract,
-    "isMixinApplication": isMixinApplication,
-    "hasNoSupertype": hasNoSupertype,
-  };
-
-  @override
   String get name {
     _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
@@ -1059,7 +2060,7 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -1076,20 +2077,20 @@
   }
 
   @override
-  UnlinkedTypeRef get supertype {
-    _supertype ??= const _UnlinkedTypeRefReader().vTableGet(_bp, 4, null);
+  EntityRef get supertype {
+    _supertype ??= const _EntityRefReader().vTableGet(_bp, 4, null);
     return _supertype;
   }
 
   @override
-  List<UnlinkedTypeRef> get mixins {
-    _mixins ??= const fb.ListReader<UnlinkedTypeRef>(const _UnlinkedTypeRefReader()).vTableGet(_bp, 5, const <UnlinkedTypeRef>[]);
+  List<EntityRef> get mixins {
+    _mixins ??= const fb.ListReader<EntityRef>(const _EntityRefReader()).vTableGet(_bp, 5, const <EntityRef>[]);
     return _mixins;
   }
 
   @override
-  List<UnlinkedTypeRef> get interfaces {
-    _interfaces ??= const fb.ListReader<UnlinkedTypeRef>(const _UnlinkedTypeRefReader()).vTableGet(_bp, 6, const <UnlinkedTypeRef>[]);
+  List<EntityRef> get interfaces {
+    _interfaces ??= const fb.ListReader<EntityRef>(const _EntityRefReader()).vTableGet(_bp, 6, const <EntityRef>[]);
     return _interfaces;
   }
 
@@ -1124,13 +2125,32 @@
   }
 }
 
-class UnlinkedCombinatorBuilder {
+abstract class _UnlinkedClassMixin implements UnlinkedClass {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "documentationComment": documentationComment,
+    "typeParameters": typeParameters,
+    "supertype": supertype,
+    "mixins": mixins,
+    "interfaces": interfaces,
+    "fields": fields,
+    "executables": executables,
+    "isAbstract": isAbstract,
+    "isMixinApplication": isMixinApplication,
+    "hasNoSupertype": hasNoSupertype,
+  };
+}
+
+class UnlinkedCombinatorBuilder extends Object with _UnlinkedCombinatorMixin implements UnlinkedCombinator {
   bool _finished = false;
 
   List<String> _shows;
   List<String> _hides;
 
-  UnlinkedCombinatorBuilder();
+  @override
+  List<String> get shows => _shows ??= <String>[];
 
   /**
    * List of names which are shown.  Empty if this is a `hide` combinator.
@@ -1140,6 +2160,9 @@
     _shows = _value;
   }
 
+  @override
+  List<String> get hides => _hides ??= <String>[];
+
   /**
    * List of names which are hidden.  Empty if this is a `show` combinator.
    */
@@ -1148,6 +2171,10 @@
     _hides = _value;
   }
 
+  UnlinkedCombinatorBuilder({List<String> shows, List<String> hides})
+    : _shows = shows,
+      _hides = hides;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -1170,13 +2197,6 @@
   }
 }
 
-UnlinkedCombinatorBuilder encodeUnlinkedCombinator({List<String> shows, List<String> hides}) {
-  UnlinkedCombinatorBuilder builder = new UnlinkedCombinatorBuilder();
-  builder.shows = shows;
-  builder.hides = hides;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a `show` or `hide` combinator in an
  * import or export declaration.
@@ -1201,7 +2221,7 @@
   _UnlinkedCombinatorImpl createObject(fb.BufferPointer bp) => new _UnlinkedCombinatorImpl(bp);
 }
 
-class _UnlinkedCombinatorImpl implements UnlinkedCombinator {
+class _UnlinkedCombinatorImpl extends Object with _UnlinkedCombinatorMixin implements UnlinkedCombinator {
   final fb.BufferPointer _bp;
 
   _UnlinkedCombinatorImpl(this._bp);
@@ -1210,12 +2230,6 @@
   List<String> _hides;
 
   @override
-  Map<String, Object> toMap() => {
-    "shows": shows,
-    "hides": hides,
-  };
-
-  @override
   List<String> get shows {
     _shows ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 0, const <String>[]);
     return _shows;
@@ -1228,14 +2242,250 @@
   }
 }
 
-class UnlinkedDocumentationCommentBuilder {
+abstract class _UnlinkedCombinatorMixin implements UnlinkedCombinator {
+  @override
+  Map<String, Object> toMap() => {
+    "shows": shows,
+    "hides": hides,
+  };
+}
+
+class UnlinkedConstBuilder extends Object with _UnlinkedConstMixin implements UnlinkedConst {
+  bool _finished = false;
+
+  List<UnlinkedConstOperation> _operations;
+  List<int> _ints;
+  List<double> _doubles;
+  List<String> _strings;
+  List<EntityRefBuilder> _references;
+
+  @override
+  List<UnlinkedConstOperation> get operations => _operations ??= <UnlinkedConstOperation>[];
+
+  /**
+   * Sequence of operations to execute (starting with an empty stack) to form
+   * the constant value.
+   */
+  void set operations(List<UnlinkedConstOperation> _value) {
+    assert(!_finished);
+    _operations = _value;
+  }
+
+  @override
+  List<int> get ints => _ints ??= <int>[];
+
+  /**
+   * Sequence of unsigned 32-bit integers consumed by the operations
+   * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
+   * `makeList`, and `makeMap`.
+   */
+  void set ints(List<int> _value) {
+    assert(!_finished);
+    assert(_value == null || _value.every((e) => e >= 0));
+    _ints = _value;
+  }
+
+  @override
+  List<double> get doubles => _doubles ??= <double>[];
+
+  /**
+   * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
+   */
+  void set doubles(List<double> _value) {
+    assert(!_finished);
+    _doubles = _value;
+  }
+
+  @override
+  List<String> get strings => _strings ??= <String>[];
+
+  /**
+   * Sequence of strings consumed by the operations `pushString` and
+   * `invokeConstructor`.
+   */
+  void set strings(List<String> _value) {
+    assert(!_finished);
+    _strings = _value;
+  }
+
+  @override
+  List<EntityRefBuilder> get references => _references ??= <EntityRefBuilder>[];
+
+  /**
+   * Sequence of language constructs consumed by the operations
+   * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`.  Note
+   * that in the case of `pushReference` (and sometimes `invokeConstructor` the
+   * actual entity being referred to may be something other than a type.
+   */
+  void set references(List<EntityRefBuilder> _value) {
+    assert(!_finished);
+    _references = _value;
+  }
+
+  UnlinkedConstBuilder({List<UnlinkedConstOperation> operations, List<int> ints, List<double> doubles, List<String> strings, List<EntityRefBuilder> references})
+    : _operations = operations,
+      _ints = ints,
+      _doubles = doubles,
+      _strings = strings,
+      _references = references;
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    assert(!_finished);
+    _finished = true;
+    fb.Offset offset_operations;
+    fb.Offset offset_ints;
+    fb.Offset offset_doubles;
+    fb.Offset offset_strings;
+    fb.Offset offset_references;
+    if (!(_operations == null || _operations.isEmpty)) {
+      offset_operations = fbBuilder.writeListUint32(_operations.map((b) => b.index).toList());
+    }
+    if (!(_ints == null || _ints.isEmpty)) {
+      offset_ints = fbBuilder.writeListUint32(_ints);
+    }
+    if (!(_doubles == null || _doubles.isEmpty)) {
+      offset_doubles = fbBuilder.writeListFloat64(_doubles);
+    }
+    if (!(_strings == null || _strings.isEmpty)) {
+      offset_strings = fbBuilder.writeList(_strings.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_references == null || _references.isEmpty)) {
+      offset_references = fbBuilder.writeList(_references.map((b) => b.finish(fbBuilder)).toList());
+    }
+    fbBuilder.startTable();
+    if (offset_operations != null) {
+      fbBuilder.addOffset(0, offset_operations);
+    }
+    if (offset_ints != null) {
+      fbBuilder.addOffset(1, offset_ints);
+    }
+    if (offset_doubles != null) {
+      fbBuilder.addOffset(2, offset_doubles);
+    }
+    if (offset_strings != null) {
+      fbBuilder.addOffset(3, offset_strings);
+    }
+    if (offset_references != null) {
+      fbBuilder.addOffset(4, offset_references);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+/**
+ * Unlinked summary information about a compile-time constant expression, or a
+ * potentially constant expression.
+ *
+ * Constant expressions are represented using a simple stack-based language
+ * where [operations] is a sequence of operations to execute starting with an
+ * empty stack.  Once all operations have been executed, the stack should
+ * contain a single value which is the value of the constant.  Note that some
+ * operations consume additional data from the other fields of this class.
+ */
+abstract class UnlinkedConst extends base.SummaryClass {
+
+  /**
+   * Sequence of operations to execute (starting with an empty stack) to form
+   * the constant value.
+   */
+  List<UnlinkedConstOperation> get operations;
+
+  /**
+   * Sequence of unsigned 32-bit integers consumed by the operations
+   * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
+   * `makeList`, and `makeMap`.
+   */
+  List<int> get ints;
+
+  /**
+   * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
+   */
+  List<double> get doubles;
+
+  /**
+   * Sequence of strings consumed by the operations `pushString` and
+   * `invokeConstructor`.
+   */
+  List<String> get strings;
+
+  /**
+   * Sequence of language constructs consumed by the operations
+   * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`.  Note
+   * that in the case of `pushReference` (and sometimes `invokeConstructor` the
+   * actual entity being referred to may be something other than a type.
+   */
+  List<EntityRef> get references;
+}
+
+class _UnlinkedConstReader extends fb.TableReader<_UnlinkedConstImpl> {
+  const _UnlinkedConstReader();
+
+  @override
+  _UnlinkedConstImpl createObject(fb.BufferPointer bp) => new _UnlinkedConstImpl(bp);
+}
+
+class _UnlinkedConstImpl extends Object with _UnlinkedConstMixin implements UnlinkedConst {
+  final fb.BufferPointer _bp;
+
+  _UnlinkedConstImpl(this._bp);
+
+  List<UnlinkedConstOperation> _operations;
+  List<int> _ints;
+  List<double> _doubles;
+  List<String> _strings;
+  List<EntityRef> _references;
+
+  @override
+  List<UnlinkedConstOperation> get operations {
+    _operations ??= const fb.ListReader<UnlinkedConstOperation>(const _UnlinkedConstOperationReader()).vTableGet(_bp, 0, const <UnlinkedConstOperation>[]);
+    return _operations;
+  }
+
+  @override
+  List<int> get ints {
+    _ints ??= const fb.ListReader<int>(const fb.Uint32Reader()).vTableGet(_bp, 1, const <int>[]);
+    return _ints;
+  }
+
+  @override
+  List<double> get doubles {
+    _doubles ??= const fb.Float64ListReader().vTableGet(_bp, 2, const <double>[]);
+    return _doubles;
+  }
+
+  @override
+  List<String> get strings {
+    _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 3, const <String>[]);
+    return _strings;
+  }
+
+  @override
+  List<EntityRef> get references {
+    _references ??= const fb.ListReader<EntityRef>(const _EntityRefReader()).vTableGet(_bp, 4, const <EntityRef>[]);
+    return _references;
+  }
+}
+
+abstract class _UnlinkedConstMixin implements UnlinkedConst {
+  @override
+  Map<String, Object> toMap() => {
+    "operations": operations,
+    "ints": ints,
+    "doubles": doubles,
+    "strings": strings,
+    "references": references,
+  };
+}
+
+class UnlinkedDocumentationCommentBuilder extends Object with _UnlinkedDocumentationCommentMixin implements UnlinkedDocumentationComment {
   bool _finished = false;
 
   String _text;
   int _offset;
   int _length;
 
-  UnlinkedDocumentationCommentBuilder();
+  @override
+  String get text => _text ??= '';
 
   /**
    * Text of the documentation comment, with '\r\n' replaced by '\n'.
@@ -1248,23 +2498,36 @@
     _text = _value;
   }
 
+  @override
+  int get offset => _offset ??= 0;
+
   /**
    * Offset of the beginning of the documentation comment relative to the
    * beginning of the file.
    */
   void set offset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _offset = _value;
   }
 
+  @override
+  int get length => _length ??= 0;
+
   /**
    * Length of the documentation comment (prior to replacing '\r\n' with '\n').
    */
   void set length(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _length = _value;
   }
 
+  UnlinkedDocumentationCommentBuilder({String text, int offset, int length})
+    : _text = text,
+      _offset = offset,
+      _length = length;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -1277,23 +2540,15 @@
       fbBuilder.addOffset(0, offset_text);
     }
     if (_offset != null && _offset != 0) {
-      fbBuilder.addInt32(1, _offset);
+      fbBuilder.addUint32(1, _offset);
     }
     if (_length != null && _length != 0) {
-      fbBuilder.addInt32(2, _length);
+      fbBuilder.addUint32(2, _length);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedDocumentationCommentBuilder encodeUnlinkedDocumentationComment({String text, int offset, int length}) {
-  UnlinkedDocumentationCommentBuilder builder = new UnlinkedDocumentationCommentBuilder();
-  builder.text = text;
-  builder.offset = offset;
-  builder.length = length;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a documentation comment.
  */
@@ -1326,7 +2581,7 @@
   _UnlinkedDocumentationCommentImpl createObject(fb.BufferPointer bp) => new _UnlinkedDocumentationCommentImpl(bp);
 }
 
-class _UnlinkedDocumentationCommentImpl implements UnlinkedDocumentationComment {
+class _UnlinkedDocumentationCommentImpl extends Object with _UnlinkedDocumentationCommentMixin implements UnlinkedDocumentationComment {
   final fb.BufferPointer _bp;
 
   _UnlinkedDocumentationCommentImpl(this._bp);
@@ -1336,13 +2591,6 @@
   int _length;
 
   @override
-  Map<String, Object> toMap() => {
-    "text": text,
-    "offset": offset,
-    "length": length,
-  };
-
-  @override
   String get text {
     _text ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _text;
@@ -1350,18 +2598,27 @@
 
   @override
   int get offset {
-    _offset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _offset;
   }
 
   @override
   int get length {
-    _length ??= const fb.Int32Reader().vTableGet(_bp, 2, 0);
+    _length ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _length;
   }
 }
 
-class UnlinkedEnumBuilder {
+abstract class _UnlinkedDocumentationCommentMixin implements UnlinkedDocumentationComment {
+  @override
+  Map<String, Object> toMap() => {
+    "text": text,
+    "offset": offset,
+    "length": length,
+  };
+}
+
+class UnlinkedEnumBuilder extends Object with _UnlinkedEnumMixin implements UnlinkedEnum {
   bool _finished = false;
 
   String _name;
@@ -1369,7 +2626,8 @@
   UnlinkedDocumentationCommentBuilder _documentationComment;
   List<UnlinkedEnumValueBuilder> _values;
 
-  UnlinkedEnumBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the enum type.
@@ -1379,14 +2637,21 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the enum name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get documentationComment => _documentationComment;
+
   /**
    * Documentation comment for the enum, or `null` if there is no documentation
    * comment.
@@ -1396,6 +2661,9 @@
     _documentationComment = _value;
   }
 
+  @override
+  List<UnlinkedEnumValueBuilder> get values => _values ??= <UnlinkedEnumValueBuilder>[];
+
   /**
    * Values listed in the enum declaration, in declaration order.
    */
@@ -1404,6 +2672,12 @@
     _values = _value;
   }
 
+  UnlinkedEnumBuilder({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedEnumValueBuilder> values})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _documentationComment = documentationComment,
+      _values = values;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -1424,7 +2698,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
@@ -1436,15 +2710,6 @@
   }
 }
 
-UnlinkedEnumBuilder encodeUnlinkedEnum({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedEnumValueBuilder> values}) {
-  UnlinkedEnumBuilder builder = new UnlinkedEnumBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.documentationComment = documentationComment;
-  builder.values = values;
-  return builder;
-}
-
 /**
  * Unlinked summary information about an enum declaration.
  */
@@ -1479,7 +2744,7 @@
   _UnlinkedEnumImpl createObject(fb.BufferPointer bp) => new _UnlinkedEnumImpl(bp);
 }
 
-class _UnlinkedEnumImpl implements UnlinkedEnum {
+class _UnlinkedEnumImpl extends Object with _UnlinkedEnumMixin implements UnlinkedEnum {
   final fb.BufferPointer _bp;
 
   _UnlinkedEnumImpl(this._bp);
@@ -1490,14 +2755,6 @@
   List<UnlinkedEnumValue> _values;
 
   @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "documentationComment": documentationComment,
-    "values": values,
-  };
-
-  @override
   String get name {
     _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
@@ -1505,7 +2762,7 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -1522,14 +2779,25 @@
   }
 }
 
-class UnlinkedEnumValueBuilder {
+abstract class _UnlinkedEnumMixin implements UnlinkedEnum {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "documentationComment": documentationComment,
+    "values": values,
+  };
+}
+
+class UnlinkedEnumValueBuilder extends Object with _UnlinkedEnumValueMixin implements UnlinkedEnumValue {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
   UnlinkedDocumentationCommentBuilder _documentationComment;
 
-  UnlinkedEnumValueBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the enumerated value.
@@ -1539,14 +2807,21 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the enum value name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get documentationComment => _documentationComment;
+
   /**
    * Documentation comment for the enum value, or `null` if there is no
    * documentation comment.
@@ -1556,6 +2831,11 @@
     _documentationComment = _value;
   }
 
+  UnlinkedEnumValueBuilder({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _documentationComment = documentationComment;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -1572,7 +2852,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
@@ -1581,14 +2861,6 @@
   }
 }
 
-UnlinkedEnumValueBuilder encodeUnlinkedEnumValue({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment}) {
-  UnlinkedEnumValueBuilder builder = new UnlinkedEnumValueBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.documentationComment = documentationComment;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a single enumerated value in an enum
  * declaration.
@@ -1619,7 +2891,7 @@
   _UnlinkedEnumValueImpl createObject(fb.BufferPointer bp) => new _UnlinkedEnumValueImpl(bp);
 }
 
-class _UnlinkedEnumValueImpl implements UnlinkedEnumValue {
+class _UnlinkedEnumValueImpl extends Object with _UnlinkedEnumValueMixin implements UnlinkedEnumValue {
   final fb.BufferPointer _bp;
 
   _UnlinkedEnumValueImpl(this._bp);
@@ -1629,13 +2901,6 @@
   UnlinkedDocumentationComment _documentationComment;
 
   @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "documentationComment": documentationComment,
-  };
-
-  @override
   String get name {
     _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
@@ -1643,7 +2908,7 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -1654,24 +2919,34 @@
   }
 }
 
-class UnlinkedExecutableBuilder {
+abstract class _UnlinkedEnumValueMixin implements UnlinkedEnumValue {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "documentationComment": documentationComment,
+  };
+}
+
+class UnlinkedExecutableBuilder extends Object with _UnlinkedExecutableMixin implements UnlinkedExecutable {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
   UnlinkedDocumentationCommentBuilder _documentationComment;
   List<UnlinkedTypeParamBuilder> _typeParameters;
-  UnlinkedTypeRefBuilder _returnType;
+  EntityRefBuilder _returnType;
   List<UnlinkedParamBuilder> _parameters;
   UnlinkedExecutableKind _kind;
   bool _isAbstract;
   bool _isStatic;
   bool _isConst;
   bool _isFactory;
-  bool _hasImplicitReturnType;
   bool _isExternal;
+  int _inferredReturnTypeSlot;
 
-  UnlinkedExecutableBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the executable.  For setters, this includes the trailing "=".  For
@@ -1683,6 +2958,9 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the executable name relative to the beginning of the file.  For
    * named constructors, this excludes the class name and excludes the ".".
@@ -1691,9 +2969,13 @@
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get documentationComment => _documentationComment;
+
   /**
    * Documentation comment for the executable, or `null` if there is no
    * documentation comment.
@@ -1703,6 +2985,9 @@
     _documentationComment = _value;
   }
 
+  @override
+  List<UnlinkedTypeParamBuilder> get typeParameters => _typeParameters ??= <UnlinkedTypeParamBuilder>[];
+
   /**
    * Type parameters of the executable, if any.  Empty if support for generic
    * method syntax is disabled.
@@ -1712,16 +2997,21 @@
     _typeParameters = _value;
   }
 
+  @override
+  EntityRefBuilder get returnType => _returnType;
+
   /**
-   * Declared return type of the executable.  Absent if the return type is
-   * `void` or the executable is a constructor.  Note that when strong mode is
-   * enabled, the actual return type may be different due to type inference.
+   * Declared return type of the executable.  Absent if the executable is a
+   * constructor or the return type is implicit.
    */
-  void set returnType(UnlinkedTypeRefBuilder _value) {
+  void set returnType(EntityRefBuilder _value) {
     assert(!_finished);
     _returnType = _value;
   }
 
+  @override
+  List<UnlinkedParamBuilder> get parameters => _parameters ??= <UnlinkedParamBuilder>[];
+
   /**
    * Parameters of the executable, if any.  Note that getters have no
    * parameters (hence this will be the empty list), and setters have a single
@@ -1732,6 +3022,9 @@
     _parameters = _value;
   }
 
+  @override
+  UnlinkedExecutableKind get kind => _kind ??= UnlinkedExecutableKind.functionOrMethod;
+
   /**
    * The kind of the executable (function/method, getter, setter, or
    * constructor).
@@ -1741,6 +3034,9 @@
     _kind = _value;
   }
 
+  @override
+  bool get isAbstract => _isAbstract ??= false;
+
   /**
    * Indicates whether the executable is declared using the `abstract` keyword.
    */
@@ -1749,6 +3045,9 @@
     _isAbstract = _value;
   }
 
+  @override
+  bool get isStatic => _isStatic ??= false;
+
   /**
    * Indicates whether the executable is declared using the `static` keyword.
    *
@@ -1761,6 +3060,9 @@
     _isStatic = _value;
   }
 
+  @override
+  bool get isConst => _isConst ??= false;
+
   /**
    * Indicates whether the executable is declared using the `const` keyword.
    */
@@ -1769,6 +3071,9 @@
     _isConst = _value;
   }
 
+  @override
+  bool get isFactory => _isFactory ??= false;
+
   /**
    * Indicates whether the executable is declared using the `factory` keyword.
    */
@@ -1777,14 +3082,8 @@
     _isFactory = _value;
   }
 
-  /**
-   * Indicates whether the executable lacks an explicit return type
-   * declaration.  False for constructors and setters.
-   */
-  void set hasImplicitReturnType(bool _value) {
-    assert(!_finished);
-    _hasImplicitReturnType = _value;
-  }
+  @override
+  bool get isExternal => _isExternal ??= false;
 
   /**
    * Indicates whether the executable is declared using the `external` keyword.
@@ -1794,6 +3093,37 @@
     _isExternal = _value;
   }
 
+  @override
+  int get inferredReturnTypeSlot => _inferredReturnTypeSlot ??= 0;
+
+  /**
+   * If this executable's return type is inferrable, nonzero slot id
+   * identifying which entry in [LinkedLibrary.types] contains the inferred
+   * return type.  If there is no matching entry in [LinkedLibrary.types], then
+   * no return type was inferred for this variable, so its static type is
+   * `dynamic`.
+   */
+  void set inferredReturnTypeSlot(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _inferredReturnTypeSlot = _value;
+  }
+
+  UnlinkedExecutableBuilder({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedTypeParamBuilder> typeParameters, EntityRefBuilder returnType, List<UnlinkedParamBuilder> parameters, UnlinkedExecutableKind kind, bool isAbstract, bool isStatic, bool isConst, bool isFactory, bool isExternal, int inferredReturnTypeSlot})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _documentationComment = documentationComment,
+      _typeParameters = typeParameters,
+      _returnType = returnType,
+      _parameters = parameters,
+      _kind = kind,
+      _isAbstract = isAbstract,
+      _isStatic = isStatic,
+      _isConst = isConst,
+      _isFactory = isFactory,
+      _isExternal = isExternal,
+      _inferredReturnTypeSlot = inferredReturnTypeSlot;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -1822,7 +3152,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
@@ -1837,7 +3167,7 @@
       fbBuilder.addOffset(5, offset_parameters);
     }
     if (_kind != null && _kind != UnlinkedExecutableKind.functionOrMethod) {
-      fbBuilder.addInt32(6, _kind.index);
+      fbBuilder.addUint32(6, _kind.index);
     }
     if (_isAbstract == true) {
       fbBuilder.addBool(7, true);
@@ -1851,34 +3181,16 @@
     if (_isFactory == true) {
       fbBuilder.addBool(10, true);
     }
-    if (_hasImplicitReturnType == true) {
+    if (_isExternal == true) {
       fbBuilder.addBool(11, true);
     }
-    if (_isExternal == true) {
-      fbBuilder.addBool(12, true);
+    if (_inferredReturnTypeSlot != null && _inferredReturnTypeSlot != 0) {
+      fbBuilder.addUint32(12, _inferredReturnTypeSlot);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedExecutableBuilder encodeUnlinkedExecutable({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters, UnlinkedExecutableKind kind, bool isAbstract, bool isStatic, bool isConst, bool isFactory, bool hasImplicitReturnType, bool isExternal}) {
-  UnlinkedExecutableBuilder builder = new UnlinkedExecutableBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.documentationComment = documentationComment;
-  builder.typeParameters = typeParameters;
-  builder.returnType = returnType;
-  builder.parameters = parameters;
-  builder.kind = kind;
-  builder.isAbstract = isAbstract;
-  builder.isStatic = isStatic;
-  builder.isConst = isConst;
-  builder.isFactory = isFactory;
-  builder.hasImplicitReturnType = hasImplicitReturnType;
-  builder.isExternal = isExternal;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a function, method, getter, or setter
  * declaration.
@@ -1913,11 +3225,10 @@
   List<UnlinkedTypeParam> get typeParameters;
 
   /**
-   * Declared return type of the executable.  Absent if the return type is
-   * `void` or the executable is a constructor.  Note that when strong mode is
-   * enabled, the actual return type may be different due to type inference.
+   * Declared return type of the executable.  Absent if the executable is a
+   * constructor or the return type is implicit.
    */
-  UnlinkedTypeRef get returnType;
+  EntityRef get returnType;
 
   /**
    * Parameters of the executable, if any.  Note that getters have no
@@ -1957,15 +3268,18 @@
   bool get isFactory;
 
   /**
-   * Indicates whether the executable lacks an explicit return type
-   * declaration.  False for constructors and setters.
-   */
-  bool get hasImplicitReturnType;
-
-  /**
    * Indicates whether the executable is declared using the `external` keyword.
    */
   bool get isExternal;
+
+  /**
+   * If this executable's return type is inferrable, nonzero slot id
+   * identifying which entry in [LinkedLibrary.types] contains the inferred
+   * return type.  If there is no matching entry in [LinkedLibrary.types], then
+   * no return type was inferred for this variable, so its static type is
+   * `dynamic`.
+   */
+  int get inferredReturnTypeSlot;
 }
 
 class _UnlinkedExecutableReader extends fb.TableReader<_UnlinkedExecutableImpl> {
@@ -1975,7 +3289,7 @@
   _UnlinkedExecutableImpl createObject(fb.BufferPointer bp) => new _UnlinkedExecutableImpl(bp);
 }
 
-class _UnlinkedExecutableImpl implements UnlinkedExecutable {
+class _UnlinkedExecutableImpl extends Object with _UnlinkedExecutableMixin implements UnlinkedExecutable {
   final fb.BufferPointer _bp;
 
   _UnlinkedExecutableImpl(this._bp);
@@ -1984,32 +3298,15 @@
   int _nameOffset;
   UnlinkedDocumentationComment _documentationComment;
   List<UnlinkedTypeParam> _typeParameters;
-  UnlinkedTypeRef _returnType;
+  EntityRef _returnType;
   List<UnlinkedParam> _parameters;
   UnlinkedExecutableKind _kind;
   bool _isAbstract;
   bool _isStatic;
   bool _isConst;
   bool _isFactory;
-  bool _hasImplicitReturnType;
   bool _isExternal;
-
-  @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "documentationComment": documentationComment,
-    "typeParameters": typeParameters,
-    "returnType": returnType,
-    "parameters": parameters,
-    "kind": kind,
-    "isAbstract": isAbstract,
-    "isStatic": isStatic,
-    "isConst": isConst,
-    "isFactory": isFactory,
-    "hasImplicitReturnType": hasImplicitReturnType,
-    "isExternal": isExternal,
-  };
+  int _inferredReturnTypeSlot;
 
   @override
   String get name {
@@ -2019,7 +3316,7 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -2036,8 +3333,8 @@
   }
 
   @override
-  UnlinkedTypeRef get returnType {
-    _returnType ??= const _UnlinkedTypeRefReader().vTableGet(_bp, 4, null);
+  EntityRef get returnType {
+    _returnType ??= const _EntityRefReader().vTableGet(_bp, 4, null);
     return _returnType;
   }
 
@@ -2049,7 +3346,7 @@
 
   @override
   UnlinkedExecutableKind get kind {
-    _kind ??= UnlinkedExecutableKind.values[const fb.Int32Reader().vTableGet(_bp, 6, 0)];
+    _kind ??= const _UnlinkedExecutableKindReader().vTableGet(_bp, 6, UnlinkedExecutableKind.functionOrMethod);
     return _kind;
   }
 
@@ -2078,78 +3375,104 @@
   }
 
   @override
-  bool get hasImplicitReturnType {
-    _hasImplicitReturnType ??= const fb.BoolReader().vTableGet(_bp, 11, false);
-    return _hasImplicitReturnType;
+  bool get isExternal {
+    _isExternal ??= const fb.BoolReader().vTableGet(_bp, 11, false);
+    return _isExternal;
   }
 
   @override
-  bool get isExternal {
-    _isExternal ??= const fb.BoolReader().vTableGet(_bp, 12, false);
-    return _isExternal;
+  int get inferredReturnTypeSlot {
+    _inferredReturnTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 12, 0);
+    return _inferredReturnTypeSlot;
   }
 }
 
-class UnlinkedExportNonPublicBuilder {
+abstract class _UnlinkedExecutableMixin implements UnlinkedExecutable {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "documentationComment": documentationComment,
+    "typeParameters": typeParameters,
+    "returnType": returnType,
+    "parameters": parameters,
+    "kind": kind,
+    "isAbstract": isAbstract,
+    "isStatic": isStatic,
+    "isConst": isConst,
+    "isFactory": isFactory,
+    "isExternal": isExternal,
+    "inferredReturnTypeSlot": inferredReturnTypeSlot,
+  };
+}
+
+class UnlinkedExportNonPublicBuilder extends Object with _UnlinkedExportNonPublicMixin implements UnlinkedExportNonPublic {
   bool _finished = false;
 
   int _offset;
   int _uriOffset;
   int _uriEnd;
 
-  UnlinkedExportNonPublicBuilder();
+  @override
+  int get offset => _offset ??= 0;
 
   /**
    * Offset of the "export" keyword.
    */
   void set offset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _offset = _value;
   }
 
+  @override
+  int get uriOffset => _uriOffset ??= 0;
+
   /**
    * Offset of the URI string (including quotes) relative to the beginning of
    * the file.
    */
   void set uriOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _uriOffset = _value;
   }
 
+  @override
+  int get uriEnd => _uriEnd ??= 0;
+
   /**
    * End of the URI string (including quotes) relative to the beginning of the
    * file.
    */
   void set uriEnd(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _uriEnd = _value;
   }
 
+  UnlinkedExportNonPublicBuilder({int offset, int uriOffset, int uriEnd})
+    : _offset = offset,
+      _uriOffset = uriOffset,
+      _uriEnd = uriEnd;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
     fbBuilder.startTable();
     if (_offset != null && _offset != 0) {
-      fbBuilder.addInt32(0, _offset);
+      fbBuilder.addUint32(0, _offset);
     }
     if (_uriOffset != null && _uriOffset != 0) {
-      fbBuilder.addInt32(1, _uriOffset);
+      fbBuilder.addUint32(1, _uriOffset);
     }
     if (_uriEnd != null && _uriEnd != 0) {
-      fbBuilder.addInt32(2, _uriEnd);
+      fbBuilder.addUint32(2, _uriEnd);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedExportNonPublicBuilder encodeUnlinkedExportNonPublic({int offset, int uriOffset, int uriEnd}) {
-  UnlinkedExportNonPublicBuilder builder = new UnlinkedExportNonPublicBuilder();
-  builder.offset = offset;
-  builder.uriOffset = uriOffset;
-  builder.uriEnd = uriEnd;
-  return builder;
-}
-
 /**
  * Unlinked summary information about an export declaration (stored outside
  * [UnlinkedPublicNamespace]).
@@ -2181,7 +3504,7 @@
   _UnlinkedExportNonPublicImpl createObject(fb.BufferPointer bp) => new _UnlinkedExportNonPublicImpl(bp);
 }
 
-class _UnlinkedExportNonPublicImpl implements UnlinkedExportNonPublic {
+class _UnlinkedExportNonPublicImpl extends Object with _UnlinkedExportNonPublicMixin implements UnlinkedExportNonPublic {
   final fb.BufferPointer _bp;
 
   _UnlinkedExportNonPublicImpl(this._bp);
@@ -2191,38 +3514,41 @@
   int _uriEnd;
 
   @override
-  Map<String, Object> toMap() => {
-    "offset": offset,
-    "uriOffset": uriOffset,
-    "uriEnd": uriEnd,
-  };
-
-  @override
   int get offset {
-    _offset ??= const fb.Int32Reader().vTableGet(_bp, 0, 0);
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _offset;
   }
 
   @override
   int get uriOffset {
-    _uriOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _uriOffset;
   }
 
   @override
   int get uriEnd {
-    _uriEnd ??= const fb.Int32Reader().vTableGet(_bp, 2, 0);
+    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _uriEnd;
   }
 }
 
-class UnlinkedExportPublicBuilder {
+abstract class _UnlinkedExportNonPublicMixin implements UnlinkedExportNonPublic {
+  @override
+  Map<String, Object> toMap() => {
+    "offset": offset,
+    "uriOffset": uriOffset,
+    "uriEnd": uriEnd,
+  };
+}
+
+class UnlinkedExportPublicBuilder extends Object with _UnlinkedExportPublicMixin implements UnlinkedExportPublic {
   bool _finished = false;
 
   String _uri;
   List<UnlinkedCombinatorBuilder> _combinators;
 
-  UnlinkedExportPublicBuilder();
+  @override
+  String get uri => _uri ??= '';
 
   /**
    * URI used in the source code to reference the exported library.
@@ -2232,6 +3558,9 @@
     _uri = _value;
   }
 
+  @override
+  List<UnlinkedCombinatorBuilder> get combinators => _combinators ??= <UnlinkedCombinatorBuilder>[];
+
   /**
    * Combinators contained in this import declaration.
    */
@@ -2240,6 +3569,10 @@
     _combinators = _value;
   }
 
+  UnlinkedExportPublicBuilder({String uri, List<UnlinkedCombinatorBuilder> combinators})
+    : _uri = uri,
+      _combinators = combinators;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -2262,13 +3595,6 @@
   }
 }
 
-UnlinkedExportPublicBuilder encodeUnlinkedExportPublic({String uri, List<UnlinkedCombinatorBuilder> combinators}) {
-  UnlinkedExportPublicBuilder builder = new UnlinkedExportPublicBuilder();
-  builder.uri = uri;
-  builder.combinators = combinators;
-  return builder;
-}
-
 /**
  * Unlinked summary information about an export declaration (stored inside
  * [UnlinkedPublicNamespace]).
@@ -2293,7 +3619,7 @@
   _UnlinkedExportPublicImpl createObject(fb.BufferPointer bp) => new _UnlinkedExportPublicImpl(bp);
 }
 
-class _UnlinkedExportPublicImpl implements UnlinkedExportPublic {
+class _UnlinkedExportPublicImpl extends Object with _UnlinkedExportPublicMixin implements UnlinkedExportPublic {
   final fb.BufferPointer _bp;
 
   _UnlinkedExportPublicImpl(this._bp);
@@ -2302,12 +3628,6 @@
   List<UnlinkedCombinator> _combinators;
 
   @override
-  Map<String, Object> toMap() => {
-    "uri": uri,
-    "combinators": combinators,
-  };
-
-  @override
   String get uri {
     _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _uri;
@@ -2320,7 +3640,15 @@
   }
 }
 
-class UnlinkedImportBuilder {
+abstract class _UnlinkedExportPublicMixin implements UnlinkedExportPublic {
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+    "combinators": combinators,
+  };
+}
+
+class UnlinkedImportBuilder extends Object with _UnlinkedImportMixin implements UnlinkedImport {
   bool _finished = false;
 
   String _uri;
@@ -2333,7 +3661,8 @@
   int _uriEnd;
   int _prefixOffset;
 
-  UnlinkedImportBuilder();
+  @override
+  String get uri => _uri ??= '';
 
   /**
    * URI used in the source code to reference the imported library.
@@ -2343,15 +3672,22 @@
     _uri = _value;
   }
 
+  @override
+  int get offset => _offset ??= 0;
+
   /**
    * If [isImplicit] is false, offset of the "import" keyword.  If [isImplicit]
    * is true, zero.
    */
   void set offset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _offset = _value;
   }
 
+  @override
+  int get prefixReference => _prefixReference ??= 0;
+
   /**
    * Index into [UnlinkedUnit.references] of the prefix declared by this
    * import declaration, or zero if this import declaration declares no prefix.
@@ -2360,9 +3696,13 @@
    */
   void set prefixReference(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _prefixReference = _value;
   }
 
+  @override
+  List<UnlinkedCombinatorBuilder> get combinators => _combinators ??= <UnlinkedCombinatorBuilder>[];
+
   /**
    * Combinators contained in this import declaration.
    */
@@ -2371,6 +3711,9 @@
     _combinators = _value;
   }
 
+  @override
+  bool get isDeferred => _isDeferred ??= false;
+
   /**
    * Indicates whether the import declaration uses the `deferred` keyword.
    */
@@ -2379,6 +3722,9 @@
     _isDeferred = _value;
   }
 
+  @override
+  bool get isImplicit => _isImplicit ??= false;
+
   /**
    * Indicates whether the import declaration is implicit.
    */
@@ -2387,33 +3733,56 @@
     _isImplicit = _value;
   }
 
+  @override
+  int get uriOffset => _uriOffset ??= 0;
+
   /**
    * Offset of the URI string (including quotes) relative to the beginning of
    * the file.  If [isImplicit] is true, zero.
    */
   void set uriOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _uriOffset = _value;
   }
 
+  @override
+  int get uriEnd => _uriEnd ??= 0;
+
   /**
    * End of the URI string (including quotes) relative to the beginning of the
    * file.  If [isImplicit] is true, zero.
    */
   void set uriEnd(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _uriEnd = _value;
   }
 
+  @override
+  int get prefixOffset => _prefixOffset ??= 0;
+
   /**
    * Offset of the prefix name relative to the beginning of the file, or zero
    * if there is no prefix.
    */
   void set prefixOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _prefixOffset = _value;
   }
 
+  UnlinkedImportBuilder({String uri, int offset, int prefixReference, List<UnlinkedCombinatorBuilder> combinators, bool isDeferred, bool isImplicit, int uriOffset, int uriEnd, int prefixOffset})
+    : _uri = uri,
+      _offset = offset,
+      _prefixReference = prefixReference,
+      _combinators = combinators,
+      _isDeferred = isDeferred,
+      _isImplicit = isImplicit,
+      _uriOffset = uriOffset,
+      _uriEnd = uriEnd,
+      _prefixOffset = prefixOffset;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -2430,10 +3799,10 @@
       fbBuilder.addOffset(0, offset_uri);
     }
     if (_offset != null && _offset != 0) {
-      fbBuilder.addInt32(1, _offset);
+      fbBuilder.addUint32(1, _offset);
     }
     if (_prefixReference != null && _prefixReference != 0) {
-      fbBuilder.addInt32(2, _prefixReference);
+      fbBuilder.addUint32(2, _prefixReference);
     }
     if (offset_combinators != null) {
       fbBuilder.addOffset(3, offset_combinators);
@@ -2445,32 +3814,18 @@
       fbBuilder.addBool(5, true);
     }
     if (_uriOffset != null && _uriOffset != 0) {
-      fbBuilder.addInt32(6, _uriOffset);
+      fbBuilder.addUint32(6, _uriOffset);
     }
     if (_uriEnd != null && _uriEnd != 0) {
-      fbBuilder.addInt32(7, _uriEnd);
+      fbBuilder.addUint32(7, _uriEnd);
     }
     if (_prefixOffset != null && _prefixOffset != 0) {
-      fbBuilder.addInt32(8, _prefixOffset);
+      fbBuilder.addUint32(8, _prefixOffset);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedImportBuilder encodeUnlinkedImport({String uri, int offset, int prefixReference, List<UnlinkedCombinatorBuilder> combinators, bool isDeferred, bool isImplicit, int uriOffset, int uriEnd, int prefixOffset}) {
-  UnlinkedImportBuilder builder = new UnlinkedImportBuilder();
-  builder.uri = uri;
-  builder.offset = offset;
-  builder.prefixReference = prefixReference;
-  builder.combinators = combinators;
-  builder.isDeferred = isDeferred;
-  builder.isImplicit = isImplicit;
-  builder.uriOffset = uriOffset;
-  builder.uriEnd = uriEnd;
-  builder.prefixOffset = prefixOffset;
-  return builder;
-}
-
 /**
  * Unlinked summary information about an import declaration.
  */
@@ -2536,7 +3891,7 @@
   _UnlinkedImportImpl createObject(fb.BufferPointer bp) => new _UnlinkedImportImpl(bp);
 }
 
-class _UnlinkedImportImpl implements UnlinkedImport {
+class _UnlinkedImportImpl extends Object with _UnlinkedImportMixin implements UnlinkedImport {
   final fb.BufferPointer _bp;
 
   _UnlinkedImportImpl(this._bp);
@@ -2552,19 +3907,6 @@
   int _prefixOffset;
 
   @override
-  Map<String, Object> toMap() => {
-    "uri": uri,
-    "offset": offset,
-    "prefixReference": prefixReference,
-    "combinators": combinators,
-    "isDeferred": isDeferred,
-    "isImplicit": isImplicit,
-    "uriOffset": uriOffset,
-    "uriEnd": uriEnd,
-    "prefixOffset": prefixOffset,
-  };
-
-  @override
   String get uri {
     _uri ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _uri;
@@ -2572,13 +3914,13 @@
 
   @override
   int get offset {
-    _offset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _offset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _offset;
   }
 
   @override
   int get prefixReference {
-    _prefixReference ??= const fb.Int32Reader().vTableGet(_bp, 2, 0);
+    _prefixReference ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _prefixReference;
   }
 
@@ -2602,36 +3944,52 @@
 
   @override
   int get uriOffset {
-    _uriOffset ??= const fb.Int32Reader().vTableGet(_bp, 6, 0);
+    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 6, 0);
     return _uriOffset;
   }
 
   @override
   int get uriEnd {
-    _uriEnd ??= const fb.Int32Reader().vTableGet(_bp, 7, 0);
+    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
     return _uriEnd;
   }
 
   @override
   int get prefixOffset {
-    _prefixOffset ??= const fb.Int32Reader().vTableGet(_bp, 8, 0);
+    _prefixOffset ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
     return _prefixOffset;
   }
 }
 
-class UnlinkedParamBuilder {
+abstract class _UnlinkedImportMixin implements UnlinkedImport {
+  @override
+  Map<String, Object> toMap() => {
+    "uri": uri,
+    "offset": offset,
+    "prefixReference": prefixReference,
+    "combinators": combinators,
+    "isDeferred": isDeferred,
+    "isImplicit": isImplicit,
+    "uriOffset": uriOffset,
+    "uriEnd": uriEnd,
+    "prefixOffset": prefixOffset,
+  };
+}
+
+class UnlinkedParamBuilder extends Object with _UnlinkedParamMixin implements UnlinkedParam {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
-  UnlinkedTypeRefBuilder _type;
+  EntityRefBuilder _type;
   List<UnlinkedParamBuilder> _parameters;
   UnlinkedParamKind _kind;
   bool _isFunctionTyped;
   bool _isInitializingFormal;
-  bool _hasImplicitType;
+  int _inferredTypeSlot;
 
-  UnlinkedParamBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the parameter.
@@ -2641,26 +3999,34 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the parameter name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  EntityRefBuilder get type => _type;
+
   /**
    * If [isFunctionTyped] is `true`, the declared return type.  If
-   * [isFunctionTyped] is `false`, the declared type.  Absent if
-   * [isFunctionTyped] is `true` and the declared return type is `void`.  Note
-   * that when strong mode is enabled, the actual type may be different due to
-   * type inference.
+   * [isFunctionTyped] is `false`, the declared type.  Absent if the type is
+   * implicit.
    */
-  void set type(UnlinkedTypeRefBuilder _value) {
+  void set type(EntityRefBuilder _value) {
     assert(!_finished);
     _type = _value;
   }
 
+  @override
+  List<UnlinkedParamBuilder> get parameters => _parameters ??= <UnlinkedParamBuilder>[];
+
   /**
    * If [isFunctionTyped] is `true`, the parameters of the function type.
    */
@@ -2669,6 +4035,9 @@
     _parameters = _value;
   }
 
+  @override
+  UnlinkedParamKind get kind => _kind ??= UnlinkedParamKind.required;
+
   /**
    * Kind of the parameter.
    */
@@ -2677,6 +4046,9 @@
     _kind = _value;
   }
 
+  @override
+  bool get isFunctionTyped => _isFunctionTyped ??= false;
+
   /**
    * Indicates whether this is a function-typed parameter.
    */
@@ -2685,6 +4057,9 @@
     _isFunctionTyped = _value;
   }
 
+  @override
+  bool get isInitializingFormal => _isInitializingFormal ??= false;
+
   /**
    * Indicates whether this is an initializing formal parameter (i.e. it is
    * declared using `this.` syntax).
@@ -2694,15 +4069,36 @@
     _isInitializingFormal = _value;
   }
 
+  @override
+  int get inferredTypeSlot => _inferredTypeSlot ??= 0;
+
   /**
-   * Indicates whether this parameter lacks an explicit type declaration.
-   * Always false for a function-typed parameter.
+   * If this parameter's type is inferrable, 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
+   * this variable, so its static type is `dynamic`.
+   *
+   * Note that although strong mode considers initializing formals to be
+   * inferrable, they are not marked as such in the summary; if their type is
+   * not specified, they always inherit the static type of the corresponding
+   * field.
    */
-  void set hasImplicitType(bool _value) {
+  void set inferredTypeSlot(int _value) {
     assert(!_finished);
-    _hasImplicitType = _value;
+    assert(_value == null || _value >= 0);
+    _inferredTypeSlot = _value;
   }
 
+  UnlinkedParamBuilder({String name, int nameOffset, EntityRefBuilder type, List<UnlinkedParamBuilder> parameters, UnlinkedParamKind kind, bool isFunctionTyped, bool isInitializingFormal, int inferredTypeSlot})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _type = type,
+      _parameters = parameters,
+      _kind = kind,
+      _isFunctionTyped = isFunctionTyped,
+      _isInitializingFormal = isInitializingFormal,
+      _inferredTypeSlot = inferredTypeSlot;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -2723,7 +4119,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_type != null) {
       fbBuilder.addOffset(2, offset_type);
@@ -2732,7 +4128,7 @@
       fbBuilder.addOffset(3, offset_parameters);
     }
     if (_kind != null && _kind != UnlinkedParamKind.required) {
-      fbBuilder.addInt32(4, _kind.index);
+      fbBuilder.addUint32(4, _kind.index);
     }
     if (_isFunctionTyped == true) {
       fbBuilder.addBool(5, true);
@@ -2740,26 +4136,13 @@
     if (_isInitializingFormal == true) {
       fbBuilder.addBool(6, true);
     }
-    if (_hasImplicitType == true) {
-      fbBuilder.addBool(7, true);
+    if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
+      fbBuilder.addUint32(7, _inferredTypeSlot);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedParamBuilder encodeUnlinkedParam({String name, int nameOffset, UnlinkedTypeRefBuilder type, List<UnlinkedParamBuilder> parameters, UnlinkedParamKind kind, bool isFunctionTyped, bool isInitializingFormal, bool hasImplicitType}) {
-  UnlinkedParamBuilder builder = new UnlinkedParamBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.type = type;
-  builder.parameters = parameters;
-  builder.kind = kind;
-  builder.isFunctionTyped = isFunctionTyped;
-  builder.isInitializingFormal = isInitializingFormal;
-  builder.hasImplicitType = hasImplicitType;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a function parameter.
  */
@@ -2777,12 +4160,10 @@
 
   /**
    * If [isFunctionTyped] is `true`, the declared return type.  If
-   * [isFunctionTyped] is `false`, the declared type.  Absent if
-   * [isFunctionTyped] is `true` and the declared return type is `void`.  Note
-   * that when strong mode is enabled, the actual type may be different due to
-   * type inference.
+   * [isFunctionTyped] is `false`, the declared type.  Absent if the type is
+   * implicit.
    */
-  UnlinkedTypeRef get type;
+  EntityRef get type;
 
   /**
    * If [isFunctionTyped] is `true`, the parameters of the function type.
@@ -2806,10 +4187,17 @@
   bool get isInitializingFormal;
 
   /**
-   * Indicates whether this parameter lacks an explicit type declaration.
-   * Always false for a function-typed parameter.
+   * If this parameter's type is inferrable, 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
+   * this variable, so its static type is `dynamic`.
+   *
+   * Note that although strong mode considers initializing formals to be
+   * inferrable, they are not marked as such in the summary; if their type is
+   * not specified, they always inherit the static type of the corresponding
+   * field.
    */
-  bool get hasImplicitType;
+  int get inferredTypeSlot;
 }
 
 class _UnlinkedParamReader extends fb.TableReader<_UnlinkedParamImpl> {
@@ -2819,31 +4207,19 @@
   _UnlinkedParamImpl createObject(fb.BufferPointer bp) => new _UnlinkedParamImpl(bp);
 }
 
-class _UnlinkedParamImpl implements UnlinkedParam {
+class _UnlinkedParamImpl extends Object with _UnlinkedParamMixin implements UnlinkedParam {
   final fb.BufferPointer _bp;
 
   _UnlinkedParamImpl(this._bp);
 
   String _name;
   int _nameOffset;
-  UnlinkedTypeRef _type;
+  EntityRef _type;
   List<UnlinkedParam> _parameters;
   UnlinkedParamKind _kind;
   bool _isFunctionTyped;
   bool _isInitializingFormal;
-  bool _hasImplicitType;
-
-  @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "type": type,
-    "parameters": parameters,
-    "kind": kind,
-    "isFunctionTyped": isFunctionTyped,
-    "isInitializingFormal": isInitializingFormal,
-    "hasImplicitType": hasImplicitType,
-  };
+  int _inferredTypeSlot;
 
   @override
   String get name {
@@ -2853,13 +4229,13 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
   @override
-  UnlinkedTypeRef get type {
-    _type ??= const _UnlinkedTypeRefReader().vTableGet(_bp, 2, null);
+  EntityRef get type {
+    _type ??= const _EntityRefReader().vTableGet(_bp, 2, null);
     return _type;
   }
 
@@ -2871,7 +4247,7 @@
 
   @override
   UnlinkedParamKind get kind {
-    _kind ??= UnlinkedParamKind.values[const fb.Int32Reader().vTableGet(_bp, 4, 0)];
+    _kind ??= const _UnlinkedParamKindReader().vTableGet(_bp, 4, UnlinkedParamKind.required);
     return _kind;
   }
 
@@ -2888,19 +4264,34 @@
   }
 
   @override
-  bool get hasImplicitType {
-    _hasImplicitType ??= const fb.BoolReader().vTableGet(_bp, 7, false);
-    return _hasImplicitType;
+  int get inferredTypeSlot {
+    _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 7, 0);
+    return _inferredTypeSlot;
   }
 }
 
-class UnlinkedPartBuilder {
+abstract class _UnlinkedParamMixin implements UnlinkedParam {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "type": type,
+    "parameters": parameters,
+    "kind": kind,
+    "isFunctionTyped": isFunctionTyped,
+    "isInitializingFormal": isInitializingFormal,
+    "inferredTypeSlot": inferredTypeSlot,
+  };
+}
+
+class UnlinkedPartBuilder extends Object with _UnlinkedPartMixin implements UnlinkedPart {
   bool _finished = false;
 
   int _uriOffset;
   int _uriEnd;
 
-  UnlinkedPartBuilder();
+  @override
+  int get uriOffset => _uriOffset ??= 0;
 
   /**
    * Offset of the URI string (including quotes) relative to the beginning of
@@ -2908,39 +4299,41 @@
    */
   void set uriOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _uriOffset = _value;
   }
 
+  @override
+  int get uriEnd => _uriEnd ??= 0;
+
   /**
    * End of the URI string (including quotes) relative to the beginning of the
    * file.
    */
   void set uriEnd(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _uriEnd = _value;
   }
 
+  UnlinkedPartBuilder({int uriOffset, int uriEnd})
+    : _uriOffset = uriOffset,
+      _uriEnd = uriEnd;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
     fbBuilder.startTable();
     if (_uriOffset != null && _uriOffset != 0) {
-      fbBuilder.addInt32(0, _uriOffset);
+      fbBuilder.addUint32(0, _uriOffset);
     }
     if (_uriEnd != null && _uriEnd != 0) {
-      fbBuilder.addInt32(1, _uriEnd);
+      fbBuilder.addUint32(1, _uriEnd);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedPartBuilder encodeUnlinkedPart({int uriOffset, int uriEnd}) {
-  UnlinkedPartBuilder builder = new UnlinkedPartBuilder();
-  builder.uriOffset = uriOffset;
-  builder.uriEnd = uriEnd;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a part declaration.
  */
@@ -2966,7 +4359,7 @@
   _UnlinkedPartImpl createObject(fb.BufferPointer bp) => new _UnlinkedPartImpl(bp);
 }
 
-class _UnlinkedPartImpl implements UnlinkedPart {
+class _UnlinkedPartImpl extends Object with _UnlinkedPartMixin implements UnlinkedPart {
   final fb.BufferPointer _bp;
 
   _UnlinkedPartImpl(this._bp);
@@ -2975,32 +4368,36 @@
   int _uriEnd;
 
   @override
-  Map<String, Object> toMap() => {
-    "uriOffset": uriOffset,
-    "uriEnd": uriEnd,
-  };
-
-  @override
   int get uriOffset {
-    _uriOffset ??= const fb.Int32Reader().vTableGet(_bp, 0, 0);
+    _uriOffset ??= const fb.Uint32Reader().vTableGet(_bp, 0, 0);
     return _uriOffset;
   }
 
   @override
   int get uriEnd {
-    _uriEnd ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _uriEnd ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _uriEnd;
   }
 }
 
-class UnlinkedPublicNameBuilder {
+abstract class _UnlinkedPartMixin implements UnlinkedPart {
+  @override
+  Map<String, Object> toMap() => {
+    "uriOffset": uriOffset,
+    "uriEnd": uriEnd,
+  };
+}
+
+class UnlinkedPublicNameBuilder extends Object with _UnlinkedPublicNameMixin implements UnlinkedPublicName {
   bool _finished = false;
 
   String _name;
-  PrelinkedReferenceKind _kind;
+  ReferenceKind _kind;
   int _numTypeParameters;
+  List<UnlinkedPublicNameBuilder> _constMembers;
 
-  UnlinkedPublicNameBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * The name itself.
@@ -3010,62 +4407,81 @@
     _name = _value;
   }
 
+  @override
+  ReferenceKind get kind => _kind ??= ReferenceKind.classOrEnum;
+
   /**
    * The kind of object referred to by the name.
    */
-  void set kind(PrelinkedReferenceKind _value) {
+  void set kind(ReferenceKind _value) {
     assert(!_finished);
     _kind = _value;
   }
 
+  @override
+  int get numTypeParameters => _numTypeParameters ??= 0;
+
   /**
    * If the entity being referred to is generic, the number of type parameters
    * it accepts.  Otherwise zero.
    */
   void set numTypeParameters(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _numTypeParameters = _value;
   }
 
+  @override
+  List<UnlinkedPublicNameBuilder> get constMembers => _constMembers ??= <UnlinkedPublicNameBuilder>[];
+
+  /**
+   * If this [UnlinkedPublicName] is a class, the list of members which can be
+   * referenced from constants - static constant fields, static methods, and
+   * constructors.  Otherwise empty.
+   */
+  void set constMembers(List<UnlinkedPublicNameBuilder> _value) {
+    assert(!_finished);
+    _constMembers = _value;
+  }
+
+  UnlinkedPublicNameBuilder({String name, ReferenceKind kind, int numTypeParameters, List<UnlinkedPublicNameBuilder> constMembers})
+    : _name = name,
+      _kind = kind,
+      _numTypeParameters = numTypeParameters,
+      _constMembers = constMembers;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
     fb.Offset offset_name;
+    fb.Offset offset_constMembers;
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
+    if (!(_constMembers == null || _constMembers.isEmpty)) {
+      offset_constMembers = fbBuilder.writeList(_constMembers.map((b) => b.finish(fbBuilder)).toList());
+    }
     fbBuilder.startTable();
     if (offset_name != null) {
       fbBuilder.addOffset(0, offset_name);
     }
-    if (_kind != null && _kind != PrelinkedReferenceKind.classOrEnum) {
-      fbBuilder.addInt32(1, _kind.index);
+    if (_kind != null && _kind != ReferenceKind.classOrEnum) {
+      fbBuilder.addUint32(1, _kind.index);
     }
     if (_numTypeParameters != null && _numTypeParameters != 0) {
-      fbBuilder.addInt32(2, _numTypeParameters);
+      fbBuilder.addUint32(2, _numTypeParameters);
+    }
+    if (offset_constMembers != null) {
+      fbBuilder.addOffset(3, offset_constMembers);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedPublicNameBuilder encodeUnlinkedPublicName({String name, PrelinkedReferenceKind kind, int numTypeParameters}) {
-  UnlinkedPublicNameBuilder builder = new UnlinkedPublicNameBuilder();
-  builder.name = name;
-  builder.kind = kind;
-  builder.numTypeParameters = numTypeParameters;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a specific name contributed by a
  * compilation unit to a library's public namespace.
  *
- * TODO(paulberry): add a count of generic parameters, so that resynthesis
- * doesn't have to peek into the library to obtain this info.
- *
- * TODO(paulberry): for classes, add info about static members and
- * constructors, since this will be needed to prelink info about constants.
- *
  * TODO(paulberry): some of this information is redundant with information
  * elsewhere in the summary.  Consider reducing the redundancy to reduce
  * summary size.
@@ -3080,13 +4496,20 @@
   /**
    * The kind of object referred to by the name.
    */
-  PrelinkedReferenceKind get kind;
+  ReferenceKind get kind;
 
   /**
    * If the entity being referred to is generic, the number of type parameters
    * it accepts.  Otherwise zero.
    */
   int get numTypeParameters;
+
+  /**
+   * If this [UnlinkedPublicName] is a class, the list of members which can be
+   * referenced from constants - static constant fields, static methods, and
+   * constructors.  Otherwise empty.
+   */
+  List<UnlinkedPublicName> get constMembers;
 }
 
 class _UnlinkedPublicNameReader extends fb.TableReader<_UnlinkedPublicNameImpl> {
@@ -3096,21 +4519,15 @@
   _UnlinkedPublicNameImpl createObject(fb.BufferPointer bp) => new _UnlinkedPublicNameImpl(bp);
 }
 
-class _UnlinkedPublicNameImpl implements UnlinkedPublicName {
+class _UnlinkedPublicNameImpl extends Object with _UnlinkedPublicNameMixin implements UnlinkedPublicName {
   final fb.BufferPointer _bp;
 
   _UnlinkedPublicNameImpl(this._bp);
 
   String _name;
-  PrelinkedReferenceKind _kind;
+  ReferenceKind _kind;
   int _numTypeParameters;
-
-  @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "kind": kind,
-    "numTypeParameters": numTypeParameters,
-  };
+  List<UnlinkedPublicName> _constMembers;
 
   @override
   String get name {
@@ -3119,26 +4536,43 @@
   }
 
   @override
-  PrelinkedReferenceKind get kind {
-    _kind ??= PrelinkedReferenceKind.values[const fb.Int32Reader().vTableGet(_bp, 1, 0)];
+  ReferenceKind get kind {
+    _kind ??= const _ReferenceKindReader().vTableGet(_bp, 1, ReferenceKind.classOrEnum);
     return _kind;
   }
 
   @override
   int get numTypeParameters {
-    _numTypeParameters ??= const fb.Int32Reader().vTableGet(_bp, 2, 0);
+    _numTypeParameters ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _numTypeParameters;
   }
+
+  @override
+  List<UnlinkedPublicName> get constMembers {
+    _constMembers ??= const fb.ListReader<UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 3, const <UnlinkedPublicName>[]);
+    return _constMembers;
+  }
 }
 
-class UnlinkedPublicNamespaceBuilder {
+abstract class _UnlinkedPublicNameMixin implements UnlinkedPublicName {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "kind": kind,
+    "numTypeParameters": numTypeParameters,
+    "constMembers": constMembers,
+  };
+}
+
+class UnlinkedPublicNamespaceBuilder extends Object with _UnlinkedPublicNamespaceMixin implements UnlinkedPublicNamespace {
   bool _finished = false;
 
   List<UnlinkedPublicNameBuilder> _names;
   List<UnlinkedExportPublicBuilder> _exports;
   List<String> _parts;
 
-  UnlinkedPublicNamespaceBuilder();
+  @override
+  List<UnlinkedPublicNameBuilder> get names => _names ??= <UnlinkedPublicNameBuilder>[];
 
   /**
    * Public names defined in the compilation unit.
@@ -3151,6 +4585,9 @@
     _names = _value;
   }
 
+  @override
+  List<UnlinkedExportPublicBuilder> get exports => _exports ??= <UnlinkedExportPublicBuilder>[];
+
   /**
    * Export declarations in the compilation unit.
    */
@@ -3159,6 +4596,9 @@
     _exports = _value;
   }
 
+  @override
+  List<String> get parts => _parts ??= <String>[];
+
   /**
    * URIs referenced by part declarations in the compilation unit.
    */
@@ -3167,6 +4607,11 @@
     _parts = _value;
   }
 
+  UnlinkedPublicNamespaceBuilder({List<UnlinkedPublicNameBuilder> names, List<UnlinkedExportPublicBuilder> exports, List<String> parts})
+    : _names = names,
+      _exports = exports,
+      _parts = parts;
+
   List<int> toBuffer() {
     fb.Builder fbBuilder = new fb.Builder();
     return fbBuilder.finish(finish(fbBuilder));
@@ -3201,14 +4646,6 @@
   }
 }
 
-UnlinkedPublicNamespaceBuilder encodeUnlinkedPublicNamespace({List<UnlinkedPublicNameBuilder> names, List<UnlinkedExportPublicBuilder> exports, List<String> parts}) {
-  UnlinkedPublicNamespaceBuilder builder = new UnlinkedPublicNamespaceBuilder();
-  builder.names = names;
-  builder.exports = exports;
-  builder.parts = parts;
-  return builder;
-}
-
 /**
  * Unlinked summary information about what a compilation unit contributes to a
  * library's public namespace.  This is the subset of [UnlinkedUnit] that is
@@ -3246,7 +4683,7 @@
   _UnlinkedPublicNamespaceImpl createObject(fb.BufferPointer bp) => new _UnlinkedPublicNamespaceImpl(bp);
 }
 
-class _UnlinkedPublicNamespaceImpl implements UnlinkedPublicNamespace {
+class _UnlinkedPublicNamespaceImpl extends Object with _UnlinkedPublicNamespaceMixin implements UnlinkedPublicNamespace {
   final fb.BufferPointer _bp;
 
   _UnlinkedPublicNamespaceImpl(this._bp);
@@ -3256,13 +4693,6 @@
   List<String> _parts;
 
   @override
-  Map<String, Object> toMap() => {
-    "names": names,
-    "exports": exports,
-    "parts": parts,
-  };
-
-  @override
   List<UnlinkedPublicName> get names {
     _names ??= const fb.ListReader<UnlinkedPublicName>(const _UnlinkedPublicNameReader()).vTableGet(_bp, 0, const <UnlinkedPublicName>[]);
     return _names;
@@ -3281,23 +4711,36 @@
   }
 }
 
-class UnlinkedReferenceBuilder {
+abstract class _UnlinkedPublicNamespaceMixin implements UnlinkedPublicNamespace {
+  @override
+  Map<String, Object> toMap() => {
+    "names": names,
+    "exports": exports,
+    "parts": parts,
+  };
+}
+
+class UnlinkedReferenceBuilder extends Object with _UnlinkedReferenceMixin implements UnlinkedReference {
   bool _finished = false;
 
   String _name;
   int _prefixReference;
 
-  UnlinkedReferenceBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
-   * Name of the entity being referred to.  The empty string refers to the
-   * pseudo-type `dynamic`.
+   * 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".
    */
   void set name(String _value) {
     assert(!_finished);
     _name = _value;
   }
 
+  @override
+  int get prefixReference => _prefixReference ??= 0;
+
   /**
    * Prefix used to refer to the entity, or zero if no prefix is used.  This is
    * an index into [UnlinkedUnit.references].
@@ -3308,9 +4751,14 @@
    */
   void set prefixReference(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _prefixReference = _value;
   }
 
+  UnlinkedReferenceBuilder({String name, int prefixReference})
+    : _name = name,
+      _prefixReference = prefixReference;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -3323,19 +4771,12 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_prefixReference != null && _prefixReference != 0) {
-      fbBuilder.addInt32(1, _prefixReference);
+      fbBuilder.addUint32(1, _prefixReference);
     }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedReferenceBuilder encodeUnlinkedReference({String name, int prefixReference}) {
-  UnlinkedReferenceBuilder builder = new UnlinkedReferenceBuilder();
-  builder.name = name;
-  builder.prefixReference = prefixReference;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a name referred to in one library that
  * might be defined in another.
@@ -3343,8 +4784,8 @@
 abstract class UnlinkedReference extends base.SummaryClass {
 
   /**
-   * Name of the entity being referred to.  The empty string refers to the
-   * pseudo-type `dynamic`.
+   * 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".
    */
   String get name;
 
@@ -3366,7 +4807,7 @@
   _UnlinkedReferenceImpl createObject(fb.BufferPointer bp) => new _UnlinkedReferenceImpl(bp);
 }
 
-class _UnlinkedReferenceImpl implements UnlinkedReference {
+class _UnlinkedReferenceImpl extends Object with _UnlinkedReferenceMixin implements UnlinkedReference {
   final fb.BufferPointer _bp;
 
   _UnlinkedReferenceImpl(this._bp);
@@ -3375,12 +4816,6 @@
   int _prefixReference;
 
   @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "prefixReference": prefixReference,
-  };
-
-  @override
   String get name {
     _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
@@ -3388,22 +4823,31 @@
 
   @override
   int get prefixReference {
-    _prefixReference ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _prefixReference ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _prefixReference;
   }
 }
 
-class UnlinkedTypedefBuilder {
+abstract class _UnlinkedReferenceMixin implements UnlinkedReference {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "prefixReference": prefixReference,
+  };
+}
+
+class UnlinkedTypedefBuilder extends Object with _UnlinkedTypedefMixin implements UnlinkedTypedef {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
   UnlinkedDocumentationCommentBuilder _documentationComment;
   List<UnlinkedTypeParamBuilder> _typeParameters;
-  UnlinkedTypeRefBuilder _returnType;
+  EntityRefBuilder _returnType;
   List<UnlinkedParamBuilder> _parameters;
 
-  UnlinkedTypedefBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the typedef.
@@ -3413,14 +4857,21 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the typedef name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get documentationComment => _documentationComment;
+
   /**
    * Documentation comment for the typedef, or `null` if there is no
    * documentation comment.
@@ -3430,6 +4881,9 @@
     _documentationComment = _value;
   }
 
+  @override
+  List<UnlinkedTypeParamBuilder> get typeParameters => _typeParameters ??= <UnlinkedTypeParamBuilder>[];
+
   /**
    * Type parameters of the typedef, if any.
    */
@@ -3438,14 +4892,20 @@
     _typeParameters = _value;
   }
 
+  @override
+  EntityRefBuilder get returnType => _returnType;
+
   /**
-   * Return type of the typedef.  Absent if the return type is `void`.
+   * Return type of the typedef.
    */
-  void set returnType(UnlinkedTypeRefBuilder _value) {
+  void set returnType(EntityRefBuilder _value) {
     assert(!_finished);
     _returnType = _value;
   }
 
+  @override
+  List<UnlinkedParamBuilder> get parameters => _parameters ??= <UnlinkedParamBuilder>[];
+
   /**
    * Parameters of the executable, if any.
    */
@@ -3454,6 +4914,14 @@
     _parameters = _value;
   }
 
+  UnlinkedTypedefBuilder({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedTypeParamBuilder> typeParameters, EntityRefBuilder returnType, List<UnlinkedParamBuilder> parameters})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _documentationComment = documentationComment,
+      _typeParameters = typeParameters,
+      _returnType = returnType,
+      _parameters = parameters;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -3482,7 +4950,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
@@ -3500,17 +4968,6 @@
   }
 }
 
-UnlinkedTypedefBuilder encodeUnlinkedTypedef({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedTypeParamBuilder> typeParameters, UnlinkedTypeRefBuilder returnType, List<UnlinkedParamBuilder> parameters}) {
-  UnlinkedTypedefBuilder builder = new UnlinkedTypedefBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.documentationComment = documentationComment;
-  builder.typeParameters = typeParameters;
-  builder.returnType = returnType;
-  builder.parameters = parameters;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a typedef declaration.
  */
@@ -3538,9 +4995,9 @@
   List<UnlinkedTypeParam> get typeParameters;
 
   /**
-   * Return type of the typedef.  Absent if the return type is `void`.
+   * Return type of the typedef.
    */
-  UnlinkedTypeRef get returnType;
+  EntityRef get returnType;
 
   /**
    * Parameters of the executable, if any.
@@ -3555,7 +5012,7 @@
   _UnlinkedTypedefImpl createObject(fb.BufferPointer bp) => new _UnlinkedTypedefImpl(bp);
 }
 
-class _UnlinkedTypedefImpl implements UnlinkedTypedef {
+class _UnlinkedTypedefImpl extends Object with _UnlinkedTypedefMixin implements UnlinkedTypedef {
   final fb.BufferPointer _bp;
 
   _UnlinkedTypedefImpl(this._bp);
@@ -3564,20 +5021,10 @@
   int _nameOffset;
   UnlinkedDocumentationComment _documentationComment;
   List<UnlinkedTypeParam> _typeParameters;
-  UnlinkedTypeRef _returnType;
+  EntityRef _returnType;
   List<UnlinkedParam> _parameters;
 
   @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "documentationComment": documentationComment,
-    "typeParameters": typeParameters,
-    "returnType": returnType,
-    "parameters": parameters,
-  };
-
-  @override
   String get name {
     _name ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _name;
@@ -3585,7 +5032,7 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -3602,8 +5049,8 @@
   }
 
   @override
-  UnlinkedTypeRef get returnType {
-    _returnType ??= const _UnlinkedTypeRefReader().vTableGet(_bp, 4, null);
+  EntityRef get returnType {
+    _returnType ??= const _EntityRefReader().vTableGet(_bp, 4, null);
     return _returnType;
   }
 
@@ -3614,14 +5061,27 @@
   }
 }
 
-class UnlinkedTypeParamBuilder {
+abstract class _UnlinkedTypedefMixin implements UnlinkedTypedef {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "documentationComment": documentationComment,
+    "typeParameters": typeParameters,
+    "returnType": returnType,
+    "parameters": parameters,
+  };
+}
+
+class UnlinkedTypeParamBuilder extends Object with _UnlinkedTypeParamMixin implements UnlinkedTypeParam {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
-  UnlinkedTypeRefBuilder _bound;
+  EntityRefBuilder _bound;
 
-  UnlinkedTypeParamBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the type parameter.
@@ -3631,23 +5091,35 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the type parameter name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  EntityRefBuilder get bound => _bound;
+
   /**
    * Bound of the type parameter, if a bound is explicitly declared.  Otherwise
    * null.
    */
-  void set bound(UnlinkedTypeRefBuilder _value) {
+  void set bound(EntityRefBuilder _value) {
     assert(!_finished);
     _bound = _value;
   }
 
+  UnlinkedTypeParamBuilder({String name, int nameOffset, EntityRefBuilder bound})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _bound = bound;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
@@ -3664,7 +5136,7 @@
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_bound != null) {
       fbBuilder.addOffset(2, offset_bound);
@@ -3673,14 +5145,6 @@
   }
 }
 
-UnlinkedTypeParamBuilder encodeUnlinkedTypeParam({String name, int nameOffset, UnlinkedTypeRefBuilder bound}) {
-  UnlinkedTypeParamBuilder builder = new UnlinkedTypeParamBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.bound = bound;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a type parameter declaration.
  */
@@ -3700,7 +5164,7 @@
    * Bound of the type parameter, if a bound is explicitly declared.  Otherwise
    * null.
    */
-  UnlinkedTypeRef get bound;
+  EntityRef get bound;
 }
 
 class _UnlinkedTypeParamReader extends fb.TableReader<_UnlinkedTypeParamImpl> {
@@ -3710,21 +5174,14 @@
   _UnlinkedTypeParamImpl createObject(fb.BufferPointer bp) => new _UnlinkedTypeParamImpl(bp);
 }
 
-class _UnlinkedTypeParamImpl implements UnlinkedTypeParam {
+class _UnlinkedTypeParamImpl extends Object with _UnlinkedTypeParamMixin implements UnlinkedTypeParam {
   final fb.BufferPointer _bp;
 
   _UnlinkedTypeParamImpl(this._bp);
 
   String _name;
   int _nameOffset;
-  UnlinkedTypeRef _bound;
-
-  @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "bound": bound,
-  };
+  EntityRef _bound;
 
   @override
   String get name {
@@ -3734,191 +5191,27 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
   @override
-  UnlinkedTypeRef get bound {
-    _bound ??= const _UnlinkedTypeRefReader().vTableGet(_bp, 2, null);
+  EntityRef get bound {
+    _bound ??= const _EntityRefReader().vTableGet(_bp, 2, null);
     return _bound;
   }
 }
 
-class UnlinkedTypeRefBuilder {
-  bool _finished = false;
-
-  int _reference;
-  int _paramReference;
-  List<UnlinkedTypeRefBuilder> _typeArguments;
-
-  UnlinkedTypeRefBuilder();
-
-  /**
-   * Index into [UnlinkedUnit.references] for the type being referred to, or
-   * zero if this is a reference to a type parameter.
-   *
-   * Note that since zero is also a valid index into
-   * [UnlinkedUnit.references], we cannot distinguish between references to
-   * type parameters and references to types by checking [reference] against
-   * zero.  To distinguish between references to type parameters and references
-   * to types, check whether [paramReference] is zero.
-   */
-  void set reference(int _value) {
-    assert(!_finished);
-    _reference = _value;
-  }
-
-  /**
-   * If this is a reference to a type parameter, one-based index into the list
-   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
-   * Bruijn index conventions; that is, innermost parameters come first, and
-   * if a class or method has multiple parameters, they are indexed from right
-   * to left.  So for instance, if the enclosing declaration is
-   *
-   *     class C<T,U> {
-   *       m<V,W> {
-   *         ...
-   *       }
-   *     }
-   *
-   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
-   * respectively.
-   *
-   * If the type being referred to is not a type parameter, [paramReference] is
-   * zero.
-   */
-  void set paramReference(int _value) {
-    assert(!_finished);
-    _paramReference = _value;
-  }
-
-  /**
-   * If this is an instantiation of a generic type, the type arguments used to
-   * instantiate it.  Trailing type arguments of type `dynamic` are omitted.
-   */
-  void set typeArguments(List<UnlinkedTypeRefBuilder> _value) {
-    assert(!_finished);
-    _typeArguments = _value;
-  }
-
-  fb.Offset finish(fb.Builder fbBuilder) {
-    assert(!_finished);
-    _finished = true;
-    fb.Offset offset_typeArguments;
-    if (!(_typeArguments == null || _typeArguments.isEmpty)) {
-      offset_typeArguments = fbBuilder.writeList(_typeArguments.map((b) => b.finish(fbBuilder)).toList());
-    }
-    fbBuilder.startTable();
-    if (_reference != null && _reference != 0) {
-      fbBuilder.addInt32(0, _reference);
-    }
-    if (_paramReference != null && _paramReference != 0) {
-      fbBuilder.addInt32(1, _paramReference);
-    }
-    if (offset_typeArguments != null) {
-      fbBuilder.addOffset(2, offset_typeArguments);
-    }
-    return fbBuilder.endTable();
-  }
-}
-
-UnlinkedTypeRefBuilder encodeUnlinkedTypeRef({int reference, int paramReference, List<UnlinkedTypeRefBuilder> typeArguments}) {
-  UnlinkedTypeRefBuilder builder = new UnlinkedTypeRefBuilder();
-  builder.reference = reference;
-  builder.paramReference = paramReference;
-  builder.typeArguments = typeArguments;
-  return builder;
-}
-
-/**
- * Unlinked summary information about a reference to a type.
- */
-abstract class UnlinkedTypeRef extends base.SummaryClass {
-
-  /**
-   * Index into [UnlinkedUnit.references] for the type being referred to, or
-   * zero if this is a reference to a type parameter.
-   *
-   * Note that since zero is also a valid index into
-   * [UnlinkedUnit.references], we cannot distinguish between references to
-   * type parameters and references to types by checking [reference] against
-   * zero.  To distinguish between references to type parameters and references
-   * to types, check whether [paramReference] is zero.
-   */
-  int get reference;
-
-  /**
-   * If this is a reference to a type parameter, one-based index into the list
-   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
-   * Bruijn index conventions; that is, innermost parameters come first, and
-   * if a class or method has multiple parameters, they are indexed from right
-   * to left.  So for instance, if the enclosing declaration is
-   *
-   *     class C<T,U> {
-   *       m<V,W> {
-   *         ...
-   *       }
-   *     }
-   *
-   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
-   * respectively.
-   *
-   * If the type being referred to is not a type parameter, [paramReference] is
-   * zero.
-   */
-  int get paramReference;
-
-  /**
-   * If this is an instantiation of a generic type, the type arguments used to
-   * instantiate it.  Trailing type arguments of type `dynamic` are omitted.
-   */
-  List<UnlinkedTypeRef> get typeArguments;
-}
-
-class _UnlinkedTypeRefReader extends fb.TableReader<_UnlinkedTypeRefImpl> {
-  const _UnlinkedTypeRefReader();
-
-  @override
-  _UnlinkedTypeRefImpl createObject(fb.BufferPointer bp) => new _UnlinkedTypeRefImpl(bp);
-}
-
-class _UnlinkedTypeRefImpl implements UnlinkedTypeRef {
-  final fb.BufferPointer _bp;
-
-  _UnlinkedTypeRefImpl(this._bp);
-
-  int _reference;
-  int _paramReference;
-  List<UnlinkedTypeRef> _typeArguments;
-
+abstract class _UnlinkedTypeParamMixin implements UnlinkedTypeParam {
   @override
   Map<String, Object> toMap() => {
-    "reference": reference,
-    "paramReference": paramReference,
-    "typeArguments": typeArguments,
+    "name": name,
+    "nameOffset": nameOffset,
+    "bound": bound,
   };
-
-  @override
-  int get reference {
-    _reference ??= const fb.Int32Reader().vTableGet(_bp, 0, 0);
-    return _reference;
-  }
-
-  @override
-  int get paramReference {
-    _paramReference ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
-    return _paramReference;
-  }
-
-  @override
-  List<UnlinkedTypeRef> get typeArguments {
-    _typeArguments ??= const fb.ListReader<UnlinkedTypeRef>(const _UnlinkedTypeRefReader()).vTableGet(_bp, 2, const <UnlinkedTypeRef>[]);
-    return _typeArguments;
-  }
 }
 
-class UnlinkedUnitBuilder {
+class UnlinkedUnitBuilder extends Object with _UnlinkedUnitMixin implements UnlinkedUnit {
   bool _finished = false;
 
   String _libraryName;
@@ -3936,7 +5229,8 @@
   List<UnlinkedTypedefBuilder> _typedefs;
   List<UnlinkedVariableBuilder> _variables;
 
-  UnlinkedUnitBuilder();
+  @override
+  String get libraryName => _libraryName ??= '';
 
   /**
    * Name of the library (from a "library" declaration, if present).
@@ -3946,24 +5240,35 @@
     _libraryName = _value;
   }
 
+  @override
+  int get libraryNameOffset => _libraryNameOffset ??= 0;
+
   /**
    * Offset of the library name relative to the beginning of the file (or 0 if
    * the library has no name).
    */
   void set libraryNameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _libraryNameOffset = _value;
   }
 
+  @override
+  int get libraryNameLength => _libraryNameLength ??= 0;
+
   /**
    * Length of the library name as it appears in the source code (or 0 if the
    * library has no name).
    */
   void set libraryNameLength(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _libraryNameLength = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get libraryDocumentationComment => _libraryDocumentationComment;
+
   /**
    * Documentation comment for the library, or `null` if there is no
    * documentation comment.
@@ -3973,6 +5278,9 @@
     _libraryDocumentationComment = _value;
   }
 
+  @override
+  UnlinkedPublicNamespaceBuilder get publicNamespace => _publicNamespace;
+
   /**
    * Unlinked public namespace of this compilation unit.
    */
@@ -3981,16 +5289,24 @@
     _publicNamespace = _value;
   }
 
+  @override
+  List<UnlinkedReferenceBuilder> get references => _references ??= <UnlinkedReferenceBuilder>[];
+
   /**
    * Top level and prefixed names referred to by this compilation unit.  The
-   * zeroth element of this array is always populated and always represents a
-   * reference to the pseudo-type "dynamic".
+   * zeroth element of this array is always populated and is used to represent
+   * the absence of a reference in places where a reference is optional (for
+   * example [UnlinkedReference.prefixReference or
+   * UnlinkedImport.prefixReference]).
    */
   void set references(List<UnlinkedReferenceBuilder> _value) {
     assert(!_finished);
     _references = _value;
   }
 
+  @override
+  List<UnlinkedClassBuilder> get classes => _classes ??= <UnlinkedClassBuilder>[];
+
   /**
    * Classes declared in the compilation unit.
    */
@@ -3999,6 +5315,9 @@
     _classes = _value;
   }
 
+  @override
+  List<UnlinkedEnumBuilder> get enums => _enums ??= <UnlinkedEnumBuilder>[];
+
   /**
    * Enums declared in the compilation unit.
    */
@@ -4007,6 +5326,9 @@
     _enums = _value;
   }
 
+  @override
+  List<UnlinkedExecutableBuilder> get executables => _executables ??= <UnlinkedExecutableBuilder>[];
+
   /**
    * Top level executable objects (functions, getters, and setters) declared in
    * the compilation unit.
@@ -4016,6 +5338,9 @@
     _executables = _value;
   }
 
+  @override
+  List<UnlinkedExportNonPublicBuilder> get exports => _exports ??= <UnlinkedExportNonPublicBuilder>[];
+
   /**
    * Export declarations in the compilation unit.
    */
@@ -4024,6 +5349,9 @@
     _exports = _value;
   }
 
+  @override
+  List<UnlinkedImportBuilder> get imports => _imports ??= <UnlinkedImportBuilder>[];
+
   /**
    * Import declarations in the compilation unit.
    */
@@ -4032,6 +5360,9 @@
     _imports = _value;
   }
 
+  @override
+  List<UnlinkedPartBuilder> get parts => _parts ??= <UnlinkedPartBuilder>[];
+
   /**
    * Part declarations in the compilation unit.
    */
@@ -4040,6 +5371,9 @@
     _parts = _value;
   }
 
+  @override
+  List<UnlinkedTypedefBuilder> get typedefs => _typedefs ??= <UnlinkedTypedefBuilder>[];
+
   /**
    * Typedefs declared in the compilation unit.
    */
@@ -4048,6 +5382,9 @@
     _typedefs = _value;
   }
 
+  @override
+  List<UnlinkedVariableBuilder> get variables => _variables ??= <UnlinkedVariableBuilder>[];
+
   /**
    * Top level variables declared in the compilation unit.
    */
@@ -4056,6 +5393,22 @@
     _variables = _value;
   }
 
+  UnlinkedUnitBuilder({String libraryName, int libraryNameOffset, int libraryNameLength, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedClassBuilder> classes, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, List<UnlinkedImportBuilder> imports, List<UnlinkedPartBuilder> parts, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
+    : _libraryName = libraryName,
+      _libraryNameOffset = libraryNameOffset,
+      _libraryNameLength = libraryNameLength,
+      _libraryDocumentationComment = libraryDocumentationComment,
+      _publicNamespace = publicNamespace,
+      _references = references,
+      _classes = classes,
+      _enums = enums,
+      _executables = executables,
+      _exports = exports,
+      _imports = imports,
+      _parts = parts,
+      _typedefs = typedefs,
+      _variables = variables;
+
   List<int> toBuffer() {
     fb.Builder fbBuilder = new fb.Builder();
     return fbBuilder.finish(finish(fbBuilder));
@@ -4117,10 +5470,10 @@
       fbBuilder.addOffset(0, offset_libraryName);
     }
     if (_libraryNameOffset != null && _libraryNameOffset != 0) {
-      fbBuilder.addInt32(1, _libraryNameOffset);
+      fbBuilder.addUint32(1, _libraryNameOffset);
     }
     if (_libraryNameLength != null && _libraryNameLength != 0) {
-      fbBuilder.addInt32(2, _libraryNameLength);
+      fbBuilder.addUint32(2, _libraryNameLength);
     }
     if (offset_libraryDocumentationComment != null) {
       fbBuilder.addOffset(3, offset_libraryDocumentationComment);
@@ -4159,25 +5512,6 @@
   }
 }
 
-UnlinkedUnitBuilder encodeUnlinkedUnit({String libraryName, int libraryNameOffset, int libraryNameLength, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedClassBuilder> classes, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, List<UnlinkedImportBuilder> imports, List<UnlinkedPartBuilder> parts, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables}) {
-  UnlinkedUnitBuilder builder = new UnlinkedUnitBuilder();
-  builder.libraryName = libraryName;
-  builder.libraryNameOffset = libraryNameOffset;
-  builder.libraryNameLength = libraryNameLength;
-  builder.libraryDocumentationComment = libraryDocumentationComment;
-  builder.publicNamespace = publicNamespace;
-  builder.references = references;
-  builder.classes = classes;
-  builder.enums = enums;
-  builder.executables = executables;
-  builder.exports = exports;
-  builder.imports = imports;
-  builder.parts = parts;
-  builder.typedefs = typedefs;
-  builder.variables = variables;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a compilation unit ("part file").
  */
@@ -4217,8 +5551,10 @@
 
   /**
    * Top level and prefixed names referred to by this compilation unit.  The
-   * zeroth element of this array is always populated and always represents a
-   * reference to the pseudo-type "dynamic".
+   * zeroth element of this array is always populated and is used to represent
+   * the absence of a reference in places where a reference is optional (for
+   * example [UnlinkedReference.prefixReference or
+   * UnlinkedImport.prefixReference]).
    */
   List<UnlinkedReference> get references;
 
@@ -4271,7 +5607,7 @@
   _UnlinkedUnitImpl createObject(fb.BufferPointer bp) => new _UnlinkedUnitImpl(bp);
 }
 
-class _UnlinkedUnitImpl implements UnlinkedUnit {
+class _UnlinkedUnitImpl extends Object with _UnlinkedUnitMixin implements UnlinkedUnit {
   final fb.BufferPointer _bp;
 
   _UnlinkedUnitImpl(this._bp);
@@ -4292,24 +5628,6 @@
   List<UnlinkedVariable> _variables;
 
   @override
-  Map<String, Object> toMap() => {
-    "libraryName": libraryName,
-    "libraryNameOffset": libraryNameOffset,
-    "libraryNameLength": libraryNameLength,
-    "libraryDocumentationComment": libraryDocumentationComment,
-    "publicNamespace": publicNamespace,
-    "references": references,
-    "classes": classes,
-    "enums": enums,
-    "executables": executables,
-    "exports": exports,
-    "imports": imports,
-    "parts": parts,
-    "typedefs": typedefs,
-    "variables": variables,
-  };
-
-  @override
   String get libraryName {
     _libraryName ??= const fb.StringReader().vTableGet(_bp, 0, '');
     return _libraryName;
@@ -4317,13 +5635,13 @@
 
   @override
   int get libraryNameOffset {
-    _libraryNameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _libraryNameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _libraryNameOffset;
   }
 
   @override
   int get libraryNameLength {
-    _libraryNameLength ??= const fb.Int32Reader().vTableGet(_bp, 2, 0);
+    _libraryNameLength ??= const fb.Uint32Reader().vTableGet(_bp, 2, 0);
     return _libraryNameLength;
   }
 
@@ -4394,19 +5712,42 @@
   }
 }
 
-class UnlinkedVariableBuilder {
+abstract class _UnlinkedUnitMixin implements UnlinkedUnit {
+  @override
+  Map<String, Object> toMap() => {
+    "libraryName": libraryName,
+    "libraryNameOffset": libraryNameOffset,
+    "libraryNameLength": libraryNameLength,
+    "libraryDocumentationComment": libraryDocumentationComment,
+    "publicNamespace": publicNamespace,
+    "references": references,
+    "classes": classes,
+    "enums": enums,
+    "executables": executables,
+    "exports": exports,
+    "imports": imports,
+    "parts": parts,
+    "typedefs": typedefs,
+    "variables": variables,
+  };
+}
+
+class UnlinkedVariableBuilder extends Object with _UnlinkedVariableMixin implements UnlinkedVariable {
   bool _finished = false;
 
   String _name;
   int _nameOffset;
   UnlinkedDocumentationCommentBuilder _documentationComment;
-  UnlinkedTypeRefBuilder _type;
+  EntityRefBuilder _type;
+  UnlinkedConstBuilder _constExpr;
   bool _isStatic;
   bool _isFinal;
   bool _isConst;
-  bool _hasImplicitType;
+  int _propagatedTypeSlot;
+  int _inferredTypeSlot;
 
-  UnlinkedVariableBuilder();
+  @override
+  String get name => _name ??= '';
 
   /**
    * Name of the variable.
@@ -4416,14 +5757,21 @@
     _name = _value;
   }
 
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
   /**
    * Offset of the variable name relative to the beginning of the file.
    */
   void set nameOffset(int _value) {
     assert(!_finished);
+    assert(_value == null || _value >= 0);
     _nameOffset = _value;
   }
 
+  @override
+  UnlinkedDocumentationCommentBuilder get documentationComment => _documentationComment;
+
   /**
    * Documentation comment for the variable, or `null` if there is no
    * documentation comment.
@@ -4433,15 +5781,32 @@
     _documentationComment = _value;
   }
 
+  @override
+  EntityRefBuilder get type => _type;
+
   /**
-   * Declared type of the variable.  Note that when strong mode is enabled, the
-   * actual type of the variable may be different due to type inference.
+   * Declared type of the variable.  Absent if the type is implicit.
    */
-  void set type(UnlinkedTypeRefBuilder _value) {
+  void set type(EntityRefBuilder _value) {
     assert(!_finished);
     _type = _value;
   }
 
+  @override
+  UnlinkedConstBuilder get constExpr => _constExpr;
+
+  /**
+   * If [isConst] is true, and the variable has an initializer, the constant
+   * expression in the initializer.
+   */
+  void set constExpr(UnlinkedConstBuilder _value) {
+    assert(!_finished);
+    _constExpr = _value;
+  }
+
+  @override
+  bool get isStatic => _isStatic ??= false;
+
   /**
    * Indicates whether the variable is declared using the `static` keyword.
    *
@@ -4454,6 +5819,9 @@
     _isStatic = _value;
   }
 
+  @override
+  bool get isFinal => _isFinal ??= false;
+
   /**
    * Indicates whether the variable is declared using the `final` keyword.
    */
@@ -4462,6 +5830,9 @@
     _isFinal = _value;
   }
 
+  @override
+  bool get isConst => _isConst ??= false;
+
   /**
    * Indicates whether the variable is declared using the `const` keyword.
    */
@@ -4470,20 +5841,57 @@
     _isConst = _value;
   }
 
+  @override
+  int get propagatedTypeSlot => _propagatedTypeSlot ??= 0;
+
   /**
-   * Indicates whether this variable lacks an explicit type declaration.
+   * If this variable is propagable, nonzero slot id identifying which entry in
+   * [LinkedLibrary.types] contains the propagated type for this variable.  If
+   * there is no matching entry in [LinkedLibrary.types], then this variable's
+   * propagated type is the same as its declared type.
+   *
+   * Non-propagable variables have a [propagatedTypeSlot] of zero.
    */
-  void set hasImplicitType(bool _value) {
+  void set propagatedTypeSlot(int _value) {
     assert(!_finished);
-    _hasImplicitType = _value;
+    assert(_value == null || _value >= 0);
+    _propagatedTypeSlot = _value;
   }
 
+  @override
+  int get inferredTypeSlot => _inferredTypeSlot ??= 0;
+
+  /**
+   * If this variable is inferrable, nonzero slot id identifying which entry in
+   * [LinkedLibrary.types] contains the inferred type for this variable.  If
+   * there is no matching entry in [LinkedLibrary.types], then no type was
+   * inferred for this variable, so its static type is `dynamic`.
+   */
+  void set inferredTypeSlot(int _value) {
+    assert(!_finished);
+    assert(_value == null || _value >= 0);
+    _inferredTypeSlot = _value;
+  }
+
+  UnlinkedVariableBuilder({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, EntityRefBuilder type, UnlinkedConstBuilder constExpr, bool isStatic, bool isFinal, bool isConst, int propagatedTypeSlot, int inferredTypeSlot})
+    : _name = name,
+      _nameOffset = nameOffset,
+      _documentationComment = documentationComment,
+      _type = type,
+      _constExpr = constExpr,
+      _isStatic = isStatic,
+      _isFinal = isFinal,
+      _isConst = isConst,
+      _propagatedTypeSlot = propagatedTypeSlot,
+      _inferredTypeSlot = inferredTypeSlot;
+
   fb.Offset finish(fb.Builder fbBuilder) {
     assert(!_finished);
     _finished = true;
     fb.Offset offset_name;
     fb.Offset offset_documentationComment;
     fb.Offset offset_type;
+    fb.Offset offset_constExpr;
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
@@ -4493,12 +5901,15 @@
     if (_type != null) {
       offset_type = _type.finish(fbBuilder);
     }
+    if (_constExpr != null) {
+      offset_constExpr = _constExpr.finish(fbBuilder);
+    }
     fbBuilder.startTable();
     if (offset_name != null) {
       fbBuilder.addOffset(0, offset_name);
     }
     if (_nameOffset != null && _nameOffset != 0) {
-      fbBuilder.addInt32(1, _nameOffset);
+      fbBuilder.addUint32(1, _nameOffset);
     }
     if (offset_documentationComment != null) {
       fbBuilder.addOffset(2, offset_documentationComment);
@@ -4506,35 +5917,28 @@
     if (offset_type != null) {
       fbBuilder.addOffset(3, offset_type);
     }
-    if (_isStatic == true) {
-      fbBuilder.addBool(4, true);
+    if (offset_constExpr != null) {
+      fbBuilder.addOffset(4, offset_constExpr);
     }
-    if (_isFinal == true) {
+    if (_isStatic == true) {
       fbBuilder.addBool(5, true);
     }
-    if (_isConst == true) {
+    if (_isFinal == true) {
       fbBuilder.addBool(6, true);
     }
-    if (_hasImplicitType == true) {
+    if (_isConst == true) {
       fbBuilder.addBool(7, true);
     }
+    if (_propagatedTypeSlot != null && _propagatedTypeSlot != 0) {
+      fbBuilder.addUint32(8, _propagatedTypeSlot);
+    }
+    if (_inferredTypeSlot != null && _inferredTypeSlot != 0) {
+      fbBuilder.addUint32(9, _inferredTypeSlot);
+    }
     return fbBuilder.endTable();
   }
 }
 
-UnlinkedVariableBuilder encodeUnlinkedVariable({String name, int nameOffset, UnlinkedDocumentationCommentBuilder documentationComment, UnlinkedTypeRefBuilder type, bool isStatic, bool isFinal, bool isConst, bool hasImplicitType}) {
-  UnlinkedVariableBuilder builder = new UnlinkedVariableBuilder();
-  builder.name = name;
-  builder.nameOffset = nameOffset;
-  builder.documentationComment = documentationComment;
-  builder.type = type;
-  builder.isStatic = isStatic;
-  builder.isFinal = isFinal;
-  builder.isConst = isConst;
-  builder.hasImplicitType = hasImplicitType;
-  return builder;
-}
-
 /**
  * Unlinked summary information about a top level variable, local variable, or
  * a field.
@@ -4558,10 +5962,15 @@
   UnlinkedDocumentationComment get documentationComment;
 
   /**
-   * Declared type of the variable.  Note that when strong mode is enabled, the
-   * actual type of the variable may be different due to type inference.
+   * Declared type of the variable.  Absent if the type is implicit.
    */
-  UnlinkedTypeRef get type;
+  EntityRef get type;
+
+  /**
+   * If [isConst] is true, and the variable has an initializer, the constant
+   * expression in the initializer.
+   */
+  UnlinkedConst get constExpr;
 
   /**
    * Indicates whether the variable is declared using the `static` keyword.
@@ -4583,9 +5992,22 @@
   bool get isConst;
 
   /**
-   * Indicates whether this variable lacks an explicit type declaration.
+   * If this variable is propagable, nonzero slot id identifying which entry in
+   * [LinkedLibrary.types] contains the propagated type for this variable.  If
+   * there is no matching entry in [LinkedLibrary.types], then this variable's
+   * propagated type is the same as its declared type.
+   *
+   * Non-propagable variables have a [propagatedTypeSlot] of zero.
    */
-  bool get hasImplicitType;
+  int get propagatedTypeSlot;
+
+  /**
+   * If this variable is inferrable, nonzero slot id identifying which entry in
+   * [LinkedLibrary.types] contains the inferred type for this variable.  If
+   * there is no matching entry in [LinkedLibrary.types], then no type was
+   * inferred for this variable, so its static type is `dynamic`.
+   */
+  int get inferredTypeSlot;
 }
 
 class _UnlinkedVariableReader extends fb.TableReader<_UnlinkedVariableImpl> {
@@ -4595,7 +6017,7 @@
   _UnlinkedVariableImpl createObject(fb.BufferPointer bp) => new _UnlinkedVariableImpl(bp);
 }
 
-class _UnlinkedVariableImpl implements UnlinkedVariable {
+class _UnlinkedVariableImpl extends Object with _UnlinkedVariableMixin implements UnlinkedVariable {
   final fb.BufferPointer _bp;
 
   _UnlinkedVariableImpl(this._bp);
@@ -4603,23 +6025,13 @@
   String _name;
   int _nameOffset;
   UnlinkedDocumentationComment _documentationComment;
-  UnlinkedTypeRef _type;
+  EntityRef _type;
+  UnlinkedConst _constExpr;
   bool _isStatic;
   bool _isFinal;
   bool _isConst;
-  bool _hasImplicitType;
-
-  @override
-  Map<String, Object> toMap() => {
-    "name": name,
-    "nameOffset": nameOffset,
-    "documentationComment": documentationComment,
-    "type": type,
-    "isStatic": isStatic,
-    "isFinal": isFinal,
-    "isConst": isConst,
-    "hasImplicitType": hasImplicitType,
-  };
+  int _propagatedTypeSlot;
+  int _inferredTypeSlot;
 
   @override
   String get name {
@@ -4629,7 +6041,7 @@
 
   @override
   int get nameOffset {
-    _nameOffset ??= const fb.Int32Reader().vTableGet(_bp, 1, 0);
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bp, 1, 0);
     return _nameOffset;
   }
 
@@ -4640,33 +6052,61 @@
   }
 
   @override
-  UnlinkedTypeRef get type {
-    _type ??= const _UnlinkedTypeRefReader().vTableGet(_bp, 3, null);
+  EntityRef get type {
+    _type ??= const _EntityRefReader().vTableGet(_bp, 3, null);
     return _type;
   }
 
   @override
+  UnlinkedConst get constExpr {
+    _constExpr ??= const _UnlinkedConstReader().vTableGet(_bp, 4, null);
+    return _constExpr;
+  }
+
+  @override
   bool get isStatic {
-    _isStatic ??= const fb.BoolReader().vTableGet(_bp, 4, false);
+    _isStatic ??= const fb.BoolReader().vTableGet(_bp, 5, false);
     return _isStatic;
   }
 
   @override
   bool get isFinal {
-    _isFinal ??= const fb.BoolReader().vTableGet(_bp, 5, false);
+    _isFinal ??= const fb.BoolReader().vTableGet(_bp, 6, false);
     return _isFinal;
   }
 
   @override
   bool get isConst {
-    _isConst ??= const fb.BoolReader().vTableGet(_bp, 6, false);
+    _isConst ??= const fb.BoolReader().vTableGet(_bp, 7, false);
     return _isConst;
   }
 
   @override
-  bool get hasImplicitType {
-    _hasImplicitType ??= const fb.BoolReader().vTableGet(_bp, 7, false);
-    return _hasImplicitType;
+  int get propagatedTypeSlot {
+    _propagatedTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 8, 0);
+    return _propagatedTypeSlot;
   }
+
+  @override
+  int get inferredTypeSlot {
+    _inferredTypeSlot ??= const fb.Uint32Reader().vTableGet(_bp, 9, 0);
+    return _inferredTypeSlot;
+  }
+}
+
+abstract class _UnlinkedVariableMixin implements UnlinkedVariable {
+  @override
+  Map<String, Object> toMap() => {
+    "name": name,
+    "nameOffset": nameOffset,
+    "documentationComment": documentationComment,
+    "type": type,
+    "constExpr": constExpr,
+    "isStatic": isStatic,
+    "isFinal": isFinal,
+    "isConst": isConst,
+    "propagatedTypeSlot": propagatedTypeSlot,
+    "inferredTypeSlot": inferredTypeSlot,
+  };
 }
 
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index ad4834f..1e3caad 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -6,7 +6,7 @@
 import 'package:analyzer/src/summary/name_filter.dart';
 
 /**
- * Create a [PrelinkedLibraryBuilder] corresponding to the given
+ * Create a [LinkedLibraryBuilder] corresponding to the given
  * [definingUnit], which should be the defining compilation unit for a library.
  * Compilation units referenced by the defining compilation unit via `part`
  * declarations will be retrieved using [getPart].  Public namespaces for
@@ -14,8 +14,8 @@
  * declarations (and files reachable from them via `part` and `export`
  * declarations) will be retrieved using [getImport].
  */
-PrelinkedLibraryBuilder prelink(UnlinkedUnit definingUnit,
-    GetPartCallback getPart, GetImportCallback getImport) {
+LinkedLibraryBuilder prelink(UnlinkedUnit definingUnit, GetPartCallback getPart,
+    GetImportCallback getImport) {
   return new _Prelinker(definingUnit, getPart, getImport).prelink();
 }
 
@@ -32,7 +32,7 @@
 
 /**
  * Type of the callback used by the prelinker to obtain unlinked summaries of
- * part files of the library to be prelinked.  [relaviteUri] should be
+ * part files of the library to be prelinked.  [relativeUri] should be
  * interpreted relative to the defining compilation unit of the library being
  * prelinked.
  *
@@ -41,6 +41,16 @@
 typedef UnlinkedUnit GetPartCallback(String relativeUri);
 
 /**
+ * A [_Meaning] representing a class.
+ */
+class _ClassMeaning extends _Meaning {
+  final Map<String, _Meaning> namespace;
+
+  _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace)
+      : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters);
+}
+
+/**
  * A [_Meaning] stores all the information necessary to find the declaration
  * referred to by a name in a namespace.
  */
@@ -53,7 +63,7 @@
   /**
    * The kind of entity being referred to.
    */
-  final PrelinkedReferenceKind kind;
+  final ReferenceKind kind;
 
   /**
    * Which of the dependencies of the library being prelinked contains the
@@ -70,10 +80,18 @@
   _Meaning(this.unit, this.kind, this.dependency, this.numTypeParameters);
 
   /**
-   * Encode this [_Meaning] as a [PrelinkedReference].
+ * Encode this [_Meaning] as a [LinkedExportName], using the given [name].
+ */
+  LinkedExportName encodeExportName(String name) {
+    return new LinkedExportNameBuilder(
+        name: name, dependency: dependency, unit: unit, kind: kind);
+  }
+
+/**
+   * Encode this [_Meaning] as a [LinkedReference].
    */
-  PrelinkedReferenceBuilder encode() {
-    return encodePrelinkedReference(
+  LinkedReferenceBuilder encodeReference() {
+    return new LinkedReferenceBuilder(
         unit: unit,
         kind: kind,
         dependency: dependency,
@@ -87,7 +105,7 @@
 class _PrefixMeaning extends _Meaning {
   final Map<String, _Meaning> namespace = <String, _Meaning>{};
 
-  _PrefixMeaning() : super(0, PrelinkedReferenceKind.prefix, 0, 0);
+  _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0);
 }
 
 /**
@@ -117,15 +135,17 @@
    * Names defined inside the library being prelinked.
    */
   final Map<String, _Meaning> privateNamespace = <String, _Meaning>{
-    '': new _Meaning(0, PrelinkedReferenceKind.classOrEnum, 0, 0)
+    'dynamic': new _Meaning(0, ReferenceKind.classOrEnum, 0, 0),
+    'void': new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)
   };
 
   /**
    * List of dependencies of the library being prelinked.  This will be output
-   * to [PrelinkedLibrary.dependencies].
+   * to [LinkedLibrary.dependencies].
    */
-  final List<PrelinkedDependencyBuilder> dependencies =
-      <PrelinkedDependencyBuilder>[encodePrelinkedDependency()];
+  final List<LinkedDependencyBuilder> dependencies = <LinkedDependencyBuilder>[
+    new LinkedDependencyBuilder()
+  ];
 
   /**
    * Map from the relative URI of a dependent library to the index of the
@@ -157,9 +177,9 @@
     int dependency = dependencies.length;
     uriToDependency[relativeUri] = dependency;
     List<String> unitUris = getUnitUris(relativeUri);
-    PrelinkedDependencyBuilder prelinkedDependency =
-        encodePrelinkedDependency(uri: relativeUri, parts: unitUris.sublist(1));
-    dependencies.add(prelinkedDependency);
+    LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder(
+        uri: relativeUri, parts: unitUris.sublist(1));
+    dependencies.add(linkedDependency);
 
     Map<String, _Meaning> aggregated = <String, _Meaning>{};
 
@@ -170,10 +190,19 @@
         continue;
       }
       for (UnlinkedPublicName name in importedNamespace.names) {
-        aggregated.putIfAbsent(
-            name.name,
-            () => new _Meaning(
-                unitNum, name.kind, dependency, name.numTypeParameters));
+        aggregated.putIfAbsent(name.name, () {
+          if (name.kind == ReferenceKind.classOrEnum) {
+            Map<String, _Meaning> namespace = <String, _Meaning>{};
+            name.constMembers.forEach((executable) {
+              namespace[executable.name] = new _Meaning(unitNum,
+                  executable.kind, dependency, executable.numTypeParameters);
+            });
+            return new _ClassMeaning(
+                unitNum, dependency, name.numTypeParameters, namespace);
+          }
+          return new _Meaning(
+              unitNum, name.kind, dependency, name.numTypeParameters);
+        });
       }
     }
 
@@ -185,10 +214,14 @@
    * Compute the export namespace for the library whose URI is reachable from
    * [definingUnit] via [relativeUri], by aggregating together public namespace
    * information from the library and the transitive closure of its exports.
+   *
+   * If [relativeUri] is `null` (meaning the export namespace of [definingUnit]
+   * should be computed), then names defined in [definingUnit] are ignored.
    */
   Map<String, _Meaning> computeExportNamespace(String relativeUri) {
-    Map<String, _Meaning> exportNamespace =
-        aggregatePublicNamespace(relativeUri);
+    Map<String, _Meaning> exportNamespace = relativeUri == null
+        ? <String, _Meaning>{}
+        : aggregatePublicNamespace(relativeUri);
     void chaseExports(
         NameFilter filter, String relativeUri, Set<String> seenUris) {
       if (seenUris.add(relativeUri)) {
@@ -197,17 +230,16 @@
         if (exportedNamespace != null) {
           for (UnlinkedExportPublic export in exportedNamespace.exports) {
             String exportUri = resolveUri(relativeUri, export.uri);
+            NameFilter newFilter = filter.merge(
+                new NameFilter.forUnlinkedCombinators(export.combinators));
             aggregatePublicNamespace(exportUri)
                 .forEach((String name, _Meaning meaning) {
-              if (filter.accepts(name) && !exportNamespace.containsKey(name)) {
+              if (newFilter.accepts(name) &&
+                  !exportNamespace.containsKey(name)) {
                 exportNamespace[name] = meaning;
               }
             });
-            chaseExports(
-                filter.merge(
-                    new NameFilter.forUnlinkedCombinators(export.combinators)),
-                exportUri,
-                seenUris);
+            chaseExports(newFilter, exportUri, seenUris);
           }
         }
         seenUris.remove(relativeUri);
@@ -224,32 +256,65 @@
    */
   void extractPrivateNames(UnlinkedUnit unit, int unitNum) {
     for (UnlinkedClass cls in unit.classes) {
-      privateNamespace.putIfAbsent(
-          cls.name,
-          () => new _Meaning(unitNum, PrelinkedReferenceKind.classOrEnum, 0,
-              cls.typeParameters.length));
+      privateNamespace.putIfAbsent(cls.name, () {
+        Map<String, _Meaning> namespace = <String, _Meaning>{};
+        cls.fields.forEach((field) {
+          if (field.isStatic && field.isConst) {
+            namespace[field.name] =
+                new _Meaning(unitNum, ReferenceKind.constField, 0, 0);
+          }
+        });
+        cls.executables.forEach((executable) {
+          ReferenceKind kind = null;
+          if (executable.kind == UnlinkedExecutableKind.constructor &&
+              executable.isConst) {
+            kind = ReferenceKind.constructor;
+          } else if (executable.kind ==
+                  UnlinkedExecutableKind.functionOrMethod &&
+              executable.isStatic) {
+            kind = ReferenceKind.staticMethod;
+          }
+          if (kind != null) {
+            namespace[executable.name] = new _Meaning(
+                unitNum, kind, 0, executable.typeParameters.length);
+          }
+        });
+        return new _ClassMeaning(
+            unitNum, 0, cls.typeParameters.length, namespace);
+      });
     }
     for (UnlinkedEnum enm in unit.enums) {
-      privateNamespace.putIfAbsent(
-          enm.name,
-          () =>
-              new _Meaning(unitNum, PrelinkedReferenceKind.classOrEnum, 0, 0));
+      privateNamespace.putIfAbsent(enm.name,
+          () => new _Meaning(unitNum, ReferenceKind.classOrEnum, 0, 0));
     }
     for (UnlinkedExecutable executable in unit.executables) {
       privateNamespace.putIfAbsent(
           executable.name,
-          () => new _Meaning(unitNum, PrelinkedReferenceKind.other, 0,
+          () => new _Meaning(
+              unitNum,
+              executable.kind == UnlinkedExecutableKind.functionOrMethod
+                  ? ReferenceKind.topLevelFunction
+                  : ReferenceKind.topLevelPropertyAccessor,
+              0,
               executable.typeParameters.length));
     }
     for (UnlinkedTypedef typedef in unit.typedefs) {
       privateNamespace.putIfAbsent(
           typedef.name,
-          () => new _Meaning(unitNum, PrelinkedReferenceKind.typedef, 0,
+          () => new _Meaning(unitNum, ReferenceKind.typedef, 0,
               typedef.typeParameters.length));
     }
     for (UnlinkedVariable variable in unit.variables) {
-      privateNamespace.putIfAbsent(variable.name,
-          () => new _Meaning(unitNum, PrelinkedReferenceKind.other, 0, 0));
+      privateNamespace.putIfAbsent(
+          variable.name,
+          () => new _Meaning(
+              unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
+      if (!(variable.isConst || variable.isFinal)) {
+        privateNamespace.putIfAbsent(
+            variable.name + '=',
+            () => new _Meaning(
+                unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
+      }
     }
   }
 
@@ -328,47 +393,60 @@
   }
 
   /**
-   * Produce a [PrelinkedUnit] for the given [unit], by resolving every one of
+   * Produce a [LinkedUnit] for the given [unit], by resolving every one of
    * its references.
    */
-  PrelinkedUnitBuilder linkUnit(UnlinkedUnit unit) {
+  LinkedUnitBuilder linkUnit(UnlinkedUnit unit) {
     if (unit == null) {
-      return encodePrelinkedUnit();
+      return new LinkedUnitBuilder();
     }
     Map<int, Map<String, _Meaning>> prefixNamespaces =
         <int, Map<String, _Meaning>>{};
-    List<PrelinkedReferenceBuilder> references = <PrelinkedReferenceBuilder>[];
+    List<LinkedReferenceBuilder> references = <LinkedReferenceBuilder>[];
     for (int i = 0; i < unit.references.length; i++) {
       UnlinkedReference reference = unit.references[i];
       Map<String, _Meaning> namespace;
-      if (reference.prefixReference != 0) {
+      if (reference.prefixReference == 0) {
+        namespace = privateNamespace;
+      } else {
         // Prefix references must always point backward.
         assert(reference.prefixReference < i);
         namespace = prefixNamespaces[reference.prefixReference];
+        // If in `a.length` the `a` prefix is a top-level variable or a field,
+        // then it must be the `String.length` property reference.
+        if (namespace == null && reference.name == 'length') {
+          ReferenceKind prefixKind = references[reference.prefixReference].kind;
+          if (prefixKind == ReferenceKind.topLevelPropertyAccessor ||
+              prefixKind == ReferenceKind.constField) {
+            references
+                .add(new LinkedReferenceBuilder(kind: ReferenceKind.length));
+            continue;
+          }
+        }
         // Prefix references must always point to proper prefixes.
         assert(namespace != null);
-      } else {
-        namespace = privateNamespace;
       }
       _Meaning meaning = namespace[reference.name];
       if (meaning != null) {
         if (meaning is _PrefixMeaning) {
           prefixNamespaces[i] = meaning.namespace;
+        } else if (meaning is _ClassMeaning) {
+          prefixNamespaces[i] = meaning.namespace;
         }
-        references.add(meaning.encode());
+        references.add(meaning.encodeReference());
       } else {
-        references.add(
-            encodePrelinkedReference(kind: PrelinkedReferenceKind.unresolved));
+        references
+            .add(new LinkedReferenceBuilder(kind: ReferenceKind.unresolved));
       }
     }
-    return encodePrelinkedUnit(references: references);
+    return new LinkedUnitBuilder(references: references);
   }
 
   /**
-   * Form the [PrelinkedLibrary] for the [definingUnit] that was passed to the
+   * Form the [LinkedLibrary] for the [definingUnit] that was passed to the
    * constructor.
    */
-  PrelinkedLibraryBuilder prelink() {
+  LinkedLibraryBuilder prelink() {
     // Gather up the unlinked summaries for all the compilation units in the
     // library.
     List<UnlinkedUnit> units = getUnitUris(null).map(getPartCached).toList();
@@ -382,6 +460,16 @@
       }
     }
 
+    // Fill in exported names.  This must be done before filling in prefixes
+    // defined in import declarations, because prefixes shouldn't shadow
+    // exports.
+    List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
+    computeExportNamespace(null).forEach((String name, _Meaning meaning) {
+      if (!privateNamespace.containsKey(name)) {
+        exportNames.add(meaning.encodeExportName(name));
+      }
+    });
+
     // Fill in prefixes defined in import declarations.
     for (UnlinkedImport import in units[0].imports) {
       if (import.prefixReference != 0) {
@@ -396,12 +484,14 @@
         definingUnit.imports.map(handleImport).toList();
 
     // Link each compilation unit.
-    List<PrelinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList();
+    List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList();
 
-    return encodePrelinkedLibrary(
+    return new LinkedLibraryBuilder(
         units: linkedUnits,
         dependencies: dependencies,
-        importDependencies: importDependencies);
+        importDependencies: importDependencies,
+        exportNames: exportNames,
+        numPrelinkedDependencies: dependencies.length);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
index e8751b0..1f24248 100644
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -14,7 +14,7 @@
 UnlinkedPublicNamespaceBuilder computePublicNamespace(CompilationUnit unit) {
   _PublicNamespaceVisitor visitor = new _PublicNamespaceVisitor();
   unit.accept(visitor);
-  return encodeUnlinkedPublicNamespace(
+  return new UnlinkedPublicNamespaceBuilder(
       names: visitor.names, exports: visitor.exports, parts: visitor.parts);
 }
 
@@ -26,12 +26,12 @@
 
   @override
   UnlinkedCombinatorBuilder visitHideCombinator(HideCombinator node) {
-    return encodeUnlinkedCombinator(hides: encodeNames(node.hiddenNames));
+    return new UnlinkedCombinatorBuilder(hides: encodeNames(node.hiddenNames));
   }
 
   @override
   UnlinkedCombinatorBuilder visitShowCombinator(ShowCombinator node) {
-    return encodeUnlinkedCombinator(shows: encodeNames(node.shownNames));
+    return new UnlinkedCombinatorBuilder(shows: encodeNames(node.shownNames));
   }
 }
 
@@ -43,36 +43,81 @@
 
   _PublicNamespaceVisitor();
 
-  void addNameIfPublic(
-      String name, PrelinkedReferenceKind kind, int numTypeParameters) {
+  UnlinkedPublicNameBuilder addNameIfPublic(
+      String name, ReferenceKind kind, int numTypeParameters) {
     if (isPublic(name)) {
-      names.add(encodeUnlinkedPublicName(
-          name: name, kind: kind, numTypeParameters: numTypeParameters));
+      UnlinkedPublicNameBuilder b = new UnlinkedPublicNameBuilder(
+          name: name, kind: kind, numTypeParameters: numTypeParameters);
+      names.add(b);
+      return b;
     }
+    return null;
   }
 
   bool isPublic(String name) => !name.startsWith('_');
 
   @override
   visitClassDeclaration(ClassDeclaration node) {
-    addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum,
+    UnlinkedPublicNameBuilder cls = addNameIfPublic(
+        node.name.name,
+        ReferenceKind.classOrEnum,
         node.typeParameters?.typeParameters?.length ?? 0);
+    if (cls != null) {
+      for (ClassMember member in node.members) {
+        if (member is FieldDeclaration &&
+            member.isStatic &&
+            member.fields.isConst) {
+          for (VariableDeclaration field in member.fields.variables) {
+            String name = field.name.name;
+            if (isPublic(name)) {
+              cls.constMembers.add(new UnlinkedPublicNameBuilder(
+                  name: name,
+                  kind: ReferenceKind.constField,
+                  numTypeParameters: 0));
+            }
+          }
+        }
+        if (member is MethodDeclaration &&
+            member.isStatic &&
+            !member.isGetter &&
+            !member.isSetter &&
+            !member.isOperator) {
+          String name = member.name.name;
+          if (isPublic(name)) {
+            cls.constMembers.add(new UnlinkedPublicNameBuilder(
+                name: name,
+                kind: ReferenceKind.staticMethod,
+                numTypeParameters:
+                    member.typeParameters?.typeParameters?.length ?? 0));
+          }
+        }
+        if (member is ConstructorDeclaration && member.constKeyword != null) {
+          String name = member.name != null ? member.name.name : '';
+          if (isPublic(name)) {
+            cls.constMembers.add(new UnlinkedPublicNameBuilder(
+                name: name,
+                kind: ReferenceKind.constructor,
+                numTypeParameters: 0));
+          }
+        }
+      }
+    }
   }
 
   @override
   visitClassTypeAlias(ClassTypeAlias node) {
-    addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum,
+    addNameIfPublic(node.name.name, ReferenceKind.classOrEnum,
         node.typeParameters?.typeParameters?.length ?? 0);
   }
 
   @override
   visitEnumDeclaration(EnumDeclaration node) {
-    addNameIfPublic(node.name.name, PrelinkedReferenceKind.classOrEnum, 0);
+    addNameIfPublic(node.name.name, ReferenceKind.classOrEnum, 0);
   }
 
   @override
   visitExportDirective(ExportDirective node) {
-    exports.add(encodeUnlinkedExportPublic(
+    exports.add(new UnlinkedExportPublicBuilder(
         uri: node.uri.stringValue,
         combinators: node.combinators
             .map((Combinator c) => c.accept(new _CombinatorEncoder()))
@@ -85,13 +130,17 @@
     if (node.isSetter) {
       name += '=';
     }
-    addNameIfPublic(name, PrelinkedReferenceKind.other,
+    addNameIfPublic(
+        name,
+        node.isGetter || node.isSetter
+            ? ReferenceKind.topLevelPropertyAccessor
+            : ReferenceKind.topLevelFunction,
         node.functionExpression.typeParameters?.typeParameters?.length ?? 0);
   }
 
   @override
   visitFunctionTypeAlias(FunctionTypeAlias node) {
-    addNameIfPublic(node.name.name, PrelinkedReferenceKind.typedef,
+    addNameIfPublic(node.name.name, ReferenceKind.typedef,
         node.typeParameters?.typeParameters?.length ?? 0);
   }
 
@@ -103,9 +152,9 @@
   @override
   visitVariableDeclaration(VariableDeclaration node) {
     String name = node.name.name;
-    addNameIfPublic(name, PrelinkedReferenceKind.other, 0);
+    addNameIfPublic(name, ReferenceKind.topLevelPropertyAccessor, 0);
     if (!node.isFinal && !node.isConst) {
-      addNameIfPublic('$name=', PrelinkedReferenceKind.other, 0);
+      addNameIfPublic('$name=', ReferenceKind.topLevelPropertyAccessor, 0);
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 23b103c..d70d392 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -4,40 +4,30 @@
 
 library summary_resynthesizer;
 
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/src/generated/element.dart';
+import 'dart:collection';
+
+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/element_handle.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 
 /**
- * Callback used by [SummaryResynthesizer] to obtain the prelinked summary for
- * a given URI.
- */
-typedef PrelinkedLibrary GetPrelinkedSummaryCallback(String uri);
-
-/**
- * Callback used by [SummaryResynthesizer] to obtain the unlinked summary for a
- * given URI.
- */
-typedef UnlinkedUnit GetUnlinkedSummaryCallback(String uri);
-
-/**
  * Implementation of [ElementResynthesizer] used when resynthesizing an element
  * model from summaries.
  */
-class SummaryResynthesizer extends ElementResynthesizer {
+abstract class SummaryResynthesizer extends ElementResynthesizer {
   /**
-   * Callback used to obtain the prelinked summary for a given URI.
+   * The parent [SummaryResynthesizer] which is asked to resynthesize elements
+   * and get summaries before this resynthesizer attempts to do this.
+   * Can be `null`.
    */
-  final GetPrelinkedSummaryCallback getPrelinkedSummary;
-
-  /**
-   * Callback used to obtain the unlinked summary for a given URI.
-   */
-  final GetUnlinkedSummaryCallback getUnlinkedSummary;
+  final SummaryResynthesizer parent;
 
   /**
    * Source factory used to convert URIs to [Source] objects.
@@ -56,6 +46,12 @@
   final TypeProvider typeProvider;
 
   /**
+   * Indicates whether the summary should be resynthesized assuming strong mode
+   * semantics.
+   */
+  final bool strongMode;
+
+  /**
    * Map of top level elements resynthesized from summaries.  The three map
    * keys are the first three elements of the element's location (the library
    * URI, the compilation unit URI, and the name of the top level declaration).
@@ -70,8 +66,8 @@
   final Map<String, LibraryElement> _resynthesizedLibraries =
       <String, LibraryElement>{};
 
-  SummaryResynthesizer(AnalysisContext context, this.typeProvider,
-      this.getPrelinkedSummary, this.getUnlinkedSummary, this.sourceFactory)
+  SummaryResynthesizer(this.parent, AnalysisContext context, this.typeProvider,
+      this.sourceFactory, this.strongMode)
       : super(context);
 
   /**
@@ -79,28 +75,68 @@
    */
   int get resynthesisCount => _resynthesizedLibraries.length;
 
+  /**
+   * Perform delayed finalization of the `dart:core` and `dart:async` libraries.
+   */
+  void finalizeCoreAsyncLibraries() {
+    (_resynthesizedLibraries['dart:core'] as LibraryElementImpl)
+        .createLoadLibraryFunction(typeProvider);
+    (_resynthesizedLibraries['dart:async'] as LibraryElementImpl)
+        .createLoadLibraryFunction(typeProvider);
+  }
+
   @override
   Element getElement(ElementLocation location) {
-    if (location.components.length == 1) {
-      return getLibraryElement(location.components[0]);
-    } else if (location.components.length == 3) {
-      String uri = location.components[0];
+    List<String> components = location.components;
+    String libraryUri = components[0];
+    // Ask the parent resynthesizer.
+    if (parent != null && parent._hasLibrarySummary(libraryUri)) {
+      return parent.getElement(location);
+    }
+    // Resynthesize locally.
+    if (components.length == 1) {
+      return getLibraryElement(libraryUri);
+    } else if (components.length == 3 || components.length == 4) {
       Map<String, Map<String, Element>> libraryMap =
-          _resynthesizedElements[uri];
+          _resynthesizedElements[libraryUri];
       if (libraryMap == null) {
-        getLibraryElement(uri);
-        libraryMap = _resynthesizedElements[uri];
+        getLibraryElement(libraryUri);
+        libraryMap = _resynthesizedElements[libraryUri];
         assert(libraryMap != null);
       }
-      Map<String, Element> compilationUnitElements =
-          libraryMap[location.components[1]];
+      Map<String, Element> compilationUnitElements = libraryMap[components[1]];
+      Element element;
       if (compilationUnitElements != null) {
-        Element element = compilationUnitElements[location.components[2]];
-        if (element != null) {
-          return element;
+        element = compilationUnitElements[components[2]];
+      }
+      if (element != null && components.length == 4) {
+        String name = components[3];
+        Element parentElement = element;
+        if (parentElement is ClassElement) {
+          if (name.endsWith('?')) {
+            element =
+                parentElement.getGetter(name.substring(0, name.length - 1));
+          } else if (name.endsWith('=')) {
+            element =
+                parentElement.getSetter(name.substring(0, name.length - 1));
+          } else if (name.isEmpty) {
+            element = parentElement.unnamedConstructor;
+          } else {
+            element = parentElement.getField(name) ??
+                parentElement.getMethod(name) ??
+                parentElement.getNamedConstructor(name);
+          }
+        } else {
+          // The only elements that are currently retrieved using 4-component
+          // locations are class members.
+          throw new StateError(
+              '4-element locations not supported for ${element.runtimeType}');
         }
       }
-      throw new Exception('Element not found in summary: $location');
+      if (element == null) {
+        throw new Exception('Element not found in summary: $location');
+      }
+      return element;
     } else {
       throw new UnimplementedError(location.toString());
     }
@@ -111,16 +147,19 @@
    * hasn't been resynthesized already.
    */
   LibraryElement getLibraryElement(String uri) {
+    if (parent != null && parent._hasLibrarySummary(uri)) {
+      return parent.getLibraryElement(uri);
+    }
     return _resynthesizedLibraries.putIfAbsent(uri, () {
-      PrelinkedLibrary serializedLibrary = getPrelinkedSummary(uri);
+      LinkedLibrary serializedLibrary = _getLinkedSummaryOrThrow(uri);
       List<UnlinkedUnit> serializedUnits = <UnlinkedUnit>[
-        getUnlinkedSummary(uri)
+        _getUnlinkedSummaryOrThrow(uri)
       ];
       Source librarySource = _getSource(uri);
       for (String part in serializedUnits[0].publicNamespace.parts) {
         Source partSource = sourceFactory.resolveUri(librarySource, part);
         String partAbsUri = partSource.uri.toString();
-        serializedUnits.add(getUnlinkedSummary(partAbsUri));
+        serializedUnits.add(_getUnlinkedSummaryOrThrow(partAbsUri));
       }
       _LibraryResynthesizer libraryResynthesizer = new _LibraryResynthesizer(
           this, serializedLibrary, serializedUnits, librarySource);
@@ -131,11 +170,73 @@
   }
 
   /**
+   * Return the [LinkedLibrary] for the given [uri] or `null` if it could not
+   * be found.  Caller has already checked that `parent.hasLibrarySummary(uri)`
+   * returns `false`.
+   */
+  LinkedLibrary getLinkedSummary(String uri);
+
+  /**
+   * Return the [UnlinkedUnit] for the given [uri] or `null` if it could not
+   * be found.  Caller has already checked that `parent.hasLibrarySummary(uri)`
+   * returns `false`.
+   */
+  UnlinkedUnit getUnlinkedSummary(String uri);
+
+  /**
+   * Return `true` if this resynthesizer can provide summaries of the libraries
+   * with the given [uri].  Caller has already checked that
+   * `parent.hasLibrarySummary(uri)` returns `false`.
+   */
+  bool hasLibrarySummary(String uri);
+
+  /**
+   * Return the [LinkedLibrary] for the given [uri] or throw [StateError] if it
+   * could not be found.
+   */
+  LinkedLibrary _getLinkedSummaryOrThrow(String uri) {
+    if (parent != null && parent._hasLibrarySummary(uri)) {
+      return parent._getLinkedSummaryOrThrow(uri);
+    }
+    LinkedLibrary summary = getLinkedSummary(uri);
+    if (summary != null) {
+      return summary;
+    }
+    throw new StateError('Unable to find linked summary: $uri');
+  }
+
+  /**
    * Get the [Source] object for the given [uri].
    */
   Source _getSource(String uri) {
     return _sources.putIfAbsent(uri, () => sourceFactory.forUri(uri));
   }
+
+  /**
+   * Return the [UnlinkedUnit] for the given [uri] or throw [StateError] if it
+   * could not be found.
+   */
+  UnlinkedUnit _getUnlinkedSummaryOrThrow(String uri) {
+    if (parent != null && parent._hasLibrarySummary(uri)) {
+      return parent._getUnlinkedSummaryOrThrow(uri);
+    }
+    UnlinkedUnit summary = getUnlinkedSummary(uri);
+    if (summary != null) {
+      return summary;
+    }
+    throw new StateError('Unable to find unlinked summary: $uri');
+  }
+
+  /**
+   * Return `true` if this resynthesizer can provide summaries of the libraries
+   * with the given [uri].
+   */
+  bool _hasLibrarySummary(String uri) {
+    if (parent != null && parent._hasLibrarySummary(uri)) {
+      return true;
+    }
+    return hasLibrarySummary(uri);
+  }
 }
 
 /**
@@ -149,9 +250,9 @@
   final SummaryResynthesizer summaryResynthesizer;
 
   /**
-   * Prelinked summary of the library to be resynthesized.
+   * Linked summary of the library to be resynthesized.
    */
-  final PrelinkedLibrary prelinkedLibrary;
+  final LinkedLibrary linkedLibrary;
 
   /**
    * Unlinked compilation units constituting the library to be resynthesized.
@@ -182,9 +283,9 @@
   ElementHolder unitHolder;
 
   /**
-   * The [PrelinkedUnit] from which elements are currently being resynthesized.
+   * The [LinkedUnit] from which elements are currently being resynthesized.
    */
-  PrelinkedUnit prelinkedUnit;
+  LinkedUnit linkedUnit;
 
   /**
    * The [UnlinkedUnit] from which elements are currently being resynthesized.
@@ -192,6 +293,12 @@
   UnlinkedUnit unlinkedUnit;
 
   /**
+   * Map from slot id to the corresponding [EntityRef] object for linked types
+   * (i.e. propagated and inferred types).
+   */
+  Map<int, EntityRef> linkedTypeMap;
+
+  /**
    * Map of top level elements that have been resynthesized so far.  The first
    * key is the URI of the compilation unit; the second is the name of the top
    * level element.
@@ -210,7 +317,14 @@
    */
   List<TypeParameterElement> currentTypeParameters = <TypeParameterElement>[];
 
-  _LibraryResynthesizer(this.summaryResynthesizer, this.prelinkedLibrary,
+  /**
+   * If a class is currently being resynthesized, map from field name to the
+   * corresponding field element.  This is used when resynthesizing
+   * initializing formal parameters.
+   */
+  Map<String, FieldElementImpl> fields;
+
+  _LibraryResynthesizer(this.summaryResynthesizer, this.linkedLibrary,
       this.unlinkedUnits, this.librarySource) {
     isCoreLibrary = librarySource.uri.toString() == 'dart:core';
   }
@@ -235,6 +349,7 @@
       }
       ClassElementImpl classElement = new ClassElementImpl(
           serializedClass.name, serializedClass.nameOffset);
+      classElement.abstract = serializedClass.isAbstract;
       classElement.mixinApplication = serializedClass.isMixinApplication;
       InterfaceTypeImpl correspondingType = new InterfaceTypeImpl(classElement);
       if (serializedClass.supertype != null) {
@@ -251,6 +366,10 @@
       classElement.mixins = serializedClass.mixins.map(buildType).toList();
       classElement.typeParameters = currentTypeParameters;
       ElementHolder memberHolder = new ElementHolder();
+      fields = <String, FieldElementImpl>{};
+      for (UnlinkedVariable serializedVariable in serializedClass.fields) {
+        buildVariable(serializedVariable, memberHolder);
+      }
       bool constructorFound = false;
       for (UnlinkedExecutable serializedExecutable
           in serializedClass.executables) {
@@ -267,9 +386,6 @@
             break;
         }
       }
-      for (UnlinkedVariable serializedVariable in serializedClass.fields) {
-        buildVariable(serializedVariable, memberHolder);
-      }
       if (!serializedClass.isMixinApplication) {
         if (!constructorFound) {
           // Synthesize implicit constructors.
@@ -292,6 +408,7 @@
       unitHolder.addType(classElement);
     } finally {
       currentTypeParameters = <TypeParameterElement>[];
+      fields = null;
     }
   }
 
@@ -350,7 +467,6 @@
    */
   void buildEnum(UnlinkedEnum serializedEnum) {
     assert(!isCoreLibrary);
-    // TODO(paulberry): add offset support (for this element type and others)
     ClassElementImpl classElement =
         new ClassElementImpl(serializedEnum.name, serializedEnum.nameOffset);
     classElement.enum2 = true;
@@ -413,6 +529,7 @@
         } else {
           MethodElementImpl executableElement =
               new MethodElementImpl(name, serializedExecutable.nameOffset);
+          executableElement.abstract = serializedExecutable.isAbstract;
           buildExecutableCommonParts(executableElement, serializedExecutable);
           executableElement.static = serializedExecutable.isStatic;
           holder.addMethod(executableElement);
@@ -427,6 +544,7 @@
           executableElement.static = true;
         } else {
           executableElement.static = serializedExecutable.isStatic;
+          executableElement.abstract = serializedExecutable.isAbstract;
         }
         buildExecutableCommonParts(executableElement, serializedExecutable);
         DartType type;
@@ -455,8 +573,6 @@
         } else {
           implicitVariable.setter = executableElement;
         }
-        // TODO(paulberry): do the right thing when getter and setter are in
-        // different units.
         break;
       default:
         // The only other executable type is a constructor, and that is handled
@@ -481,18 +597,21 @@
     }
     executableElement.parameters =
         serializedExecutable.parameters.map(buildParameter).toList();
-    if (serializedExecutable.returnType != null) {
-      executableElement.returnType = buildType(serializedExecutable.returnType);
-    } else if (serializedExecutable.kind ==
-        UnlinkedExecutableKind.constructor) {
-      // Return type was set by the caller.
+    if (serializedExecutable.kind == UnlinkedExecutableKind.constructor) {
+      // Caller handles setting the return type.
+      assert(serializedExecutable.returnType == null);
     } else {
-      executableElement.returnType = VoidTypeImpl.instance;
+      bool isSetter =
+          serializedExecutable.kind == UnlinkedExecutableKind.setter;
+      executableElement.returnType =
+          buildLinkedType(serializedExecutable.inferredReturnTypeSlot) ??
+              buildType(serializedExecutable.returnType,
+                  defaultVoid: isSetter && summaryResynthesizer.strongMode);
+      executableElement.hasImplicitReturnType =
+          serializedExecutable.returnType == null;
     }
     executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
         executableElement, null, oldTypeArguments, false);
-    executableElement.hasImplicitReturnType =
-        serializedExecutable.hasImplicitReturnType;
     executableElement.external = serializedExecutable.isExternal;
     currentTypeParameters.removeRange(
         oldTypeParametersLength, currentTypeParameters.length);
@@ -523,6 +642,62 @@
   }
 
   /**
+   * Build an [ElementHandle] referring to the entity referred to by the given
+   * [exportName].
+   */
+  ElementHandle buildExportName(LinkedExportName exportName) {
+    String name = exportName.name;
+    if (exportName.kind == ReferenceKind.topLevelPropertyAccessor &&
+        !name.endsWith('=')) {
+      name += '?';
+    }
+    ElementLocationImpl location = getReferencedLocation(
+        linkedLibrary.dependencies[exportName.dependency],
+        exportName.unit,
+        name);
+    switch (exportName.kind) {
+      case ReferenceKind.classOrEnum:
+        return new ClassElementHandle(summaryResynthesizer, location);
+      case ReferenceKind.typedef:
+        return new FunctionTypeAliasElementHandle(
+            summaryResynthesizer, location);
+      case ReferenceKind.topLevelFunction:
+        return new FunctionElementHandle(summaryResynthesizer, location);
+      case ReferenceKind.topLevelPropertyAccessor:
+        return new PropertyAccessorElementHandle(
+            summaryResynthesizer, location);
+      case ReferenceKind.constructor:
+      case ReferenceKind.constField:
+      case ReferenceKind.staticMethod:
+      case ReferenceKind.length:
+      case ReferenceKind.prefix:
+      case ReferenceKind.unresolved:
+        // 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}');
+    }
+  }
+
+  /**
+   * Build the export namespace for the library by aggregating together its
+   * [publicNamespace] and [exportNames].
+   */
+  Namespace buildExportNamespace(
+      Namespace publicNamespace, List<LinkedExportName> exportNames) {
+    HashMap<String, Element> definedNames = new HashMap<String, Element>();
+    // Start by populating all the public names from [publicNamespace].
+    publicNamespace.definedNames.forEach((String name, Element element) {
+      definedNames[name] = element;
+    });
+    // Add all the names from [exportNames].
+    for (LinkedExportName exportName in exportNames) {
+      definedNames.putIfAbsent(
+          exportName.name, () => buildExportName(exportName));
+    }
+    return new Namespace(definedNames);
+  }
+
+  /**
    * Resynthesize a [FieldElement].
    */
   FieldElement buildField(UnlinkedVariable serializedField) {
@@ -618,13 +793,10 @@
    */
   ImportElement buildImport(UnlinkedImport serializedImport, int dependency) {
     bool isSynthetic = serializedImport.isImplicit;
-    // TODO(paulberry): it seems problematic for the offset to be 0 for
-    // non-synthetic imports, since it is used to disambiguate location.
     ImportElementImpl importElement =
         new ImportElementImpl(isSynthetic ? -1 : serializedImport.offset);
     String absoluteUri = summaryResynthesizer.sourceFactory
-        .resolveUri(
-            librarySource, prelinkedLibrary.dependencies[dependency].uri)
+        .resolveUri(librarySource, linkedLibrary.dependencies[dependency].uri)
         .uri
         .toString();
     importElement.importedLibrary = new LibraryElementHandle(
@@ -636,7 +808,9 @@
       importElement.uri = serializedImport.uri;
       importElement.uriOffset = serializedImport.uriOffset;
       importElement.uriEnd = serializedImport.uriEnd;
+      importElement.deferred = serializedImport.isDeferred;
     }
+    importElement.prefixOffset = serializedImport.prefixOffset;
     if (serializedImport.prefixReference != 0) {
       UnlinkedReference serializedPrefix =
           unlinkedUnits[0].references[serializedImport.prefixReference];
@@ -653,36 +827,35 @@
    */
   LibraryElement buildLibrary() {
     bool hasName = unlinkedUnits[0].libraryName.isNotEmpty;
-    LibraryElementImpl libraryElement = new LibraryElementImpl(
+    LibraryElementImpl library = new LibraryElementImpl(
         summaryResynthesizer.context,
         unlinkedUnits[0].libraryName,
         hasName ? unlinkedUnits[0].libraryNameOffset : -1,
         unlinkedUnits[0].libraryNameLength);
-    buildDocumentation(
-        libraryElement, unlinkedUnits[0].libraryDocumentationComment);
+    buildDocumentation(library, unlinkedUnits[0].libraryDocumentationComment);
     CompilationUnitElementImpl definingCompilationUnit =
         new CompilationUnitElementImpl(librarySource.shortName);
-    libraryElement.definingCompilationUnit = definingCompilationUnit;
+    library.definingCompilationUnit = definingCompilationUnit;
     definingCompilationUnit.source = librarySource;
     definingCompilationUnit.librarySource = librarySource;
     List<CompilationUnitElement> parts = <CompilationUnitElement>[];
     UnlinkedUnit unlinkedDefiningUnit = unlinkedUnits[0];
     assert(unlinkedDefiningUnit.publicNamespace.parts.length + 1 ==
-        prelinkedLibrary.units.length);
-    for (int i = 1; i < prelinkedLibrary.units.length; i++) {
+        linkedLibrary.units.length);
+    for (int i = 1; i < linkedLibrary.units.length; i++) {
       CompilationUnitElementImpl part = buildPart(
           unlinkedDefiningUnit.publicNamespace.parts[i - 1],
           unlinkedDefiningUnit.parts[i - 1],
           unlinkedUnits[i]);
       parts.add(part);
     }
-    libraryElement.parts = parts;
+    library.parts = parts;
     List<ImportElement> imports = <ImportElement>[];
     for (int i = 0; i < unlinkedDefiningUnit.imports.length; i++) {
       imports.add(buildImport(unlinkedDefiningUnit.imports[i],
-          prelinkedLibrary.importDependencies[i]));
+          linkedLibrary.importDependencies[i]));
     }
-    libraryElement.imports = imports;
+    library.imports = imports;
     List<ExportElement> exports = <ExportElement>[];
     assert(unlinkedDefiningUnit.exports.length ==
         unlinkedDefiningUnit.publicNamespace.exports.length);
@@ -690,40 +863,75 @@
       exports.add(buildExport(unlinkedDefiningUnit.publicNamespace.exports[i],
           unlinkedDefiningUnit.exports[i]));
     }
-    libraryElement.exports = exports;
+    library.exports = exports;
     populateUnit(definingCompilationUnit, 0);
     for (int i = 0; i < parts.length; i++) {
       populateUnit(parts[i], i + 1);
     }
+    BuildLibraryElementUtils.patchTopLevelAccessors(library);
+    // Update delayed Object class references.
     if (isCoreLibrary) {
-      ClassElement objectElement = libraryElement.getType('Object');
+      ClassElement objectElement = library.getType('Object');
       assert(objectElement != null);
       for (ClassElementImpl classElement in delayedObjectSubclasses) {
         classElement.supertype = objectElement.type;
       }
     }
     // Compute namespaces.
-    libraryElement.publicNamespace =
-        new NamespaceBuilder().createPublicNamespaceForLibrary(libraryElement);
-    // TODO(paulberry): compute the export namespace from prelinked data, so
-    // that exported libraries won't be unnecessarily resynthesized.
-    libraryElement.exportNamespace =
-        new NamespaceBuilder().createExportNamespaceForLibrary(libraryElement);
-    // Find the entry point.
-    libraryElement.entryPoint =
-        libraryElement.exportNamespace.definedNames.values.firstWhere(
-            (element) => element is FunctionElement && element.isEntryPoint,
-            orElse: () => null);
+    library.publicNamespace =
+        new NamespaceBuilder().createPublicNamespaceForLibrary(library);
+    library.exportNamespace = buildExportNamespace(
+        library.publicNamespace, linkedLibrary.exportNames);
+    // Find the entry point.  Note: we can't use element.isEntryPoint because
+    // that will trigger resynthesis of exported libraries.
+    Element entryPoint =
+        library.exportNamespace.get(FunctionElement.MAIN_FUNCTION_NAME);
+    if (entryPoint is FunctionElement) {
+      library.entryPoint = entryPoint;
+    }
+    // Create the synthetic element for `loadLibrary`.
+    // Until the client received dart:core and dart:async, we cannot do this,
+    // because the TypeProvider is not fully initialized. So, it is up to the
+    // Dart SDK client to initialize TypeProvider and finish the dart:core and
+    // dart:async libraries creation.
+    if (library.name != 'dart.core' && library.name != 'dart.async') {
+      library.createLoadLibraryFunction(summaryResynthesizer.typeProvider);
+    }
     // Done.
-    return libraryElement;
+    return library;
+  }
+
+  /**
+   * Build the appropriate [DartType] object corresponding to a slot id in the
+   * [LinkedUnit.types] table.
+   */
+  DartType buildLinkedType(int slot) {
+    if (slot == 0) {
+      // A slot id of 0 means there is no [DartType] object to build.
+      return null;
+    }
+    EntityRef type = linkedTypeMap[slot];
+    if (type == null) {
+      // A missing entry in [LinkedUnit.types] means there is no [DartType]
+      // stored in this slot.
+      return null;
+    }
+    return buildType(type);
   }
 
   /**
    * Resynthesize a [ParameterElement].
    */
   ParameterElement buildParameter(UnlinkedParam serializedParameter) {
-    ParameterElementImpl parameterElement = new ParameterElementImpl(
-        serializedParameter.name, serializedParameter.nameOffset);
+    ParameterElementImpl parameterElement;
+    if (serializedParameter.isInitializingFormal) {
+      parameterElement = new FieldFormalParameterElementImpl.forNameAndOffset(
+          serializedParameter.name, serializedParameter.nameOffset)
+        ..field = fields[serializedParameter.name];
+    } else {
+      parameterElement = new ParameterElementImpl(
+          serializedParameter.name, serializedParameter.nameOffset);
+    }
     if (serializedParameter.isFunctionTyped) {
       FunctionElementImpl parameterTypeElement =
           new FunctionElementImpl('', -1);
@@ -732,16 +940,21 @@
           serializedParameter.parameters.map(buildParameter).toList();
       parameterTypeElement.enclosingElement = parameterElement;
       parameterTypeElement.shareParameters(parameterElement.parameters);
-      if (serializedParameter.type != null) {
-        parameterTypeElement.returnType = buildType(serializedParameter.type);
-      } else {
-        parameterTypeElement.returnType = VoidTypeImpl.instance;
-      }
+      parameterTypeElement.returnType = buildType(serializedParameter.type);
       parameterElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
           parameterTypeElement, null, currentTypeArguments, false);
     } else {
-      parameterElement.type = buildType(serializedParameter.type);
-      parameterElement.hasImplicitType = serializedParameter.hasImplicitType;
+      if (serializedParameter.isInitializingFormal &&
+          serializedParameter.type == null) {
+        // The type is inherited from the matching field.
+        parameterElement.type = fields[serializedParameter.name]?.type ??
+            summaryResynthesizer.typeProvider.dynamicType;
+      } else {
+        parameterElement.type =
+            buildLinkedType(serializedParameter.inferredTypeSlot) ??
+                buildType(serializedParameter.type);
+      }
+      parameterElement.hasImplicitType = serializedParameter.type == null;
     }
     switch (serializedParameter.kind) {
       case UnlinkedParamKind.named:
@@ -776,55 +989,47 @@
   }
 
   /**
-   * Build a [DartType] object based on an [UnlinkedTypeRef].  This [DartType]
+   * Build a [DartType] object based on a [EntityRef].  This [DartType]
    * may refer to elements in other libraries than the library being
    * deserialized, so handles are used to avoid having to deserialize other
    * libraries in the process.
    */
-  DartType buildType(UnlinkedTypeRef type) {
+  DartType buildType(EntityRef type, {bool defaultVoid: false}) {
+    if (type == null) {
+      if (defaultVoid) {
+        return VoidTypeImpl.instance;
+      } else {
+        return summaryResynthesizer.typeProvider.dynamicType;
+      }
+    }
     if (type.paramReference != 0) {
       // TODO(paulberry): make this work for generic methods.
       return currentTypeParameters[
-              currentTypeParameters.length - type.paramReference]
-          .type;
+          currentTypeParameters.length - type.paramReference].type;
     } else {
-      // TODO(paulberry): handle references to things other than classes (note:
-      // this should only occur in the case of erroneous code).
-      // TODO(paulberry): test reference to something inside a part.
-      // TODO(paulberry): test reference to something inside a part of the
-      // current lib.
-      UnlinkedReference reference = unlinkedUnit.references[type.reference];
-      PrelinkedReference referenceResolution =
-          prelinkedUnit.references[type.reference];
-      String referencedLibraryUri;
-      String partUri;
-      if (referenceResolution.dependency != 0) {
-        PrelinkedDependency dependency =
-            prelinkedLibrary.dependencies[referenceResolution.dependency];
-        Source referencedLibrarySource = summaryResynthesizer.sourceFactory
-            .resolveUri(librarySource, dependency.uri);
-        referencedLibraryUri = referencedLibrarySource.uri.toString();
-        // TODO(paulberry): consider changing Location format so that this is
-        // not necessary (2nd string in location should just be the unit
-        // number).
-        if (referenceResolution.unit != 0) {
-          UnlinkedUnit referencedLibraryDefiningUnit =
-              summaryResynthesizer.getUnlinkedSummary(referencedLibraryUri);
-          String uri = referencedLibraryDefiningUnit.publicNamespace.parts[
-              referenceResolution.unit - 1];
-          Source partSource = summaryResynthesizer.sourceFactory
-              .resolveUri(referencedLibrarySource, uri);
-          partUri = partSource.uri.toString();
-        } else {
-          partUri = referencedLibraryUri;
-        }
-      } else if (referenceResolution.kind ==
-          PrelinkedReferenceKind.unresolved) {
-        return summaryResynthesizer.typeProvider.undefinedType;
-      } else if (reference.name.isEmpty) {
-        return summaryResynthesizer.typeProvider.dynamicType;
+      LinkedReference referenceResolution =
+          linkedUnit.references[type.reference];
+      String name;
+      if (type.reference < unlinkedUnit.references.length) {
+        name = unlinkedUnit.references[type.reference].name;
       } else {
-        referencedLibraryUri = librarySource.uri.toString();
+        name = referenceResolution.name;
+      }
+      ElementLocationImpl location;
+      if (referenceResolution.dependency != 0) {
+        location = getReferencedLocation(
+            linkedLibrary.dependencies[referenceResolution.dependency],
+            referenceResolution.unit,
+            name);
+      } else if (referenceResolution.kind == ReferenceKind.unresolved) {
+        return summaryResynthesizer.typeProvider.undefinedType;
+      } else if (name == 'dynamic') {
+        return summaryResynthesizer.typeProvider.dynamicType;
+      } else if (name == 'void') {
+        return VoidTypeImpl.instance;
+      } else {
+        String referencedLibraryUri = librarySource.uri.toString();
+        String partUri;
         if (referenceResolution.unit != 0) {
           String uri = unlinkedUnits[0].publicNamespace.parts[
               referenceResolution.unit - 1];
@@ -834,9 +1039,9 @@
         } else {
           partUri = referencedLibraryUri;
         }
+        location = new ElementLocationImpl.con3(
+            <String>[referencedLibraryUri, partUri, name]);
       }
-      ElementLocationImpl location = new ElementLocationImpl.con3(
-          <String>[referencedLibraryUri, partUri, reference.name]);
       List<DartType> typeArguments = const <DartType>[];
       if (referenceResolution.numTypeParameters != 0) {
         typeArguments = <DartType>[];
@@ -849,16 +1054,16 @@
         }
       }
       switch (referenceResolution.kind) {
-        case PrelinkedReferenceKind.classOrEnum:
+        case ReferenceKind.classOrEnum:
           return new InterfaceTypeImpl.elementWithNameAndArgs(
               new ClassElementHandle(summaryResynthesizer, location),
-              reference.name,
+              name,
               typeArguments);
-        case PrelinkedReferenceKind.typedef:
+        case ReferenceKind.typedef:
           return new FunctionTypeImpl.elementWithNameAndArgs(
               new FunctionTypeAliasElementHandle(
                   summaryResynthesizer, location),
-              reference.name,
+              name,
               typeArguments,
               typeArguments.isNotEmpty);
         default:
@@ -886,12 +1091,8 @@
               serializedTypedef.name, serializedTypedef.nameOffset);
       functionTypeAliasElement.parameters =
           serializedTypedef.parameters.map(buildParameter).toList();
-      if (serializedTypedef.returnType != null) {
-        functionTypeAliasElement.returnType =
-            buildType(serializedTypedef.returnType);
-      } else {
-        functionTypeAliasElement.returnType = VoidTypeImpl.instance;
-      }
+      functionTypeAliasElement.returnType =
+          buildType(serializedTypedef.returnType);
       functionTypeAliasElement.type =
           new FunctionTypeImpl.forTypedef(functionTypeAliasElement);
       functionTypeAliasElement.typeParameters = currentTypeParameters;
@@ -938,6 +1139,7 @@
       element.static = serializedVariable.isStatic;
       holder.addField(element);
       buildImplicitAccessors(element, holder);
+      fields[element.name] = element;
     }
   }
 
@@ -946,9 +1148,13 @@
    */
   void buildVariableCommonParts(PropertyInducingElementImpl element,
       UnlinkedVariable serializedVariable) {
-    element.type = buildType(serializedVariable.type);
+    element.type = buildLinkedType(serializedVariable.inferredTypeSlot) ??
+        buildType(serializedVariable.type);
     element.const3 = serializedVariable.isConst;
-    element.hasImplicitType = serializedVariable.hasImplicitType;
+    element.final2 = serializedVariable.isFinal;
+    element.hasImplicitType = serializedVariable.type == null;
+    element.propagatedType =
+        buildLinkedType(serializedVariable.propagatedTypeSlot);
     buildDocumentation(element, serializedVariable.documentationComment);
   }
 
@@ -963,12 +1169,44 @@
   }
 
   /**
+   * Build an [ElementLocationImpl] for the entity in the given [unit] of the
+   * given [dependency], having the given [name].
+   */
+  ElementLocationImpl getReferencedLocation(
+      LinkedDependency dependency, int unit, String name) {
+    Source referencedLibrarySource = summaryResynthesizer.sourceFactory
+        .resolveUri(librarySource, dependency.uri);
+    String referencedLibraryUri = referencedLibrarySource.uri.toString();
+    // TODO(paulberry): consider changing Location format so that this is
+    // not necessary (2nd string in location should just be the unit
+    // number).
+    String partUri;
+    if (unit != 0) {
+      UnlinkedUnit referencedLibraryDefiningUnit =
+          summaryResynthesizer._getUnlinkedSummaryOrThrow(referencedLibraryUri);
+      String uri =
+          referencedLibraryDefiningUnit.publicNamespace.parts[unit - 1];
+      Source partSource = summaryResynthesizer.sourceFactory
+          .resolveUri(referencedLibrarySource, uri);
+      partUri = partSource.uri.toString();
+    } else {
+      partUri = referencedLibraryUri;
+    }
+    return new ElementLocationImpl.con3(
+        <String>[referencedLibraryUri, partUri, name]);
+  }
+
+  /**
    * Populate a [CompilationUnitElement] by deserializing all the elements
    * contained in it.
    */
   void populateUnit(CompilationUnitElementImpl unit, int unitNum) {
-    prelinkedUnit = prelinkedLibrary.units[unitNum];
+    linkedUnit = linkedLibrary.units[unitNum];
     unlinkedUnit = unlinkedUnits[unitNum];
+    linkedTypeMap = <int, EntityRef>{};
+    for (EntityRef t in linkedUnit.types) {
+      linkedTypeMap[t.slot] = t;
+    }
     unitHolder = new ElementHolder();
     unlinkedUnit.classes.forEach(buildClass);
     unlinkedUnit.enums.forEach(buildEnum);
@@ -998,9 +1236,16 @@
     for (FunctionTypeAliasElement typeAlias in unit.functionTypeAliases) {
       elementMap[typeAlias.name] = typeAlias;
     }
+    for (FunctionElement function in unit.functions) {
+      elementMap[function.name] = function;
+    }
+    for (PropertyAccessorElementImpl accessor in unit.accessors) {
+      elementMap[accessor.identifier] = accessor;
+    }
     resummarizedElements[absoluteUri] = elementMap;
     unitHolder = null;
-    prelinkedUnit = null;
+    linkedUnit = null;
     unlinkedUnit = null;
+    linkedTypeMap = null;
   }
 }
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
new file mode 100644
index 0000000..c43a9b9
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -0,0 +1,884 @@
+// 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 serialization.summarize_ast;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/public_namespace_computer.dart';
+import 'package:analyzer/src/summary/summarize_const_expr.dart';
+
+/**
+ * Serialize all the declarations in [compilationUnit] to an unlinked summary.
+ */
+UnlinkedUnitBuilder serializeAstUnlinked(CompilationUnit compilationUnit) {
+  return new _SummarizeAstVisitor().serializeCompilationUnit(compilationUnit);
+}
+
+/**
+ * Instances of this class keep track of intermediate state during
+ * serialization of a single constant [Expression].
+ */
+class _ConstExprSerializer extends AbstractConstExprSerializer {
+  final _SummarizeAstVisitor visitor;
+
+  _ConstExprSerializer(this.visitor);
+
+  @override
+  EntityRefBuilder serializeConstructorName(ConstructorName constructor) {
+    EntityRefBuilder typeBuilder = serializeType(constructor.type);
+    if (constructor.name == null) {
+      return typeBuilder;
+    } else {
+      String name = constructor.name.name;
+      int nameRef = visitor.serializeReference(typeBuilder.reference, name);
+      return new EntityRefBuilder(reference: nameRef);
+    }
+  }
+
+  EntityRefBuilder serializeIdentifier(Identifier identifier) {
+    EntityRefBuilder b = new EntityRefBuilder();
+    if (identifier is SimpleIdentifier) {
+      b.reference = visitor.serializeReference(null, identifier.name);
+    } else if (identifier is PrefixedIdentifier) {
+      int prefix = visitor.serializeReference(null, identifier.prefix.name);
+      b.reference =
+          visitor.serializeReference(prefix, identifier.identifier.name);
+    } else {
+      throw new StateError(
+          'Unexpected identifier type: ${identifier.runtimeType}');
+    }
+    return b;
+  }
+
+  @override
+  EntityRefBuilder serializePropertyAccess(PropertyAccess access) {
+    Expression target = access.target;
+    if (target is Identifier) {
+      EntityRefBuilder targetRef = serializeIdentifier(target);
+      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}');
+    }
+  }
+
+  @override
+  EntityRefBuilder serializeType(TypeName node) {
+    return visitor.serializeTypeName(node);
+  }
+}
+
+/**
+ * An [_OtherScopedEntity] is a [_ScopedEntity] that does not refer to a type
+ * parameter.  Since we don't need to track any special information about these
+ * types of scoped entities, it is a singleton class.
+ */
+class _OtherScopedEntity extends _ScopedEntity {
+  static final _OtherScopedEntity _instance = new _OtherScopedEntity._();
+
+  factory _OtherScopedEntity() => _instance;
+
+  _OtherScopedEntity._();
+}
+
+/**
+ * A [_Scope] represents a set of name/value pairs defined locally within a
+ * limited span of a compilation unit.  (Note that the spec also uses the term
+ * "scope" to refer to the set of names defined at top level within a
+ * compilation unit, but we do not use [_Scope] for that purpose).
+ */
+class _Scope {
+  /**
+   * Names defined in this scope, and their meanings.
+   */
+  Map<String, _ScopedEntity> _definedNames = <String, _ScopedEntity>{};
+
+  /**
+   * Look up the meaning associated with the given [name], and return it.  If
+   * [name] is not defined in this scope, return `null`.
+   */
+  _ScopedEntity operator [](String name) => _definedNames[name];
+
+  /**
+   * Let the given [name] refer to [entity] within this scope.
+   */
+  void operator []=(String name, _ScopedEntity entity) {
+    _definedNames[name] = entity;
+  }
+}
+
+/**
+ * Base class for entities that can live inside a scope.
+ */
+abstract class _ScopedEntity {}
+
+/**
+ * A [_ScopedTypeParameter] is a [_ScopedEntity] that refers to a type
+ * parameter of a class, typedef, or executable.
+ */
+class _ScopedTypeParameter extends _ScopedEntity {
+  /**
+   * Index of the type parameter within this scope.  Since summaries use De
+   * Bruijn indices to refer to type parameters, which count upwards from the
+   * innermost bound name, the last type parameter in the scope has an index of
+   * 1, and each preceding type parameter has the next higher index.
+   */
+  final int index;
+
+  _ScopedTypeParameter(this.index);
+}
+
+/**
+ * Visitor used to create a summary from an AST.
+ */
+class _SummarizeAstVisitor extends SimpleAstVisitor {
+  /**
+   * List of objects which should be written to [UnlinkedUnit.classes].
+   */
+  final List<UnlinkedClassBuilder> classes = <UnlinkedClassBuilder>[];
+
+  /**
+   * List of objects which should be written to [UnlinkedUnit.enums].
+   */
+  final List<UnlinkedEnumBuilder> enums = <UnlinkedEnumBuilder>[];
+
+  /**
+   * List of objects which should be written to [UnlinkedUnit.executables]
+   * or [UnlinkedClass.executables].
+   */
+  List<UnlinkedExecutableBuilder> executables = <UnlinkedExecutableBuilder>[];
+
+  /**
+   * List of objects which should be written to [UnlinkedUnit.exports].
+   */
+  final List<UnlinkedExportNonPublicBuilder> exports =
+      <UnlinkedExportNonPublicBuilder>[];
+
+  /**
+   * List of objects which should be written to [UnlinkedUnit.parts].
+   */
+  final List<UnlinkedPartBuilder> parts = <UnlinkedPartBuilder>[];
+
+  /**
+   * List of objects which should be written to [UnlinkedUnit.typedefs].
+   */
+  final List<UnlinkedTypedefBuilder> typedefs = <UnlinkedTypedefBuilder>[];
+
+  /**
+   * List of objects which should be written to [UnlinkedUnit.variables] or
+   * [UnlinkedClass.fields].
+   */
+  List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
+
+  /**
+   * The unlinked portion of the "imports table".  This is the list of objects
+   * which should be written to [UnlinkedUnit.imports].
+   */
+  final List<UnlinkedImportBuilder> unlinkedImports = <UnlinkedImportBuilder>[];
+
+  /**
+   * The unlinked portion of the "references table".  This is the list of
+   * objects which should be written to [UnlinkedUnit.references].
+   */
+  final List<UnlinkedReferenceBuilder> unlinkedReferences =
+      <UnlinkedReferenceBuilder>[new UnlinkedReferenceBuilder()];
+
+  /**
+   * Map associating names used as prefixes in this compilation unit with their
+   * associated indices into [UnlinkedUnit.references].
+   */
+  final Map<String, int> prefixIndices = <String, int>{};
+
+  /**
+   * List of [_Scope]s currently in effect.  This is used to resolve type names
+   * to type parameters within classes, typedefs, and executables.
+   */
+  final List<_Scope> scopes = <_Scope>[];
+
+  /**
+   * True if 'dart:core' has been explicitly imported.
+   */
+  bool hasCoreBeenImported = false;
+
+  /**
+   * Names referenced by this compilation unit.  Structured as a map from
+   * prefix index to (map from name to reference table index), where "prefix
+   * index" means the index into [UnlinkedUnit.references] of the prefix (or
+   * `null` if there is no prefix), and "reference table index" means the index
+   * into [UnlinkedUnit.references] for the name itself.
+   */
+  final Map<int, Map<String, int>> nameToReference = <int, Map<String, int>>{};
+
+  /**
+   * If the library has a library directive, the library name derived from it.
+   * Otherwise `null`.
+   */
+  String libraryName;
+
+  /**
+   * If the library has a library directive, the offset of the library name.
+   * Otherwise `null`.
+   */
+  int libraryNameOffset;
+
+  /**
+   * If the library has a library directive, the length of the library name, as
+   * it appears in the source file.  Otherwise `null`.
+   */
+  int libraryNameLength;
+
+  /**
+   * If the library has a library directive, the documentation comment for it
+   * (if any).  Otherwise `null`.
+   */
+  UnlinkedDocumentationCommentBuilder libraryDocumentationComment;
+
+  /**
+   * The number of slot ids which have been assigned to this compilation unit.
+   */
+  int numSlots = 0;
+
+  /**
+   * Create a slot id for storing a propagated or inferred type.
+   */
+  int assignTypeSlot() => ++numSlots;
+
+  /**
+   * Build a [_Scope] object containing the names defined within the body of a
+   * class declaration.
+   */
+  _Scope buildClassMemberScope(NodeList<ClassMember> members) {
+    _Scope scope = new _Scope();
+    for (ClassMember member in members) {
+      // TODO(paulbery): consider replacing these if-tests with dynamic method
+      // dispatch.
+      if (member is MethodDeclaration) {
+        if (member.isSetter || member.isOperator) {
+          // We don't have to handle setters or operators because the only
+          // thing we look up is type names.
+        } else {
+          scope[member.name.name] = new _OtherScopedEntity();
+        }
+      } else if (member is FieldDeclaration) {
+        for (VariableDeclaration field in member.fields.variables) {
+          // A field declaration introduces two names, one with a trailing `=`.
+          // We don't have to worry about the one with a trailing `=` because
+          // the only thing we look up is type names.
+          scope[field.name.name] = new _OtherScopedEntity();
+        }
+      }
+    }
+    return scope;
+  }
+
+  /**
+   * Serialize a [ClassDeclaration] or [ClassTypeAlias] into an [UnlinkedClass]
+   * and store the result in [classes].
+   */
+  void serializeClass(
+      Token abstractKeyword,
+      String name,
+      int nameOffset,
+      TypeParameterList typeParameters,
+      TypeName superclass,
+      WithClause withClause,
+      ImplementsClause implementsClause,
+      NodeList<ClassMember> members,
+      bool isMixinApplication,
+      Comment documentationComment) {
+    int oldScopesLength = scopes.length;
+    List<UnlinkedExecutableBuilder> oldExecutables = executables;
+    executables = <UnlinkedExecutableBuilder>[];
+    List<UnlinkedVariableBuilder> oldVariables = variables;
+    variables = <UnlinkedVariableBuilder>[];
+    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+    scopes.add(typeParameterScope);
+    UnlinkedClassBuilder b = new UnlinkedClassBuilder();
+    b.name = name;
+    b.nameOffset = nameOffset;
+    b.isMixinApplication = isMixinApplication;
+    b.typeParameters =
+        serializeTypeParameters(typeParameters, typeParameterScope);
+    if (superclass != null) {
+      b.supertype = serializeTypeName(superclass);
+    }
+    if (withClause != null) {
+      b.mixins = withClause.mixinTypes.map(serializeTypeName).toList();
+    }
+    if (implementsClause != null) {
+      b.interfaces =
+          implementsClause.interfaces.map(serializeTypeName).toList();
+    }
+    if (members != null) {
+      scopes.add(buildClassMemberScope(members));
+      for (ClassMember member in members) {
+        member.accept(this);
+      }
+      scopes.removeLast();
+    }
+    b.executables = executables;
+    b.fields = variables;
+    b.isAbstract = abstractKeyword != null;
+    b.documentationComment = serializeDocumentation(documentationComment);
+    classes.add(b);
+    scopes.removeLast();
+    assert(scopes.length == oldScopesLength);
+    executables = oldExecutables;
+    variables = oldVariables;
+  }
+
+  /**
+   * Serialize a [Combinator] into an [UnlinkedCombinator].
+   */
+  UnlinkedCombinatorBuilder serializeCombinator(Combinator combinator) {
+    UnlinkedCombinatorBuilder b = new UnlinkedCombinatorBuilder();
+    if (combinator is ShowCombinator) {
+      b.shows =
+          combinator.shownNames.map((SimpleIdentifier id) => id.name).toList();
+    } else if (combinator is HideCombinator) {
+      b.hides =
+          combinator.hiddenNames.map((SimpleIdentifier id) => id.name).toList();
+    } else {
+      throw new StateError(
+          'Unexpected combinator type: ${combinator.runtimeType}');
+    }
+    return b;
+  }
+
+  /**
+   * Main entry point for serializing an AST.
+   */
+  UnlinkedUnitBuilder serializeCompilationUnit(
+      CompilationUnit compilationUnit) {
+    compilationUnit.directives.accept(this);
+    if (!hasCoreBeenImported) {
+      unlinkedImports.add(new UnlinkedImportBuilder(isImplicit: true));
+    }
+    compilationUnit.declarations.accept(this);
+    UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
+    b.libraryName = libraryName;
+    b.libraryNameOffset = libraryNameOffset;
+    b.libraryNameLength = libraryNameLength;
+    b.libraryDocumentationComment = libraryDocumentationComment;
+    b.classes = classes;
+    b.enums = enums;
+    b.executables = executables;
+    b.exports = exports;
+    b.imports = unlinkedImports;
+    b.parts = parts;
+    b.references = unlinkedReferences;
+    b.typedefs = typedefs;
+    b.variables = variables;
+    b.publicNamespace = computePublicNamespace(compilationUnit);
+    return b;
+  }
+
+  /**
+   * Serialize the given [expression], creating an [UnlinkedConstBuilder].
+   */
+  UnlinkedConstBuilder serializeConstExpr(Expression expression) {
+    _ConstExprSerializer serializer = new _ConstExprSerializer(this);
+    serializer.serialize(expression);
+    return serializer.toBuilder();
+  }
+
+  /**
+   * Serialize a [Comment] node into an [UnlinkedDocumentationComment] object.
+   */
+  UnlinkedDocumentationCommentBuilder serializeDocumentation(
+      Comment documentationComment) {
+    if (documentationComment == null) {
+      return null;
+    }
+    String text = documentationComment.tokens
+        .map((Token t) => t.toString())
+        .join()
+        .replaceAll('\r\n', '\n');
+    return new UnlinkedDocumentationCommentBuilder(
+        text: text,
+        offset: documentationComment.offset,
+        length: documentationComment.length);
+  }
+
+  /**
+   * Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
+   * [UnlinkedExecutable].
+   */
+  UnlinkedExecutableBuilder serializeExecutable(
+      SimpleIdentifier name,
+      bool isGetter,
+      bool isSetter,
+      TypeName returnType,
+      FormalParameterList formalParameters,
+      FunctionBody body,
+      bool isTopLevel,
+      bool isDeclaredStatic,
+      Comment documentationComment,
+      TypeParameterList typeParameters,
+      bool isExternal) {
+    int oldScopesLength = scopes.length;
+    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+    scopes.add(typeParameterScope);
+    UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
+    String nameString = name.name;
+    if (isGetter) {
+      b.kind = UnlinkedExecutableKind.getter;
+    } else if (isSetter) {
+      b.kind = UnlinkedExecutableKind.setter;
+      nameString = '$nameString=';
+    } else {
+      b.kind = UnlinkedExecutableKind.functionOrMethod;
+    }
+    b.isAbstract = body is EmptyFunctionBody;
+    b.name = nameString;
+    b.nameOffset = name.offset;
+    b.typeParameters =
+        serializeTypeParameters(typeParameters, typeParameterScope);
+    if (!isTopLevel) {
+      b.isStatic = isDeclaredStatic;
+    }
+    b.returnType = serializeTypeName(returnType);
+    b.isExternal = isExternal;
+    bool isSemanticallyStatic = isTopLevel || isDeclaredStatic;
+    if (formalParameters != null) {
+      b.parameters = formalParameters.parameters
+          .map((FormalParameter p) => p.accept(this))
+          .toList();
+      if (!isSemanticallyStatic) {
+        for (int i = 0; i < formalParameters.parameters.length; i++) {
+          if (!b.parameters[i].isFunctionTyped &&
+              b.parameters[i].type == null) {
+            b.parameters[i].inferredTypeSlot = assignTypeSlot();
+          }
+        }
+      }
+    }
+    b.documentationComment = serializeDocumentation(documentationComment);
+    if (returnType == null && !isSemanticallyStatic) {
+      b.inferredReturnTypeSlot = assignTypeSlot();
+    }
+    scopes.removeLast();
+    assert(scopes.length == oldScopesLength);
+    return b;
+  }
+
+  /**
+   * Serialize the return type and parameters of a function-typed formal
+   * parameter and store them in [b].
+   */
+  void serializeFunctionTypedParameterDetails(UnlinkedParamBuilder b,
+      TypeName returnType, FormalParameterList parameters) {
+    EntityRefBuilder serializedReturnType = serializeTypeName(returnType);
+    if (serializedReturnType != null) {
+      b.type = serializedReturnType;
+    }
+    b.parameters = parameters.parameters
+        .map((FormalParameter p) => p.accept(this))
+        .toList();
+  }
+
+  /**
+   * Serialize a [FieldFormalParameter], [FunctionTypedFormalParameter], or
+   * [SimpleFormalParameter] into an [UnlinkedParam].
+   */
+  UnlinkedParamBuilder serializeParameter(NormalFormalParameter node) {
+    UnlinkedParamBuilder b = new UnlinkedParamBuilder();
+    b.name = node.identifier.name;
+    b.nameOffset = node.identifier.offset;
+    switch (node.kind) {
+      case ParameterKind.REQUIRED:
+        b.kind = UnlinkedParamKind.required;
+        break;
+      case ParameterKind.POSITIONAL:
+        b.kind = UnlinkedParamKind.positional;
+        break;
+      case ParameterKind.NAMED:
+        b.kind = UnlinkedParamKind.named;
+        break;
+      default:
+        throw new StateError('Unexpected parameter kind: ${node.kind}');
+    }
+    return b;
+  }
+
+  /**
+   * Serialize a reference to a top level name declared elsewhere, by adding an
+   * entry to the references table if necessary.  If [prefixIndex] is not null,
+   * the reference is associated with the prefix having the given index in the
+   * references table.
+   */
+  int serializeReference(int prefixIndex, String name) => nameToReference
+          .putIfAbsent(prefixIndex, () => <String, int>{})
+          .putIfAbsent(name, () {
+        int index = unlinkedReferences.length;
+        unlinkedReferences.add(new UnlinkedReferenceBuilder(
+            prefixReference: prefixIndex, name: name));
+        return index;
+      });
+
+  /**
+   * Serialize a type name (which might be defined in a nested scope, at top
+   * level within this library, or at top level within an imported library) to
+   * a [EntityRef].  Note that this method does the right thing if the
+   * name doesn't refer to an entity other than a type (e.g. a class member).
+   */
+  EntityRefBuilder serializeTypeName(TypeName node) {
+    if (node == null) {
+      return null;
+    } else {
+      EntityRefBuilder b = new EntityRefBuilder();
+      Identifier identifier = node.name;
+      if (identifier is SimpleIdentifier) {
+        String name = identifier.name;
+        int indexOffset = 0;
+        for (int i = scopes.length - 1; i >= 0; i--) {
+          _Scope scope = scopes[i];
+          _ScopedEntity entity = scope[name];
+          if (entity != null) {
+            if (entity is _ScopedTypeParameter) {
+              b.paramReference = indexOffset + entity.index;
+              return b;
+            } else {
+              // None of the other things that can be declared in local scopes
+              // are types, so this is an error and should be treated as a
+              // reference to `dynamic`.
+              b.reference = serializeReference(null, 'dynamic');
+              return b;
+            }
+          }
+          if (scope is _TypeParameterScope) {
+            indexOffset += scope.length;
+          }
+        }
+        b.reference = serializeReference(null, name);
+      } else if (identifier is PrefixedIdentifier) {
+        int prefixIndex = prefixIndices.putIfAbsent(identifier.prefix.name,
+            () => serializeReference(null, identifier.prefix.name));
+        b.reference =
+            serializeReference(prefixIndex, identifier.identifier.name);
+      } else {
+        throw new StateError(
+            'Unexpected identifier type: ${identifier.runtimeType}');
+      }
+      if (node.typeArguments != null) {
+        // Trailing type arguments of type 'dynamic' should be omitted.
+        NodeList<TypeName> args = node.typeArguments.arguments;
+        int numArgsToSerialize = args.length;
+        while (
+            numArgsToSerialize > 0 && isDynamic(args[numArgsToSerialize - 1])) {
+          --numArgsToSerialize;
+        }
+        if (numArgsToSerialize > 0) {
+          List<EntityRefBuilder> serializedArguments = <EntityRefBuilder>[];
+          for (int i = 0; i < numArgsToSerialize; i++) {
+            serializedArguments.add(serializeTypeName(args[i]));
+          }
+          b.typeArguments = serializedArguments;
+        }
+      }
+      return b;
+    }
+  }
+
+  /**
+   * Serialize the given [typeParameters] into a list of [UnlinkedTypeParam]s,
+   * and also store them in [typeParameterScope].
+   */
+  List<UnlinkedTypeParamBuilder> serializeTypeParameters(
+      TypeParameterList typeParameters,
+      _TypeParameterScope typeParameterScope) {
+    if (typeParameters != null) {
+      for (int i = 0; i < typeParameters.typeParameters.length; i++) {
+        TypeParameter typeParameter = typeParameters.typeParameters[i];
+        typeParameterScope[typeParameter.name.name] =
+            new _ScopedTypeParameter(typeParameters.typeParameters.length - i);
+      }
+      return typeParameters.typeParameters.map(visitTypeParameter).toList();
+    }
+    return const <UnlinkedTypeParamBuilder>[];
+  }
+
+  /**
+   * Serialize the given [variables] into [UnlinkedVariable]s, and store them
+   * in [this.variables].
+   */
+  void serializeVariables(VariableDeclarationList variables,
+      bool isDeclaredStatic, Comment documentationComment, bool isField) {
+    for (VariableDeclaration variable in variables.variables) {
+      UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
+      b.isFinal = variables.isFinal;
+      b.isConst = variables.isConst;
+      b.isStatic = isDeclaredStatic;
+      b.name = variable.name.name;
+      b.nameOffset = variable.name.offset;
+      b.type = serializeTypeName(variables.type);
+      b.documentationComment = serializeDocumentation(documentationComment);
+      if (variable.isConst) {
+        Expression initializer = variable.initializer;
+        if (initializer != null) {
+          b.constExpr = serializeConstExpr(initializer);
+        }
+      }
+      if (variable.initializer != null &&
+          (variables.isFinal || variables.isConst)) {
+        b.propagatedTypeSlot = assignTypeSlot();
+      }
+      bool isSemanticallyStatic = !isField || isDeclaredStatic;
+      if (variables.type == null &&
+          (variable.initializer != null || !isSemanticallyStatic)) {
+        b.inferredTypeSlot = assignTypeSlot();
+      }
+      this.variables.add(b);
+    }
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    TypeName superclass =
+        node.extendsClause == null ? null : node.extendsClause.superclass;
+    serializeClass(
+        node.abstractKeyword,
+        node.name.name,
+        node.name.offset,
+        node.typeParameters,
+        superclass,
+        node.withClause,
+        node.implementsClause,
+        node.members,
+        false,
+        node.documentationComment);
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    serializeClass(
+        node.abstractKeyword,
+        node.name.name,
+        node.name.offset,
+        node.typeParameters,
+        node.superclass,
+        node.withClause,
+        node.implementsClause,
+        null,
+        true,
+        node.documentationComment);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
+    if (node.name != null) {
+      b.name = node.name.name;
+      b.nameOffset = node.name.offset;
+    } else {
+      b.nameOffset = node.returnType.offset;
+    }
+    b.parameters = node.parameters.parameters
+        .map((FormalParameter p) => p.accept(this))
+        .toList();
+    b.kind = UnlinkedExecutableKind.constructor;
+    b.isFactory = node.factoryKeyword != null;
+    b.isConst = node.constKeyword != null;
+    b.isExternal = node.externalKeyword != null;
+    b.documentationComment = serializeDocumentation(node.documentationComment);
+    executables.add(b);
+  }
+
+  @override
+  UnlinkedParamBuilder visitDefaultFormalParameter(
+      DefaultFormalParameter node) {
+    return node.parameter.accept(this);
+  }
+
+  @override
+  void visitEnumDeclaration(EnumDeclaration node) {
+    UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
+    b.name = node.name.name;
+    b.nameOffset = node.name.offset;
+    b.values = node.constants
+        .map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder(
+            name: value.name.name, nameOffset: value.name.offset))
+        .toList();
+    b.documentationComment = serializeDocumentation(node.documentationComment);
+    enums.add(b);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    UnlinkedExportNonPublicBuilder b = new UnlinkedExportNonPublicBuilder(
+        uriOffset: node.uri.offset, uriEnd: node.uri.end, offset: node.offset);
+    exports.add(b);
+  }
+
+  @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    serializeVariables(node.fields, node.staticKeyword != null,
+        node.documentationComment, true);
+  }
+
+  @override
+  UnlinkedParamBuilder visitFieldFormalParameter(FieldFormalParameter node) {
+    UnlinkedParamBuilder b = serializeParameter(node);
+    b.isInitializingFormal = true;
+    if (node.type != null || node.parameters != null) {
+      b.isFunctionTyped = node.parameters != null;
+      if (node.parameters != null) {
+        serializeFunctionTypedParameterDetails(b, node.type, node.parameters);
+      } else {
+        b.type = serializeTypeName(node.type);
+      }
+    }
+    return b;
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    executables.add(serializeExecutable(
+        node.name,
+        node.isGetter,
+        node.isSetter,
+        node.returnType,
+        node.functionExpression.parameters,
+        node.functionExpression.body,
+        true,
+        false,
+        node.documentationComment,
+        node.functionExpression.typeParameters,
+        node.externalKeyword != null));
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    int oldScopesLength = scopes.length;
+    _TypeParameterScope typeParameterScope = new _TypeParameterScope();
+    scopes.add(typeParameterScope);
+    UnlinkedTypedefBuilder b = new UnlinkedTypedefBuilder();
+    b.name = node.name.name;
+    b.nameOffset = node.name.offset;
+    b.typeParameters =
+        serializeTypeParameters(node.typeParameters, typeParameterScope);
+    EntityRefBuilder serializedReturnType = serializeTypeName(node.returnType);
+    if (serializedReturnType != null) {
+      b.returnType = serializedReturnType;
+    }
+    b.parameters = node.parameters.parameters
+        .map((FormalParameter p) => p.accept(this))
+        .toList();
+    b.documentationComment = serializeDocumentation(node.documentationComment);
+    typedefs.add(b);
+    scopes.removeLast();
+    assert(scopes.length == oldScopesLength);
+  }
+
+  @override
+  UnlinkedParamBuilder visitFunctionTypedFormalParameter(
+      FunctionTypedFormalParameter node) {
+    UnlinkedParamBuilder b = serializeParameter(node);
+    b.isFunctionTyped = true;
+    serializeFunctionTypedParameterDetails(b, node.returnType, node.parameters);
+    return b;
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    UnlinkedImportBuilder b = new UnlinkedImportBuilder();
+    if (node.uri.stringValue == 'dart:core') {
+      hasCoreBeenImported = true;
+    }
+    b.offset = node.offset;
+    b.combinators = node.combinators.map(serializeCombinator).toList();
+    if (node.prefix != null) {
+      b.prefixReference = serializeReference(null, node.prefix.name);
+      b.prefixOffset = node.prefix.offset;
+    }
+    b.isDeferred = node.deferredKeyword != null;
+    b.uri = node.uri.stringValue;
+    b.uriOffset = node.uri.offset;
+    b.uriEnd = node.uri.end;
+    unlinkedImports.add(b);
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    libraryName =
+        node.name.components.map((SimpleIdentifier id) => id.name).join('.');
+    libraryNameOffset = node.name.offset;
+    libraryNameLength = node.name.length;
+    libraryDocumentationComment =
+        serializeDocumentation(node.documentationComment);
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    executables.add(serializeExecutable(
+        node.name,
+        node.isGetter,
+        node.isSetter,
+        node.returnType,
+        node.parameters,
+        node.body,
+        false,
+        node.isStatic,
+        node.documentationComment,
+        node.typeParameters,
+        node.externalKeyword != null));
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    parts.add(new UnlinkedPartBuilder(
+        uriOffset: node.uri.offset, uriEnd: node.uri.end));
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {}
+
+  @override
+  UnlinkedParamBuilder visitSimpleFormalParameter(SimpleFormalParameter node) {
+    UnlinkedParamBuilder b = serializeParameter(node);
+    b.type = serializeTypeName(node.type);
+    return b;
+  }
+
+  @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    serializeVariables(node.variables, false, node.documentationComment, false);
+  }
+
+  @override
+  UnlinkedTypeParamBuilder visitTypeParameter(TypeParameter node) {
+    UnlinkedTypeParamBuilder b = new UnlinkedTypeParamBuilder();
+    b.name = node.name.name;
+    b.nameOffset = node.name.offset;
+    if (node.bound != null) {
+      b.bound = serializeTypeName(node.bound);
+    }
+    return b;
+  }
+
+  /**
+   * Helper method to determine if a given [typeName] refers to `dynamic`.
+   */
+  static bool isDynamic(TypeName typeName) {
+    Identifier name = typeName.name;
+    return name is SimpleIdentifier && name.name == 'dynamic';
+  }
+}
+
+/**
+ * A [_TypeParameterScope] is a [_Scope] which defines [_ScopedTypeParameter]s.
+ */
+class _TypeParameterScope extends _Scope {
+  /**
+   * Get the number of [_ScopedTypeParameter]s defined in this
+   * [_TypeParameterScope].
+   */
+  int get length => _definedNames.length;
+}
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
new file mode 100644
index 0000000..f6dea26
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -0,0 +1,308 @@
+// 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 serialization.summarize_const_expr;
+
+import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/summary/format.dart';
+
+/**
+ * Instances of this class keep track of intermediate state during
+ * serialization of a single constant [Expression].
+ */
+abstract class AbstractConstExprSerializer {
+  /**
+   * See [UnlinkedConstBuilder.operations].
+   */
+  final List<UnlinkedConstOperation> operations = <UnlinkedConstOperation>[];
+
+  /**
+   * See [UnlinkedConstBuilder.ints].
+   */
+  final List<int> ints = <int>[];
+
+  /**
+   * See [UnlinkedConstBuilder.doubles].
+   */
+  final List<double> doubles = <double>[];
+
+  /**
+   * See [UnlinkedConstBuilder.strings].
+   */
+  final List<String> strings = <String>[];
+
+  /**
+   * See [UnlinkedConstBuilder.references].
+   */
+  final List<EntityRefBuilder> references = <EntityRefBuilder>[];
+
+  /**
+   * Serialize the given [expr] expression into this serializer state.
+   */
+  void serialize(Expression expr) {
+    if (expr is IntegerLiteral) {
+      _pushInt(expr.value);
+    } else if (expr is DoubleLiteral) {
+      operations.add(UnlinkedConstOperation.pushDouble);
+      doubles.add(expr.value);
+    } else if (expr is BooleanLiteral) {
+      if (expr.value) {
+        operations.add(UnlinkedConstOperation.pushTrue);
+      } else {
+        operations.add(UnlinkedConstOperation.pushFalse);
+      }
+    } else if (expr is StringLiteral) {
+      _serializeString(expr);
+    } else if (expr is SymbolLiteral) {
+      strings.add(expr.components.map((token) => token.lexeme).join('.'));
+      operations.add(UnlinkedConstOperation.pushString);
+      operations.add(UnlinkedConstOperation.makeSymbol);
+    } else if (expr is NullLiteral) {
+      operations.add(UnlinkedConstOperation.pushNull);
+    } else if (expr is Identifier) {
+      references.add(serializeIdentifier(expr));
+      operations.add(UnlinkedConstOperation.pushReference);
+    } else if (expr is InstanceCreationExpression) {
+      _serializeInstanceCreation(expr);
+    } else if (expr is ListLiteral) {
+      _serializeListLiteral(expr);
+    } else if (expr is MapLiteral) {
+      _serializeMapLiteral(expr);
+    } else if (expr is MethodInvocation) {
+      String name = expr.methodName.name;
+      if (name != 'identical') {
+        throw new _ConstExprSerializationError(
+            'Only "identity" function invocation is allowed.');
+      }
+      if (expr.argumentList == null ||
+          expr.argumentList.arguments.length != 2) {
+        throw new _ConstExprSerializationError(
+            'The function "identity" requires exactly 2 arguments.');
+      }
+      expr.argumentList.arguments.forEach(serialize);
+      operations.add(UnlinkedConstOperation.identical);
+    } else if (expr is BinaryExpression) {
+      _serializeBinaryExpression(expr);
+    } else if (expr is ConditionalExpression) {
+      serialize(expr.condition);
+      serialize(expr.thenExpression);
+      serialize(expr.elseExpression);
+      operations.add(UnlinkedConstOperation.conditional);
+    } else if (expr is PrefixExpression) {
+      _serializePrefixExpression(expr);
+    } else if (expr is PropertyAccess) {
+      if (expr.target is! PrefixedIdentifier &&
+          expr.propertyName.name == 'length') {
+        serialize(expr.target);
+        operations.add(UnlinkedConstOperation.length);
+      } else {
+        references.add(serializePropertyAccess(expr));
+        operations.add(UnlinkedConstOperation.pushReference);
+      }
+    } else if (expr is ParenthesizedExpression) {
+      serialize(expr.expression);
+    } else {
+      throw new _ConstExprSerializationError('Unknown expression type: $expr');
+    }
+  }
+
+  /**
+   * Return [EntityRefBuilder] that corresponds to the given [constructor].
+   */
+  EntityRefBuilder serializeConstructorName(ConstructorName constructor);
+
+  /**
+   * Return [EntityRefBuilder] that corresponds to the given [identifier].
+   */
+  EntityRefBuilder serializeIdentifier(Identifier identifier);
+
+  /**
+   * Return [EntityRefBuilder] that corresponds to the given [access].
+   */
+  EntityRefBuilder serializePropertyAccess(PropertyAccess access);
+
+  /**
+   * Return [EntityRefBuilder] that corresponds to the given [type].
+   */
+  EntityRefBuilder serializeType(TypeName type);
+
+  /**
+   * Return the [UnlinkedConstBuilder] that corresponds to the state of this
+   * serializer.
+   */
+  UnlinkedConstBuilder toBuilder() {
+    return new UnlinkedConstBuilder(
+        operations: operations,
+        ints: ints,
+        doubles: doubles,
+        strings: strings,
+        references: references);
+  }
+
+  void _pushInt(int value) {
+    assert(value >= 0);
+    if (value >= (1 << 32)) {
+      _pushInt(value >> 32);
+      operations.add(UnlinkedConstOperation.shiftOr);
+      ints.add(value & 0xFFFFFFFF);
+    } else {
+      operations.add(UnlinkedConstOperation.pushInt);
+      ints.add(value);
+    }
+  }
+
+  void _serializeBinaryExpression(BinaryExpression expr) {
+    serialize(expr.leftOperand);
+    serialize(expr.rightOperand);
+    TokenType operator = expr.operator.type;
+    if (operator == TokenType.EQ_EQ) {
+      operations.add(UnlinkedConstOperation.equal);
+    } else if (operator == TokenType.BANG_EQ) {
+      operations.add(UnlinkedConstOperation.equal);
+      operations.add(UnlinkedConstOperation.not);
+    } else if (operator == TokenType.AMPERSAND_AMPERSAND) {
+      operations.add(UnlinkedConstOperation.and);
+    } else if (operator == TokenType.BAR_BAR) {
+      operations.add(UnlinkedConstOperation.or);
+    } else if (operator == TokenType.CARET) {
+      operations.add(UnlinkedConstOperation.bitXor);
+    } else if (operator == TokenType.AMPERSAND) {
+      operations.add(UnlinkedConstOperation.bitAnd);
+    } else if (operator == TokenType.BAR) {
+      operations.add(UnlinkedConstOperation.bitOr);
+    } else if (operator == TokenType.GT_GT) {
+      operations.add(UnlinkedConstOperation.bitShiftRight);
+    } else if (operator == TokenType.LT_LT) {
+      operations.add(UnlinkedConstOperation.bitShiftLeft);
+    } else if (operator == TokenType.PLUS) {
+      operations.add(UnlinkedConstOperation.add);
+    } else if (operator == TokenType.MINUS) {
+      operations.add(UnlinkedConstOperation.subtract);
+    } else if (operator == TokenType.STAR) {
+      operations.add(UnlinkedConstOperation.multiply);
+    } else if (operator == TokenType.SLASH) {
+      operations.add(UnlinkedConstOperation.divide);
+    } else if (operator == TokenType.TILDE_SLASH) {
+      operations.add(UnlinkedConstOperation.floorDivide);
+    } else if (operator == TokenType.GT) {
+      operations.add(UnlinkedConstOperation.greater);
+    } else if (operator == TokenType.LT) {
+      operations.add(UnlinkedConstOperation.less);
+    } else if (operator == TokenType.GT_EQ) {
+      operations.add(UnlinkedConstOperation.greaterEqual);
+    } else if (operator == TokenType.LT_EQ) {
+      operations.add(UnlinkedConstOperation.lessEqual);
+    } else if (operator == TokenType.PERCENT) {
+      operations.add(UnlinkedConstOperation.modulo);
+    } else {
+      throw new _ConstExprSerializationError('Unknown operator: $operator');
+    }
+  }
+
+  void _serializeInstanceCreation(InstanceCreationExpression expr) {
+    ConstructorName constructor = expr.constructorName;
+    List<Expression> arguments = expr.argumentList.arguments;
+    // Serialize the arguments.
+    List<String> argumentNames = <String>[];
+    arguments.forEach((arg) {
+      if (arg is NamedExpression) {
+        argumentNames.add(arg.name.label.name);
+        serialize(arg.expression);
+      } else {
+        serialize(arg);
+      }
+    });
+    // Add the op-code and numbers of named and positional arguments.
+    operations.add(UnlinkedConstOperation.invokeConstructor);
+    ints.add(argumentNames.length);
+    strings.addAll(argumentNames);
+    ints.add(arguments.length - argumentNames.length);
+    // Serialize the reference.
+    references.add(serializeConstructorName(constructor));
+  }
+
+  void _serializeListLiteral(ListLiteral expr) {
+    List<Expression> elements = expr.elements;
+    elements.forEach(serialize);
+    ints.add(elements.length);
+    if (expr.typeArguments != null &&
+        expr.typeArguments.arguments.length == 1) {
+      references.add(serializeType(expr.typeArguments.arguments[0]));
+      operations.add(UnlinkedConstOperation.makeTypedList);
+    } else {
+      operations.add(UnlinkedConstOperation.makeUntypedList);
+    }
+  }
+
+  void _serializeMapLiteral(MapLiteral expr) {
+    for (MapLiteralEntry entry in expr.entries) {
+      serialize(entry.key);
+      serialize(entry.value);
+    }
+    ints.add(expr.entries.length);
+    if (expr.typeArguments != null &&
+        expr.typeArguments.arguments.length == 2) {
+      references.add(serializeType(expr.typeArguments.arguments[0]));
+      references.add(serializeType(expr.typeArguments.arguments[1]));
+      operations.add(UnlinkedConstOperation.makeTypedMap);
+    } else {
+      operations.add(UnlinkedConstOperation.makeUntypedMap);
+    }
+  }
+
+  void _serializePrefixExpression(PrefixExpression expr) {
+    serialize(expr.operand);
+    TokenType operator = expr.operator.type;
+    if (operator == TokenType.BANG) {
+      operations.add(UnlinkedConstOperation.not);
+    } else if (operator == TokenType.MINUS) {
+      operations.add(UnlinkedConstOperation.negate);
+    } else if (operator == TokenType.TILDE) {
+      operations.add(UnlinkedConstOperation.complement);
+    } else {
+      throw new _ConstExprSerializationError('Unknown operator: $operator');
+    }
+  }
+
+  void _serializeString(StringLiteral expr) {
+    if (expr is AdjacentStrings) {
+      if (expr.strings.every((string) => string is SimpleStringLiteral)) {
+        operations.add(UnlinkedConstOperation.pushString);
+        strings.add(expr.stringValue);
+      } else {
+        expr.strings.forEach(_serializeString);
+        operations.add(UnlinkedConstOperation.concatenate);
+        ints.add(expr.strings.length);
+      }
+    } else if (expr is SimpleStringLiteral) {
+      operations.add(UnlinkedConstOperation.pushString);
+      strings.add(expr.value);
+    } else {
+      StringInterpolation interpolation = expr as StringInterpolation;
+      for (InterpolationElement element in interpolation.elements) {
+        if (element is InterpolationString) {
+          operations.add(UnlinkedConstOperation.pushString);
+          strings.add(element.value);
+        } else {
+          serialize((element as InterpolationExpression).expression);
+        }
+      }
+      operations.add(UnlinkedConstOperation.concatenate);
+      ints.add(interpolation.elements.length);
+    }
+  }
+}
+
+/**
+ * Error that describes a problem during a constant expression serialization.
+ */
+class _ConstExprSerializationError {
+  final String message;
+
+  _ConstExprSerializationError(this.message);
+
+  @override
+  String toString() => message;
+}
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 0eac910..66f31ecc 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -6,32 +6,65 @@
 
 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/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/name_filter.dart';
+import 'package:analyzer/src/summary/summarize_const_expr.dart';
 
 /**
  * Serialize all the elements in [lib] to a summary using [ctx] as the context
  * for building the summary, and using [typeProvider] to find built-in types.
  */
 LibrarySerializationResult serializeLibrary(
-    LibraryElement lib, TypeProvider typeProvider) {
-  var serializer = new _LibrarySerializer(lib, typeProvider);
-  PrelinkedLibraryBuilder prelinked = serializer.serializeLibrary();
+    LibraryElement lib, TypeProvider typeProvider, bool strongMode) {
+  var serializer = new _LibrarySerializer(lib, typeProvider, strongMode);
+  LinkedLibraryBuilder linked = serializer.serializeLibrary();
   return new LibrarySerializationResult(
-      prelinked, serializer.unlinkedUnits, serializer.unitUris);
+      linked, serializer.unlinkedUnits, serializer.unitUris);
 }
 
+ReferenceKind _getReferenceKind(Element element) {
+  if (element == null ||
+      element is ClassElement ||
+      element is DynamicElementImpl) {
+    return ReferenceKind.classOrEnum;
+  } else if (element is ConstructorElement) {
+    return ReferenceKind.constructor;
+  } else if (element is FunctionElement) {
+    return ReferenceKind.topLevelFunction;
+  } else if (element is FunctionTypeAliasElement) {
+    return ReferenceKind.typedef;
+  } else if (element is PropertyAccessorElement) {
+    if (element.enclosingElement is ClassElement) {
+      return ReferenceKind.constField;
+    }
+    return ReferenceKind.topLevelPropertyAccessor;
+  } else if (element is MethodElement) {
+    return ReferenceKind.staticMethod;
+  } else {
+    throw new Exception('Unexpected element kind: ${element.runtimeType}');
+  }
+}
+
+/**
+ * Type of closures used by [_LibrarySerializer] to defer generation of
+ * [EntityRefBuilder] objects until the end of serialization of a
+ * compilation unit.
+ */
+typedef EntityRefBuilder _SerializeTypeRef();
+
 /**
  * Data structure holding the result of serializing a [LibraryElement].
  */
 class LibrarySerializationResult {
   /**
-   * Pre-linked information the given library.
+   * Linked information the given library.
    */
-  final PrelinkedLibraryBuilder prelinked;
+  final LinkedLibraryBuilder linked;
 
   /**
    * Unlinked information for the compilation units constituting the library.
@@ -46,58 +79,45 @@
    */
   final List<String> unitUris;
 
-  LibrarySerializationResult(this.prelinked, this.unlinkedUnits, this.unitUris);
+  LibrarySerializationResult(this.linked, this.unlinkedUnits, this.unitUris);
 }
 
 /**
  * Instances of this class keep track of intermediate state during
- * serialization of a single library.`
+ * serialization of a single compilation unit.
  */
-class _LibrarySerializer {
+class _CompilationUnitSerializer {
   /**
-   * The library to be serialized.
+   * The [_LibrarySerializer] which is serializing the library of which
+   * [compilationUnit] is a part.
    */
-  final LibraryElement libraryElement;
+  final _LibrarySerializer librarySerializer;
 
   /**
-   * The type provider.  This is used to locate the library for `dart:core`.
+   * The [CompilationUnitElement] being serialized.
    */
-  final TypeProvider typeProvider;
+  final CompilationUnitElement compilationUnit;
 
   /**
-   * List of objects which should be written to [PrelinkedLibrary.units].
+   * The ordinal index of [compilationUnit] within the library, where 0
+   * represents the defining compilation unit.
    */
-  final List<PrelinkedUnitBuilder> prelinkedUnits = <PrelinkedUnitBuilder>[];
+  final int unitNum;
 
   /**
-   * List of unlinked units corresponding to the pre-linked units in
-   * [prelinkedUnits],
+   * The final linked summary of the compilation unit.
    */
-  final List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
+  final LinkedUnitBuilder linkedUnit = new LinkedUnitBuilder();
 
   /**
-   * List of absolute URIs of the compilation units in the library.
+   * The final unlinked summary of the compilation unit.
    */
-  final List<String> unitUris = <String>[];
+  final UnlinkedUnitBuilder unlinkedUnit = new UnlinkedUnitBuilder();
 
-  /**
-   * Map from [LibraryElement] to the index of the entry in the "dependency
-   * table" that refers to it.
-   */
-  final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{};
-
-  /**
-   * The "dependency table".  This is the list of objects which should be
-   * written to [PrelinkedLibrary.dependencies].
-   */
-  final List<PrelinkedDependencyBuilder> dependencies =
-      <PrelinkedDependencyBuilder>[];
-
-  /**
-   * The prelinked portion of the "imports table".  This is the list of ints
-   * which should be written to [PrelinkedLibrary.imports].
-   */
-  final List<int> prelinkedImports = <int>[];
+/**
+ * Absolute URI of the compilation unit.
+ */
+  String unitUri;
 
   /**
    * Map from [Element] to the index of the entry in the "references table"
@@ -112,12 +132,21 @@
   List<UnlinkedReferenceBuilder> unlinkedReferences;
 
   /**
-   * The prelinked portion of the "references table".  This is the list of
-   * objects which should be written to [PrelinkedUnit.references].
+   * The linked portion of the "references table".  This is the list of
+   * objects which should be written to [LinkedUnit.references].
    */
-  List<PrelinkedReferenceBuilder> prelinkedReferences;
+  List<LinkedReferenceBuilder> linkedReferences;
 
-  //final Map<String, int> prefixIndices = <String, int>{};
+  /**
+   * The number of slot ids which have been assigned to this compilation unit.
+   */
+  int numSlots = 0;
+
+  /**
+   * List of closures which should be invoked at the end of serialization of a
+   * compilation unit, to produce [LinkedUnit.types].
+   */
+  final List<_SerializeTypeRef> deferredLinkedTypes = <_SerializeTypeRef>[];
 
   /**
    * Index into the "references table" representing an unresolved reference, if
@@ -126,99 +155,86 @@
    */
   int unresolvedReferenceIndex = null;
 
-  /**
-   * Set of libraries which have been seen so far while visiting the transitive
-   * closure of exports.
-   */
-  final Set<LibraryElement> librariesAddedToTransitiveExportClosure =
-      new Set<LibraryElement>();
-
-  /**
-   * Map from imported element to the prefix which may be used to refer to that
-   * element; elements for which no prefix is needed are absent from this map.
-   */
-  final Map<Element, PrefixElement> prefixMap = <Element, PrefixElement>{};
-
-  _LibrarySerializer(this.libraryElement, this.typeProvider) {
-    dependencies.add(encodePrelinkedDependency());
-    dependencyMap[libraryElement] = 0;
-  }
-
-  /**
-   * Retrieve the library element for `dart:core`.
-   */
-  LibraryElement get coreLibrary => typeProvider.objectType.element.library;
+  _CompilationUnitSerializer(
+      this.librarySerializer, this.compilationUnit, this.unitNum);
 
   /**
    * Add all classes, enums, typedefs, executables, and top level variables
-   * from the given compilation unit [element] to the library summary.
+   * from the given compilation unit [element] to the compilation unit summary.
    * [unitNum] indicates the ordinal position of this compilation unit in the
    * library.
    */
-  void addCompilationUnitElements(CompilationUnitElement element, int unitNum) {
-    UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
-    referenceMap.clear();
-    unlinkedReferences = <UnlinkedReferenceBuilder>[encodeUnlinkedReference()];
-    prelinkedReferences = <PrelinkedReferenceBuilder>[
-      encodePrelinkedReference(kind: PrelinkedReferenceKind.classOrEnum)
+  void addCompilationUnitElements() {
+    unlinkedReferences = <UnlinkedReferenceBuilder>[
+      new UnlinkedReferenceBuilder()
+    ];
+    linkedReferences = <LinkedReferenceBuilder>[
+      new LinkedReferenceBuilder(kind: ReferenceKind.classOrEnum)
     ];
     List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
-    for (PropertyAccessorElement accessor in element.accessors) {
+    for (PropertyAccessorElement accessor in compilationUnit.accessors) {
       if (accessor.isPublic) {
-        names.add(encodeUnlinkedPublicName(
-            kind: PrelinkedReferenceKind.other,
+        names.add(new UnlinkedPublicNameBuilder(
+            kind: ReferenceKind.topLevelPropertyAccessor,
             name: accessor.name,
             numTypeParameters: accessor.typeParameters.length));
       }
     }
-    for (ClassElement cls in element.types) {
+    for (ClassElement cls in compilationUnit.types) {
       if (cls.isPublic) {
-        names.add(encodeUnlinkedPublicName(
-            kind: PrelinkedReferenceKind.classOrEnum,
+        names.add(new UnlinkedPublicNameBuilder(
+            kind: ReferenceKind.classOrEnum,
             name: cls.name,
-            numTypeParameters: cls.typeParameters.length));
+            numTypeParameters: cls.typeParameters.length,
+            constMembers: serializeClassConstMembers(cls)));
       }
     }
-    for (ClassElement enm in element.enums) {
+    for (ClassElement enm in compilationUnit.enums) {
       if (enm.isPublic) {
-        names.add(encodeUnlinkedPublicName(
-            kind: PrelinkedReferenceKind.classOrEnum, name: enm.name));
+        names.add(new UnlinkedPublicNameBuilder(
+            kind: ReferenceKind.classOrEnum, name: enm.name));
       }
     }
-    for (FunctionElement function in element.functions) {
+    for (FunctionElement function in compilationUnit.functions) {
       if (function.isPublic) {
-        names.add(encodeUnlinkedPublicName(
-            kind: PrelinkedReferenceKind.other,
+        names.add(new UnlinkedPublicNameBuilder(
+            kind: ReferenceKind.topLevelFunction,
             name: function.name,
             numTypeParameters: function.typeParameters.length));
       }
     }
-    for (FunctionTypeAliasElement typedef in element.functionTypeAliases) {
+    for (FunctionTypeAliasElement typedef
+        in compilationUnit.functionTypeAliases) {
       if (typedef.isPublic) {
-        names.add(encodeUnlinkedPublicName(
-            kind: PrelinkedReferenceKind.typedef,
+        names.add(new UnlinkedPublicNameBuilder(
+            kind: ReferenceKind.typedef,
             name: typedef.name,
             numTypeParameters: typedef.typeParameters.length));
       }
     }
     if (unitNum == 0) {
+      LibraryElement libraryElement = librarySerializer.libraryElement;
       if (libraryElement.name.isNotEmpty) {
-        b.libraryName = libraryElement.name;
-        b.libraryNameOffset = libraryElement.nameOffset;
-        b.libraryNameLength = libraryElement.nameLength;
-        b.libraryDocumentationComment = serializeDocumentation(libraryElement);
+        LibraryElement libraryElement = librarySerializer.libraryElement;
+        unlinkedUnit.libraryName = libraryElement.name;
+        unlinkedUnit.libraryNameOffset = libraryElement.nameOffset;
+        unlinkedUnit.libraryNameLength = libraryElement.nameLength;
+        unlinkedUnit.libraryDocumentationComment =
+            serializeDocumentation(libraryElement);
       }
-      b.publicNamespace = encodeUnlinkedPublicNamespace(
+      unlinkedUnit.publicNamespace = new UnlinkedPublicNamespaceBuilder(
           exports: libraryElement.exports.map(serializeExportPublic).toList(),
           parts: libraryElement.parts
               .map((CompilationUnitElement e) => e.uri)
               .toList(),
           names: names);
-      b.exports = libraryElement.exports.map(serializeExportNonPublic).toList();
-      b.imports = libraryElement.imports.map(serializeImport).toList();
-      b.parts = libraryElement.parts
+      unlinkedUnit.exports =
+          libraryElement.exports.map(serializeExportNonPublic).toList();
+      unlinkedUnit.imports =
+          libraryElement.imports.map(serializeImport).toList();
+      unlinkedUnit.parts = libraryElement.parts
           .map((CompilationUnitElement e) =>
-              encodeUnlinkedPart(uriOffset: e.uriOffset, uriEnd: e.uriEnd))
+              new UnlinkedPartBuilder(uriOffset: e.uriOffset, uriEnd: e.uriEnd))
           .toList();
     } else {
       // TODO(paulberry): we need to figure out a way to record library, part,
@@ -227,21 +243,23 @@
       // language), so that if the user makes code changes that cause a
       // non-defining compilation unit to become a defining compilation unit,
       // we can create a correct summary by simply re-linking.
-      b.publicNamespace = encodeUnlinkedPublicNamespace(names: names);
+      unlinkedUnit.publicNamespace =
+          new UnlinkedPublicNamespaceBuilder(names: names);
     }
-    b.classes = element.types.map(serializeClass).toList();
-    b.enums = element.enums.map(serializeEnum).toList();
-    b.typedefs = element.functionTypeAliases.map(serializeTypedef).toList();
+    unlinkedUnit.classes = compilationUnit.types.map(serializeClass).toList();
+    unlinkedUnit.enums = compilationUnit.enums.map(serializeEnum).toList();
+    unlinkedUnit.typedefs =
+        compilationUnit.functionTypeAliases.map(serializeTypedef).toList();
     List<UnlinkedExecutableBuilder> executables =
-        element.functions.map(serializeExecutable).toList();
-    for (PropertyAccessorElement accessor in element.accessors) {
+        compilationUnit.functions.map(serializeExecutable).toList();
+    for (PropertyAccessorElement accessor in compilationUnit.accessors) {
       if (!accessor.isSynthetic) {
         executables.add(serializeExecutable(accessor));
       }
     }
-    b.executables = executables;
+    unlinkedUnit.executables = executables;
     List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[];
-    for (PropertyAccessorElement accessor in element.accessors) {
+    for (PropertyAccessorElement accessor in compilationUnit.accessors) {
       if (accessor.isSynthetic && accessor.isGetter) {
         PropertyInducingElement variable = accessor.variable;
         if (variable != null) {
@@ -250,45 +268,20 @@
         }
       }
     }
-    b.variables = variables;
-    b.references = unlinkedReferences;
-    unlinkedUnits.add(b);
-    prelinkedUnits.add(encodePrelinkedUnit(references: prelinkedReferences));
-    unitUris.add(element.source.uri.toString());
-    unlinkedReferences = null;
-    prelinkedReferences = null;
+    unlinkedUnit.variables = variables;
+    unlinkedUnit.references = unlinkedReferences;
+    linkedUnit.references = linkedReferences;
+    unitUri = compilationUnit.source.uri.toString();
   }
 
   /**
-   * Add [exportedLibrary] (and the transitive closure of all libraries it
-   * exports) to the dependency table ([PrelinkedLibrary.dependencies]).
+   * Create the [LinkedUnit.types] table based on deferred types that were
+   * found during [addCompilationUnitElements].
    */
-  void addTransitiveExportClosure(LibraryElement exportedLibrary) {
-    if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) {
-      serializeDependency(exportedLibrary);
-      for (LibraryElement transitiveExport
-          in exportedLibrary.exportedLibraries) {
-        addTransitiveExportClosure(transitiveExport);
-      }
-    }
-  }
-
-  /**
-   * Fill in [prefixMap] using information from [libraryElement.imports].
-   */
-  void computePrefixMap() {
-    for (ImportElement import in libraryElement.imports) {
-      if (import.prefix == null) {
-        continue;
-      }
-      import.importedLibrary.exportNamespace.definedNames
-          .forEach((String name, Element e) {
-        if (new NameFilter.forNamespaceCombinators(import.combinators)
-            .accepts(name)) {
-          prefixMap[e] = import.prefix;
-        }
-      });
-    }
+  void createLinkedTypes() {
+    linkedUnit.types = deferredLinkedTypes
+        .map((_SerializeTypeRef closure) => closure())
+        .toList();
   }
 
   /**
@@ -321,6 +314,23 @@
   }
 
   /**
+   * Get the type arguments for the given [type], or `null` if the type has no
+   * type arguments.
+   *
+   * TODO(paulberry): consider adding an abstract getter to [DartType] to do
+   * this.
+   */
+  List<DartType> getTypeArguments(DartType type) {
+    if (type is InterfaceType) {
+      return type.typeArguments;
+    } else if (type is FunctionType) {
+      return type.typeArguments;
+    } else {
+      return null;
+    }
+  }
+
+  /**
    * Serialize the given [classElement], creating an [UnlinkedClass].
    */
   UnlinkedClassBuilder serializeClass(ClassElement classElement) {
@@ -369,6 +379,43 @@
   }
 
   /**
+   * If [cls] is a class, return the list of its members available for
+   * constants - static constant fields, static methods and constructors.
+   * Otherwise return `null`.
+   */
+  List<UnlinkedPublicNameBuilder> serializeClassConstMembers(ClassElement cls) {
+    if (cls.kind == ElementKind.CLASS) {
+      List<UnlinkedPublicNameBuilder> bs = <UnlinkedPublicNameBuilder>[];
+      for (FieldElement field in cls.fields) {
+        if (field.isStatic && field.isConst && field.isPublic) {
+          bs.add(new UnlinkedPublicNameBuilder(
+              name: field.name,
+              kind: ReferenceKind.constField,
+              numTypeParameters: 0));
+        }
+      }
+      for (MethodElement method in cls.methods) {
+        if (method.isStatic && method.isPublic) {
+          bs.add(new UnlinkedPublicNameBuilder(
+              name: method.name,
+              kind: ReferenceKind.staticMethod,
+              numTypeParameters: method.typeParameters.length));
+        }
+      }
+      for (ConstructorElement constructor in cls.constructors) {
+        if (constructor.isConst && constructor.isPublic) {
+          bs.add(new UnlinkedPublicNameBuilder(
+              name: constructor.name,
+              kind: ReferenceKind.constructor,
+              numTypeParameters: 0));
+        }
+      }
+      return bs;
+    }
+    return null;
+  }
+
+  /**
    * Serialize the given [combinator] into an [UnlinkedCombinator].
    */
   UnlinkedCombinatorBuilder serializeCombinator(
@@ -383,20 +430,12 @@
   }
 
   /**
-   * Return the index of the entry in the dependency table
-   * ([PrelinkedLibrary.dependencies]) for the given [dependentLibrary].  A new
-   * entry is added to the table if necessary to satisfy the request.
+   * Serialize the given [expression], creating an [UnlinkedConstBuilder].
    */
-  int serializeDependency(LibraryElement dependentLibrary) {
-    return dependencyMap.putIfAbsent(dependentLibrary, () {
-      int index = dependencies.length;
-      List<String> parts = dependentLibrary.parts
-          .map((CompilationUnitElement e) => e.source.uri.toString())
-          .toList();
-      dependencies.add(encodePrelinkedDependency(
-          uri: dependentLibrary.source.uri.toString(), parts: parts));
-      return index;
-    });
+  UnlinkedConstBuilder serializeConstExpr(Expression expression) {
+    _ConstExprSerializer serializer = new _ConstExprSerializer(this);
+    serializer.serialize(expression);
+    return serializer.toBuilder();
   }
 
   /**
@@ -409,20 +448,13 @@
     if (element.documentationComment == null) {
       return null;
     }
-    return encodeUnlinkedDocumentationComment(
+    return new UnlinkedDocumentationCommentBuilder(
         text: element.documentationComment,
         offset: element.docRange.offset,
         length: element.docRange.length);
   }
 
   /**
-   * Return the index of the entry in the references table
-   * ([UnlinkedLibrary.references] and [PrelinkedLibrary.references])
-   * representing the pseudo-type `dynamic`.
-   */
-  int serializeDynamicReference() => 0;
-
-  /**
    * Serialize the given [enumElement], creating an [UnlinkedEnum].
    */
   UnlinkedEnumBuilder serializeEnum(ClassElement enumElement) {
@@ -432,7 +464,7 @@
     List<UnlinkedEnumValueBuilder> values = <UnlinkedEnumValueBuilder>[];
     for (FieldElement field in enumElement.fields) {
       if (field.isConst && field.type.element == enumElement) {
-        values.add(encodeUnlinkedEnumValue(
+        values.add(new UnlinkedEnumValueBuilder(
             name: field.name,
             nameOffset: field.nameOffset,
             documentationComment: serializeDocumentation(field)));
@@ -451,10 +483,14 @@
     UnlinkedExecutableBuilder b = new UnlinkedExecutableBuilder();
     b.name = executableElement.name;
     b.nameOffset = executableElement.nameOffset;
-    if (executableElement is! ConstructorElement &&
-        !executableElement.type.returnType.isVoid) {
-      b.returnType = serializeTypeRef(
-          executableElement.type.returnType, executableElement);
+    if (executableElement is! ConstructorElement) {
+      if (!executableElement.hasImplicitReturnType) {
+        b.returnType = serializeTypeRef(
+            executableElement.type.returnType, executableElement);
+      } else if (!executableElement.isStatic) {
+        b.inferredReturnTypeSlot =
+            storeInferredType(executableElement.returnType, executableElement);
+      }
     }
     b.typeParameters =
         executableElement.typeParameters.map(serializeTypeParam).toList();
@@ -476,7 +512,6 @@
     b.isAbstract = executableElement.isAbstract;
     b.isStatic = executableElement.isStatic &&
         executableElement.enclosingElement is ClassElement;
-    b.hasImplicitReturnType = executableElement.hasImplicitReturnType;
     b.isExternal = executableElement.isExternal;
     b.documentationComment = serializeDocumentation(executableElement);
     return b;
@@ -507,12 +542,11 @@
 
   /**
    * Serialize the given [importElement] yielding an [UnlinkedImportBuilder].
-   * Also, add pre-linked information about it to the [prelinkedImports] list.
+   * Also, add linked information about it to the [linkedImports] list.
    */
   UnlinkedImportBuilder serializeImport(ImportElement importElement) {
     UnlinkedImportBuilder b = new UnlinkedImportBuilder();
     b.isDeferred = importElement.isDeferred;
-    b.offset = importElement.nameOffset;
     b.combinators = importElement.combinators.map(serializeCombinator).toList();
     if (importElement.prefix != null) {
       b.prefixReference = serializePrefix(importElement.prefix);
@@ -521,36 +555,15 @@
     if (importElement.isSynthetic) {
       b.isImplicit = true;
     } else {
+      b.offset = importElement.nameOffset;
       b.uri = importElement.uri;
       b.uriOffset = importElement.uriOffset;
       b.uriEnd = importElement.uriEnd;
     }
-    addTransitiveExportClosure(importElement.importedLibrary);
-    prelinkedImports.add(serializeDependency(importElement.importedLibrary));
     return b;
   }
 
   /**
-   * Serialize the whole library element into a [PrelinkedLibrary].  Should be
-   * called exactly once for each instance of [_LibrarySerializer].
-   *
-   * The unlinked compilation units are stored in [unlinkedUnits], and their
-   * absolute URIs are stored in [unitUris].
-   */
-  PrelinkedLibraryBuilder serializeLibrary() {
-    computePrefixMap();
-    PrelinkedLibraryBuilder pb = new PrelinkedLibraryBuilder();
-    addCompilationUnitElements(libraryElement.definingCompilationUnit, 0);
-    for (int i = 0; i < libraryElement.parts.length; i++) {
-      addCompilationUnitElements(libraryElement.parts[i], i + 1);
-    }
-    pb.units = prelinkedUnits;
-    pb.dependencies = dependencies;
-    pb.importDependencies = prelinkedImports;
-    return pb;
-  }
-
-  /**
    * Serialize the given [parameter] into an [UnlinkedParam].
    */
   UnlinkedParamBuilder serializeParam(ParameterElement parameter,
@@ -572,17 +585,24 @@
     }
     b.isInitializingFormal = parameter.isInitializingFormal;
     DartType type = parameter.type;
-    if (type is FunctionType) {
-      b.isFunctionTyped = true;
-      if (!type.returnType.isVoid) {
-        b.type = serializeTypeRef(type.returnType, parameter);
+    if (parameter.hasImplicitType) {
+      Element contextParent = context.enclosingElement;
+      if (!parameter.isInitializingFormal &&
+          contextParent is ExecutableElement &&
+          !contextParent.isStatic &&
+          contextParent is! ConstructorElement) {
+        b.inferredTypeSlot = storeInferredType(type, context);
       }
-      b.parameters = type.parameters
-          .map((parameter) => serializeParam(parameter, context))
-          .toList();
     } else {
-      b.type = serializeTypeRef(type, context);
-      b.hasImplicitType = parameter.hasImplicitType;
+      if (type is FunctionType) {
+        b.isFunctionTyped = true;
+        b.type = serializeTypeRef(type.returnType, parameter);
+        b.parameters = type.parameters
+            .map((parameter) => serializeParam(parameter, context))
+            .toList();
+      } else {
+        b.type = serializeTypeRef(type, context);
+      }
     }
     return b;
   }
@@ -592,16 +612,36 @@
    */
   int serializePrefix(PrefixElement element) {
     return referenceMap.putIfAbsent(element, () {
-      assert(unlinkedReferences.length == prelinkedReferences.length);
+      assert(unlinkedReferences.length == linkedReferences.length);
       int index = unlinkedReferences.length;
-      unlinkedReferences.add(encodeUnlinkedReference(name: element.name));
-      prelinkedReferences
-          .add(encodePrelinkedReference(kind: PrelinkedReferenceKind.prefix));
+      unlinkedReferences.add(new UnlinkedReferenceBuilder(name: element.name));
+      linkedReferences
+          .add(new LinkedReferenceBuilder(kind: ReferenceKind.prefix));
       return index;
     });
   }
 
   /**
+   * Compute the reference index which should be stored in a [EntityRef].
+   *
+   * If [linked] is true, and a new reference has to be created, the reference
+   * will only be stored in [linkedReferences].
+   */
+  int serializeReferenceForType(DartType type, bool linked) {
+    Element element = type.element;
+    LibraryElement dependentLibrary = element?.library;
+    if (dependentLibrary == null) {
+      assert(type.isDynamic || type.isVoid);
+      if (type is UndefinedTypeImpl) {
+        return serializeUnresolvedReference();
+      }
+      // Note: for a type which is truly `dynamic` or `void`, fall through to
+      // use [_getElementReferenceId].
+    }
+    return _getElementReferenceId(element, linked: linked);
+  }
+
+  /**
    * Serialize the given [typedefElement], creating an [UnlinkedTypedef].
    */
   UnlinkedTypedefBuilder serializeTypedef(
@@ -611,10 +651,7 @@
     b.nameOffset = typedefElement.nameOffset;
     b.typeParameters =
         typedefElement.typeParameters.map(serializeTypeParam).toList();
-    if (!typedefElement.returnType.isVoid) {
-      b.returnType =
-          serializeTypeRef(typedefElement.returnType, typedefElement);
-    }
+    b.returnType = serializeTypeRef(typedefElement.returnType, typedefElement);
     b.parameters = typedefElement.parameters.map(serializeParam).toList();
     b.documentationComment = serializeDocumentation(typedefElement);
     return b;
@@ -635,67 +672,37 @@
   }
 
   /**
-   * Serialize the given [type] into an [UnlinkedTypeRef].
+   * Serialize the given [type] into a [EntityRef].  If [slot] is provided,
+   * it should be included in the [EntityRef].  If [linked] is true, any
+   * references that are created will be populated into [linkedReferences] but
+   * [not [unlinkedReferences].
+   *
+   * [context] is the element within which the [EntityRef] will be
+   * interpreted; this is used to serialize type parameters.
    */
-  UnlinkedTypeRefBuilder serializeTypeRef(DartType type, Element context) {
-    UnlinkedTypeRefBuilder b = new UnlinkedTypeRefBuilder();
+  EntityRefBuilder serializeTypeRef(DartType type, Element context,
+      {bool linked: false, int slot}) {
+    EntityRefBuilder b = new EntityRefBuilder(slot: slot);
     if (type is TypeParameterType) {
       b.paramReference = findTypeParameterIndex(type, context);
     } else {
-      Element element = type.element;
-      LibraryElement dependentLibrary = element.library;
-      if (dependentLibrary == null) {
-        assert(type.isDynamic);
-        if (type is UndefinedTypeImpl) {
-          b.reference = serializeUnresolvedReference();
-        } else {
-          b.reference = serializeDynamicReference();
+      b.reference = serializeReferenceForType(type, linked);
+      List<DartType> typeArguments = getTypeArguments(type);
+      if (typeArguments != null) {
+        // Trailing type arguments of type 'dynamic' should be omitted.
+        int numArgsToSerialize = typeArguments.length;
+        while (numArgsToSerialize > 0 &&
+            typeArguments[numArgsToSerialize - 1].isDynamic) {
+          --numArgsToSerialize;
         }
-      } else {
-        b.reference = referenceMap.putIfAbsent(element, () {
-          assert(unlinkedReferences.length == prelinkedReferences.length);
-          CompilationUnitElement unitElement =
-              element.getAncestor((Element e) => e is CompilationUnitElement);
-          int unit = dependentLibrary.units.indexOf(unitElement);
-          assert(unit != -1);
-          int numTypeParameters = 0;
-          if (element is TypeParameterizedElement) {
-            numTypeParameters = element.typeParameters.length;
+        if (numArgsToSerialize > 0) {
+          List<EntityRefBuilder> serializedArguments = <EntityRefBuilder>[];
+          for (int i = 0; i < numArgsToSerialize; i++) {
+            serializedArguments.add(
+                serializeTypeRef(typeArguments[i], context, linked: linked));
           }
-          // Figure out a prefix that may be used to refer to the given type.
-          // TODO(paulberry): to avoid subtle relinking inconsistencies we
-          // should use the actual prefix from the AST (a given type may be
-          // reachable via multiple prefixes), but sadly, this information is
-          // not recorded in the element model.
-          int prefixReference = 0;
-          PrefixElement prefix = prefixMap[element];
-          if (prefix != null) {
-            prefixReference = serializePrefix(prefix);
-          }
-          int index = unlinkedReferences.length;
-          unlinkedReferences.add(encodeUnlinkedReference(
-              name: element.name, prefixReference: prefixReference));
-          prelinkedReferences.add(encodePrelinkedReference(
-              dependency: serializeDependency(dependentLibrary),
-              kind: element is FunctionTypeAliasElement
-                  ? PrelinkedReferenceKind.typedef
-                  : PrelinkedReferenceKind.classOrEnum,
-              unit: unit,
-              numTypeParameters: numTypeParameters));
-          return index;
-        });
-      }
-      List<DartType> typeArguments;
-      if (type is InterfaceType) {
-        typeArguments = type.typeArguments;
-      } else if (type is FunctionType) {
-        typeArguments = type.typeArguments;
-      }
-      if (typeArguments != null &&
-          typeArguments.any((DartType argument) => !argument.isDynamic)) {
-        b.typeArguments = typeArguments
-            .map((DartType t) => serializeTypeRef(t, context))
-            .toList();
+          b.typeArguments = serializedArguments;
+        }
       }
     }
     return b;
@@ -703,7 +710,7 @@
 
   /**
    * Return the index of the entry in the references table
-   * ([UnlinkedLibrary.references] and [PrelinkedLibrary.references]) used for
+   * ([UnlinkedLibrary.references] and [LinkedLibrary.references]) used for
    * unresolved references.  A new entry is added to the table if necessary to
    * satisfy the request.
    */
@@ -713,11 +720,12 @@
     // the element model.  For the moment we use a name that can't possibly
     // ever exist.
     if (unresolvedReferenceIndex == null) {
-      assert(unlinkedReferences.length == prelinkedReferences.length);
+      assert(unlinkedReferences.length == linkedReferences.length);
       unresolvedReferenceIndex = unlinkedReferences.length;
-      unlinkedReferences.add(encodeUnlinkedReference(name: '*unresolved*'));
-      prelinkedReferences.add(
-          encodePrelinkedReference(kind: PrelinkedReferenceKind.unresolved));
+      unlinkedReferences
+          .add(new UnlinkedReferenceBuilder(name: '*unresolved*'));
+      linkedReferences
+          .add(new LinkedReferenceBuilder(kind: ReferenceKind.unresolved));
     }
     return unresolvedReferenceIndex;
   }
@@ -729,12 +737,390 @@
     UnlinkedVariableBuilder b = new UnlinkedVariableBuilder();
     b.name = variable.name;
     b.nameOffset = variable.nameOffset;
-    b.type = serializeTypeRef(variable.type, variable);
+    if (!variable.hasImplicitType) {
+      b.type = serializeTypeRef(variable.type, variable);
+    }
     b.isStatic = variable.isStatic && variable.enclosingElement is ClassElement;
     b.isFinal = variable.isFinal;
     b.isConst = variable.isConst;
-    b.hasImplicitType = variable.hasImplicitType;
     b.documentationComment = serializeDocumentation(variable);
+    if (variable.isConst && variable is ConstVariableElement) {
+      ConstVariableElement constVariable = variable as ConstVariableElement;
+      Expression initializer = constVariable.constantInitializer;
+      if (initializer != null) {
+        b.constExpr = serializeConstExpr(initializer);
+      }
+    }
+    if (b.isFinal || b.isConst) {
+      b.propagatedTypeSlot = storeLinkedType(variable.propagatedType, variable);
+    } else {
+      // Variable is not propagable.
+      assert(variable.propagatedType == null);
+    }
+    if (variable.hasImplicitType &&
+        (variable.initializer != null || !variable.isStatic)) {
+      b.inferredTypeSlot = storeInferredType(variable.type, variable);
+    }
     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].
+   *
+   * [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);
+  }
+
+  /**
+   * Create a slot id for the given [type] (which may be either a propagated
+   * type or an inferred type).  If [type] is not `null`, it is stored in
+   * [linkedTypes] so that once the compilation unit has been fully visited,
+   * it will be serialized to [LinkedUnit.types].
+   *
+   * [context] is the element within which the slot id will appear; this is
+   * used to serialize type parameters.
+   */
+  int storeLinkedType(DartType type, Element context) {
+    int slot = ++numSlots;
+    if (type != null) {
+      deferredLinkedTypes
+          .add(() => serializeTypeRef(type, context, linked: true, slot: slot));
+    }
+    return slot;
+  }
+
+  int _getElementReferenceId(Element element, {bool linked: false}) {
+    return referenceMap.putIfAbsent(element, () {
+      if (element is ConstructorElement && element.displayName.isEmpty) {
+        return _getElementReferenceId(element.enclosingElement, linked: linked);
+      }
+      if (element is MethodElement && !element.isStatic) {
+        throw new StateError('Only static methods can be serialized.');
+      }
+      if (element is PropertyAccessorElement) {
+        Element enclosing = element.enclosingElement;
+        if (!(enclosing is CompilationUnitElement || element.isStatic)) {
+          throw new StateError(
+              'Only top-level or static property accessors can be serialized.');
+        }
+      }
+      LibraryElement dependentLibrary = element?.library;
+      int unit;
+      if (dependentLibrary == null) {
+        assert(element == librarySerializer.typeProvider.dynamicType.element ||
+            element == null);
+        unit = 0;
+        dependentLibrary = librarySerializer.libraryElement;
+      } else {
+        CompilationUnitElement unitElement =
+            element.getAncestor((Element e) => e is CompilationUnitElement);
+        unit = dependentLibrary.units.indexOf(unitElement);
+        assert(unit != -1);
+      }
+      int numTypeParameters = 0;
+      if (element is TypeParameterizedElement) {
+        numTypeParameters = element.typeParameters.length;
+      }
+      LinkedReferenceBuilder linkedReference = new LinkedReferenceBuilder(
+          dependency: librarySerializer.serializeDependency(dependentLibrary),
+          kind: _getReferenceKind(element),
+          unit: unit,
+          numTypeParameters: numTypeParameters);
+      String name = element == null ? 'void' : element.name;
+      if (linked) {
+        linkedReference.name = name;
+      } else {
+        assert(unlinkedReferences.length == linkedReferences.length);
+        int prefixReference = 0;
+        Element enclosing = element?.enclosingElement;
+        if (enclosing == null || enclosing is CompilationUnitElement) {
+          // Figure out a prefix that may be used to refer to the given element.
+          // TODO(paulberry): to avoid subtle relinking inconsistencies we
+          // should use the actual prefix from the AST (a given type may be
+          // reachable via multiple prefixes), but sadly, this information is
+          // not recorded in the element model.
+          PrefixElement prefix = librarySerializer.prefixMap[element];
+          if (prefix != null) {
+            prefixReference = serializePrefix(prefix);
+          }
+        } else {
+          prefixReference = _getElementReferenceId(enclosing, linked: linked);
+        }
+        unlinkedReferences.add(new UnlinkedReferenceBuilder(
+            name: name, prefixReference: prefixReference));
+      }
+      int index = linkedReferences.length;
+      linkedReferences.add(linkedReference);
+      return index;
+    });
+  }
+
+  int _getLengthPropertyReference(int prefix) {
+    assert(unlinkedReferences.length == linkedReferences.length);
+    int index = linkedReferences.length;
+    unlinkedReferences.add(
+        new UnlinkedReferenceBuilder(name: 'length', prefixReference: prefix));
+    LinkedReferenceBuilder linkedReference =
+        new LinkedReferenceBuilder(kind: ReferenceKind.length);
+    linkedReferences.add(linkedReference);
+    return index;
+  }
+}
+
+/**
+ * Instances of this class keep track of intermediate state during
+ * serialization of a single constant [Expression].
+ */
+class _ConstExprSerializer extends AbstractConstExprSerializer {
+  final _CompilationUnitSerializer serializer;
+
+  _ConstExprSerializer(this.serializer);
+
+  @override
+  EntityRefBuilder serializeConstructorName(ConstructorName constructor) {
+    ConstructorElement element = constructor.staticElement;
+    assert(element != null);
+    int referenceId = serializer._getElementReferenceId(element);
+    return new EntityRefBuilder(reference: referenceId);
+  }
+
+  EntityRefBuilder serializeIdentifier(Identifier identifier) {
+    Element element = identifier.staticElement;
+    assert(element != null);
+    // The only supported instance property accessor - `length`.
+    if (identifier is PrefixedIdentifier &&
+        element is PropertyAccessorElement &&
+        !element.isStatic) {
+      assert(element.name == 'length');
+      Element prefixElement = identifier.prefix.staticElement;
+      int prefixRef = serializer._getElementReferenceId(prefixElement);
+      int lengthRef = serializer._getLengthPropertyReference(prefixRef);
+      return new EntityRefBuilder(reference: lengthRef);
+    }
+    return new EntityRefBuilder(
+        reference: serializer._getElementReferenceId(element));
+  }
+
+  @override
+  EntityRefBuilder serializePropertyAccess(PropertyAccess access) {
+    Element element = access.propertyName.staticElement;
+    assert(element != null);
+    // The only supported instance property accessor - `length`.
+    Expression target = access.target;
+    if (target is Identifier &&
+        element is PropertyAccessorElement &&
+        !element.isStatic) {
+      assert(element.name == 'length');
+      Element prefixElement = target.staticElement;
+      int prefixRef = serializer._getElementReferenceId(prefixElement);
+      int lengthRef = serializer._getLengthPropertyReference(prefixRef);
+      return new EntityRefBuilder(reference: lengthRef);
+    }
+    return new EntityRefBuilder(
+        reference: serializer._getElementReferenceId(element));
+  }
+
+  @override
+  EntityRefBuilder serializeType(TypeName typeName) {
+    DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance;
+    return serializer.serializeTypeRef(type, null);
+  }
+}
+
+/**
+ * Instances of this class keep track of intermediate state during
+ * serialization of a single library.
+ */
+class _LibrarySerializer {
+  /**
+   * The library to be serialized.
+   */
+  final LibraryElement libraryElement;
+
+  /**
+   * The type provider.  This is used to locate the library for `dart:core`.
+   */
+  final TypeProvider typeProvider;
+
+  /**
+   * Indicates whether the element model being serialized was analyzed using
+   * strong mode.
+   */
+  final bool strongMode;
+
+  /**
+   * Map from [LibraryElement] to the index of the entry in the "dependency
+   * table" that refers to it.
+   */
+  final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{};
+
+  /**
+   * The "dependency table".  This is the list of objects which should be
+   * written to [LinkedLibrary.dependencies].
+   */
+  final List<LinkedDependencyBuilder> dependencies =
+      <LinkedDependencyBuilder>[];
+
+  /**
+   * The linked portion of the "imports table".  This is the list of ints
+   * which should be written to [LinkedLibrary.imports].
+   */
+  final List<int> linkedImports = <int>[];
+
+  /**
+   * Set of libraries which have been seen so far while visiting the transitive
+   * closure of exports.
+   */
+  final Set<LibraryElement> librariesAddedToTransitiveExportClosure =
+      new Set<LibraryElement>();
+
+  /**
+   * Map from imported element to the prefix which may be used to refer to that
+   * element; elements for which no prefix is needed are absent from this map.
+   */
+  final Map<Element, PrefixElement> prefixMap = <Element, PrefixElement>{};
+
+  /**
+   * List of serializers for the compilation units constituting this library.
+   */
+  final List<_CompilationUnitSerializer> compilationUnitSerializers =
+      <_CompilationUnitSerializer>[];
+
+  _LibrarySerializer(this.libraryElement, this.typeProvider, this.strongMode) {
+    dependencies.add(new LinkedDependencyBuilder());
+    dependencyMap[libraryElement] = 0;
+  }
+
+  /**
+   * Retrieve a list of the URIs for the compilation units in the library.
+   */
+  List<String> get unitUris => compilationUnitSerializers
+      .map((_CompilationUnitSerializer s) => s.unitUri)
+      .toList();
+
+  /**
+   * Retrieve a list of the [UnlinkedUnitBuilder]s for the compilation units in
+   * the library.
+   */
+  List<UnlinkedUnitBuilder> get unlinkedUnits => compilationUnitSerializers
+      .map((_CompilationUnitSerializer s) => s.unlinkedUnit)
+      .toList();
+
+  /**
+   * Add [exportedLibrary] (and the transitive closure of all libraries it
+   * exports) to the dependency table ([LinkedLibrary.dependencies]).
+   */
+  void addTransitiveExportClosure(LibraryElement exportedLibrary) {
+    if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) {
+      serializeDependency(exportedLibrary);
+      for (LibraryElement transitiveExport
+          in exportedLibrary.exportedLibraries) {
+        addTransitiveExportClosure(transitiveExport);
+      }
+    }
+  }
+
+  /**
+   * Fill in [prefixMap] using information from [libraryElement.imports].
+   */
+  void computePrefixMap() {
+    for (ImportElement import in libraryElement.imports) {
+      if (import.prefix == null) {
+        continue;
+      }
+      import.importedLibrary.exportNamespace.definedNames
+          .forEach((String name, Element e) {
+        if (new NameFilter.forNamespaceCombinators(import.combinators)
+            .accepts(name)) {
+          prefixMap[e] = import.prefix;
+        }
+      });
+    }
+  }
+
+  /**
+   * Return the index of the entry in the dependency table
+   * ([LinkedLibrary.dependencies]) for the given [dependentLibrary].  A new
+   * entry is added to the table if necessary to satisfy the request.
+   */
+  int serializeDependency(LibraryElement dependentLibrary) {
+    return dependencyMap.putIfAbsent(dependentLibrary, () {
+      int index = dependencies.length;
+      List<String> parts = dependentLibrary.parts
+          .map((CompilationUnitElement e) => e.source.uri.toString())
+          .toList();
+      dependencies.add(new LinkedDependencyBuilder(
+          uri: dependentLibrary.source.uri.toString(), parts: parts));
+      return index;
+    });
+  }
+
+  /**
+   * Serialize the whole library element into a [LinkedLibrary].  Should be
+   * called exactly once for each instance of [_LibrarySerializer].
+   *
+   * The unlinked compilation units are stored in [unlinkedUnits], and their
+   * absolute URIs are stored in [unitUris].
+   */
+  LinkedLibraryBuilder serializeLibrary() {
+    computePrefixMap();
+    LinkedLibraryBuilder pb = new LinkedLibraryBuilder();
+    for (ExportElement exportElement in libraryElement.exports) {
+      addTransitiveExportClosure(exportElement.exportedLibrary);
+    }
+    for (ImportElement importElement in libraryElement.imports) {
+      addTransitiveExportClosure(importElement.importedLibrary);
+      linkedImports.add(serializeDependency(importElement.importedLibrary));
+    }
+    compilationUnitSerializers.add(new _CompilationUnitSerializer(
+        this, libraryElement.definingCompilationUnit, 0));
+    for (int i = 0; i < libraryElement.parts.length; i++) {
+      compilationUnitSerializers.add(
+          new _CompilationUnitSerializer(this, libraryElement.parts[i], i + 1));
+    }
+    for (_CompilationUnitSerializer compilationUnitSerializer
+        in compilationUnitSerializers) {
+      compilationUnitSerializer.addCompilationUnitElements();
+    }
+    pb.units = compilationUnitSerializers
+        .map((_CompilationUnitSerializer s) => s.linkedUnit)
+        .toList();
+    pb.dependencies = dependencies;
+    pb.numPrelinkedDependencies = dependencies.length;
+    for (_CompilationUnitSerializer compilationUnitSerializer
+        in compilationUnitSerializers) {
+      compilationUnitSerializer.createLinkedTypes();
+    }
+    pb.importDependencies = linkedImports;
+    List<String> exportedNames =
+        libraryElement.exportNamespace.definedNames.keys.toList();
+    exportedNames.sort();
+    List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
+    for (String name in exportedNames) {
+      if (libraryElement.publicNamespace.definedNames.containsKey(name)) {
+        continue;
+      }
+      Element element = libraryElement.exportNamespace.get(name);
+      LibraryElement dependentLibrary = element.library;
+      CompilationUnitElement unitElement =
+          element.getAncestor((Element e) => e is CompilationUnitElement);
+      int unit = dependentLibrary.units.indexOf(unitElement);
+      assert(unit != -1);
+      ReferenceKind kind = _getReferenceKind(element);
+      exportNames.add(new LinkedExportNameBuilder(
+          name: name,
+          dependency: serializeDependency(dependentLibrary),
+          unit: unit,
+          kind: kind));
+    }
+    pb.exportNames = exportNames;
+    return pb;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 4d9b9fe..95c33f4 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -10,12 +10,15 @@
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart' show Source, SourceKind;
+import 'package:analyzer/src/generated/source.dart'
+    show DartUriResolver, Source, SourceFactory, SourceKind;
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/task/dart.dart'
     show
+        CONSTANT_VALUE,
         LIBRARY_ELEMENT1,
         LIBRARY_ELEMENT2,
         LIBRARY_ELEMENT3,
@@ -32,32 +35,40 @@
 import 'package:analyzer/task/model.dart'
     show AnalysisTarget, ResultDescriptor, TargetedResult;
 
-/**
- * An [SdkAnalysisContext] for Dart SDK with a summary [SdkBundle].
- */
-class SummarySdkAnalysisContext extends SdkAnalysisContext {
+class SdkSummaryResultProvider implements SummaryResultProvider {
+  final InternalAnalysisContext context;
   final SdkBundle bundle;
   final SummaryTypeProvider typeProvider = new SummaryTypeProvider();
 
+  @override
   SummaryResynthesizer resynthesizer;
 
-  SummarySdkAnalysisContext(this.bundle);
+  SdkSummaryResultProvider(this.context, this.bundle) {
+    resynthesizer = new SdkSummaryResynthesizer(
+        context, typeProvider, context.sourceFactory, bundle);
+    _buildCoreLibrary();
+    _buildAsyncLibrary();
+    resynthesizer.finalizeCoreAsyncLibraries();
+    context.typeProvider = typeProvider;
+  }
 
   @override
-  bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
-    if (resynthesizer == null) {
-      resynthesizer = new SummaryResynthesizer(this, typeProvider,
-          _getPrelinkedSummary, _getUnlinkedSummary, sourceFactory);
-      _buildCoreLibrary();
-      _buildAsyncLibrary();
-    }
+  bool compute(CacheEntry entry, ResultDescriptor result) {
     if (result == TYPE_PROVIDER) {
+//      print('SummarySdkAnalysisContext: $result');
       entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
       return true;
     }
     AnalysisTarget target = entry.target;
-//    print('SummarySdkAnalysisContext: $result of $target');
+    // TODO(scheglov) we don't actually update "evaluationResult" yet
+    if (result == CONSTANT_VALUE) {
+      if (target.source != null && target.source.isInSystemLibrary) {
+        entry.setValue(result, target, TargetedResult.EMPTY_LIST);
+        return true;
+      }
+    }
     if (target is Source && target.isInSystemLibrary) {
+//      print('SummarySdkAnalysisContext: $result of $target');
       if (result == LIBRARY_ELEMENT1 ||
           result == LIBRARY_ELEMENT2 ||
           result == LIBRARY_ELEMENT3 ||
@@ -80,12 +91,9 @@
         return true;
       } else if (result == SOURCE_KIND) {
         String uri = target.uri.toString();
-        if (bundle.prelinkedLibraryUris.contains(uri)) {
-          entry.setValue(result, SourceKind.LIBRARY, TargetedResult.EMPTY_LIST);
-          return true;
-        }
-        if (bundle.unlinkedUnitUris.contains(uri)) {
-          entry.setValue(result, SourceKind.PART, TargetedResult.EMPTY_LIST);
+        SourceKind kind = _getSourceKind(uri);
+        if (kind != null) {
+          entry.setValue(result, kind, TargetedResult.EMPTY_LIST);
           return true;
         }
         return false;
@@ -106,23 +114,65 @@
     typeProvider.initializeCore(library);
   }
 
-  PrelinkedLibrary _getPrelinkedSummary(String uri) {
-    for (int i = 0; i < bundle.prelinkedLibraryUris.length; i++) {
-      if (bundle.prelinkedLibraryUris[i] == uri) {
-        return bundle.prelinkedLibraries[i];
-      }
+  /**
+   * Return the [SourceKind] of the given [uri] or `null` if it is unknown.
+   */
+  SourceKind _getSourceKind(String uri) {
+    if (bundle.linkedLibraryUris.contains(uri)) {
+      return SourceKind.LIBRARY;
     }
-    throw new StateError('Unable to find prelinked summary for $uri');
+    if (bundle.unlinkedUnitUris.contains(uri)) {
+      return SourceKind.PART;
+    }
+    return null;
+  }
+}
+
+/**
+ * The implementation of [SummaryResynthesizer] for Dart SDK.
+ */
+class SdkSummaryResynthesizer extends SummaryResynthesizer {
+  final SdkBundle bundle;
+  final Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
+  final Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{};
+
+  SdkSummaryResynthesizer(AnalysisContext context, TypeProvider typeProvider,
+      SourceFactory sourceFactory, this.bundle)
+      : super(null, context, typeProvider, sourceFactory, false) {
+    // TODO(paulberry): we always resynthesize the summary in weak mode.  Is
+    // this ok?
+    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
+      unlinkedSummaries[bundle.unlinkedUnitUris[i]] = bundle.unlinkedUnits[i];
+    }
+    for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
+      linkedSummaries[bundle.linkedLibraryUris[i]] = bundle.linkedLibraries[i];
+    }
   }
 
-  UnlinkedUnit _getUnlinkedSummary(String uri) {
-    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
-      if (bundle.unlinkedUnitUris[i] == uri) {
-        return bundle.unlinkedUnits[i];
-      }
-    }
-    throw new StateError('Unable to find unlinked summary for $uri');
+  @override
+  LinkedLibrary getLinkedSummary(String uri) {
+    return linkedSummaries[uri];
   }
+
+  @override
+  UnlinkedUnit getUnlinkedSummary(String uri) {
+    return unlinkedSummaries[uri];
+  }
+
+  @override
+  bool hasLibrarySummary(String uri) {
+    return uri.startsWith('dart:');
+  }
+}
+
+/**
+ * Provider for analysis results.
+ */
+abstract class SummaryResultProvider extends ResultProvider {
+  /**
+   * The [SummaryResynthesizer] of this context, maybe `null`.
+   */
+  SummaryResynthesizer get resynthesizer;
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index df4e7ac..2c99cd2 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -6,11 +6,14 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/context/cache.dart';
+import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -1226,10 +1229,24 @@
     TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
     //
+    // Build the enum members if they have not already been created.
+    //
+    EnumDeclaration findFirstEnum() {
+      for (CompilationUnitMember member in unit.declarations) {
+        if (member is EnumDeclaration) {
+          return member;
+        }
+      }
+      return null;
+    }
+    EnumDeclaration firstEnum = findFirstEnum();
+    if (firstEnum != null && firstEnum.element.accessors.isEmpty) {
+      EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
+      unit.accept(builder);
+    }
+    //
     // Record outputs.
     //
-    EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
-    unit.accept(builder);
     outputs[CREATED_RESOLVED_UNIT2] = true;
     outputs[RESOLVED_UNIT2] = unit;
   }
@@ -1395,7 +1412,6 @@
     //
     // Update "part" directives.
     //
-    LibraryDirective libraryDirective = null;
     LibraryIdentifier libraryNameNode = null;
     String partsLibraryName = _UNKNOWN_LIBRARY_NAME;
     bool hasPartDirective = false;
@@ -1406,11 +1422,8 @@
         <CompilationUnitElementImpl>[];
     for (Directive directive in definingCompilationUnit.directives) {
       if (directive is LibraryDirective) {
-        if (libraryDirective == null) {
-          libraryDirective = directive;
-          libraryNameNode = directive.name;
-          directivesToResolve.add(directive);
-        }
+        libraryNameNode = directive.name;
+        directivesToResolve.add(directive);
       } else if (directive is PartDirective) {
         PartDirective partDirective = directive;
         StringLiteral partUri = partDirective.uri;
@@ -1488,12 +1501,13 @@
     for (Directive directive in directivesToResolve) {
       directive.element = libraryElement;
     }
-    if (sourcedCompilationUnits.isNotEmpty) {
-      _patchTopLevelAccessors(libraryElement);
+    BuildLibraryElementUtils.patchTopLevelAccessors(libraryElement);
+    // set the library documentation to the docs associated with the first
+    // directive in the compilation unit.
+    if (definingCompilationUnit.directives.isNotEmpty) {
+      _setDoc(libraryElement, definingCompilationUnit.directives.first);
     }
-    if (libraryDirective != null) {
-      _setDoc(libraryElement, libraryDirective);
-    }
+
     //
     // Record outputs.
     //
@@ -1503,25 +1517,6 @@
   }
 
   /**
-   * Add all of the non-synthetic [getters] and [setters] defined in the given
-   * [unit] that have no corresponding accessor to one of the given collections.
-   */
-  void _collectAccessors(Map<String, PropertyAccessorElement> getters,
-      List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
-    for (PropertyAccessorElement accessor in unit.accessors) {
-      if (accessor.isGetter) {
-        if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
-          getters[accessor.displayName] = accessor;
-        }
-      } else {
-        if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
-          setters.add(accessor);
-        }
-      }
-    }
-  }
-
-  /**
    * Return the top-level [FunctionElement] entry point, or `null` if the given
    * [element] does not define an entry point.
    */
@@ -1553,33 +1548,6 @@
   }
 
   /**
-   * Look through all of the compilation units defined for the given [library],
-   * looking for getters and setters that are defined in different compilation
-   * units but that have the same names. If any are found, make sure that they
-   * have the same variable element.
-   */
-  void _patchTopLevelAccessors(LibraryElementImpl library) {
-    HashMap<String, PropertyAccessorElement> getters =
-        new HashMap<String, PropertyAccessorElement>();
-    List<PropertyAccessorElement> setters = <PropertyAccessorElement>[];
-    _collectAccessors(getters, setters, library.definingCompilationUnit);
-    for (CompilationUnitElement unit in library.parts) {
-      _collectAccessors(getters, setters, unit);
-    }
-    for (PropertyAccessorElement setter in setters) {
-      PropertyAccessorElement getter = getters[setter.displayName];
-      if (getter != null) {
-        TopLevelVariableElementImpl variable = getter.variable;
-        TopLevelVariableElementImpl setterVariable = setter.variable;
-        CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement;
-        setterUnit.replaceTopLevelVariable(setterVariable, variable);
-        variable.setter = setter;
-        (setter as PropertyAccessorElementImpl).variable = variable;
-      }
-    }
-  }
-
-  /**
    * If the given [node] has a documentation comment, remember its content
    * and range into the given [element].
    */
@@ -1765,6 +1733,11 @@
     //
     // Record outputs.
     //
+    if (!context.analysisOptions.enableAsync) {
+      AnalysisContextImpl contextImpl = context;
+      asyncLibrary = contextImpl.createMockAsyncLib(coreLibrary);
+      asyncNamespace = asyncLibrary.publicNamespace;
+    }
     TypeProvider typeProvider =
         new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace);
     (context as InternalAnalysisContext).typeProvider = typeProvider;
@@ -3257,14 +3230,7 @@
       if (newType == null || newType.isBottom) {
         newType = typeProvider.dynamicType;
       }
-      variable.type = newType;
-      (variable.initializer as ExecutableElementImpl).returnType = newType;
-      if (variable is PropertyInducingElementImpl) {
-        setReturnType(variable.getter, newType);
-        if (!variable.isFinal && !variable.isConst) {
-          setParameterType(variable.setter, newType);
-        }
-      }
+      setFieldType(variable, newType);
     } else {
       // TODO(brianwilkerson) For now we simply don't infer any type for
       // variables or fields involved in a cycle. We could try to be smarter
@@ -3591,6 +3557,16 @@
     HashSet<Source> importedSourceSet =
         new HashSet.from(explicitlyImportedSourceSet);
     Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
+    if (coreLibrarySource == null) {
+      String message;
+      DartSdk sdk = context.sourceFactory.dartSdk;
+      if (sdk == null) {
+        message = 'Could not resolve "dart:core": SDK not defined';
+      } else {
+        message = 'Could not resolve "dart:core": SDK incorrectly configured';
+      }
+      throw new AnalysisException(message);
+    }
     importedSourceSet.add(coreLibrarySource);
     //
     // Compute kind.
@@ -5087,7 +5063,8 @@
       'ScanDartTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM]);
+      <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM],
+      suitabilityFor: suitabilityFor);
 
   /**
    * Initialize a newly created task to access the content of the source
@@ -5183,6 +5160,21 @@
       AnalysisContext context, AnalysisTarget target) {
     return new ScanDartTask(context, target);
   }
+
+  /**
+   * Return an indication of how suitable this task is for the given [target].
+   */
+  static TaskSuitability suitabilityFor(AnalysisTarget target) {
+    if (target is Source) {
+      if (target.shortName.endsWith(AnalysisEngine.SUFFIX_DART)) {
+        return TaskSuitability.HIGHEST;
+      }
+      return TaskSuitability.LOWEST;
+    } else if (target is DartScript) {
+      return TaskSuitability.HIGHEST;
+    }
+    return TaskSuitability.NONE;
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index db9cd1d..0f3b523 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -154,7 +154,7 @@
   /**
    * Create a work order that will produce the given [result] for the given
    * [target]. Return the work order that was created, or `null` if the result
-   * has already been computed.
+   * has either already been computed or cannot be computed.
    */
   WorkOrder createWorkOrderForResult(
       AnalysisTarget target, ResultDescriptor result) {
@@ -166,6 +166,9 @@
       return null;
     }
     TaskDescriptor taskDescriptor = taskManager.findTask(target, result);
+    if (taskDescriptor == null) {
+      return null;
+    }
     try {
       WorkItem workItem =
           new WorkItem(context, target, taskDescriptor, result, 0, null);
@@ -709,11 +712,22 @@
           try {
             TaskDescriptor descriptor =
                 taskManager.findTask(inputTarget, inputResult);
+            if (descriptor == null) {
+              throw new AnalysisException(
+                  'Cannot find task to build $inputResult for $inputTarget');
+            }
             return new WorkItem(context, inputTarget, descriptor, inputResult,
                 level + 1, workOrder);
           } on AnalysisException catch (exception, stackTrace) {
             this.exception = new CaughtException(exception, stackTrace);
             return null;
+          } catch (exception, stackTrace) {
+            this.exception = new CaughtException(
+                throw new AnalysisException(
+                    'Cannot create work order to build $inputResult for $inputTarget',
+                    exception),
+                stackTrace);
+            return null;
           }
         }
       } else {
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index b6a771a..01cdd5a 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -279,7 +279,8 @@
       'ParseHtmlTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[HTML_DOCUMENT, HTML_DOCUMENT_ERRORS, LINE_INFO]);
+      <ResultDescriptor>[HTML_DOCUMENT, HTML_DOCUMENT_ERRORS, LINE_INFO],
+      suitabilityFor: suitabilityFor);
 
   /**
    * Initialize a newly created task to access the content of the source
@@ -358,6 +359,20 @@
   }
 
   /**
+   * Return an indication of how suitable this task is for the given [target].
+   */
+  static TaskSuitability suitabilityFor(AnalysisTarget target) {
+    if (target is Source) {
+      String name = target.shortName;
+      if (name.endsWith(AnalysisEngine.SUFFIX_HTML) ||
+          name.endsWith(AnalysisEngine.SUFFIX_HTM)) {
+        return TaskSuitability.HIGHEST;
+      }
+    }
+    return TaskSuitability.NONE;
+  }
+
+  /**
    * Compute [LineInfo] for the given [content].
    */
   static LineInfo _computeLineInfo(String content) {
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 07550c5..05029d3 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -6,10 +6,11 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/lib/src/task/manager.dart b/pkg/analyzer/lib/src/task/manager.dart
index eebc084..c8252fa 100644
--- a/pkg/analyzer/lib/src/task/manager.dart
+++ b/pkg/analyzer/lib/src/task/manager.dart
@@ -83,7 +83,7 @@
       throw new AnalysisException(
           'No tasks registered to compute $result for $target');
     }
-    return _findBestTask(descriptors);
+    return _findBestTask(descriptors, target);
   }
 
   /**
@@ -104,11 +104,20 @@
 
   /**
    * Given a list of task [descriptors] that can be used to compute some
-   * unspecified result, return the descriptor that will compute the result with
-   * the least amount of work.
+   * unspecified result for the given [target], return the descriptor that
+   * should be used to compute the result.
    */
-  TaskDescriptor _findBestTask(List<TaskDescriptor> descriptors) {
-    // TODO(brianwilkerson) Improve this implementation.
-    return descriptors[0];
+  TaskDescriptor _findBestTask(
+      List<TaskDescriptor> descriptors, AnalysisTarget target) {
+    TaskDescriptor best = null;
+    for (TaskDescriptor descriptor in descriptors) {
+      TaskSuitability suitability = descriptor.suitabilityFor(target);
+      if (suitability == TaskSuitability.HIGHEST) {
+        return descriptor;
+      } else if (best == null && suitability == TaskSuitability.LOWEST) {
+        best = descriptor;
+      }
+    }
+    return best;
   }
 }
diff --git a/pkg/analyzer/lib/src/task/model.dart b/pkg/analyzer/lib/src/task/model.dart
index 8eaa838..56e2827 100644
--- a/pkg/analyzer/lib/src/task/model.dart
+++ b/pkg/analyzer/lib/src/task/model.dart
@@ -126,13 +126,23 @@
   final List<ResultDescriptor> results;
 
   /**
+   * The function used to determine whether the described task is suitable for
+   * a given target.
+   */
+  final SuitabilityFor _suitabilityFor;
+
+  /**
    * Initialize a newly created task descriptor to have the given [name] and to
-   * describe a task that takes the inputs built using the given [createTaskInputs],
-   * and produces the given [results]. The [buildTask] will be used to create
-   * the instance of [AnalysisTask] thusly described.
+   * describe a task that takes the inputs built using the given [inputBuilder],
+   * and produces the given [results]. The [buildTask] function will be used to
+   * create the instance of [AnalysisTask] being described. If provided, the
+   * [isAppropriateFor] function will be used to determine whether the task can
+   * be used on a specific target.
    */
   TaskDescriptorImpl(
-      this.name, this.buildTask, this.createTaskInputs, this.results);
+      this.name, this.buildTask, this.createTaskInputs, this.results,
+      {SuitabilityFor suitabilityFor})
+      : _suitabilityFor = suitabilityFor ?? _defaultSuitability;
 
   @override
   AnalysisTask createTask(AnalysisContext context, AnalysisTarget target,
@@ -143,5 +153,16 @@
   }
 
   @override
+  TaskSuitability suitabilityFor(AnalysisTarget target) =>
+      _suitabilityFor(target);
+
+  @override
   String toString() => name;
+
+  /**
+   * The function that will be used to determine the suitability of a task if no
+   * other function is provided.
+   */
+  static TaskSuitability _defaultSuitability(AnalysisTarget target) =>
+      TaskSuitability.LOWEST;
 }
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 6775408..4a6483c 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -202,7 +202,8 @@
       'GenerateOptionsErrorsTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[ANALYSIS_OPTIONS_ERRORS, LINE_INFO]);
+      <ResultDescriptor>[ANALYSIS_OPTIONS_ERRORS, LINE_INFO],
+      suitabilityFor: suitabilityFor);
 
   final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
 
@@ -257,6 +258,17 @@
   static GenerateOptionsErrorsTask createTask(
           AnalysisContext context, AnalysisTarget target) =>
       new GenerateOptionsErrorsTask(context, target);
+
+  /**
+   * Return an indication of how suitable this task is for the given [target].
+   */
+  static TaskSuitability suitabilityFor(AnalysisTarget target) {
+    if (target is Source &&
+        target.shortName == AnalysisEngine.ANALYSIS_OPTIONS_FILE) {
+      return TaskSuitability.HIGHEST;
+    }
+    return TaskSuitability.NONE;
+  }
 }
 
 /// Validates `analyzer` language configuration options.
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 29857b0..a67251e7 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -7,10 +7,11 @@
 library analyzer.src.task.strong.checker;
 
 import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+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/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
 import 'package:analyzer/src/generated/type_system.dart';
@@ -129,14 +130,9 @@
       Expression arg = list[i];
       ParameterElement element = arg.staticParameterElement;
       if (element == null) {
-        if (type.parameters.length < len) {
-          // We found an argument mismatch, the analyzer will report this too,
-          // so no need to insert an error for this here.
-          continue;
-        }
-        element = type.parameters[i];
-        // TODO(vsm): When can this happen?
-        assert(element != null);
+        // We found an argument mismatch, the analyzer will report this too,
+        // so no need to insert an error for this here.
+        continue;
       }
       DartType expectedType = _elementType(element);
       if (expectedType == null) expectedType = DynamicTypeImpl.instance;
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index cf4f822..4f39f6b 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -8,10 +8,10 @@
 // refactored to fit into analyzer.
 library analyzer.src.task.strong.info;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 
@@ -95,13 +95,15 @@
             baseType.isAssignableTo(_cast.toType)));
   }
 
-  @override List<Object> get arguments => [node, baseType, convertedType];
+  @override
+  List<Object> get arguments => [baseType, convertedType];
 
   Cast get cast => _cast;
 
   DartType get convertedType => _cast.toType;
-  @override String get message => '{0} ({1}) will need runtime check '
-      'to cast to type {2}';
+
+  @override
+  String get message => 'Unsound implicit cast from {0} to {1}';
 
   // Factory to create correct DownCast variant.
   static StaticInfo create(
@@ -122,20 +124,18 @@
     }
 
     // Inference "casts":
-    if (expression is Literal) {
+    if (expression is Literal || expression is FunctionExpression) {
       // fromT should be an exact type - this will almost certainly fail at
       // runtime.
       return new StaticTypeError(rules, expression, toT, reason: reason);
     }
-    if (expression is FunctionExpression) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      return new UninferredClosure(rules, expression, cast);
-    }
     if (expression is InstanceCreationExpression) {
-      // fromT should be an exact type - this will almost certainly fail at
-      // runtime.
-      return new StaticTypeError(rules, expression, toT, reason: reason);
+      ConstructorElement e = expression.staticElement;
+      if (e == null || !e.isFactory) {
+        // fromT should be an exact type - this will almost certainly fail at
+        // runtime.
+        return new StaticTypeError(rules, expression, toT, reason: reason);
+      }
     }
 
     // TODO(vsm): Change this to an assert when we have generic methods and
@@ -292,9 +292,11 @@
       TypeSystem rules, Expression expression, this._type)
       : super(rules, expression);
 
-  @override List get arguments => [node, type];
+  @override
+  List get arguments => [node, type];
   DartType get convertedType => type;
-  @override String get message => '{0} has inferred type {1}';
+  @override
+  String get message => '{0} has inferred type {1}';
   DartType get type => _type;
 
   toErrorCode() => new HintCode(name, message);
@@ -370,7 +372,8 @@
         fromMixin = node.parent is WithClause,
         super(node);
 
-  @override List<Object> get arguments =>
+  @override
+  List<Object> get arguments =>
       [parent.name, element.name, subType, base, baseType];
 
   ClassElement get parent => element.enclosingElement;
@@ -392,8 +395,10 @@
       TypeSystem rules, FormalParameter declaration, this.expectedType)
       : super(declaration);
 
-  @override List<Object> get arguments => [node, expectedType];
-  @override String get message => 'Type check failed: {0} is not of type {1}';
+  @override
+  List<Object> get arguments => [node, expectedType];
+  @override
+  String get message => 'Type check failed: {0} is not of type {1}';
   @override
   String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION';
 }
@@ -424,14 +429,15 @@
 /// could be if initializers have side effects.
 ///
 /// Better to have `super` at the end, as required by the Dart style guide:
-/// <http://goo.gl/q1T4BB>
+/// <https://goo.gl/EY6hDP>
 ///
 /// For now this is the only pattern we support.
 class InvalidSuperInvocation extends StaticError {
   InvalidSuperInvocation(SuperConstructorInvocation node) : super(node);
 
-  @override String get message => "super call must be last in an initializer "
-      "list (see http://goo.gl/q1T4BB): {0}";
+  @override
+  String get message => "super call must be last in an initializer "
+      "list (see https://goo.gl/EY6hDP): {0}";
 
   @override
   String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION';
@@ -444,8 +450,10 @@
       TypeSystem rules, AstNode declaration, this.expectedType)
       : super(declaration);
 
-  @override List<Object> get arguments => [expectedType];
-  @override String get message => 'Type check failed: null is not of type {0}';
+  @override
+  List<Object> get arguments => [expectedType];
+  @override
+  String get message => 'Type check failed: null is not of type {0}';
 
   @override
   String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION';
@@ -459,7 +467,8 @@
     assert(node is IsExpression || node is AsExpression);
   }
 
-  @override List<Object> get arguments => [type];
+  @override
+  List<Object> get arguments => [type];
   String get message =>
       "Runtime check on non-ground type {0} may throw StrongModeError";
 
@@ -541,31 +550,13 @@
       : baseType = expression.staticType ?? DynamicTypeImpl.instance,
         super(expression);
 
-  @override List<Object> get arguments => [node, baseType, expectedType];
-  @override String get message =>
+  @override
+  List<Object> get arguments => [node, baseType, expectedType];
+  @override
+  String get message =>
       'Type check failed: {0} ({1}) is not of type {2}' +
       ((reason == null) ? '' : ' because $reason');
 
   @override
   String get name => 'STRONG_MODE_STATIC_TYPE_ERROR';
 }
-
-//
-// Temporary "casts" of allocation sites - literals, constructor invocations,
-// and closures.  These should be handled by contextual inference.  In most
-// cases, inference will be sufficient, though in some it may unmask an actual
-// error: e.g.,
-//   List<int> l = [1, 2, 3]; // Inference succeeds
-//   List<String> l = [1, 2, 3]; // Inference reveals static type error
-// We're marking all as warnings for now.
-//
-// TODO(vsm,leafp): Remove this.
-class UninferredClosure extends DownCast {
-  UninferredClosure(TypeSystem rules, FunctionExpression expression, Cast cast)
-      : super._internal(rules, expression, cast);
-
-  @override
-  String get name => 'STRONG_MODE_UNINFERRED_CLOSURE';
-
-  toErrorCode() => new StaticTypeWarningCode(name, message);
-}
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 46b84e0..05b5f1a 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -6,67 +6,31 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/ast.dart';
 import 'package:analyzer/src/generated/resolver.dart'
     show TypeProvider, InheritanceManager;
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
 /**
- * Set the type of the sole parameter of the given [element] to the given [type].
+ * Sets the type of the field. This is stored in the field itself, and the
+ * synthetic getter/setter types.
  */
-void setParameterType(PropertyAccessorElement element, DartType type) {
-  if (element is PropertyAccessorElementImpl) {
-    ParameterElement parameter = _getParameter(element);
-    if (parameter is ParameterElementImpl) {
-      //
-      // Update the type of the parameter.
-      //
-      parameter.type = type;
-      //
-      // Update the type of the setter to reflect the new parameter type.
-      //
-      // TODO(jmesserly): why is this necessary? The function type should always
-      // delegate to the orginal element.
-      FunctionType functionType = element.type;
-      if (functionType is FunctionTypeImpl) {
-        element.type = new FunctionTypeImpl(element);
-      } else {
-        assert(false);
-      }
-    } else {
-      assert(false);
-    }
-  } else {
-    throw new StateError('element is an instance of ${element.runtimeType}');
-    assert(false);
+void setFieldType(VariableElement field, DartType newType) {
+  (field as VariableElementImpl).type = newType;
+  if (field.initializer != null) {
+    (field.initializer as ExecutableElementImpl).returnType = newType;
   }
-}
-
-/**
- * Set the return type of the given [element] to the given [type].
- */
-void setReturnType(ExecutableElement element, DartType type) {
-  if (element is ExecutableElementImpl) {
-    //
-    // Update the return type of the element, which is stored in two places:
-    // directly in the element and indirectly in the type of the element.
-    //
-    // TODO(jmesserly): why is this necessary? The function type should always
-    // delegate to the orginal element.
-    element.returnType = type;
-    FunctionType functionType = element.type;
-    if (functionType is FunctionTypeImpl) {
-      element.type = new FunctionTypeImpl(element);
-    } else {
-      assert(false);
+  if (field is PropertyInducingElementImpl) {
+    (field.getter as ExecutableElementImpl).returnType = newType;
+    if (!field.isFinal && !field.isConst) {
+      (field.setter.parameters[0] as ParameterElementImpl).type =
+          newType;
     }
-  } else {
-    assert(false);
   }
 }
 
@@ -317,7 +281,8 @@
           !_allSameElementKind(element, overriddenMethods)) {
         return;
       }
-      setReturnType(element, _computeReturnType(overriddenMethods));
+      (element as ExecutableElementImpl).returnType =
+          _computeReturnType(overriddenMethods);
       if (element is PropertyAccessorElement) {
         _updateSyntheticVariableType(element);
       }
@@ -387,11 +352,7 @@
       if (newType == null || newType.isBottom) {
         newType = typeProvider.dynamicType;
       }
-      (fieldElement as FieldElementImpl).type = newType;
-      setReturnType(fieldElement.getter, newType);
-      if (!fieldElement.isFinal && !fieldElement.isConst) {
-        setParameterType(fieldElement.setter, newType);
-      }
+      setFieldType(fieldElement, newType);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/task/yaml.dart b/pkg/analyzer/lib/src/task/yaml.dart
new file mode 100644
index 0000000..8ce7ec1
--- /dev/null
+++ b/pkg/analyzer/lib/src/task/yaml.dart
@@ -0,0 +1,155 @@
+// 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 analyzer.src.task.yaml;
+
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/general.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:analyzer/task/yaml.dart';
+import 'package:source_span/source_span.dart';
+import 'package:yaml/yaml.dart';
+
+/**
+ * A task that scans the content of a YAML file, producing a YAML document.
+ */
+class ParseYamlTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input whose value is the content of the file.
+   */
+  static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ParseYamlTask',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[YAML_DOCUMENT, YAML_ERRORS, LINE_INFO],
+      suitabilityFor: suitabilityFor);
+
+  /**
+   * Initialize a newly created task to access the content of the source
+   * associated with the given [target] in the given [context].
+   */
+  ParseYamlTask(InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    Source source = target.source;
+    String uri = source.uri.toString();
+    String content = getRequiredInput(CONTENT_INPUT_NAME);
+
+    if (context.getModificationStamp(source) < 0) {
+      String message = 'Content could not be read';
+      if (context is InternalAnalysisContext) {
+        CacheEntry entry =
+            (context as InternalAnalysisContext).getCacheEntry(target);
+        CaughtException exception = entry.exception;
+        if (exception != null) {
+          message = exception.toString();
+        }
+      }
+      //
+      // Record outputs.
+      //
+      outputs[YAML_DOCUMENT] = loadYamlDocument('', sourceUrl: uri);
+      outputs[YAML_ERRORS] = <AnalysisError>[
+        new AnalysisError(
+            source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message])
+      ];
+      outputs[LINE_INFO] = new LineInfo(<int>[0]);
+    } else {
+      YamlDocument document;
+      List<AnalysisError> errors = <AnalysisError>[];
+      try {
+        document = loadYamlDocument(content, sourceUrl: uri);
+      } on YamlException catch (exception) {
+        SourceSpan span = exception.span;
+        int offset = span.start.offset;
+        int length = span.end.offset - offset;
+        errors.add(new AnalysisError(source, offset, length,
+            YamlErrorCode.PARSE_ERROR, [exception.message]));
+      } catch (exception, stackTrace) {
+        throw new AnalysisException('Error while parsing ${source.fullName}',
+            new CaughtException(exception, stackTrace));
+      }
+      //
+      // Record outputs.
+      //
+      outputs[YAML_DOCUMENT] = document;
+      outputs[YAML_ERRORS] = errors;
+      outputs[LINE_INFO] = new LineInfo.fromContent(content);
+    }
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the given
+   * [source].
+   */
+  static Map<String, TaskInput> buildInputs(Source source) {
+    return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(source)};
+  }
+
+  /**
+   * Create a [ParseYamlTask] based on the given [target] in the given [context].
+   */
+  static ParseYamlTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ParseYamlTask(context, target);
+  }
+
+  /**
+   * Return an indication of how suitable this task is for the given [target].
+   */
+  static TaskSuitability suitabilityFor(AnalysisTarget target) {
+    if (target is Source && target.shortName.endsWith('.yaml')) {
+      return TaskSuitability.HIGHEST;
+    }
+    return TaskSuitability.NONE;
+  }
+}
+
+/**
+ * The error codes used for errors in YAML files.
+ */
+class YamlErrorCode extends ErrorCode {
+  // TODO(brianwilkerson) Move this class to error.dart.
+
+  /**
+   * An error code indicating that there is a syntactic error in the file.
+   *
+   * Parameters:
+   * 0: the error message from the parse error
+   */
+  static const YamlErrorCode PARSE_ERROR =
+      const YamlErrorCode('PARSE_ERROR', '{0}');
+
+  /**
+   * Initialize a newly created error code to have the given [name]. The message
+   * associated with the error will be created from the given [message]
+   * template. The correction associated with the error will be created from the
+   * given [correction] template.
+   */
+  const YamlErrorCode(String name, String message, [String correction])
+      : super(name, message, correction);
+
+  @override
+  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+  @override
+  ErrorType get type => ErrorType.COMPILE_TIME_ERROR;
+}
diff --git a/pkg/analyzer/lib/task/dart.dart b/pkg/analyzer/lib/task/dart.dart
index 27258c3..ea132e3 100644
--- a/pkg/analyzer/lib/task/dart.dart
+++ b/pkg/analyzer/lib/task/dart.dart
@@ -4,8 +4,8 @@
 
 library analyzer.task.dart;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index c320659..58e095b 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -36,6 +36,14 @@
 typedef Map<String, TaskInput> CreateTaskInputs(AnalysisTarget target);
 
 /**
+ * A function that takes the target for which a task will produce results and
+ * returns an indication of how suitable the task is for the target. Such
+ * functions are passed to a [TaskDescriptor] to be used to determine their
+ * suitability for computing results.
+ */
+typedef TaskSuitability SuitabilityFor(AnalysisTarget target);
+
+/**
  * A function that converts an object of the type [B] into a [TaskInput].
  * This is used, for example, by a [ListTaskInput] to create task inputs
  * for each value in a list of values.
@@ -355,37 +363,36 @@
    * Return a task input that can be used to compute a flatten list whose
    * elements are combined [subListResult]'s associated with those elements.
    */
-  ListTaskInput /*<V>*/ toFlattenListOf /*<V>*/ (
-      ListResultDescriptor /*<V>*/ subListResult);
+  ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
+      ListResultDescriptor/*<V>*/ subListResult);
 
   /**
    * Return a task input that can be used to compute a list whose elements are
    * the result of passing the elements of this input to the [mapper] function.
    */
-  ListTaskInput /*<V>*/ toList /*<V>*/ (
-      UnaryFunction<E, dynamic /*<=V>*/ > mapper);
+  ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*<=V>*/ > mapper);
 
   /**
    * Return a task input that can be used to compute a list whose elements are
    * [valueResult]'s associated with those elements.
    */
-  ListTaskInput /*<V>*/ toListOf /*<V>*/ (ResultDescriptor /*<V>*/ valueResult);
+  ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult);
 
   /**
    * Return a task input that can be used to compute a map whose keys are the
    * elements of this input and whose values are the result of passing the
    * corresponding key to the [mapper] function.
    */
-  MapTaskInput<E, dynamic /*=V*/ > toMap /*<V>*/ (
-      UnaryFunction<E, dynamic /*=V*/ > mapper);
+  MapTaskInput<E, dynamic/*=V*/ > toMap/*<V>*/(
+      UnaryFunction<E, dynamic/*=V*/ > mapper);
 
   /**
    * Return a task input that can be used to compute a map whose keys are the
    * elements of this input and whose values are the [valueResult]'s associated
    * with those elements.
    */
-  MapTaskInput<AnalysisTarget, dynamic /*=V*/ > toMapOf /*<V>*/ (
-      ResultDescriptor /*<V>*/ valueResult);
+  MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
+      ResultDescriptor/*<V>*/ valueResult);
 }
 
 /**
@@ -400,8 +407,8 @@
    * the result of passing keys [K] and the corresponding elements of [V] to
    * the [mapper] function.
    */
-  TaskInput<List /*<E>*/ > toFlattenList /*<E>*/ (
-      BinaryFunction<K, dynamic /*element of V*/, dynamic /*=E*/ > mapper);
+  TaskInput<List/*<E>*/ > toFlattenList/*<E>*/(
+      BinaryFunction<K, dynamic /*element of V*/, dynamic/*=E*/ > mapper);
 }
 
 /**
@@ -523,14 +530,14 @@
   /**
    * Initialize a newly created task descriptor to have the given [name] and to
    * describe a task that takes the inputs built using the given [inputBuilder],
-   * and produces the given [results]. The [buildTask] will be used to create
-   * the instance of [AnalysisTask] thusly described.
+   * and produces the given [results]. The [buildTask] function will be used to
+   * create the instance of [AnalysisTask] being described. If provided, the
+   * [isAppropriateFor] function will be used to determine whether the task can
+   * be used on a specific target.
    */
-  factory TaskDescriptor(
-      String name,
-      BuildTask buildTask,
-      CreateTaskInputs inputBuilder,
-      List<ResultDescriptor> results) = TaskDescriptorImpl;
+  factory TaskDescriptor(String name, BuildTask buildTask,
+      CreateTaskInputs inputBuilder, List<ResultDescriptor> results,
+      {SuitabilityFor suitabilityFor}) = TaskDescriptorImpl;
 
   /**
    * Return the builder used to build the inputs to the task.
@@ -553,6 +560,11 @@
    */
   AnalysisTask createTask(AnalysisContext context, AnalysisTarget target,
       Map<String, dynamic> inputs);
+
+  /**
+   * Return an indication of how suitable this task is for the given [target].
+   */
+  TaskSuitability suitabilityFor(AnalysisTarget target);
 }
 
 /**
@@ -571,7 +583,7 @@
    * Return a task input that can be used to compute a list whose elements are
    * the result of passing the result of this input to the [mapper] function.
    */
-  ListTaskInput /*<E>*/ mappedToList /*<E>*/ (List /*<E>*/ mapper(V value));
+  ListTaskInput/*<E>*/ mappedToList/*<E>*/(List/*<E>*/ mapper(V value));
 }
 
 /**
@@ -651,6 +663,11 @@
 }
 
 /**
+ * An indication of how suitable a task is for a given target.
+ */
+enum TaskSuitability { NONE, LOWEST, HIGHEST }
+
+/**
  * [WorkManager]s are used to drive analysis.
  *
  * They know specific of the targets and results they care about,
diff --git a/pkg/analyzer/lib/task/yaml.dart b/pkg/analyzer/lib/task/yaml.dart
new file mode 100644
index 0000000..1795d8f
--- /dev/null
+++ b/pkg/analyzer/lib/task/yaml.dart
@@ -0,0 +1,23 @@
+// 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 analyzer.task.yaml;
+
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:yaml/yaml.dart';
+
+/**
+ * The result of parsing a YAML file.
+ */
+final ResultDescriptor<YamlDocument> YAML_DOCUMENT =
+    new ResultDescriptor<YamlDocument>('YAML_DOCUMENT', null);
+
+/**
+ * The analysis errors associated with a [Source] representing a YAML file.
+ */
+final ListResultDescriptor<AnalysisError> YAML_ERRORS =
+    new ListResultDescriptor<AnalysisError>(
+        'YAML_ERRORS', AnalysisError.NO_ERRORS);
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 607b92c..01abc35 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.1+2
+version: 0.27.2-alpha.0
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: http://www.dartlang.org
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
new file mode 100644
index 0000000..f8d51f1
--- /dev/null
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -0,0 +1,1308 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.dart.ast.ast_test;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../generated/parser_test.dart' show ParserTestCase;
+import '../../generated/test_support.dart';
+import '../../reflective_tests.dart';
+import '../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(ClassDeclarationTest);
+  runReflectiveTests(ClassTypeAliasTest);
+  runReflectiveTests(ConstructorDeclarationTest);
+  runReflectiveTests(FieldFormalParameterTest);
+  runReflectiveTests(IndexExpressionTest);
+  runReflectiveTests(NodeListTest);
+  runReflectiveTests(SimpleIdentifierTest);
+  runReflectiveTests(SimpleStringLiteralTest);
+  runReflectiveTests(StringInterpolationTest);
+  runReflectiveTests(VariableDeclarationTest);
+}
+
+@reflectiveTest
+class ClassDeclarationTest extends ParserTestCase {
+  void test_getConstructor() {
+    List<ConstructorInitializer> initializers =
+        new List<ConstructorInitializer>();
+    ConstructorDeclaration defaultConstructor =
+        AstFactory.constructorDeclaration(AstFactory.identifier3("Test"), null,
+            AstFactory.formalParameterList(), initializers);
+    ConstructorDeclaration aConstructor = AstFactory.constructorDeclaration(
+        AstFactory.identifier3("Test"),
+        "a",
+        AstFactory.formalParameterList(),
+        initializers);
+    ConstructorDeclaration bConstructor = AstFactory.constructorDeclaration(
+        AstFactory.identifier3("Test"),
+        "b",
+        AstFactory.formalParameterList(),
+        initializers);
+    ClassDeclaration clazz = AstFactory.classDeclaration(null, "Test", null,
+        null, null, null, [defaultConstructor, aConstructor, bConstructor]);
+    expect(clazz.getConstructor(null), same(defaultConstructor));
+    expect(clazz.getConstructor("a"), same(aConstructor));
+    expect(clazz.getConstructor("b"), same(bConstructor));
+    expect(clazz.getConstructor("noSuchConstructor"), same(null));
+  }
+
+  void test_getField() {
+    VariableDeclaration aVar = AstFactory.variableDeclaration("a");
+    VariableDeclaration bVar = AstFactory.variableDeclaration("b");
+    VariableDeclaration cVar = AstFactory.variableDeclaration("c");
+    ClassDeclaration clazz =
+        AstFactory.classDeclaration(null, "Test", null, null, null, null, [
+      AstFactory.fieldDeclaration2(false, null, [aVar]),
+      AstFactory.fieldDeclaration2(false, null, [bVar, cVar])
+    ]);
+    expect(clazz.getField("a"), same(aVar));
+    expect(clazz.getField("b"), same(bVar));
+    expect(clazz.getField("c"), same(cVar));
+    expect(clazz.getField("noSuchField"), same(null));
+  }
+
+  void test_getMethod() {
+    MethodDeclaration aMethod = AstFactory.methodDeclaration(null, null, null,
+        null, AstFactory.identifier3("a"), AstFactory.formalParameterList());
+    MethodDeclaration bMethod = AstFactory.methodDeclaration(null, null, null,
+        null, AstFactory.identifier3("b"), AstFactory.formalParameterList());
+    ClassDeclaration clazz = AstFactory.classDeclaration(
+        null, "Test", null, null, null, null, [aMethod, bMethod]);
+    expect(clazz.getMethod("a"), same(aMethod));
+    expect(clazz.getMethod("b"), same(bMethod));
+    expect(clazz.getMethod("noSuchMethod"), same(null));
+  }
+
+  void test_isAbstract() {
+    expect(
+        AstFactory
+            .classDeclaration(null, "A", null, null, null, null)
+            .isAbstract,
+        isFalse);
+    expect(
+        AstFactory
+            .classDeclaration(Keyword.ABSTRACT, "B", null, null, null, null)
+            .isAbstract,
+        isTrue);
+  }
+}
+
+@reflectiveTest
+class ClassTypeAliasTest extends ParserTestCase {
+  void test_isAbstract() {
+    expect(
+        AstFactory.classTypeAlias("A", null, null, null, null, null).isAbstract,
+        isFalse);
+    expect(
+        AstFactory
+            .classTypeAlias("B", null, Keyword.ABSTRACT, null, null, null)
+            .isAbstract,
+        isTrue);
+  }
+}
+
+@reflectiveTest
+class ConstructorDeclarationTest extends EngineTestCase {
+  void test_firstTokenAfterCommentAndMetadata_all_inverted() {
+    Token externalKeyword = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    externalKeyword.offset = 14;
+    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
+        Keyword.CONST,
+        Keyword.FACTORY,
+        AstFactory.identifier3('int'),
+        null,
+        null,
+        null,
+        null);
+    declaration.externalKeyword = externalKeyword;
+    declaration.constKeyword.offset = 8;
+    Token factoryKeyword = declaration.factoryKeyword;
+    factoryKeyword.offset = 0;
+    expect(declaration.firstTokenAfterCommentAndMetadata, factoryKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_all_normal() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    token.offset = 0;
+    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
+        Keyword.CONST,
+        Keyword.FACTORY,
+        AstFactory.identifier3('int'),
+        null,
+        null,
+        null,
+        null);
+    declaration.externalKeyword = token;
+    declaration.constKeyword.offset = 9;
+    declaration.factoryKeyword.offset = 15;
+    expect(declaration.firstTokenAfterCommentAndMetadata, token);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_constOnly() {
+    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
+        Keyword.CONST,
+        null,
+        AstFactory.identifier3('int'),
+        null,
+        null,
+        null,
+        null);
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.constKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_externalOnly() {
+    Token externalKeyword = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
+        null, null, AstFactory.identifier3('int'), null, null, null, null);
+    declaration.externalKeyword = externalKeyword;
+    expect(declaration.firstTokenAfterCommentAndMetadata, externalKeyword);
+  }
+
+  void test_firstTokenAfterCommentAndMetadata_factoryOnly() {
+    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
+        null,
+        Keyword.FACTORY,
+        AstFactory.identifier3('int'),
+        null,
+        null,
+        null,
+        null);
+    expect(declaration.firstTokenAfterCommentAndMetadata,
+        declaration.factoryKeyword);
+  }
+}
+
+@reflectiveTest
+class FieldFormalParameterTest extends EngineTestCase {
+  void test_endToken_noParameters() {
+    FieldFormalParameter parameter = AstFactory.fieldFormalParameter2('field');
+    expect(parameter.endToken, parameter.identifier.endToken);
+  }
+
+  void test_endToken_parameters() {
+    FieldFormalParameter parameter = AstFactory.fieldFormalParameter(
+        null, null, 'field', AstFactory.formalParameterList([]));
+    expect(parameter.endToken, parameter.parameters.endToken);
+  }
+}
+
+@reflectiveTest
+class IndexExpressionTest extends EngineTestCase {
+  void test_inGetterContext_assignment_compound_left() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // a[b] += c
+    AstFactory.assignmentExpression(
+        expression, TokenType.PLUS_EQ, AstFactory.identifier3("c"));
+    expect(expression.inGetterContext(), isTrue);
+  }
+
+  void test_inGetterContext_assignment_simple_left() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // a[b] = c
+    AstFactory.assignmentExpression(
+        expression, TokenType.EQ, AstFactory.identifier3("c"));
+    expect(expression.inGetterContext(), isFalse);
+  }
+
+  void test_inGetterContext_nonAssignment() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // a[b] + c
+    AstFactory.binaryExpression(
+        expression, TokenType.PLUS, AstFactory.identifier3("c"));
+    expect(expression.inGetterContext(), isTrue);
+  }
+
+  void test_inSetterContext_assignment_compound_left() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // a[b] += c
+    AstFactory.assignmentExpression(
+        expression, TokenType.PLUS_EQ, AstFactory.identifier3("c"));
+    expect(expression.inSetterContext(), isTrue);
+  }
+
+  void test_inSetterContext_assignment_compound_right() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // c += a[b]
+    AstFactory.assignmentExpression(
+        AstFactory.identifier3("c"), TokenType.PLUS_EQ, expression);
+    expect(expression.inSetterContext(), isFalse);
+  }
+
+  void test_inSetterContext_assignment_simple_left() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // a[b] = c
+    AstFactory.assignmentExpression(
+        expression, TokenType.EQ, AstFactory.identifier3("c"));
+    expect(expression.inSetterContext(), isTrue);
+  }
+
+  void test_inSetterContext_assignment_simple_right() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // c = a[b]
+    AstFactory.assignmentExpression(
+        AstFactory.identifier3("c"), TokenType.EQ, expression);
+    expect(expression.inSetterContext(), isFalse);
+  }
+
+  void test_inSetterContext_nonAssignment() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    AstFactory.binaryExpression(
+        expression, TokenType.PLUS, AstFactory.identifier3("c"));
+    // a[b] + cc
+    expect(expression.inSetterContext(), isFalse);
+  }
+
+  void test_inSetterContext_postfix() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    AstFactory.postfixExpression(expression, TokenType.PLUS_PLUS);
+    // a[b]++
+    expect(expression.inSetterContext(), isTrue);
+  }
+
+  void test_inSetterContext_prefix_bang() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // !a[b]
+    AstFactory.prefixExpression(TokenType.BANG, expression);
+    expect(expression.inSetterContext(), isFalse);
+  }
+
+  void test_inSetterContext_prefix_minusMinus() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // --a[b]
+    AstFactory.prefixExpression(TokenType.MINUS_MINUS, expression);
+    expect(expression.inSetterContext(), isTrue);
+  }
+
+  void test_inSetterContext_prefix_plusPlus() {
+    IndexExpression expression = AstFactory.indexExpression(
+        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
+    // ++a[b]
+    AstFactory.prefixExpression(TokenType.PLUS_PLUS, expression);
+    expect(expression.inSetterContext(), isTrue);
+  }
+}
+
+@reflectiveTest
+class NodeListTest extends EngineTestCase {
+  void test_add() {
+    AstNode parent = AstFactory.argumentList();
+    AstNode firstNode = AstFactory.booleanLiteral(true);
+    AstNode secondNode = AstFactory.booleanLiteral(false);
+    NodeList<AstNode> list = new NodeList<AstNode>(parent);
+    list.insert(0, secondNode);
+    list.insert(0, firstNode);
+    expect(list, hasLength(2));
+    expect(list[0], same(firstNode));
+    expect(list[1], same(secondNode));
+    expect(firstNode.parent, same(parent));
+    expect(secondNode.parent, same(parent));
+    AstNode thirdNode = AstFactory.booleanLiteral(false);
+    list.insert(1, thirdNode);
+    expect(list, hasLength(3));
+    expect(list[0], same(firstNode));
+    expect(list[1], same(thirdNode));
+    expect(list[2], same(secondNode));
+    expect(firstNode.parent, same(parent));
+    expect(secondNode.parent, same(parent));
+    expect(thirdNode.parent, same(parent));
+  }
+
+  void test_add_negative() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      list.insert(-1, AstFactory.booleanLiteral(true));
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_add_tooBig() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      list.insert(1, AstFactory.booleanLiteral(true));
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_addAll() {
+    AstNode parent = AstFactory.argumentList();
+    List<AstNode> firstNodes = new List<AstNode>();
+    AstNode firstNode = AstFactory.booleanLiteral(true);
+    AstNode secondNode = AstFactory.booleanLiteral(false);
+    firstNodes.add(firstNode);
+    firstNodes.add(secondNode);
+    NodeList<AstNode> list = new NodeList<AstNode>(parent);
+    list.addAll(firstNodes);
+    expect(list, hasLength(2));
+    expect(list[0], same(firstNode));
+    expect(list[1], same(secondNode));
+    expect(firstNode.parent, same(parent));
+    expect(secondNode.parent, same(parent));
+    List<AstNode> secondNodes = new List<AstNode>();
+    AstNode thirdNode = AstFactory.booleanLiteral(true);
+    AstNode fourthNode = AstFactory.booleanLiteral(false);
+    secondNodes.add(thirdNode);
+    secondNodes.add(fourthNode);
+    list.addAll(secondNodes);
+    expect(list, hasLength(4));
+    expect(list[0], same(firstNode));
+    expect(list[1], same(secondNode));
+    expect(list[2], same(thirdNode));
+    expect(list[3], same(fourthNode));
+    expect(firstNode.parent, same(parent));
+    expect(secondNode.parent, same(parent));
+    expect(thirdNode.parent, same(parent));
+    expect(fourthNode.parent, same(parent));
+  }
+
+  void test_creation() {
+    AstNode owner = AstFactory.argumentList();
+    NodeList<AstNode> list = new NodeList<AstNode>(owner);
+    expect(list, isNotNull);
+    expect(list, hasLength(0));
+    expect(list.owner, same(owner));
+  }
+
+  void test_get_negative() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      list[-1];
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_get_tooBig() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      list[1];
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_getBeginToken_empty() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    expect(list.beginToken, isNull);
+  }
+
+  void test_getBeginToken_nonEmpty() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    AstNode node =
+        AstFactory.parenthesizedExpression(AstFactory.booleanLiteral(true));
+    list.add(node);
+    expect(list.beginToken, same(node.beginToken));
+  }
+
+  void test_getEndToken_empty() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    expect(list.endToken, isNull);
+  }
+
+  void test_getEndToken_nonEmpty() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    AstNode node =
+        AstFactory.parenthesizedExpression(AstFactory.booleanLiteral(true));
+    list.add(node);
+    expect(list.endToken, same(node.endToken));
+  }
+
+  void test_indexOf() {
+    List<AstNode> nodes = new List<AstNode>();
+    AstNode firstNode = AstFactory.booleanLiteral(true);
+    AstNode secondNode = AstFactory.booleanLiteral(false);
+    AstNode thirdNode = AstFactory.booleanLiteral(true);
+    AstNode fourthNode = AstFactory.booleanLiteral(false);
+    nodes.add(firstNode);
+    nodes.add(secondNode);
+    nodes.add(thirdNode);
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    list.addAll(nodes);
+    expect(list, hasLength(3));
+    expect(list.indexOf(firstNode), 0);
+    expect(list.indexOf(secondNode), 1);
+    expect(list.indexOf(thirdNode), 2);
+    expect(list.indexOf(fourthNode), -1);
+    expect(list.indexOf(null), -1);
+  }
+
+  void test_remove() {
+    List<AstNode> nodes = new List<AstNode>();
+    AstNode firstNode = AstFactory.booleanLiteral(true);
+    AstNode secondNode = AstFactory.booleanLiteral(false);
+    AstNode thirdNode = AstFactory.booleanLiteral(true);
+    nodes.add(firstNode);
+    nodes.add(secondNode);
+    nodes.add(thirdNode);
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    list.addAll(nodes);
+    expect(list, hasLength(3));
+    expect(list.removeAt(1), same(secondNode));
+    expect(list, hasLength(2));
+    expect(list[0], same(firstNode));
+    expect(list[1], same(thirdNode));
+  }
+
+  void test_remove_negative() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      list.removeAt(-1);
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_remove_tooBig() {
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      list.removeAt(1);
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_set() {
+    List<AstNode> nodes = new List<AstNode>();
+    AstNode firstNode = AstFactory.booleanLiteral(true);
+    AstNode secondNode = AstFactory.booleanLiteral(false);
+    AstNode thirdNode = AstFactory.booleanLiteral(true);
+    nodes.add(firstNode);
+    nodes.add(secondNode);
+    nodes.add(thirdNode);
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    list.addAll(nodes);
+    expect(list, hasLength(3));
+    AstNode fourthNode = AstFactory.integer(0);
+    expect(javaListSet(list, 1, fourthNode), same(secondNode));
+    expect(list, hasLength(3));
+    expect(list[0], same(firstNode));
+    expect(list[1], same(fourthNode));
+    expect(list[2], same(thirdNode));
+  }
+
+  void test_set_negative() {
+    AstNode node = AstFactory.booleanLiteral(true);
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      javaListSet(list, -1, node);
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+
+  void test_set_tooBig() {
+    AstNode node = AstFactory.booleanLiteral(true);
+    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
+    try {
+      javaListSet(list, 1, node);
+      fail("Expected IndexOutOfBoundsException");
+    } on RangeError {
+      // Expected
+    }
+  }
+}
+
+@reflectiveTest
+class SimpleIdentifierTest extends ParserTestCase {
+  void test_inDeclarationContext_catch_exception() {
+    SimpleIdentifier identifier =
+        AstFactory.catchClause("e").exceptionParameter;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_catch_stack() {
+    SimpleIdentifier identifier =
+        AstFactory.catchClause2("e", "s").stackTraceParameter;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_classDeclaration() {
+    SimpleIdentifier identifier =
+        AstFactory.classDeclaration(null, "C", null, null, null, null).name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_classTypeAlias() {
+    SimpleIdentifier identifier =
+        AstFactory.classTypeAlias("C", null, null, null, null, null).name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_constructorDeclaration() {
+    SimpleIdentifier identifier = AstFactory
+        .constructorDeclaration(AstFactory.identifier3("C"), "c", null, null)
+        .name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_declaredIdentifier() {
+    DeclaredIdentifier declaredIdentifier = AstFactory.declaredIdentifier3("v");
+    SimpleIdentifier identifier = declaredIdentifier.identifier;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_enumConstantDeclaration() {
+    EnumDeclaration enumDeclaration =
+        AstFactory.enumDeclaration2('MyEnum', ['CONST']);
+    SimpleIdentifier identifier = enumDeclaration.constants[0].name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_enumDeclaration() {
+    EnumDeclaration enumDeclaration =
+        AstFactory.enumDeclaration2('MyEnum', ['A', 'B', 'C']);
+    SimpleIdentifier identifier = enumDeclaration.name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_fieldFormalParameter() {
+    SimpleIdentifier identifier =
+        AstFactory.fieldFormalParameter2("p").identifier;
+    expect(identifier.inDeclarationContext(), isFalse);
+  }
+
+  void test_inDeclarationContext_functionDeclaration() {
+    SimpleIdentifier identifier =
+        AstFactory.functionDeclaration(null, null, "f", null).name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_functionTypeAlias() {
+    SimpleIdentifier identifier =
+        AstFactory.typeAlias(null, "F", null, null).name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_label_false() {
+    SimpleIdentifier identifier =
+        AstFactory.namedExpression2("l", AstFactory.integer(0)).name.label;
+    expect(identifier.inDeclarationContext(), isFalse);
+  }
+
+  void test_inDeclarationContext_label_true() {
+    Label label = AstFactory.label2("l");
+    SimpleIdentifier identifier = label.label;
+    AstFactory.labeledStatement([label], AstFactory.emptyStatement());
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_methodDeclaration() {
+    SimpleIdentifier identifier = AstFactory.identifier3("m");
+    AstFactory.methodDeclaration2(
+        null, null, null, null, identifier, null, null);
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_prefix() {
+    SimpleIdentifier identifier =
+        AstFactory.importDirective3("uri", "pref").prefix;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_simpleFormalParameter() {
+    SimpleIdentifier identifier =
+        AstFactory.simpleFormalParameter3("p").identifier;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_typeParameter_bound() {
+    TypeName bound = AstFactory.typeName4("A");
+    SimpleIdentifier identifier = bound.name as SimpleIdentifier;
+    AstFactory.typeParameter2("E", bound);
+    expect(identifier.inDeclarationContext(), isFalse);
+  }
+
+  void test_inDeclarationContext_typeParameter_name() {
+    SimpleIdentifier identifier = AstFactory.typeParameter("E").name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inDeclarationContext_variableDeclaration() {
+    SimpleIdentifier identifier = AstFactory.variableDeclaration("v").name;
+    expect(identifier.inDeclarationContext(), isTrue);
+  }
+
+  void test_inGetterContext() {
+    for (_WrapperKind wrapper in _WrapperKind.values) {
+      for (_AssignmentKind assignment in _AssignmentKind.values) {
+        SimpleIdentifier identifier = _createIdentifier(wrapper, assignment);
+        if (assignment == _AssignmentKind.SIMPLE_LEFT &&
+            wrapper != _WrapperKind.PREFIXED_LEFT &&
+            wrapper != _WrapperKind.PROPERTY_LEFT) {
+          if (identifier.inGetterContext()) {
+            fail("Expected ${_topMostNode(identifier).toSource()} to be false");
+          }
+        } else {
+          if (!identifier.inGetterContext()) {
+            fail("Expected ${_topMostNode(identifier).toSource()} to be true");
+          }
+        }
+      }
+    }
+  }
+
+  void test_inGetterContext_forEachLoop() {
+    SimpleIdentifier identifier = AstFactory.identifier3("a");
+    Expression iterator = AstFactory.listLiteral();
+    Statement body = AstFactory.block();
+    AstFactory.forEachStatement2(identifier, iterator, body);
+    expect(identifier.inGetterContext(), isFalse);
+  }
+
+  void test_inReferenceContext() {
+    SimpleIdentifier identifier = AstFactory.identifier3("id");
+    AstFactory.namedExpression(
+        AstFactory.label(identifier), AstFactory.identifier3("_"));
+    expect(identifier.inGetterContext(), isFalse);
+    expect(identifier.inSetterContext(), isFalse);
+  }
+
+  void test_inSetterContext() {
+    for (_WrapperKind wrapper in _WrapperKind.values) {
+      for (_AssignmentKind assignment in _AssignmentKind.values) {
+        SimpleIdentifier identifier = _createIdentifier(wrapper, assignment);
+        if (wrapper == _WrapperKind.PREFIXED_LEFT ||
+            wrapper == _WrapperKind.PROPERTY_LEFT ||
+            assignment == _AssignmentKind.BINARY ||
+            assignment == _AssignmentKind.COMPOUND_RIGHT ||
+            assignment == _AssignmentKind.PREFIX_NOT ||
+            assignment == _AssignmentKind.SIMPLE_RIGHT ||
+            assignment == _AssignmentKind.NONE) {
+          if (identifier.inSetterContext()) {
+            fail("Expected ${_topMostNode(identifier).toSource()} to be false");
+          }
+        } else {
+          if (!identifier.inSetterContext()) {
+            fail("Expected ${_topMostNode(identifier).toSource()} to be true");
+          }
+        }
+      }
+    }
+  }
+
+  void test_inSetterContext_forEachLoop() {
+    SimpleIdentifier identifier = AstFactory.identifier3("a");
+    Expression iterator = AstFactory.listLiteral();
+    Statement body = AstFactory.block();
+    AstFactory.forEachStatement2(identifier, iterator, body);
+    expect(identifier.inSetterContext(), isTrue);
+  }
+
+  void test_isQualified_inMethodInvocation_noTarget() {
+    MethodInvocation invocation =
+        AstFactory.methodInvocation2("test", [AstFactory.identifier3("arg0")]);
+    SimpleIdentifier identifier = invocation.methodName;
+    expect(identifier.isQualified, isFalse);
+  }
+
+  void test_isQualified_inMethodInvocation_withTarget() {
+    MethodInvocation invocation = AstFactory.methodInvocation(
+        AstFactory.identifier3("target"),
+        "test",
+        [AstFactory.identifier3("arg0")]);
+    SimpleIdentifier identifier = invocation.methodName;
+    expect(identifier.isQualified, isTrue);
+  }
+
+  void test_isQualified_inPrefixedIdentifier_name() {
+    SimpleIdentifier identifier = AstFactory.identifier3("test");
+    AstFactory.identifier4("prefix", identifier);
+    expect(identifier.isQualified, isTrue);
+  }
+
+  void test_isQualified_inPrefixedIdentifier_prefix() {
+    SimpleIdentifier identifier = AstFactory.identifier3("test");
+    AstFactory.identifier(identifier, AstFactory.identifier3("name"));
+    expect(identifier.isQualified, isFalse);
+  }
+
+  void test_isQualified_inPropertyAccess_name() {
+    SimpleIdentifier identifier = AstFactory.identifier3("test");
+    AstFactory.propertyAccess(AstFactory.identifier3("target"), identifier);
+    expect(identifier.isQualified, isTrue);
+  }
+
+  void test_isQualified_inPropertyAccess_target() {
+    SimpleIdentifier identifier = AstFactory.identifier3("test");
+    AstFactory.propertyAccess(identifier, AstFactory.identifier3("name"));
+    expect(identifier.isQualified, isFalse);
+  }
+
+  void test_isQualified_inReturnStatement() {
+    SimpleIdentifier identifier = AstFactory.identifier3("test");
+    AstFactory.returnStatement2(identifier);
+    expect(identifier.isQualified, isFalse);
+  }
+
+  SimpleIdentifier _createIdentifier(
+      _WrapperKind wrapper, _AssignmentKind assignment) {
+    SimpleIdentifier identifier = AstFactory.identifier3("a");
+    Expression expression = identifier;
+    while (true) {
+      if (wrapper == _WrapperKind.PREFIXED_LEFT) {
+        expression =
+            AstFactory.identifier(identifier, AstFactory.identifier3("_"));
+      } else if (wrapper == _WrapperKind.PREFIXED_RIGHT) {
+        expression =
+            AstFactory.identifier(AstFactory.identifier3("_"), identifier);
+      } else if (wrapper == _WrapperKind.PROPERTY_LEFT) {
+        expression = AstFactory.propertyAccess2(expression, "_");
+      } else if (wrapper == _WrapperKind.PROPERTY_RIGHT) {
+        expression =
+            AstFactory.propertyAccess(AstFactory.identifier3("_"), identifier);
+      } else if (wrapper == _WrapperKind.NONE) {}
+      break;
+    }
+    while (true) {
+      if (assignment == _AssignmentKind.BINARY) {
+        AstFactory.binaryExpression(
+            expression, TokenType.PLUS, AstFactory.identifier3("_"));
+      } else if (assignment == _AssignmentKind.COMPOUND_LEFT) {
+        AstFactory.assignmentExpression(
+            expression, TokenType.PLUS_EQ, AstFactory.identifier3("_"));
+      } else if (assignment == _AssignmentKind.COMPOUND_RIGHT) {
+        AstFactory.assignmentExpression(
+            AstFactory.identifier3("_"), TokenType.PLUS_EQ, expression);
+      } else if (assignment == _AssignmentKind.POSTFIX_INC) {
+        AstFactory.postfixExpression(expression, TokenType.PLUS_PLUS);
+      } else if (assignment == _AssignmentKind.PREFIX_DEC) {
+        AstFactory.prefixExpression(TokenType.MINUS_MINUS, expression);
+      } else if (assignment == _AssignmentKind.PREFIX_INC) {
+        AstFactory.prefixExpression(TokenType.PLUS_PLUS, expression);
+      } else if (assignment == _AssignmentKind.PREFIX_NOT) {
+        AstFactory.prefixExpression(TokenType.BANG, expression);
+      } else if (assignment == _AssignmentKind.SIMPLE_LEFT) {
+        AstFactory.assignmentExpression(
+            expression, TokenType.EQ, AstFactory.identifier3("_"));
+      } else if (assignment == _AssignmentKind.SIMPLE_RIGHT) {
+        AstFactory.assignmentExpression(
+            AstFactory.identifier3("_"), TokenType.EQ, expression);
+      } else if (assignment == _AssignmentKind.NONE) {}
+      break;
+    }
+    return identifier;
+  }
+
+  /**
+   * Return the top-most node in the AST structure containing the given identifier.
+   *
+   * @param identifier the identifier in the AST structure being traversed
+   * @return the root of the AST structure containing the identifier
+   */
+  AstNode _topMostNode(SimpleIdentifier identifier) {
+    AstNode child = identifier;
+    AstNode parent = identifier.parent;
+    while (parent != null) {
+      child = parent;
+      parent = parent.parent;
+    }
+    return child;
+  }
+}
+
+@reflectiveTest
+class SimpleStringLiteralTest extends ParserTestCase {
+  void test_contentsEnd() {
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X")
+            .contentsEnd,
+        2);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString('"X"'), "X")
+            .contentsEnd,
+        2);
+
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString('"""X"""'), "X")
+            .contentsEnd,
+        4);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
+            .contentsEnd,
+        4);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("'''  \nX'''"), "X")
+            .contentsEnd,
+        7);
+
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
+            .contentsEnd,
+        3);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString('r"X"'), "X")
+            .contentsEnd,
+        3);
+
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString('r"""X"""'), "X")
+            .contentsEnd,
+        5);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
+            .contentsEnd,
+        5);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("r'''  \nX'''"), "X")
+            .contentsEnd,
+        8);
+  }
+
+  void test_contentsOffset() {
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X")
+            .contentsOffset,
+        1);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("\"X\""), "X")
+            .contentsOffset,
+        1);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X")
+            .contentsOffset,
+        3);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
+            .contentsOffset,
+        3);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
+            .contentsOffset,
+        2);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r\"X\""), "X")
+            .contentsOffset,
+        2);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X")
+            .contentsOffset,
+        4);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
+            .contentsOffset,
+        4);
+    // leading whitespace
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("''' \ \nX''"), "X")
+            .contentsOffset,
+        6);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString('r""" \ \nX"""'), "X")
+            .contentsOffset,
+        7);
+  }
+
+  void test_isMultiline() {
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X")
+            .isMultiline,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
+            .isMultiline,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("\"X\""), "X")
+            .isMultiline,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r\"X\""), "X")
+            .isMultiline,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
+            .isMultiline,
+        isTrue);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
+            .isMultiline,
+        isTrue);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X")
+            .isMultiline,
+        isTrue);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X")
+            .isMultiline,
+        isTrue);
+  }
+
+  void test_isRaw() {
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X").isRaw,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("\"X\""), "X")
+            .isRaw,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X")
+            .isRaw,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
+            .isRaw,
+        isFalse);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
+            .isRaw,
+        isTrue);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r\"X\""), "X")
+            .isRaw,
+        isTrue);
+    expect(
+        new SimpleStringLiteral(
+                TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X")
+            .isRaw,
+        isTrue);
+    expect(
+        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
+            .isRaw,
+        isTrue);
+  }
+
+  void test_isSingleQuoted() {
+    // '
+    {
+      var token = TokenFactory.tokenFromString("'X'");
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isTrue);
+    }
+    // '''
+    {
+      var token = TokenFactory.tokenFromString("'''X'''");
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isTrue);
+    }
+    // "
+    {
+      var token = TokenFactory.tokenFromString('"X"');
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isFalse);
+    }
+    // """
+    {
+      var token = TokenFactory.tokenFromString('"""X"""');
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isFalse);
+    }
+  }
+
+  void test_isSingleQuoted_raw() {
+    // r'
+    {
+      var token = TokenFactory.tokenFromString("r'X'");
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isTrue);
+    }
+    // r'''
+    {
+      var token = TokenFactory.tokenFromString("r'''X'''");
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isTrue);
+    }
+    // r"
+    {
+      var token = TokenFactory.tokenFromString('r"X"');
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isFalse);
+    }
+    // r"""
+    {
+      var token = TokenFactory.tokenFromString('r"""X"""');
+      var node = new SimpleStringLiteral(token, null);
+      expect(node.isSingleQuoted, isFalse);
+    }
+  }
+
+  void test_simple() {
+    Token token = TokenFactory.tokenFromString("'value'");
+    SimpleStringLiteral stringLiteral = new SimpleStringLiteral(token, "value");
+    expect(stringLiteral.literal, same(token));
+    expect(stringLiteral.beginToken, same(token));
+    expect(stringLiteral.endToken, same(token));
+    expect(stringLiteral.value, "value");
+  }
+}
+
+@reflectiveTest
+class StringInterpolationTest extends ParserTestCase {
+  void test_contentsOffsetEnd() {
+    AstFactory.interpolationExpression(AstFactory.identifier3('bb'));
+    // 'a${bb}ccc'
+    {
+      var ae = AstFactory.interpolationString("'a", "a");
+      var cToken = new StringToken(TokenType.STRING, "ccc'", 10);
+      var cElement = new InterpolationString(cToken, 'ccc');
+      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
+      expect(node.contentsOffset, 1);
+      expect(node.contentsEnd, 10 + 4 - 1);
+    }
+    // '''a${bb}ccc'''
+    {
+      var ae = AstFactory.interpolationString("'''a", "a");
+      var cToken = new StringToken(TokenType.STRING, "ccc'''", 10);
+      var cElement = new InterpolationString(cToken, 'ccc');
+      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
+      expect(node.contentsOffset, 3);
+      expect(node.contentsEnd, 10 + 4 - 1);
+    }
+    // """a${bb}ccc"""
+    {
+      var ae = AstFactory.interpolationString('"""a', "a");
+      var cToken = new StringToken(TokenType.STRING, 'ccc"""', 10);
+      var cElement = new InterpolationString(cToken, 'ccc');
+      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
+      expect(node.contentsOffset, 3);
+      expect(node.contentsEnd, 10 + 4 - 1);
+    }
+    // r'a${bb}ccc'
+    {
+      var ae = AstFactory.interpolationString("r'a", "a");
+      var cToken = new StringToken(TokenType.STRING, "ccc'", 10);
+      var cElement = new InterpolationString(cToken, 'ccc');
+      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
+      expect(node.contentsOffset, 2);
+      expect(node.contentsEnd, 10 + 4 - 1);
+    }
+    // r'''a${bb}ccc'''
+    {
+      var ae = AstFactory.interpolationString("r'''a", "a");
+      var cToken = new StringToken(TokenType.STRING, "ccc'''", 10);
+      var cElement = new InterpolationString(cToken, 'ccc');
+      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
+      expect(node.contentsOffset, 4);
+      expect(node.contentsEnd, 10 + 4 - 1);
+    }
+    // r"""a${bb}ccc"""
+    {
+      var ae = AstFactory.interpolationString('r"""a', "a");
+      var cToken = new StringToken(TokenType.STRING, 'ccc"""', 10);
+      var cElement = new InterpolationString(cToken, 'ccc');
+      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
+      expect(node.contentsOffset, 4);
+      expect(node.contentsEnd, 10 + 4 - 1);
+    }
+  }
+
+  void test_isMultiline() {
+    var b = AstFactory.interpolationExpression(AstFactory.identifier3('bb'));
+    // '
+    {
+      var a = AstFactory.interpolationString("'a", "a");
+      var c = AstFactory.interpolationString("ccc'", "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isMultiline, isFalse);
+    }
+    // '''
+    {
+      var a = AstFactory.interpolationString("'''a", "a");
+      var c = AstFactory.interpolationString("ccc'''", "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isMultiline, isTrue);
+    }
+    // "
+    {
+      var a = AstFactory.interpolationString('"a', "a");
+      var c = AstFactory.interpolationString('ccc"', "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isMultiline, isFalse);
+    }
+    // """
+    {
+      var a = AstFactory.interpolationString('"""a', "a");
+      var c = AstFactory.interpolationString('ccc"""', "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isMultiline, isTrue);
+    }
+  }
+
+  void test_isRaw() {
+    StringInterpolation node = AstFactory.string();
+    expect(node.isRaw, isFalse);
+  }
+
+  void test_isSingleQuoted() {
+    var b = AstFactory.interpolationExpression(AstFactory.identifier3('bb'));
+    // "
+    {
+      var a = AstFactory.interpolationString('"a', "a");
+      var c = AstFactory.interpolationString('ccc"', "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isSingleQuoted, isFalse);
+    }
+    // """
+    {
+      var a = AstFactory.interpolationString('"""a', "a");
+      var c = AstFactory.interpolationString('ccc"""', "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isSingleQuoted, isFalse);
+    }
+    // '
+    {
+      var a = AstFactory.interpolationString("'a", "a");
+      var c = AstFactory.interpolationString("ccc'", "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isSingleQuoted, isTrue);
+    }
+    // '''
+    {
+      var a = AstFactory.interpolationString("'''a", "a");
+      var c = AstFactory.interpolationString("ccc'''", "ccc");
+      StringInterpolation node = AstFactory.string([a, b, c]);
+      expect(node.isSingleQuoted, isTrue);
+    }
+  }
+}
+
+@reflectiveTest
+class VariableDeclarationTest extends ParserTestCase {
+  void test_getDocumentationComment_onGrandParent() {
+    VariableDeclaration varDecl = AstFactory.variableDeclaration("a");
+    TopLevelVariableDeclaration decl =
+        AstFactory.topLevelVariableDeclaration2(Keyword.VAR, [varDecl]);
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
+    expect(varDecl.documentationComment, isNull);
+    decl.documentationComment = comment;
+    expect(varDecl.documentationComment, isNotNull);
+    expect(decl.documentationComment, isNotNull);
+  }
+
+  void test_getDocumentationComment_onNode() {
+    VariableDeclaration decl = AstFactory.variableDeclaration("a");
+    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
+    decl.documentationComment = comment;
+    expect(decl.documentationComment, isNotNull);
+  }
+}
+
+class _AssignmentKind {
+  static const _AssignmentKind BINARY = const _AssignmentKind('BINARY', 0);
+
+  static const _AssignmentKind COMPOUND_LEFT =
+      const _AssignmentKind('COMPOUND_LEFT', 1);
+
+  static const _AssignmentKind COMPOUND_RIGHT =
+      const _AssignmentKind('COMPOUND_RIGHT', 2);
+
+  static const _AssignmentKind POSTFIX_INC =
+      const _AssignmentKind('POSTFIX_INC', 3);
+
+  static const _AssignmentKind PREFIX_DEC =
+      const _AssignmentKind('PREFIX_DEC', 4);
+
+  static const _AssignmentKind PREFIX_INC =
+      const _AssignmentKind('PREFIX_INC', 5);
+
+  static const _AssignmentKind PREFIX_NOT =
+      const _AssignmentKind('PREFIX_NOT', 6);
+
+  static const _AssignmentKind SIMPLE_LEFT =
+      const _AssignmentKind('SIMPLE_LEFT', 7);
+
+  static const _AssignmentKind SIMPLE_RIGHT =
+      const _AssignmentKind('SIMPLE_RIGHT', 8);
+
+  static const _AssignmentKind NONE = const _AssignmentKind('NONE', 9);
+
+  static const List<_AssignmentKind> values = const [
+    BINARY,
+    COMPOUND_LEFT,
+    COMPOUND_RIGHT,
+    POSTFIX_INC,
+    PREFIX_DEC,
+    PREFIX_INC,
+    PREFIX_NOT,
+    SIMPLE_LEFT,
+    SIMPLE_RIGHT,
+    NONE
+  ];
+
+  final String name;
+
+  final int ordinal;
+
+  const _AssignmentKind(this.name, this.ordinal);
+
+  int get hashCode => ordinal;
+
+  int compareTo(_AssignmentKind other) => ordinal - other.ordinal;
+
+  String toString() => name;
+}
+
+class _WrapperKind {
+  static const _WrapperKind PREFIXED_LEFT =
+      const _WrapperKind('PREFIXED_LEFT', 0);
+
+  static const _WrapperKind PREFIXED_RIGHT =
+      const _WrapperKind('PREFIXED_RIGHT', 1);
+
+  static const _WrapperKind PROPERTY_LEFT =
+      const _WrapperKind('PROPERTY_LEFT', 2);
+
+  static const _WrapperKind PROPERTY_RIGHT =
+      const _WrapperKind('PROPERTY_RIGHT', 3);
+
+  static const _WrapperKind NONE = const _WrapperKind('NONE', 4);
+
+  static const List<_WrapperKind> values = const [
+    PREFIXED_LEFT,
+    PREFIXED_RIGHT,
+    PROPERTY_LEFT,
+    PROPERTY_RIGHT,
+    NONE
+  ];
+
+  final String name;
+
+  final int ordinal;
+
+  const _WrapperKind(this.name, this.ordinal);
+
+  int get hashCode => ordinal;
+
+  int compareTo(_WrapperKind other) => ordinal - other.ordinal;
+
+  String toString() => name;
+}
diff --git a/pkg/analyzer/test/dart/ast/test_all.dart b/pkg/analyzer/test/dart/ast/test_all.dart
new file mode 100644
index 0000000..64f8170
--- /dev/null
+++ b/pkg/analyzer/test/dart/ast/test_all.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.dart.ast.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../utils.dart';
+import 'ast_test.dart' as ast;
+import 'visitor_test.dart' as visitor;
+
+/// Utility for manually running all tests.
+main() {
+  initializeTestEnvironment();
+  group('ast tests', () {
+    ast.main();
+    visitor.main();
+  });
+}
diff --git a/pkg/analyzer/test/dart/ast/visitor_test.dart b/pkg/analyzer/test/dart/ast/visitor_test.dart
new file mode 100644
index 0000000..1645daa
--- /dev/null
+++ b/pkg/analyzer/test/dart/ast/visitor_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.dart.ast.visitor_test;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../generated/parser_test.dart' show ParserTestCase;
+import '../../generated/test_support.dart';
+import '../../reflective_tests.dart';
+import '../../utils.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(BreadthFirstVisitorTest);
+}
+
+@reflectiveTest
+class BreadthFirstVisitorTest extends ParserTestCase {
+  void test_it() {
+    String source = r'''
+class A {
+  bool get g => true;
+}
+class B {
+  int f() {
+    num q() {
+      return 3;
+    }
+  return q() + 4;
+  }
+}
+A f(var p) {
+  if ((p as A).g) {
+    return p;
+  } else {
+    return null;
+  }
+}''';
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(source);
+    List<AstNode> nodes = new List<AstNode>();
+    BreadthFirstVisitor<Object> visitor =
+        new _BreadthFirstVisitorTestHelper(nodes);
+    visitor.visitAllNodes(unit);
+    expect(nodes, hasLength(59));
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is CompilationUnit, CompilationUnit, nodes[0]);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is ClassDeclaration, ClassDeclaration, nodes[2]);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is FunctionDeclaration, FunctionDeclaration, nodes[3]);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is FunctionDeclarationStatement,
+        FunctionDeclarationStatement,
+        nodes[27]);
+    EngineTestCase.assertInstanceOf(
+        (obj) => obj is IntegerLiteral, IntegerLiteral, nodes[58]);
+    //3
+  }
+}
+
+/**
+ * A helper class used to collect the nodes that were visited and to preserve
+ * the order in which they were visited.
+ */
+class _BreadthFirstVisitorTestHelper extends BreadthFirstVisitor<Object> {
+  List<AstNode> nodes;
+
+  _BreadthFirstVisitorTestHelper(this.nodes) : super();
+
+  @override
+  Object visitNode(AstNode node) {
+    nodes.add(node);
+    return super.visitNode(node);
+  }
+}
diff --git a/pkg/analyzer/test/dart/element/test_all.dart b/pkg/analyzer/test/dart/element/test_all.dart
index 392c06a..5dac037 100644
--- a/pkg/analyzer/test/dart/element/test_all.dart
+++ b/pkg/analyzer/test/dart/element/test_all.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.generated.test_all;
+library analyzer.test.dart.element.test_all;
 
 import 'package:unittest/unittest.dart';
 
@@ -12,7 +12,7 @@
 /// Utility for manually running all tests.
 main() {
   initializeTestEnvironment();
-  group('generated tests', () {
+  group('element tests', () {
     element.main();
   });
 }
diff --git a/pkg/analyzer/test/dart/test_all.dart b/pkg/analyzer/test/dart/test_all.dart
index 669b706..df7ff55 100644
--- a/pkg/analyzer/test/dart/test_all.dart
+++ b/pkg/analyzer/test/dart/test_all.dart
@@ -7,12 +7,14 @@
 import 'package:unittest/unittest.dart';
 
 import '../utils.dart';
+import 'ast/test_all.dart' as ast;
 import 'element/test_all.dart' as element;
 
 /// Utility for manually running all tests.
 main() {
   initializeTestEnvironment();
   group('dart tests', () {
+    ast.main();
     element.main();
   });
 }
diff --git a/pkg/analyzer/test/enum_test.dart b/pkg/analyzer/test/enum_test.dart
index 625cf40..a61765d 100644
--- a/pkg/analyzer/test/enum_test.dart
+++ b/pkg/analyzer/test/enum_test.dart
@@ -7,6 +7,7 @@
 import 'dart:mirrors';
 
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -15,7 +16,6 @@
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:unittest/unittest.dart';
 
-import 'generated/ast_test.dart';
 import 'reflective_tests.dart';
 import 'utils.dart';
 
@@ -32,12 +32,6 @@
       ..check_explicit_values();
   }
 
-  void test_AssignmentKind() {
-    new EnumTester<AssignmentKind>()
-      ..check_getters()
-      ..check_explicit_values();
-  }
-
   void test_CacheState() {
     new EnumTester<CacheState>()
       ..check_getters()
@@ -103,12 +97,6 @@
       ..check_getters()
       ..check_explicit_values();
   }
-
-  void test_WrapperKind() {
-    new EnumTester<WrapperKind>()
-      ..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 f8ca1dc..34b9797 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -4,11 +4,12 @@
 
 library analyzer.test.generated.all_the_rest_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart' hide ConstantEvaluator;
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -25,26 +26,19 @@
 import 'package:analyzer/src/generated/testing/element_factory.dart';
 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_collection.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:path/path.dart';
 import 'package:source_span/source_span.dart';
 import 'package:unittest/unittest.dart';
 
 import '../reflective_tests.dart';
 import '../utils.dart';
-import 'engine_test.dart';
 import 'parser_test.dart';
 import 'resolver_test.dart';
 import 'test_support.dart';
 
 main() {
   initializeTestEnvironment();
-  runReflectiveTests(ConstantEvaluatorTest);
-  runReflectiveTests(ConstantFinderTest);
-  runReflectiveTests(ConstantValueComputerTest);
-  runReflectiveTests(ConstantVisitorTest);
   runReflectiveTests(ContentCacheTest);
   runReflectiveTests(CustomUriResolverTest);
   runReflectiveTests(DartObjectImplTest);
@@ -61,2120 +55,10 @@
   runReflectiveTests(ExitDetectorTest2);
   runReflectiveTests(FileBasedSourceTest);
   runReflectiveTests(FileUriResolverTest);
-  runReflectiveTests(ReferenceFinderTest);
   runReflectiveTests(SDKLibrariesReaderTest);
   runReflectiveTests(UriKindTest);
 }
 
-/**
- * Implementation of [ConstantEvaluationValidator] used during unit tests;
- * verifies that any nodes referenced during constant evaluation are present in
- * the dependency graph.
- */
-class ConstantEvaluationValidator_ForTest
-    implements ConstantEvaluationValidator {
-  ConstantValueComputer computer;
-
-  ConstantEvaluationTarget _nodeBeingEvaluated;
-
-  @override
-  void beforeComputeValue(ConstantEvaluationTarget constant) {
-    _nodeBeingEvaluated = constant;
-  }
-
-  @override
-  void beforeGetConstantInitializers(ConstructorElement constructor) {
-    // Make sure we properly recorded the dependency.
-    expect(
-        computer.referenceGraph.containsPath(_nodeBeingEvaluated, constructor),
-        isTrue);
-  }
-
-  @override
-  void beforeGetEvaluationResult(ConstantEvaluationTarget constant) {
-    // Make sure we properly recorded the dependency.
-    expect(computer.referenceGraph.containsPath(_nodeBeingEvaluated, constant),
-        isTrue);
-  }
-
-  @override
-  void beforeGetFieldEvaluationResult(FieldElementImpl field) {
-    // Make sure we properly recorded the dependency.
-    expect(computer.referenceGraph.containsPath(_nodeBeingEvaluated, field),
-        isTrue);
-  }
-
-  @override
-  void beforeGetParameterDefault(ParameterElement parameter) {
-    // Make sure we properly recorded the dependency.
-    expect(computer.referenceGraph.containsPath(_nodeBeingEvaluated, parameter),
-        isTrue);
-  }
-}
-
-@reflectiveTest
-class ConstantEvaluatorTest extends ResolverTestCase {
-  void fail_constructor() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_class() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_function() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_static() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_staticMethod() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_topLevel() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_typeParameter() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_prefixedIdentifier_invalid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_prefixedIdentifier_valid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_propertyAccess_invalid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_propertyAccess_valid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_simpleIdentifier_invalid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_simpleIdentifier_valid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void test_bitAnd_int_int() {
-    _assertValue3(74 & 42, "74 & 42");
-  }
-
-  void test_bitNot() {
-    _assertValue3(~42, "~42");
-  }
-
-  void test_bitOr_int_int() {
-    _assertValue3(74 | 42, "74 | 42");
-  }
-
-  void test_bitXor_int_int() {
-    _assertValue3(74 ^ 42, "74 ^ 42");
-  }
-
-  void test_divide_double_double() {
-    _assertValue2(3.2 / 2.3, "3.2 / 2.3");
-  }
-
-  void test_divide_double_double_byZero() {
-    EvaluationResult result = _getExpressionValue("3.2 / 0.0");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value.type.name, "double");
-    expect(value.toDoubleValue().isInfinite, isTrue);
-  }
-
-  void test_divide_int_int() {
-    _assertValue2(1.5, "3 / 2");
-  }
-
-  void test_divide_int_int_byZero() {
-    EvaluationResult result = _getExpressionValue("3 / 0");
-    expect(result.isValid, isTrue);
-  }
-
-  void test_equal_boolean_boolean() {
-    _assertValue(false, "true == false");
-  }
-
-  void test_equal_int_int() {
-    _assertValue(false, "2 == 3");
-  }
-
-  void test_equal_invalidLeft() {
-    EvaluationResult result = _getExpressionValue("a == 3");
-    expect(result.isValid, isFalse);
-  }
-
-  void test_equal_invalidRight() {
-    EvaluationResult result = _getExpressionValue("2 == a");
-    expect(result.isValid, isFalse);
-  }
-
-  void test_equal_string_string() {
-    _assertValue(false, "'a' == 'b'");
-  }
-
-  void test_greaterThan_int_int() {
-    _assertValue(false, "2 > 3");
-  }
-
-  void test_greaterThanOrEqual_int_int() {
-    _assertValue(false, "2 >= 3");
-  }
-
-  void test_leftShift_int_int() {
-    _assertValue3(64, "16 << 2");
-  }
-
-  void test_lessThan_int_int() {
-    _assertValue(true, "2 < 3");
-  }
-
-  void test_lessThanOrEqual_int_int() {
-    _assertValue(true, "2 <= 3");
-  }
-
-  void test_literal_boolean_false() {
-    _assertValue(false, "false");
-  }
-
-  void test_literal_boolean_true() {
-    _assertValue(true, "true");
-  }
-
-  void test_literal_list() {
-    EvaluationResult result = _getExpressionValue("const ['a', 'b', 'c']");
-    expect(result.isValid, isTrue);
-  }
-
-  void test_literal_map() {
-    EvaluationResult result =
-        _getExpressionValue("const {'a' : 'm', 'b' : 'n', 'c' : 'o'}");
-    expect(result.isValid, isTrue);
-  }
-
-  void test_literal_null() {
-    EvaluationResult result = _getExpressionValue("null");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value.isNull, isTrue);
-  }
-
-  void test_literal_number_double() {
-    _assertValue2(3.45, "3.45");
-  }
-
-  void test_literal_number_integer() {
-    _assertValue3(42, "42");
-  }
-
-  void test_literal_string_adjacent() {
-    _assertValue4("abcdef", "'abc' 'def'");
-  }
-
-  void test_literal_string_interpolation_invalid() {
-    EvaluationResult result = _getExpressionValue("'a\${f()}c'");
-    expect(result.isValid, isFalse);
-  }
-
-  void test_literal_string_interpolation_valid() {
-    _assertValue4("a3c", "'a\${3}c'");
-  }
-
-  void test_literal_string_simple() {
-    _assertValue4("abc", "'abc'");
-  }
-
-  void test_logicalAnd() {
-    _assertValue(false, "true && false");
-  }
-
-  void test_logicalNot() {
-    _assertValue(false, "!true");
-  }
-
-  void test_logicalOr() {
-    _assertValue(true, "true || false");
-  }
-
-  void test_minus_double_double() {
-    _assertValue2(3.2 - 2.3, "3.2 - 2.3");
-  }
-
-  void test_minus_int_int() {
-    _assertValue3(1, "3 - 2");
-  }
-
-  void test_negated_boolean() {
-    EvaluationResult result = _getExpressionValue("-true");
-    expect(result.isValid, isFalse);
-  }
-
-  void test_negated_double() {
-    _assertValue2(-42.3, "-42.3");
-  }
-
-  void test_negated_integer() {
-    _assertValue3(-42, "-42");
-  }
-
-  void test_notEqual_boolean_boolean() {
-    _assertValue(true, "true != false");
-  }
-
-  void test_notEqual_int_int() {
-    _assertValue(true, "2 != 3");
-  }
-
-  void test_notEqual_invalidLeft() {
-    EvaluationResult result = _getExpressionValue("a != 3");
-    expect(result.isValid, isFalse);
-  }
-
-  void test_notEqual_invalidRight() {
-    EvaluationResult result = _getExpressionValue("2 != a");
-    expect(result.isValid, isFalse);
-  }
-
-  void test_notEqual_string_string() {
-    _assertValue(true, "'a' != 'b'");
-  }
-
-  void test_parenthesizedExpression() {
-    _assertValue4("a", "('a')");
-  }
-
-  void test_plus_double_double() {
-    _assertValue2(2.3 + 3.2, "2.3 + 3.2");
-  }
-
-  void test_plus_int_int() {
-    _assertValue3(5, "2 + 3");
-  }
-
-  void test_plus_string_string() {
-    _assertValue4("ab", "'a' + 'b'");
-  }
-
-  void test_remainder_double_double() {
-    _assertValue2(3.2 % 2.3, "3.2 % 2.3");
-  }
-
-  void test_remainder_int_int() {
-    _assertValue3(2, "8 % 3");
-  }
-
-  void test_rightShift() {
-    _assertValue3(16, "64 >> 2");
-  }
-
-  void test_stringLength_complex() {
-    _assertValue3(6, "('qwe' + 'rty').length");
-  }
-
-  void test_stringLength_simple() {
-    _assertValue3(6, "'Dvorak'.length");
-  }
-
-  void test_times_double_double() {
-    _assertValue2(2.3 * 3.2, "2.3 * 3.2");
-  }
-
-  void test_times_int_int() {
-    _assertValue3(6, "2 * 3");
-  }
-
-  void test_truncatingDivide_double_double() {
-    _assertValue3(1, "3.2 ~/ 2.3");
-  }
-
-  void test_truncatingDivide_int_int() {
-    _assertValue3(3, "10 ~/ 3");
-  }
-
-  void _assertValue(bool expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
-    DartObject value = result.value;
-    expect(value.type.name, "bool");
-    expect(value.toBoolValue(), expectedValue);
-  }
-
-  void _assertValue2(double expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value.type.name, "double");
-    expect(value.toDoubleValue(), expectedValue);
-  }
-
-  void _assertValue3(int expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value.type.name, "int");
-    expect(value.toIntValue(), expectedValue);
-  }
-
-  void _assertValue4(String expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
-    DartObject value = result.value;
-    expect(value, isNotNull);
-    ParameterizedType type = value.type;
-    expect(type, isNotNull);
-    expect(type.name, "String");
-    expect(value.toStringValue(), expectedValue);
-  }
-
-  EvaluationResult _getExpressionValue(String contents) {
-    Source source = addSource("var x = $contents;");
-    LibraryElement library = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, library);
-    expect(unit, isNotNull);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember declaration = declarations[0];
-    EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableDeclaration,
-        TopLevelVariableDeclaration, declaration);
-    NodeList<VariableDeclaration> variables =
-        (declaration as TopLevelVariableDeclaration).variables.variables;
-    expect(variables, hasLength(1));
-    ConstantEvaluator evaluator = new ConstantEvaluator(
-        source, analysisContext.typeProvider,
-        typeSystem: analysisContext.typeSystem);
-    return evaluator.evaluate(variables[0].initializer);
-  }
-}
-
-@reflectiveTest
-class ConstantFinderTest {
-  AstNode _node;
-  TypeProvider _typeProvider;
-  AnalysisContext _context;
-  Source _source;
-
-  void setUp() {
-    _typeProvider = new TestTypeProvider();
-    _context = new TestAnalysisContext_ConstantFinderTest();
-    _source = new TestSource();
-  }
-
-  /**
-   * Test an annotation that consists solely of an identifier (and hence
-   * represents a reference to a compile-time constant variable).
-   */
-  void test_visitAnnotation_constantVariable() {
-    _node = AstFactory.annotation(AstFactory.identifier3('x'));
-    expect(_findAnnotations(), contains(_node));
-  }
-
-  /**
-   * Test an annotation that represents the invocation of a constant
-   * constructor.
-   */
-  void test_visitAnnotation_invocation() {
-    _node = AstFactory.annotation2(
-        AstFactory.identifier3('A'), null, AstFactory.argumentList());
-    expect(_findAnnotations(), contains(_node));
-  }
-
-  void test_visitConstructorDeclaration_const() {
-    ConstructorElement element = _setupConstructorDeclaration("A", true);
-    expect(_findConstants(), contains(element));
-  }
-
-  void test_visitConstructorDeclaration_nonConst() {
-    _setupConstructorDeclaration("A", false);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_const() {
-    VariableElement element = _setupVariableDeclaration("v", true, true);
-    expect(_findConstants(), contains(element));
-  }
-
-  void test_visitVariableDeclaration_final_inClass() {
-    _setupFieldDeclaration('C', 'f', Keyword.FINAL);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
-        hasConstConstructor: true);
-    expect(_findConstants(), contains(field.element));
-  }
-
-  void test_visitVariableDeclaration_final_outsideClass() {
-    _setupVariableDeclaration('v', false, true, isFinal: true);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_noInitializer() {
-    _setupVariableDeclaration("v", true, false);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_nonConst() {
-    _setupVariableDeclaration("v", false, true);
-    expect(_findConstants(), isEmpty);
-  }
-
-  void test_visitVariableDeclaration_static_const_inClass() {
-    VariableDeclaration field =
-        _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
-    expect(_findConstants(), contains(field.element));
-  }
-
-  void test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
-        isStatic: true, hasConstConstructor: true);
-    expect(_findConstants(), contains(field.element));
-  }
-
-  void test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
-        isStatic: true, hasConstConstructor: true);
-    expect(_findConstants(), isNot(contains(field.element)));
-  }
-
-  void test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
-    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
-        isInitialized: false, hasConstConstructor: true);
-    expect(_findConstants(), isNot(contains(field.element)));
-  }
-
-  void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
-    _setupFieldDeclaration('C', 'f', Keyword.CONST,
-        isStatic: true, isInitialized: false);
-    expect(_findConstants(), isEmpty);
-  }
-
-  List<Annotation> _findAnnotations() {
-    Set<Annotation> annotations = new Set<Annotation>();
-    for (ConstantEvaluationTarget target in _findConstants()) {
-      if (target is ConstantEvaluationTarget_Annotation) {
-        expect(target.context, same(_context));
-        expect(target.source, same(_source));
-        annotations.add(target.annotation);
-      }
-    }
-    return new List<Annotation>.from(annotations);
-  }
-
-  Set<ConstantEvaluationTarget> _findConstants() {
-    ConstantFinder finder = new ConstantFinder(_context, _source, _source);
-    _node.accept(finder);
-    Set<ConstantEvaluationTarget> constants = finder.constantsToCompute;
-    expect(constants, isNotNull);
-    return constants;
-  }
-
-  ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
-    Keyword constKeyword = isConst ? Keyword.CONST : null;
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration2(
-            constKeyword,
-            null,
-            null,
-            name,
-            AstFactory.formalParameterList(),
-            null,
-            AstFactory.blockFunctionBody2());
-    ClassElement classElement = ElementFactory.classElement2(name);
-    ConstructorElement element =
-        ElementFactory.constructorElement(classElement, name, isConst);
-    constructorDeclaration.element = element;
-    _node = constructorDeclaration;
-    return element;
-  }
-
-  VariableDeclaration _setupFieldDeclaration(
-      String className, String fieldName, Keyword keyword,
-      {bool isInitialized: true,
-      bool isStatic: false,
-      bool hasConstConstructor: false}) {
-    VariableDeclaration variableDeclaration = isInitialized
-        ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
-        : AstFactory.variableDeclaration(fieldName);
-    VariableElement fieldElement = ElementFactory.fieldElement(
-        fieldName,
-        isStatic,
-        keyword == Keyword.FINAL,
-        keyword == Keyword.CONST,
-        _typeProvider.intType);
-    variableDeclaration.name.staticElement = fieldElement;
-    FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
-        isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
-    ClassDeclaration classDeclaration =
-        AstFactory.classDeclaration(null, className, null, null, null, null);
-    classDeclaration.members.add(fieldDeclaration);
-    _node = classDeclaration;
-    ClassElementImpl classElement = ElementFactory.classElement2(className);
-    classElement.fields = <FieldElement>[fieldElement];
-    classDeclaration.name.staticElement = classElement;
-    if (hasConstConstructor) {
-      ConstructorDeclaration constructorDeclaration = AstFactory
-          .constructorDeclaration2(
-              Keyword.CONST,
-              null,
-              AstFactory.identifier3(className),
-              null,
-              AstFactory.formalParameterList(),
-              null,
-              AstFactory.blockFunctionBody2());
-      classDeclaration.members.add(constructorDeclaration);
-      ConstructorElement constructorElement =
-          ElementFactory.constructorElement(classElement, '', true);
-      constructorDeclaration.element = constructorElement;
-      classElement.constructors = <ConstructorElement>[constructorElement];
-    } else {
-      classElement.constructors = ConstructorElement.EMPTY_LIST;
-    }
-    return variableDeclaration;
-  }
-
-  VariableElement _setupVariableDeclaration(
-      String name, bool isConst, bool isInitialized,
-      {isFinal: false}) {
-    VariableDeclaration variableDeclaration = isInitialized
-        ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
-        : AstFactory.variableDeclaration(name);
-    SimpleIdentifier identifier = variableDeclaration.name;
-    VariableElement element = ElementFactory.localVariableElement(identifier);
-    identifier.staticElement = element;
-    Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
-    AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
-    _node = variableDeclaration;
-    return element;
-  }
-}
-
-@reflectiveTest
-class ConstantValueComputerTest extends ResolverTestCase {
-  void test_annotation_constConstructor() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A(this.i);
-}
-
-class C {
-  @A(5)
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
-    _assertIntField(annotationFields, 'i', 5);
-  }
-
-  void test_annotation_constConstructor_named() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A.named(this.i);
-}
-
-class C {
-  @A.named(5)
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
-    _assertIntField(annotationFields, 'i', 5);
-  }
-
-  void test_annotation_constConstructor_noArgs() {
-    // Failing to pass arguments to an annotation which is a constant
-    // constructor is illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A(this.i);
-}
-
-class C {
-  @A
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_constConstructor_noArgs_named() {
-    // Failing to pass arguments to an annotation which is a constant
-    // constructor is illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  const A.named(this.i);
-}
-
-class C {
-  @A.named
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_nonConstConstructor() {
-    // Calling a non-const constructor from an annotation that is illegal, but
-    // shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  final int i;
-  A(this.i);
-}
-
-class C {
-  @A(5)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_staticConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class C {
-  static const int i = 5;
-
-  @i
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_annotation_staticConst_args() {
-    // Applying arguments to an annotation that is a static const is
-    // illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class C {
-  static const int i = 5;
-
-  @i(1)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_staticConst_otherClass() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  static const int i = 5;
-}
-
-class C {
-  @A.i
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_annotation_staticConst_otherClass_args() {
-    // Applying arguments to an annotation that is a static const is
-    // illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  static const int i = 5;
-}
-
-class C {
-  @A.i(1)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_annotation_toplevelVariable() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const int i = 5;
-class C {
-  @i
-  f() {}
-}
-''');
-    EvaluationResultImpl result =
-        _evaluateAnnotation(compilationUnit, "C", "f");
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_annotation_toplevelVariable_args() {
-    // Applying arguments to an annotation that is a toplevel variable is
-    // illegal, but shouldn't crash analysis.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const int i = 5;
-class C {
-  @i(1)
-  f() {}
-}
-''');
-    _evaluateAnnotation(compilationUnit, "C", "f");
-  }
-
-  void test_computeValues_cycle() {
-    TestLogger logger = new TestLogger();
-    AnalysisEngine.instance.logger = logger;
-    try {
-      Source librarySource = addSource(r'''
-  const int a = c;
-  const int b = a;
-  const int c = b;''');
-      LibraryElement libraryElement = resolve2(librarySource);
-      CompilationUnit unit =
-          analysisContext.resolveCompilationUnit(librarySource, libraryElement);
-      analysisContext.computeErrors(librarySource);
-      expect(unit, isNotNull);
-      ConstantValueComputer computer = _makeConstantValueComputer();
-      computer.add(unit, librarySource, librarySource);
-      computer.computeValues();
-      NodeList<CompilationUnitMember> members = unit.declarations;
-      expect(members, hasLength(3));
-      _validate(false, (members[0] as TopLevelVariableDeclaration).variables);
-      _validate(false, (members[1] as TopLevelVariableDeclaration).variables);
-      _validate(false, (members[2] as TopLevelVariableDeclaration).variables);
-    } finally {
-      AnalysisEngine.instance.logger = Logger.NULL;
-    }
-  }
-
-  void test_computeValues_dependentVariables() {
-    Source librarySource = addSource(r'''
-const int b = a;
-const int a = 0;''');
-    LibraryElement libraryElement = resolve2(librarySource);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, librarySource, librarySource);
-    computer.computeValues();
-    NodeList<CompilationUnitMember> members = unit.declarations;
-    expect(members, hasLength(2));
-    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
-    _validate(true, (members[1] as TopLevelVariableDeclaration).variables);
-  }
-
-  void test_computeValues_empty() {
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.computeValues();
-  }
-
-  void test_computeValues_multipleSources() {
-    Source librarySource = addNamedSource(
-        "/lib.dart",
-        r'''
-library lib;
-part 'part.dart';
-const int c = b;
-const int a = 0;''');
-    Source partSource = addNamedSource(
-        "/part.dart",
-        r'''
-part of lib;
-const int b = a;
-const int d = c;''');
-    LibraryElement libraryElement = resolve2(librarySource);
-    CompilationUnit libraryUnit =
-        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
-    expect(libraryUnit, isNotNull);
-    CompilationUnit partUnit =
-        analysisContext.resolveCompilationUnit(partSource, libraryElement);
-    expect(partUnit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(libraryUnit, librarySource, librarySource);
-    computer.add(partUnit, partSource, librarySource);
-    computer.computeValues();
-    NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
-    expect(libraryMembers, hasLength(2));
-    _validate(
-        true, (libraryMembers[0] as TopLevelVariableDeclaration).variables);
-    _validate(
-        true, (libraryMembers[1] as TopLevelVariableDeclaration).variables);
-    NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations;
-    expect(partMembers, hasLength(2));
-    _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables);
-    _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables);
-  }
-
-  void test_computeValues_singleVariable() {
-    Source librarySource = addSource("const int a = 0;");
-    LibraryElement libraryElement = resolve2(librarySource);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, librarySource, librarySource);
-    computer.computeValues();
-    NodeList<CompilationUnitMember> members = unit.declarations;
-    expect(members, hasLength(1));
-    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
-  }
-
-  void test_computeValues_value_depends_on_enum() {
-    Source librarySource = addSource('''
-enum E { id0, id1 }
-const E e = E.id0;
-''');
-    LibraryElement libraryElement = resolve2(librarySource);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, librarySource, librarySource);
-    computer.computeValues();
-    TopLevelVariableDeclaration declaration = unit.declarations
-        .firstWhere((member) => member is TopLevelVariableDeclaration);
-    _validate(true, declaration.variables);
-  }
-
-  void test_dependencyOnConstructor() {
-    // x depends on "const A()"
-    _assertProperDependencies(r'''
-class A {
-  const A();
-}
-const x = const A();''');
-  }
-
-  void test_dependencyOnConstructorArgument() {
-    // "const A(x)" depends on x
-    _assertProperDependencies(r'''
-class A {
-  const A(this.next);
-  final A next;
-}
-const A x = const A(null);
-const A y = const A(x);''');
-  }
-
-  void test_dependencyOnConstructorArgument_unresolvedConstructor() {
-    // "const A.a(x)" depends on x even if the constructor A.a can't be found.
-    _assertProperDependencies(
-        r'''
-class A {
-}
-const int x = 1;
-const A y = const A.a(x);''',
-        [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
-  }
-
-  void test_dependencyOnConstructorInitializer() {
-    // "const A()" depends on x
-    _assertProperDependencies(r'''
-const int x = 1;
-class A {
-  const A() : v = x;
-  final int v;
-}''');
-  }
-
-  void test_dependencyOnExplicitSuperConstructor() {
-    // b depends on B() depends on A()
-    _assertProperDependencies(r'''
-class A {
-  const A(this.x);
-  final int x;
-}
-class B extends A {
-  const B() : super(5);
-}
-const B b = const B();''');
-  }
-
-  void test_dependencyOnExplicitSuperConstructorParameters() {
-    // b depends on B() depends on i
-    _assertProperDependencies(r'''
-class A {
-  const A(this.x);
-  final int x;
-}
-class B extends A {
-  const B() : super(i);
-}
-const B b = const B();
-const int i = 5;''');
-  }
-
-  void test_dependencyOnFactoryRedirect() {
-    // a depends on A.foo() depends on A.bar()
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  factory const A.foo() = A.bar;
-  const A.bar();
-}''');
-  }
-
-  void test_dependencyOnFactoryRedirectWithTypeParams() {
-    _assertProperDependencies(r'''
-class A {
-  const factory A(var a) = B<int>;
-}
-
-class B<T> implements A {
-  final T x;
-  const B(this.x);
-}
-
-const A a = const A(10);''');
-  }
-
-  void test_dependencyOnImplicitSuperConstructor() {
-    // b depends on B() depends on A()
-    _assertProperDependencies(r'''
-class A {
-  const A() : x = 5;
-  final int x;
-}
-class B extends A {
-  const B();
-}
-const B b = const B();''');
-  }
-
-  void test_dependencyOnInitializedFinal() {
-    // a depends on A() depends on A.x
-    _assertProperDependencies('''
-class A {
-  const A();
-  final int x = 1;
-}
-const A a = const A();
-''');
-  }
-
-  void test_dependencyOnInitializedNonStaticConst() {
-    // Even though non-static consts are not allowed by the language, we need
-    // to handle them for error recovery purposes.
-    // a depends on A() depends on A.x
-    _assertProperDependencies(
-        '''
-class A {
-  const A();
-  const int x = 1;
-}
-const A a = const A();
-''',
-        [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
-  }
-
-  void test_dependencyOnNonFactoryRedirect() {
-    // a depends on A.foo() depends on A.bar()
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this.bar();
-  const A.bar();
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_arg() {
-    // a depends on A.foo() depends on b
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-const int b = 1;
-class A {
-  const A.foo() : this.bar(b);
-  const A.bar(x) : y = x;
-  final int y;
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_defaultValue() {
-    // a depends on A.foo() depends on A.bar() depends on b
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-const int b = 1;
-class A {
-  const A.foo() : this.bar();
-  const A.bar([x = b]) : y = x;
-  final int y;
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_toMissing() {
-    // a depends on A.foo() which depends on nothing, since A.bar() is
-    // missing.
-    _assertProperDependencies(
-        r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this.bar();
-}''',
-        [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
-  }
-
-  void test_dependencyOnNonFactoryRedirect_toNonConst() {
-    // a depends on A.foo() which depends on nothing, since A.bar() is
-    // non-const.
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this.bar();
-  A.bar();
-}''');
-  }
-
-  void test_dependencyOnNonFactoryRedirect_unnamed() {
-    // a depends on A.foo() depends on A()
-    _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
-  const A.foo() : this();
-  const A();
-}''');
-  }
-
-  void test_dependencyOnOptionalParameterDefault() {
-    // a depends on A() depends on B()
-    _assertProperDependencies(r'''
-class A {
-  const A([x = const B()]) : b = x;
-  final B b;
-}
-class B {
-  const B();
-}
-const A a = const A();''');
-  }
-
-  void test_dependencyOnVariable() {
-    // x depends on y
-    _assertProperDependencies(r'''
-const x = y + 1;
-const y = 2;''');
-  }
-
-  void test_final_initialized_at_declaration() {
-    CompilationUnit compilationUnit = resolveSource('''
-class A {
-  final int i = 123;
-  const A();
-}
-
-const A a = const A();
-''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, 'a');
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "i", 123);
-  }
-
-  void test_fromEnvironment_bool_default_false() {
-    expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false);
-  }
-
-  void test_fromEnvironment_bool_default_overridden() {
-    expect(
-        _assertValidBool(_check_fromEnvironment_bool("false", "true")), false);
-  }
-
-  void test_fromEnvironment_bool_default_parseError() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")),
-        true);
-  }
-
-  void test_fromEnvironment_bool_default_true() {
-    expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true);
-  }
-
-  void test_fromEnvironment_bool_false() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false);
-  }
-
-  void test_fromEnvironment_bool_parseError() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)),
-        false);
-  }
-
-  void test_fromEnvironment_bool_true() {
-    expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true);
-  }
-
-  void test_fromEnvironment_bool_undeclared() {
-    _assertValidUnknown(_check_fromEnvironment_bool(null, null));
-  }
-
-  void test_fromEnvironment_int_default_overridden() {
-    expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234);
-  }
-
-  void test_fromEnvironment_int_default_parseError() {
-    expect(
-        _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123);
-  }
-
-  void test_fromEnvironment_int_default_undeclared() {
-    expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123);
-  }
-
-  void test_fromEnvironment_int_ok() {
-    expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234);
-  }
-
-  void test_fromEnvironment_int_parseError() {
-    _assertValidNull(_check_fromEnvironment_int("parseError", null));
-  }
-
-  void test_fromEnvironment_int_parseError_nullDefault() {
-    _assertValidNull(_check_fromEnvironment_int("parseError", "null"));
-  }
-
-  void test_fromEnvironment_int_undeclared() {
-    _assertValidUnknown(_check_fromEnvironment_int(null, null));
-  }
-
-  void test_fromEnvironment_int_undeclared_nullDefault() {
-    _assertValidNull(_check_fromEnvironment_int(null, "null"));
-  }
-
-  void test_fromEnvironment_string_default_overridden() {
-    expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")),
-        "abc");
-  }
-
-  void test_fromEnvironment_string_default_undeclared() {
-    expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")),
-        "def");
-  }
-
-  void test_fromEnvironment_string_empty() {
-    expect(_assertValidString(_check_fromEnvironment_string("", null)), "");
-  }
-
-  void test_fromEnvironment_string_ok() {
-    expect(
-        _assertValidString(_check_fromEnvironment_string("abc", null)), "abc");
-  }
-
-  void test_fromEnvironment_string_undeclared() {
-    _assertValidUnknown(_check_fromEnvironment_string(null, null));
-  }
-
-  void test_fromEnvironment_string_undeclared_nullDefault() {
-    _assertValidNull(_check_fromEnvironment_string(null, "null"));
-  }
-
-  void test_instanceCreationExpression_computedField() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(4, 5);
-class A {
-  const A(int i, int j) : k = 2 * i + j;
-  final int k;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "k", 13);
-  }
-
-  void test_instanceCreationExpression_computedField_namedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(false, true, true);
-  }
-
-  void test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(false, true, false);
-  }
-
-  void test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(false, false, true);
-  }
-
-  void test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(false, false, false);
-  }
-
-  void test_instanceCreationExpression_computedField_usesConstConstructor() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-class A {
-  const A(int i) : b = const B(4);
-  final int b;
-}
-class B {
-  const B(this.k);
-  final int k;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A");
-    expect(fieldsOfA, hasLength(1));
-    Map<String, DartObjectImpl> fieldsOfB =
-        _assertFieldType(fieldsOfA, "b", "B");
-    expect(fieldsOfB, hasLength(1));
-    _assertIntField(fieldsOfB, "k", 4);
-  }
-
-  void test_instanceCreationExpression_computedField_usesStaticConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-class A {
-  const A(int i) : k = i + B.bar;
-  final int k;
-}
-class B {
-  static const bar = 4;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "k", 7);
-  }
-
-  void test_instanceCreationExpression_computedField_usesToplevelConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-const bar = 4;
-class A {
-  const A(int i) : k = i + bar;
-  final int k;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "k", 7);
-  }
-
-  void test_instanceCreationExpression_explicitSuper() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const B(4, 5);
-class A {
-  const A(this.x);
-  final int x;
-}
-class B extends A {
-  const B(int x, this.y) : super(x * 2);
-  final int y;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B");
-    expect(fields, hasLength(2));
-    _assertIntField(fields, "y", 5);
-    Map<String, DartObjectImpl> superclassFields =
-        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
-    expect(superclassFields, hasLength(1));
-    _assertIntField(superclassFields, "x", 8);
-  }
-
-  void test_instanceCreationExpression_fieldFormalParameter() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(42);
-class A {
-  int x;
-  const A(this.x)
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "x", 42);
-  }
-
-  void test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(true, true, true);
-  }
-
-  void test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(true, true, false);
-  }
-
-  void test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() {
-    _checkInstanceCreationOptionalParams(true, false, true);
-  }
-
-  void test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() {
-    _checkInstanceCreationOptionalParams(true, false, false);
-  }
-
-  void test_instanceCreationExpression_implicitSuper() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const B(4);
-class A {
-  const A() : x = 3;
-  final int x;
-}
-class B extends A {
-  const B(this.y);
-  final int y;
-}''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B");
-    expect(fields, hasLength(2));
-    _assertIntField(fields, "y", 4);
-    Map<String, DartObjectImpl> superclassFields =
-        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
-    expect(superclassFields, hasLength(1));
-    _assertIntField(superclassFields, "x", 3);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-  const A.a2() : x = 5;
-  final int x;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'x', 5);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_arg() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1(1);
-class A {
-  const A.a1(x) : this.a2(x + 100);
-  const A.a2(x) : y = x + 10;
-  final int y;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'y', 111);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_cycle() {
-    // It is an error to have a cycle in non-factory redirects; however, we
-    // need to make sure that even if the error occurs, attempting to evaluate
-    // the constant will terminate.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const A() : this.b();
-  const A.b() : this();
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-  const A.a2([x = 100]) : y = x + 10;
-  final int y;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'y', 110);
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_toMissing() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-}''');
-    // We don't care what value foo evaluates to (since there is a compile
-    // error), but we shouldn't crash, and we should figure
-    // out that it evaluates to an instance of class A.
-    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this.a2();
-  A.a2();
-}''');
-    // We don't care what value foo evaluates to (since there is a compile
-    // error), but we shouldn't crash, and we should figure
-    // out that it evaluates to an instance of class A.
-    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-  }
-
-  void test_instanceCreationExpression_nonFactoryRedirect_unnamed() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
-  const A.a1() : this();
-  const A() : x = 5;
-  final int x;
-}''');
-    Map<String, DartObjectImpl> aFields =
-        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
-    _assertIntField(aFields, 'x', 5);
-  }
-
-  void test_instanceCreationExpression_redirect() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const factory A() = B;
-}
-class B implements A {
-  const B();
-}''');
-    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B");
-  }
-
-  void test_instanceCreationExpression_redirect_cycle() {
-    // It is an error to have a cycle in factory redirects; however, we need
-    // to make sure that even if the error occurs, attempting to evaluate the
-    // constant will terminate.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const factory A() = A.b;
-  const factory A.b() = A;
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_redirect_extern() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  external const factory A();
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_redirect_nonConst() {
-    // It is an error for a const factory constructor redirect to a non-const
-    // constructor; however, we need to make sure that even if the error
-    // attempting to evaluate the constant won't cause a crash.
-    CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
-  const factory A() = A.b;
-  A.b();
-}''');
-    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
-  }
-
-  void test_instanceCreationExpression_redirectWithTypeParams() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A {
-  const factory A(var a) = B<int>;
-}
-
-class B<T> implements A {
-  final T x;
-  const B(this.x);
-}
-
-const A a = const A(10);''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "a");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "x", 10);
-  }
-
-  void test_instanceCreationExpression_redirectWithTypeSubstitution() {
-    // To evaluate the redirection of A<int>,
-    // A's template argument (T=int) must be substituted
-    // into B's template argument (B<U> where U=T) to get B<int>.
-    CompilationUnit compilationUnit = resolveSource(r'''
-class A<T> {
-  const factory A(var a) = B<T>;
-}
-
-class B<U> implements A {
-  final U x;
-  const B(this.x);
-}
-
-const A<int> a = const A<int>(10);''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, "a");
-    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "x", 10);
-  }
-
-  void test_instanceCreationExpression_symbol() {
-    CompilationUnit compilationUnit =
-        resolveSource("const foo = const Symbol('a');");
-    EvaluationResultImpl evaluationResult =
-        _evaluateTopLevelVariable(compilationUnit, "foo");
-    expect(evaluationResult.value, isNotNull);
-    DartObjectImpl value = evaluationResult.value;
-    expect(value.type, typeProvider.symbolType);
-    expect(value.toSymbolValue(), "a");
-  }
-
-  void test_instanceCreationExpression_withSupertypeParams_explicit() {
-    _checkInstanceCreation_withSupertypeParams(true);
-  }
-
-  void test_instanceCreationExpression_withSupertypeParams_implicit() {
-    _checkInstanceCreation_withSupertypeParams(false);
-  }
-
-  void test_instanceCreationExpression_withTypeParams() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-class C<E> {
-  const C();
-}
-const c_int = const C<int>();
-const c_num = const C<num>();''');
-    EvaluationResultImpl c_int =
-        _evaluateTopLevelVariable(compilationUnit, "c_int");
-    _assertType(c_int, "C<int>");
-    DartObjectImpl c_int_value = c_int.value;
-    EvaluationResultImpl c_num =
-        _evaluateTopLevelVariable(compilationUnit, "c_num");
-    _assertType(c_num, "C<num>");
-    DartObjectImpl c_num_value = c_num.value;
-    expect(c_int_value == c_num_value, isFalse);
-  }
-
-  void test_isValidSymbol() {
-    expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse);
-    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse);
-  }
-
-  void test_length_of_improperly_typed_string_expression() {
-    // Since type annotations are ignored in unchecked mode, the improper
-    // types on s1 and s2 shouldn't prevent us from evaluating i to
-    // 'alpha'.length.
-    CompilationUnit compilationUnit = resolveSource('''
-const int s1 = 'alpha';
-const int s2 = 'beta';
-const int i = (true ? s1 : s2).length;
-''');
-    ConstTopLevelVariableElementImpl element =
-        findTopLevelDeclaration(compilationUnit, 'i').element;
-    EvaluationResultImpl result = element.evaluationResult;
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_length_of_improperly_typed_string_identifier() {
-    // Since type annotations are ignored in unchecked mode, the improper type
-    // on s shouldn't prevent us from evaluating i to 'alpha'.length.
-    CompilationUnit compilationUnit = resolveSource('''
-const int s = 'alpha';
-const int i = s.length;
-''');
-    ConstTopLevelVariableElementImpl element =
-        findTopLevelDeclaration(compilationUnit, 'i').element;
-    EvaluationResultImpl result = element.evaluationResult;
-    expect(_assertValidInt(result), 5);
-  }
-
-  void test_non_static_const_initialized_at_declaration() {
-    // Even though non-static consts are not allowed by the language, we need
-    // to handle them for error recovery purposes.
-    CompilationUnit compilationUnit = resolveSource('''
-class A {
-  const int i = 123;
-  const A();
-}
-
-const A a = const A();
-''');
-    EvaluationResultImpl result =
-        _evaluateTopLevelVariable(compilationUnit, 'a');
-    Map<String, DartObjectImpl> fields = _assertType(result, "A");
-    expect(fields, hasLength(1));
-    _assertIntField(fields, "i", 123);
-  }
-
-  void test_symbolLiteral_void() {
-    CompilationUnit compilationUnit =
-        resolveSource("const voidSymbol = #void;");
-    VariableDeclaration voidSymbol =
-        findTopLevelDeclaration(compilationUnit, "voidSymbol");
-    EvaluationResultImpl voidSymbolResult =
-        (voidSymbol.element as VariableElementImpl).evaluationResult;
-    DartObjectImpl value = voidSymbolResult.value;
-    expect(value.type, typeProvider.symbolType);
-    expect(value.toSymbolValue(), "void");
-  }
-
-  Map<String, DartObjectImpl> _assertFieldType(
-      Map<String, DartObjectImpl> fields,
-      String fieldName,
-      String expectedType) {
-    DartObjectImpl field = fields[fieldName];
-    expect(field.type.displayName, expectedType);
-    return field.fields;
-  }
-
-  void _assertIntField(
-      Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) {
-    DartObjectImpl field = fields[fieldName];
-    expect(field.type.name, "int");
-    expect(field.toIntValue(), expectedValue);
-  }
-
-  void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) {
-    DartObjectImpl field = fields[fieldName];
-    expect(field.isNull, isTrue);
-  }
-
-  void _assertProperDependencies(String sourceText,
-      [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
-    Source source = addSource(sourceText);
-    LibraryElement element = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, element);
-    expect(unit, isNotNull);
-    ConstantValueComputer computer = _makeConstantValueComputer();
-    computer.add(unit, source, source);
-    computer.computeValues();
-    assertErrors(source, expectedErrorCodes);
-  }
-
-  Map<String, DartObjectImpl> _assertType(
-      EvaluationResultImpl result, String typeName) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type.displayName, typeName);
-    return value.fields;
-  }
-
-  bool _assertValidBool(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.boolType);
-    bool boolValue = value.toBoolValue();
-    expect(boolValue, isNotNull);
-    return boolValue;
-  }
-
-  int _assertValidInt(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.intType);
-    return value.toIntValue();
-  }
-
-  void _assertValidNull(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.nullType);
-  }
-
-  String _assertValidString(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.type, typeProvider.stringType);
-    return value.toStringValue();
-  }
-
-  void _assertValidUnknown(EvaluationResultImpl result) {
-    expect(result.value, isNotNull);
-    DartObjectImpl value = result.value;
-    expect(value.isUnknown, isTrue);
-  }
-
-  EvaluationResultImpl _check_fromEnvironment_bool(
-      String valueInEnvironment, String defaultExpr) {
-    String envVarName = "x";
-    String varName = "foo";
-    if (valueInEnvironment != null) {
-      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
-    }
-    String defaultArg =
-        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
-    CompilationUnit compilationUnit = resolveSource(
-        "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);");
-    return _evaluateTopLevelVariable(compilationUnit, varName);
-  }
-
-  EvaluationResultImpl _check_fromEnvironment_int(
-      String valueInEnvironment, String defaultExpr) {
-    String envVarName = "x";
-    String varName = "foo";
-    if (valueInEnvironment != null) {
-      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
-    }
-    String defaultArg =
-        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
-    CompilationUnit compilationUnit = resolveSource(
-        "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);");
-    return _evaluateTopLevelVariable(compilationUnit, varName);
-  }
-
-  EvaluationResultImpl _check_fromEnvironment_string(
-      String valueInEnvironment, String defaultExpr) {
-    String envVarName = "x";
-    String varName = "foo";
-    if (valueInEnvironment != null) {
-      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
-    }
-    String defaultArg =
-        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
-    CompilationUnit compilationUnit = resolveSource(
-        "const $varName = const String.fromEnvironment('$envVarName'$defaultArg);");
-    return _evaluateTopLevelVariable(compilationUnit, varName);
-  }
-
-  void _checkInstanceCreation_withSupertypeParams(bool isExplicit) {
-    String superCall = isExplicit ? " : super()" : "";
-    CompilationUnit compilationUnit = resolveSource("""
-class A<T> {
-  const A();
-}
-class B<T, U> extends A<T> {
-  const B()$superCall;
-}
-class C<T, U> extends A<U> {
-  const C()$superCall;
-}
-const b_int_num = const B<int, num>();
-const c_int_num = const C<int, num>();""");
-    EvaluationResultImpl b_int_num =
-        _evaluateTopLevelVariable(compilationUnit, "b_int_num");
-    Map<String, DartObjectImpl> b_int_num_fields =
-        _assertType(b_int_num, "B<int, num>");
-    _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>");
-    EvaluationResultImpl c_int_num =
-        _evaluateTopLevelVariable(compilationUnit, "c_int_num");
-    Map<String, DartObjectImpl> c_int_num_fields =
-        _assertType(c_int_num, "C<int, num>");
-    _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>");
-  }
-
-  void _checkInstanceCreationOptionalParams(
-      bool isFieldFormal, bool isNamed, bool hasDefault) {
-    String fieldName = "j";
-    String paramName = isFieldFormal ? fieldName : "i";
-    String formalParam =
-        "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : ""}";
-    CompilationUnit compilationUnit = resolveSource("""
-const x = const A();
-const y = const A(${isNamed ? '$paramName: ' : ''}10);
-class A {
-  const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"};
-  final int $fieldName;
-}""");
-    EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x");
-    Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A");
-    expect(fieldsOfX, hasLength(1));
-    if (hasDefault) {
-      _assertIntField(fieldsOfX, fieldName, 3);
-    } else {
-      _assertNullField(fieldsOfX, fieldName);
-    }
-    EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y");
-    Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A");
-    expect(fieldsOfY, hasLength(1));
-    _assertIntField(fieldsOfY, fieldName, 10);
-  }
-
-  /**
-   * Search [compilationUnit] for a class named [className], containing a
-   * method [methodName], with exactly one annotation.  Return the constant
-   * value of the annotation.
-   */
-  EvaluationResultImpl _evaluateAnnotation(
-      CompilationUnit compilationUnit, String className, String memberName) {
-    for (CompilationUnitMember member in compilationUnit.declarations) {
-      if (member is ClassDeclaration && member.name.name == className) {
-        for (ClassMember classMember in member.members) {
-          if (classMember is MethodDeclaration &&
-              classMember.name.name == memberName) {
-            expect(classMember.metadata, hasLength(1));
-            ElementAnnotationImpl elementAnnotation =
-                classMember.metadata[0].elementAnnotation;
-            return elementAnnotation.evaluationResult;
-          }
-        }
-      }
-    }
-    fail('Class member not found');
-    return null;
-  }
-
-  EvaluationResultImpl _evaluateTopLevelVariable(
-      CompilationUnit compilationUnit, String name) {
-    VariableDeclaration varDecl =
-        findTopLevelDeclaration(compilationUnit, name);
-    ConstTopLevelVariableElementImpl varElement = varDecl.element;
-    return varElement.evaluationResult;
-  }
-
-  ConstantValueComputer _makeConstantValueComputer() {
-    ConstantEvaluationValidator_ForTest validator =
-        new ConstantEvaluationValidator_ForTest();
-    validator.computer = new ConstantValueComputer(
-        analysisContext2,
-        analysisContext2.typeProvider,
-        analysisContext2.declaredVariables,
-        validator,
-        analysisContext2.typeSystem);
-    return validator.computer;
-  }
-
-  void _validate(bool shouldBeValid, VariableDeclarationList declarationList) {
-    for (VariableDeclaration declaration in declarationList.variables) {
-      VariableElementImpl element = declaration.element as VariableElementImpl;
-      expect(element, isNotNull);
-      EvaluationResultImpl result = element.evaluationResult;
-      if (shouldBeValid) {
-        expect(result.value, isNotNull);
-      } else {
-        expect(result.value, isNull);
-      }
-    }
-  }
-}
-
-@reflectiveTest
-class ConstantVisitorTest extends ResolverTestCase {
-  void test_visitConditionalExpression_false() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.integer(0);
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(false), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    _assertValue(
-        0,
-        expression.accept(new ConstantVisitor(
-            new ConstantEvaluationEngine(
-                new TestTypeProvider(), new DeclaredVariables(),
-                typeSystem: new TypeSystemImpl()),
-            errorReporter)));
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitConditionalExpression_nonBooleanCondition() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.integer(0);
-    NullLiteral conditionExpression = AstFactory.nullLiteral();
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        conditionExpression, thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(
-            new TestTypeProvider(), new DeclaredVariables(),
-            typeSystem: new TypeSystemImpl()),
-        errorReporter));
-    expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
-  }
-
-  void test_visitConditionalExpression_nonConstantElse() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.identifier3("x");
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(
-            new TestTypeProvider(), new DeclaredVariables(),
-            typeSystem: new TypeSystemImpl()),
-        errorReporter));
-    expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
-  }
-
-  void test_visitConditionalExpression_nonConstantThen() {
-    Expression thenExpression = AstFactory.identifier3("x");
-    Expression elseExpression = AstFactory.integer(0);
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(
-            new TestTypeProvider(), new DeclaredVariables(),
-            typeSystem: new TypeSystemImpl()),
-        errorReporter));
-    expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
-  }
-
-  void test_visitConditionalExpression_true() {
-    Expression thenExpression = AstFactory.integer(1);
-    Expression elseExpression = AstFactory.integer(0);
-    ConditionalExpression expression = AstFactory.conditionalExpression(
-        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    _assertValue(
-        1,
-        expression.accept(new ConstantVisitor(
-            new ConstantEvaluationEngine(
-                new TestTypeProvider(), new DeclaredVariables(),
-                typeSystem: new TypeSystemImpl()),
-            errorReporter)));
-    errorListener.assertNoErrors();
-  }
-
-  void test_visitSimpleIdentifier_className() {
-    CompilationUnit compilationUnit = resolveSource('''
-const a = C;
-class C {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
-    expect(result.type, typeProvider.typeType);
-    expect(result.toTypeValue().name, 'C');
-  }
-
-  void test_visitSimpleIdentifier_dynamic() {
-    CompilationUnit compilationUnit = resolveSource('''
-const a = dynamic;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
-    expect(result.type, typeProvider.typeType);
-    expect(result.toTypeValue(), typeProvider.dynamicType);
-  }
-
-  void test_visitSimpleIdentifier_inEnvironment() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
-    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
-    DartObjectImpl six =
-        new DartObjectImpl(typeProvider.intType, new IntState(6));
-    environment["b"] = six;
-    _assertValue(6, _evaluateConstant(compilationUnit, "a", environment));
-  }
-
-  void test_visitSimpleIdentifier_notInEnvironment() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
-    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
-    DartObjectImpl six =
-        new DartObjectImpl(typeProvider.intType, new IntState(6));
-    environment["c"] = six;
-    _assertValue(3, _evaluateConstant(compilationUnit, "a", environment));
-  }
-
-  void test_visitSimpleIdentifier_withoutEnvironment() {
-    CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
-    _assertValue(3, _evaluateConstant(compilationUnit, "a", null));
-  }
-
-  void _assertValue(int expectedValue, DartObjectImpl result) {
-    expect(result, isNotNull);
-    expect(result.type.name, "int");
-    expect(result.toIntValue(), expectedValue);
-  }
-
-  NonExistingSource _dummySource() {
-    String path = '/test.dart';
-    return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
-  }
-
-  DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
-      Map<String, DartObjectImpl> lexicalEnvironment) {
-    Source source = compilationUnit.element.source;
-    Expression expression =
-        findTopLevelConstantExpression(compilationUnit, name);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
-    DartObjectImpl result = expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
-            typeSystem: typeSystem),
-        errorReporter,
-        lexicalEnvironment: lexicalEnvironment));
-    errorListener.assertNoErrors();
-    return result;
-  }
-}
-
 @reflectiveTest
 class ContentCacheTest {
   void test_setContents() {
@@ -4603,7 +2487,25 @@
 }
 
 @reflectiveTest
-class ElementBuilderTest extends EngineTestCase {
+class ElementBuilderTest extends ParserTestCase {
+  void fail_visitMethodDeclaration_setter_duplicate() {
+    // https://github.com/dart-lang/sdk/issues/25601
+    String code = r'''
+class C {
+  set zzz(x) {}
+  set zzz(y) {}
+}
+''';
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(code);
+    ElementHolder holder = new ElementHolder();
+    ElementBuilder builder = new ElementBuilder(holder);
+    unit.accept(builder);
+    ClassElement classElement = holder.types[0];
+    for (PropertyAccessorElement accessor in classElement.accessors) {
+      expect(accessor.variable.setter, same(accessor));
+    }
+  }
+
   void test_visitCatchClause() {
     // } catch (e, s) {
     ElementHolder holder = new ElementHolder();
@@ -4857,8 +2759,8 @@
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     String className = "A";
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration2(
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
             null,
             null,
             AstFactory.identifier3(className),
@@ -4886,8 +2788,8 @@
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     String className = "A";
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration2(
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
             null,
             Keyword.FACTORY,
             AstFactory.identifier3(className),
@@ -4913,8 +2815,8 @@
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     String className = "A";
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration2(
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
             null,
             null,
             AstFactory.identifier3(className),
@@ -4946,8 +2848,8 @@
     ElementBuilder builder = new ElementBuilder(holder);
     String className = "A";
     String constructorName = "c";
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration2(
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
             null,
             null,
             AstFactory.identifier3(className),
@@ -4975,8 +2877,8 @@
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     String className = "A";
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration2(
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
             null,
             null,
             AstFactory.identifier3(className),
@@ -5056,8 +2958,8 @@
     ElementHolder holder = new ElementHolder();
     ElementBuilder builder = new ElementBuilder(holder);
     String parameterName = 'p';
-    DefaultFormalParameter formalParameter = AstFactory
-        .positionalFormalParameter(
+    DefaultFormalParameter formalParameter =
+        AstFactory.positionalFormalParameter(
             AstFactory.simpleFormalParameter3(parameterName),
             AstFactory.integer(0));
     formalParameter.accept(builder);
@@ -6462,7 +4364,8 @@
         (obj) => obj is FunctionElement, FunctionElement, element);
   }
 
-  void test_locate_Identifier_annotationClass_namedConstructor_forSimpleFormalParameter() {
+  void
+      test_locate_Identifier_annotationClass_namedConstructor_forSimpleFormalParameter() {
     AstNode id = _findNodeIndexedIn(
         "Class",
         2,
@@ -6477,7 +4380,8 @@
         (obj) => obj is ClassElement, ClassElement, element);
   }
 
-  void test_locate_Identifier_annotationClass_unnamedConstructor_forSimpleFormalParameter() {
+  void
+      test_locate_Identifier_annotationClass_unnamedConstructor_forSimpleFormalParameter() {
     AstNode id = _findNodeIndexedIn(
         "Class",
         2,
@@ -6584,8 +4488,8 @@
     SimpleIdentifier identifier = AstFactory.identifier3("A");
     PrefixedIdentifier prefixedIdentifier =
         AstFactory.identifier4("pref", identifier);
-    InstanceCreationExpression creation = AstFactory
-        .instanceCreationExpression2(
+    InstanceCreationExpression creation =
+        AstFactory.instanceCreationExpression2(
             Keyword.NEW, AstFactory.typeName3(prefixedIdentifier));
     // set ClassElement
     ClassElement classElement = ElementFactory.classElement2("A");
@@ -6602,8 +4506,8 @@
   void test_locate_InstanceCreationExpression_type_simpleIdentifier() {
     // prepare: new A()
     SimpleIdentifier identifier = AstFactory.identifier3("A");
-    InstanceCreationExpression creation = AstFactory
-        .instanceCreationExpression2(
+    InstanceCreationExpression creation =
+        AstFactory.instanceCreationExpression2(
             Keyword.NEW, AstFactory.typeName3(identifier));
     // set ClassElement
     ClassElement classElement = ElementFactory.classElement2("A");
@@ -8052,98 +5956,6 @@
 }
 
 @reflectiveTest
-class ReferenceFinderTest {
-  DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
-  VariableElement _head;
-  Element _tail;
-
-  void setUp() {
-    _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
-    _head = ElementFactory.topLevelVariableElement2("v1");
-  }
-
-  void test_visitSimpleIdentifier_const() {
-    _visitNode(_makeTailVariable("v2", true));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSimpleIdentifier_nonConst() {
-    _visitNode(_makeTailVariable("v2", false));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSuperConstructorInvocation_const() {
-    _visitNode(_makeTailSuperConstructorInvocation("A", true));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSuperConstructorInvocation_nonConst() {
-    _visitNode(_makeTailSuperConstructorInvocation("A", false));
-    _assertOneArc(_tail);
-  }
-
-  void test_visitSuperConstructorInvocation_unresolved() {
-    SuperConstructorInvocation superConstructorInvocation =
-        AstFactory.superConstructorInvocation();
-    _visitNode(superConstructorInvocation);
-    _assertNoArcs();
-  }
-
-  void _assertNoArcs() {
-    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
-    expect(tails, hasLength(0));
-  }
-
-  void _assertOneArc(Element tail) {
-    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
-    expect(tails, hasLength(1));
-    expect(tails.first, same(tail));
-  }
-
-  ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
-      new ReferenceFinder((ConstantEvaluationTarget dependency) {
-        _referenceGraph.addEdge(source, dependency);
-      });
-  SuperConstructorInvocation _makeTailSuperConstructorInvocation(
-      String name, bool isConst) {
-    List<ConstructorInitializer> initializers =
-        new List<ConstructorInitializer>();
-    ConstructorDeclaration constructorDeclaration = AstFactory
-        .constructorDeclaration(AstFactory.identifier3(name), null,
-            AstFactory.formalParameterList(), initializers);
-    if (isConst) {
-      constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
-    }
-    ClassElementImpl classElement = ElementFactory.classElement2(name);
-    SuperConstructorInvocation superConstructorInvocation =
-        AstFactory.superConstructorInvocation();
-    ConstructorElementImpl constructorElement =
-        ElementFactory.constructorElement(classElement, name, isConst);
-    _tail = constructorElement;
-    superConstructorInvocation.staticElement = constructorElement;
-    return superConstructorInvocation;
-  }
-
-  SimpleIdentifier _makeTailVariable(String name, bool isConst) {
-    VariableDeclaration variableDeclaration =
-        AstFactory.variableDeclaration(name);
-    ConstLocalVariableElementImpl variableElement =
-        ElementFactory.constLocalVariableElement(name);
-    _tail = variableElement;
-    variableElement.const3 = isConst;
-    AstFactory.variableDeclarationList2(
-        isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
-    SimpleIdentifier identifier = AstFactory.identifier3(name);
-    identifier.staticElement = variableElement;
-    return identifier;
-  }
-
-  void _visitNode(AstNode node) {
-    node.accept(_createReferenceFinder(_head));
-  }
-}
-
-@reflectiveTest
 class SDKLibrariesReaderTest extends EngineTestCase {
   void test_readFrom_dart2js() {
     LibraryMap libraryMap = new SdkLibrariesReader(true).readFromFile(
@@ -8218,16 +6030,6 @@
   }
 }
 
-class TestAnalysisContext_ConstantFinderTest extends TestAnalysisContext {
-  bool invoked = false;
-  TestAnalysisContext_ConstantFinderTest();
-
-  @override
-  InternalAnalysisContext getContextFor(Source source) {
-    return this;
-  }
-}
-
 @reflectiveTest
 class UriKindTest {
   void test_fromEncoding() {
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 5f2abf5..15ef8ad 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -897,7 +897,8 @@
     // TODO(paulberry): the error CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE is
     // redundant and ought to be suppressed.
     assertErrors(source, [
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
+      CompileTimeErrorCode
+          .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
       CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
     ]);
     verify([source]);
@@ -1265,6 +1266,20 @@
     verify([source]);
   }
 
+  void test_constInitializedWithNonConstValue_finalField() {
+    // Regression test for bug #25526 which previously
+    // caused two errors to be reported.
+    Source source = addSource(r'''
+class Foo {
+  final field = [];
+  foo([int x = field]) {}
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+    verify([source]);
+  }
+
   void test_constInitializedWithNonConstValue_missingConstInListLiteral() {
     Source source = addSource("const List L = [0];");
     computeLibrarySourceErrors(source);
@@ -1291,7 +1306,8 @@
 import 'lib1.dart' deferred as a;
 const B = a.V;'''
     ], <ErrorCode>[
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY
+      CompileTimeErrorCode
+          .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY
     ]);
   }
 
@@ -1305,7 +1321,8 @@
 import 'lib1.dart' deferred as a;
 const B = a.V + 1;'''
     ], <ErrorCode>[
-      CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY
+      CompileTimeErrorCode
+          .CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE_FROM_DEFERRED_LIBRARY
     ]);
   }
 
@@ -1827,7 +1844,8 @@
     verify([source]);
   }
 
-  void test_duplicateDefinitionInheritance_instanceGetterAbstract_staticGetter() {
+  void
+      test_duplicateDefinitionInheritance_instanceGetterAbstract_staticGetter() {
     Source source = addSource(r'''
 abstract class A {
   int get x;
@@ -1855,7 +1873,8 @@
     verify([source]);
   }
 
-  void test_duplicateDefinitionInheritance_instanceMethodAbstract_staticMethod() {
+  void
+      test_duplicateDefinitionInheritance_instanceMethodAbstract_staticMethod() {
     Source source = addSource(r'''
 abstract class A {
   x();
@@ -1883,7 +1902,8 @@
     verify([source]);
   }
 
-  void test_duplicateDefinitionInheritance_instanceSetterAbstract_staticSetter() {
+  void
+      test_duplicateDefinitionInheritance_instanceSetterAbstract_staticSetter() {
     Source source = addSource(r'''
 abstract class A {
   set x(value);
@@ -1967,9 +1987,7 @@
   void test_extendsDisallowedClass_class_double() {
     Source source = addSource("class A extends double {}");
     computeLibrarySourceErrors(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS
-    ]);
+    assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
@@ -1996,9 +2014,7 @@
   void test_extendsDisallowedClass_class_num() {
     Source source = addSource("class A extends num {}");
     computeLibrarySourceErrors(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS
-    ]);
+    assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
     verify([source]);
   }
 
@@ -2638,7 +2654,8 @@
     verify([source]);
   }
 
-  void test_implicitThisReferenceInInitializer_redirectingConstructorInvocation() {
+  void
+      test_implicitThisReferenceInInitializer_redirectingConstructorInvocation() {
     Source source = addSource(r'''
 class A {
   A(p) {}
@@ -3004,7 +3021,8 @@
     verify([source]);
   }
 
-  void test_invalidAnnotation_importWithPrefix_notVariableOrConstructorInvocation() {
+  void
+      test_invalidAnnotation_importWithPrefix_notVariableOrConstructorInvocation() {
     addNamedSource(
         "/lib.dart",
         r'''
@@ -4653,7 +4671,8 @@
   const A() : x = a.c;
 }'''
     ], <ErrorCode>[
-      CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
+      CompileTimeErrorCode
+          .NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
     ]);
   }
 
@@ -4670,7 +4689,8 @@
   const A() : x = a.c + 1;
 }'''
     ], <ErrorCode>[
-      CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
+      CompileTimeErrorCode
+          .NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
     ]);
   }
 
@@ -4687,7 +4707,8 @@
   const A() : this.named(a.c);
 }'''
     ], <ErrorCode>[
-      CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
+      CompileTimeErrorCode
+          .NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
     ]);
   }
 
@@ -4706,7 +4727,8 @@
   const B() : super(a.c);
 }'''
     ], <ErrorCode>[
-      CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
+      CompileTimeErrorCode
+          .NON_CONSTANT_VALUE_IN_INITIALIZER_FROM_DEFERRED_LIBRARY
     ]);
   }
 
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
new file mode 100644
index 0000000..04592ff
--- /dev/null
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -0,0 +1,2290 @@
+// 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 analyzer.test.constant_test;
+
+import 'package:analyzer/dart/ast/ast.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/generated/constant.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/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:path/path.dart';
+import 'package:unittest/unittest.dart';
+
+import '../reflective_tests.dart';
+import '../utils.dart';
+import 'engine_test.dart';
+import 'resolver_test.dart';
+import 'test_support.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(ConstantEvaluatorTest);
+  runReflectiveTests(ConstantFinderTest);
+  runReflectiveTests(ConstantValueComputerTest);
+  runReflectiveTests(ConstantVisitorTest);
+  runReflectiveTests(ReferenceFinderTest);
+}
+
+/**
+ * Implementation of [ConstantEvaluationValidator] used during unit tests;
+ * verifies that any nodes referenced during constant evaluation are present in
+ * the dependency graph.
+ */
+class ConstantEvaluationValidator_ForTest
+    implements ConstantEvaluationValidator {
+  final InternalAnalysisContext context;
+  ConstantValueComputer computer;
+  ConstantEvaluationTarget _nodeBeingEvaluated;
+
+  ConstantEvaluationValidator_ForTest(this.context);
+
+  @override
+  void beforeComputeValue(ConstantEvaluationTarget constant) {
+    _nodeBeingEvaluated = constant;
+  }
+
+  @override
+  void beforeGetConstantInitializers(ConstructorElement constructor) =>
+      _checkPathTo(constructor);
+
+  @override
+  void beforeGetEvaluationResult(ConstantEvaluationTarget constant) =>
+      _checkPathTo(constant);
+
+  @override
+  void beforeGetFieldEvaluationResult(FieldElementImpl field) =>
+      _checkPathTo(field);
+
+  @override
+  void beforeGetParameterDefault(ParameterElement parameter) =>
+      _checkPathTo(parameter);
+
+  void _checkPathTo(ConstantEvaluationTarget target) {
+    if (computer.referenceGraph.containsPath(_nodeBeingEvaluated, target)) {
+      return; // pass
+    }
+    // print a nice error message on failure
+    StringBuffer out = new StringBuffer();
+    out.writeln("missing path in constant dependency graph");
+    out.writeln("from $_nodeBeingEvaluated to $target");
+    for (var s in context.analysisCache.sources) {
+      String text = context.getContents(s).data;
+      if (text != "") {
+        out.writeln('''
+=== ${s.shortName}
+$text''');
+      }
+    }
+    fail(out.toString());
+  }
+}
+
+@reflectiveTest
+class ConstantEvaluatorTest extends ResolverTestCase {
+  void fail_constructor() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_identifier_class() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_identifier_function() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_identifier_static() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_identifier_staticMethod() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_identifier_topLevel() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_identifier_typeParameter() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_prefixedIdentifier_invalid() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_prefixedIdentifier_valid() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_propertyAccess_invalid() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_propertyAccess_valid() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_simpleIdentifier_invalid() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void fail_simpleIdentifier_valid() {
+    EvaluationResult result = _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  void test_bitAnd_int_int() {
+    _assertValue3(74 & 42, "74 & 42");
+  }
+
+  void test_bitNot() {
+    _assertValue3(~42, "~42");
+  }
+
+  void test_bitOr_int_int() {
+    _assertValue3(74 | 42, "74 | 42");
+  }
+
+  void test_bitXor_int_int() {
+    _assertValue3(74 ^ 42, "74 ^ 42");
+  }
+
+  void test_divide_double_double() {
+    _assertValue2(3.2 / 2.3, "3.2 / 2.3");
+  }
+
+  void test_divide_double_double_byZero() {
+    EvaluationResult result = _getExpressionValue("3.2 / 0.0");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value.type.name, "double");
+    expect(value.toDoubleValue().isInfinite, isTrue);
+  }
+
+  void test_divide_int_int() {
+    _assertValue2(1.5, "3 / 2");
+  }
+
+  void test_divide_int_int_byZero() {
+    EvaluationResult result = _getExpressionValue("3 / 0");
+    expect(result.isValid, isTrue);
+  }
+
+  void test_equal_boolean_boolean() {
+    _assertValue(false, "true == false");
+  }
+
+  void test_equal_int_int() {
+    _assertValue(false, "2 == 3");
+  }
+
+  void test_equal_invalidLeft() {
+    EvaluationResult result = _getExpressionValue("a == 3");
+    expect(result.isValid, isFalse);
+  }
+
+  void test_equal_invalidRight() {
+    EvaluationResult result = _getExpressionValue("2 == a");
+    expect(result.isValid, isFalse);
+  }
+
+  void test_equal_string_string() {
+    _assertValue(false, "'a' == 'b'");
+  }
+
+  void test_greaterThan_int_int() {
+    _assertValue(false, "2 > 3");
+  }
+
+  void test_greaterThanOrEqual_int_int() {
+    _assertValue(false, "2 >= 3");
+  }
+
+  void test_leftShift_int_int() {
+    _assertValue3(64, "16 << 2");
+  }
+
+  void test_lessThan_int_int() {
+    _assertValue(true, "2 < 3");
+  }
+
+  void test_lessThanOrEqual_int_int() {
+    _assertValue(true, "2 <= 3");
+  }
+
+  void test_literal_boolean_false() {
+    _assertValue(false, "false");
+  }
+
+  void test_literal_boolean_true() {
+    _assertValue(true, "true");
+  }
+
+  void test_literal_list() {
+    EvaluationResult result = _getExpressionValue("const ['a', 'b', 'c']");
+    expect(result.isValid, isTrue);
+  }
+
+  void test_literal_map() {
+    EvaluationResult result =
+        _getExpressionValue("const {'a' : 'm', 'b' : 'n', 'c' : 'o'}");
+    expect(result.isValid, isTrue);
+  }
+
+  void test_literal_null() {
+    EvaluationResult result = _getExpressionValue("null");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value.isNull, isTrue);
+  }
+
+  void test_literal_number_double() {
+    _assertValue2(3.45, "3.45");
+  }
+
+  void test_literal_number_integer() {
+    _assertValue3(42, "42");
+  }
+
+  void test_literal_string_adjacent() {
+    _assertValue4("abcdef", "'abc' 'def'");
+  }
+
+  void test_literal_string_interpolation_invalid() {
+    EvaluationResult result = _getExpressionValue("'a\${f()}c'");
+    expect(result.isValid, isFalse);
+  }
+
+  void test_literal_string_interpolation_valid() {
+    _assertValue4("a3c", "'a\${3}c'");
+  }
+
+  void test_literal_string_simple() {
+    _assertValue4("abc", "'abc'");
+  }
+
+  void test_logicalAnd() {
+    _assertValue(false, "true && false");
+  }
+
+  void test_logicalNot() {
+    _assertValue(false, "!true");
+  }
+
+  void test_logicalOr() {
+    _assertValue(true, "true || false");
+  }
+
+  void test_minus_double_double() {
+    _assertValue2(3.2 - 2.3, "3.2 - 2.3");
+  }
+
+  void test_minus_int_int() {
+    _assertValue3(1, "3 - 2");
+  }
+
+  void test_negated_boolean() {
+    EvaluationResult result = _getExpressionValue("-true");
+    expect(result.isValid, isFalse);
+  }
+
+  void test_negated_double() {
+    _assertValue2(-42.3, "-42.3");
+  }
+
+  void test_negated_integer() {
+    _assertValue3(-42, "-42");
+  }
+
+  void test_notEqual_boolean_boolean() {
+    _assertValue(true, "true != false");
+  }
+
+  void test_notEqual_int_int() {
+    _assertValue(true, "2 != 3");
+  }
+
+  void test_notEqual_invalidLeft() {
+    EvaluationResult result = _getExpressionValue("a != 3");
+    expect(result.isValid, isFalse);
+  }
+
+  void test_notEqual_invalidRight() {
+    EvaluationResult result = _getExpressionValue("2 != a");
+    expect(result.isValid, isFalse);
+  }
+
+  void test_notEqual_string_string() {
+    _assertValue(true, "'a' != 'b'");
+  }
+
+  void test_parenthesizedExpression() {
+    _assertValue4("a", "('a')");
+  }
+
+  void test_plus_double_double() {
+    _assertValue2(2.3 + 3.2, "2.3 + 3.2");
+  }
+
+  void test_plus_int_int() {
+    _assertValue3(5, "2 + 3");
+  }
+
+  void test_plus_string_string() {
+    _assertValue4("ab", "'a' + 'b'");
+  }
+
+  void test_remainder_double_double() {
+    _assertValue2(3.2 % 2.3, "3.2 % 2.3");
+  }
+
+  void test_remainder_int_int() {
+    _assertValue3(2, "8 % 3");
+  }
+
+  void test_rightShift() {
+    _assertValue3(16, "64 >> 2");
+  }
+
+  void test_stringLength_complex() {
+    _assertValue3(6, "('qwe' + 'rty').length");
+  }
+
+  void test_stringLength_simple() {
+    _assertValue3(6, "'Dvorak'.length");
+  }
+
+  void test_times_double_double() {
+    _assertValue2(2.3 * 3.2, "2.3 * 3.2");
+  }
+
+  void test_times_int_int() {
+    _assertValue3(6, "2 * 3");
+  }
+
+  void test_truncatingDivide_double_double() {
+    _assertValue3(1, "3.2 ~/ 2.3");
+  }
+
+  void test_truncatingDivide_int_int() {
+    _assertValue3(3, "10 ~/ 3");
+  }
+
+  void _assertValue(bool expectedValue, String contents) {
+    EvaluationResult result = _getExpressionValue(contents);
+    DartObject value = result.value;
+    expect(value.type.name, "bool");
+    expect(value.toBoolValue(), expectedValue);
+  }
+
+  void _assertValue2(double expectedValue, String contents) {
+    EvaluationResult result = _getExpressionValue(contents);
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value.type.name, "double");
+    expect(value.toDoubleValue(), expectedValue);
+  }
+
+  void _assertValue3(int expectedValue, String contents) {
+    EvaluationResult result = _getExpressionValue(contents);
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value.type.name, "int");
+    expect(value.toIntValue(), expectedValue);
+  }
+
+  void _assertValue4(String expectedValue, String contents) {
+    EvaluationResult result = _getExpressionValue(contents);
+    DartObject value = result.value;
+    expect(value, isNotNull);
+    ParameterizedType type = value.type;
+    expect(type, isNotNull);
+    expect(type.name, "String");
+    expect(value.toStringValue(), expectedValue);
+  }
+
+  EvaluationResult _getExpressionValue(String contents) {
+    Source source = addSource("var x = $contents;");
+    LibraryElement library = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, library);
+    expect(unit, isNotNull);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember declaration = declarations[0];
+    EngineTestCase.assertInstanceOf((obj) => obj is TopLevelVariableDeclaration,
+        TopLevelVariableDeclaration, declaration);
+    NodeList<VariableDeclaration> variables =
+        (declaration as TopLevelVariableDeclaration).variables.variables;
+    expect(variables, hasLength(1));
+    ConstantEvaluator evaluator = new ConstantEvaluator(
+        source, analysisContext.typeProvider,
+        typeSystem: analysisContext.typeSystem);
+    return evaluator.evaluate(variables[0].initializer);
+  }
+}
+
+@reflectiveTest
+class ConstantFinderTest {
+  AstNode _node;
+  TypeProvider _typeProvider;
+  AnalysisContext _context;
+  Source _source;
+
+  void setUp() {
+    _typeProvider = new TestTypeProvider();
+    _context = new _TestAnalysisContext();
+    _source = new TestSource();
+  }
+
+  /**
+   * Test an annotation that consists solely of an identifier (and hence
+   * represents a reference to a compile-time constant variable).
+   */
+  void test_visitAnnotation_constantVariable() {
+    _node = AstFactory.annotation(AstFactory.identifier3('x'));
+    expect(_findAnnotations(), contains(_node));
+  }
+
+  /**
+   * Test an annotation that represents the invocation of a constant
+   * constructor.
+   */
+  void test_visitAnnotation_invocation() {
+    _node = AstFactory.annotation2(
+        AstFactory.identifier3('A'), null, AstFactory.argumentList());
+    expect(_findAnnotations(), contains(_node));
+  }
+
+  void test_visitConstructorDeclaration_const() {
+    ConstructorElement element = _setupConstructorDeclaration("A", true);
+    expect(_findConstants(), contains(element));
+  }
+
+  void test_visitConstructorDeclaration_nonConst() {
+    _setupConstructorDeclaration("A", false);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_const() {
+    VariableElement element = _setupVariableDeclaration("v", true, true);
+    expect(_findConstants(), contains(element));
+  }
+
+  void test_visitVariableDeclaration_final_inClass() {
+    _setupFieldDeclaration('C', 'f', Keyword.FINAL);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+        hasConstConstructor: true);
+    expect(_findConstants(), contains(field.element));
+  }
+
+  void test_visitVariableDeclaration_final_outsideClass() {
+    _setupVariableDeclaration('v', false, true, isFinal: true);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_noInitializer() {
+    _setupVariableDeclaration("v", true, false);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_nonConst() {
+    _setupVariableDeclaration("v", false, true);
+    expect(_findConstants(), isEmpty);
+  }
+
+  void test_visitVariableDeclaration_static_const_inClass() {
+    VariableDeclaration field =
+        _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
+    expect(_findConstants(), contains(field.element));
+  }
+
+  void
+      test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
+        isStatic: true, hasConstConstructor: true);
+    expect(_findConstants(), contains(field.element));
+  }
+
+  void
+      test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+        isStatic: true, hasConstConstructor: true);
+    expect(_findConstants(), isNot(contains(field.element)));
+  }
+
+  void
+      test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
+    VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+        isInitialized: false, hasConstConstructor: true);
+    expect(_findConstants(), isNot(contains(field.element)));
+  }
+
+  void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
+    _setupFieldDeclaration('C', 'f', Keyword.CONST,
+        isStatic: true, isInitialized: false);
+    expect(_findConstants(), isEmpty);
+  }
+
+  List<Annotation> _findAnnotations() {
+    Set<Annotation> annotations = new Set<Annotation>();
+    for (ConstantEvaluationTarget target in _findConstants()) {
+      if (target is ConstantEvaluationTarget_Annotation) {
+        expect(target.context, same(_context));
+        expect(target.source, same(_source));
+        annotations.add(target.annotation);
+      }
+    }
+    return new List<Annotation>.from(annotations);
+  }
+
+  Set<ConstantEvaluationTarget> _findConstants() {
+    ConstantFinder finder = new ConstantFinder(_context, _source, _source);
+    _node.accept(finder);
+    Set<ConstantEvaluationTarget> constants = finder.constantsToCompute;
+    expect(constants, isNotNull);
+    return constants;
+  }
+
+  ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
+    Keyword constKeyword = isConst ? Keyword.CONST : null;
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration2(
+            constKeyword,
+            null,
+            null,
+            name,
+            AstFactory.formalParameterList(),
+            null,
+            AstFactory.blockFunctionBody2());
+    ClassElement classElement = ElementFactory.classElement2(name);
+    ConstructorElement element =
+        ElementFactory.constructorElement(classElement, name, isConst);
+    constructorDeclaration.element = element;
+    _node = constructorDeclaration;
+    return element;
+  }
+
+  VariableDeclaration _setupFieldDeclaration(
+      String className, String fieldName, Keyword keyword,
+      {bool isInitialized: true,
+      bool isStatic: false,
+      bool hasConstConstructor: false}) {
+    VariableDeclaration variableDeclaration = isInitialized
+        ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
+        : AstFactory.variableDeclaration(fieldName);
+    VariableElement fieldElement = ElementFactory.fieldElement(
+        fieldName,
+        isStatic,
+        keyword == Keyword.FINAL,
+        keyword == Keyword.CONST,
+        _typeProvider.intType);
+    variableDeclaration.name.staticElement = fieldElement;
+    FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
+        isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
+    ClassDeclaration classDeclaration =
+        AstFactory.classDeclaration(null, className, null, null, null, null);
+    classDeclaration.members.add(fieldDeclaration);
+    _node = classDeclaration;
+    ClassElementImpl classElement = ElementFactory.classElement2(className);
+    classElement.fields = <FieldElement>[fieldElement];
+    classDeclaration.name.staticElement = classElement;
+    if (hasConstConstructor) {
+      ConstructorDeclaration constructorDeclaration =
+          AstFactory.constructorDeclaration2(
+              Keyword.CONST,
+              null,
+              AstFactory.identifier3(className),
+              null,
+              AstFactory.formalParameterList(),
+              null,
+              AstFactory.blockFunctionBody2());
+      classDeclaration.members.add(constructorDeclaration);
+      ConstructorElement constructorElement =
+          ElementFactory.constructorElement(classElement, '', true);
+      constructorDeclaration.element = constructorElement;
+      classElement.constructors = <ConstructorElement>[constructorElement];
+    } else {
+      classElement.constructors = ConstructorElement.EMPTY_LIST;
+    }
+    return variableDeclaration;
+  }
+
+  VariableElement _setupVariableDeclaration(
+      String name, bool isConst, bool isInitialized,
+      {isFinal: false}) {
+    VariableDeclaration variableDeclaration = isInitialized
+        ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
+        : AstFactory.variableDeclaration(name);
+    SimpleIdentifier identifier = variableDeclaration.name;
+    VariableElement element = ElementFactory.localVariableElement(identifier);
+    identifier.staticElement = element;
+    Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
+    AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
+    _node = variableDeclaration;
+    return element;
+  }
+}
+
+@reflectiveTest
+class ConstantValueComputerTest extends ResolverTestCase {
+  void test_annotation_constConstructor() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A(this.i);
+}
+
+class C {
+  @A(5)
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
+    _assertIntField(annotationFields, 'i', 5);
+  }
+
+  void test_annotation_constConstructor_named() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A.named(this.i);
+}
+
+class C {
+  @A.named(5)
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
+    _assertIntField(annotationFields, 'i', 5);
+  }
+
+  void test_annotation_constConstructor_noArgs() {
+    // Failing to pass arguments to an annotation which is a constant
+    // constructor is illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A(this.i);
+}
+
+class C {
+  @A
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_constConstructor_noArgs_named() {
+    // Failing to pass arguments to an annotation which is a constant
+    // constructor is illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  const A.named(this.i);
+}
+
+class C {
+  @A.named
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_nonConstConstructor() {
+    // Calling a non-const constructor from an annotation that is illegal, but
+    // shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  final int i;
+  A(this.i);
+}
+
+class C {
+  @A(5)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_staticConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class C {
+  static const int i = 5;
+
+  @i
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_annotation_staticConst_args() {
+    // Applying arguments to an annotation that is a static const is
+    // illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class C {
+  static const int i = 5;
+
+  @i(1)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_staticConst_otherClass() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  static const int i = 5;
+}
+
+class C {
+  @A.i
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_annotation_staticConst_otherClass_args() {
+    // Applying arguments to an annotation that is a static const is
+    // illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  static const int i = 5;
+}
+
+class C {
+  @A.i(1)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_annotation_toplevelVariable() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const int i = 5;
+class C {
+  @i
+  f() {}
+}
+''');
+    EvaluationResultImpl result =
+        _evaluateAnnotation(compilationUnit, "C", "f");
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_annotation_toplevelVariable_args() {
+    // Applying arguments to an annotation that is a toplevel variable is
+    // illegal, but shouldn't crash analysis.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const int i = 5;
+class C {
+  @i(1)
+  f() {}
+}
+''');
+    _evaluateAnnotation(compilationUnit, "C", "f");
+  }
+
+  void test_computeValues_cycle() {
+    TestLogger logger = new TestLogger();
+    AnalysisEngine.instance.logger = logger;
+    try {
+      Source source = addSource(r'''
+  const int a = c;
+  const int b = a;
+  const int c = b;''');
+      LibraryElement libraryElement = resolve2(source);
+      CompilationUnit unit =
+          analysisContext.resolveCompilationUnit(source, libraryElement);
+      analysisContext.computeErrors(source);
+      expect(unit, isNotNull);
+      ConstantValueComputer computer = _makeConstantValueComputer();
+      computer.add(unit, source, source);
+      computer.computeValues();
+      NodeList<CompilationUnitMember> members = unit.declarations;
+      expect(members, hasLength(3));
+      _validate(false, (members[0] as TopLevelVariableDeclaration).variables);
+      _validate(false, (members[1] as TopLevelVariableDeclaration).variables);
+      _validate(false, (members[2] as TopLevelVariableDeclaration).variables);
+    } finally {
+      AnalysisEngine.instance.logger = Logger.NULL;
+    }
+  }
+
+  void test_computeValues_dependentVariables() {
+    Source source = addSource(r'''
+const int b = a;
+const int a = 0;''');
+    LibraryElement libraryElement = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, libraryElement);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    NodeList<CompilationUnitMember> members = unit.declarations;
+    expect(members, hasLength(2));
+    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
+    _validate(true, (members[1] as TopLevelVariableDeclaration).variables);
+  }
+
+  void test_computeValues_empty() {
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.computeValues();
+  }
+
+  void test_computeValues_multipleSources() {
+    Source librarySource = addNamedSource(
+        "/lib.dart",
+        r'''
+library lib;
+part 'part.dart';
+const int c = b;
+const int a = 0;''');
+    Source partSource = addNamedSource(
+        "/part.dart",
+        r'''
+part of lib;
+const int b = a;
+const int d = c;''');
+    LibraryElement libraryElement = resolve2(librarySource);
+    CompilationUnit libraryUnit =
+        analysisContext.resolveCompilationUnit(librarySource, libraryElement);
+    expect(libraryUnit, isNotNull);
+    CompilationUnit partUnit =
+        analysisContext.resolveCompilationUnit(partSource, libraryElement);
+    expect(partUnit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(libraryUnit, librarySource, librarySource);
+    computer.add(partUnit, partSource, librarySource);
+    computer.computeValues();
+    NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
+    expect(libraryMembers, hasLength(2));
+    _validate(
+        true, (libraryMembers[0] as TopLevelVariableDeclaration).variables);
+    _validate(
+        true, (libraryMembers[1] as TopLevelVariableDeclaration).variables);
+    NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations;
+    expect(partMembers, hasLength(2));
+    _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables);
+    _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables);
+  }
+
+  void test_computeValues_singleVariable() {
+    Source source = addSource("const int a = 0;");
+    LibraryElement libraryElement = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, libraryElement);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    NodeList<CompilationUnitMember> members = unit.declarations;
+    expect(members, hasLength(1));
+    _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
+  }
+
+  void test_computeValues_value_depends_on_enum() {
+    Source source = addSource('''
+enum E { id0, id1 }
+const E e = E.id0;
+''');
+    LibraryElement libraryElement = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, libraryElement);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    TopLevelVariableDeclaration declaration = unit.declarations
+        .firstWhere((member) => member is TopLevelVariableDeclaration);
+    _validate(true, declaration.variables);
+  }
+
+  void test_dependencyOnConstructor() {
+    // x depends on "const A()"
+    _assertProperDependencies(r'''
+class A {
+  const A();
+}
+const x = const A();''');
+  }
+
+  void test_dependencyOnConstructorArgument() {
+    // "const A(x)" depends on x
+    _assertProperDependencies(r'''
+class A {
+  const A(this.next);
+  final A next;
+}
+const A x = const A(null);
+const A y = const A(x);''');
+  }
+
+  void test_dependencyOnConstructorArgument_unresolvedConstructor() {
+    // "const A.a(x)" depends on x even if the constructor A.a can't be found.
+    _assertProperDependencies(
+        r'''
+class A {
+}
+const int x = 1;
+const A y = const A.a(x);''',
+        [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
+  }
+
+  void test_dependencyOnConstructorInitializer() {
+    // "const A()" depends on x
+    _assertProperDependencies(r'''
+const int x = 1;
+class A {
+  const A() : v = x;
+  final int v;
+}''');
+  }
+
+  void test_dependencyOnExplicitSuperConstructor() {
+    // b depends on B() depends on A()
+    _assertProperDependencies(r'''
+class A {
+  const A(this.x);
+  final int x;
+}
+class B extends A {
+  const B() : super(5);
+}
+const B b = const B();''');
+  }
+
+  void test_dependencyOnExplicitSuperConstructorParameters() {
+    // b depends on B() depends on i
+    _assertProperDependencies(r'''
+class A {
+  const A(this.x);
+  final int x;
+}
+class B extends A {
+  const B() : super(i);
+}
+const B b = const B();
+const int i = 5;''');
+  }
+
+  void test_dependencyOnFactoryRedirect() {
+    // a depends on A.foo() depends on A.bar()
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  factory const A.foo() = A.bar;
+  const A.bar();
+}''');
+  }
+
+  void test_dependencyOnFactoryRedirectWithTypeParams() {
+    _assertProperDependencies(r'''
+class A {
+  const factory A(var a) = B<int>;
+}
+
+class B<T> implements A {
+  final T x;
+  const B(this.x);
+}
+
+const A a = const A(10);''');
+  }
+
+  void test_dependencyOnImplicitSuperConstructor() {
+    // b depends on B() depends on A()
+    _assertProperDependencies(r'''
+class A {
+  const A() : x = 5;
+  final int x;
+}
+class B extends A {
+  const B();
+}
+const B b = const B();''');
+  }
+
+  void test_dependencyOnInitializedFinal() {
+    // a depends on A() depends on A.x
+    _assertProperDependencies('''
+class A {
+  const A();
+  final int x = 1;
+}
+const A a = const A();
+''');
+  }
+
+  void test_dependencyOnInitializedNonStaticConst() {
+    // Even though non-static consts are not allowed by the language, we need
+    // to handle them for error recovery purposes.
+    // a depends on A() depends on A.x
+    _assertProperDependencies(
+        '''
+class A {
+  const A();
+  const int x = 1;
+}
+const A a = const A();
+''',
+        [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
+  }
+
+  void test_dependencyOnNonFactoryRedirect() {
+    // a depends on A.foo() depends on A.bar()
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this.bar();
+  const A.bar();
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_arg() {
+    // a depends on A.foo() depends on b
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+const int b = 1;
+class A {
+  const A.foo() : this.bar(b);
+  const A.bar(x) : y = x;
+  final int y;
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_defaultValue() {
+    // a depends on A.foo() depends on A.bar() depends on b
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+const int b = 1;
+class A {
+  const A.foo() : this.bar();
+  const A.bar([x = b]) : y = x;
+  final int y;
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_toMissing() {
+    // a depends on A.foo() which depends on nothing, since A.bar() is
+    // missing.
+    _assertProperDependencies(
+        r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this.bar();
+}''',
+        [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
+  }
+
+  void test_dependencyOnNonFactoryRedirect_toNonConst() {
+    // a depends on A.foo() which depends on nothing, since A.bar() is
+    // non-const.
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this.bar();
+  A.bar();
+}''');
+  }
+
+  void test_dependencyOnNonFactoryRedirect_unnamed() {
+    // a depends on A.foo() depends on A()
+    _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+  const A.foo() : this();
+  const A();
+}''');
+  }
+
+  void test_dependencyOnOptionalParameterDefault() {
+    // a depends on A() depends on B()
+    _assertProperDependencies(r'''
+class A {
+  const A([x = const B()]) : b = x;
+  final B b;
+}
+class B {
+  const B();
+}
+const A a = const A();''');
+  }
+
+  void test_dependencyOnVariable() {
+    // x depends on y
+    _assertProperDependencies(r'''
+const x = y + 1;
+const y = 2;''');
+  }
+
+  void test_final_initialized_at_declaration() {
+    CompilationUnit compilationUnit = resolveSource('''
+class A {
+  final int i = 123;
+  const A();
+}
+
+const A a = const A();
+''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, 'a');
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "i", 123);
+  }
+
+  void test_fromEnvironment_bool_default_false() {
+    expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false);
+  }
+
+  void test_fromEnvironment_bool_default_overridden() {
+    expect(
+        _assertValidBool(_check_fromEnvironment_bool("false", "true")), false);
+  }
+
+  void test_fromEnvironment_bool_default_parseError() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")),
+        true);
+  }
+
+  void test_fromEnvironment_bool_default_true() {
+    expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true);
+  }
+
+  void test_fromEnvironment_bool_false() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false);
+  }
+
+  void test_fromEnvironment_bool_parseError() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)),
+        false);
+  }
+
+  void test_fromEnvironment_bool_true() {
+    expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true);
+  }
+
+  void test_fromEnvironment_bool_undeclared() {
+    _assertValidUnknown(_check_fromEnvironment_bool(null, null));
+  }
+
+  void test_fromEnvironment_int_default_overridden() {
+    expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234);
+  }
+
+  void test_fromEnvironment_int_default_parseError() {
+    expect(
+        _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123);
+  }
+
+  void test_fromEnvironment_int_default_undeclared() {
+    expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123);
+  }
+
+  void test_fromEnvironment_int_ok() {
+    expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234);
+  }
+
+  void test_fromEnvironment_int_parseError() {
+    _assertValidNull(_check_fromEnvironment_int("parseError", null));
+  }
+
+  void test_fromEnvironment_int_parseError_nullDefault() {
+    _assertValidNull(_check_fromEnvironment_int("parseError", "null"));
+  }
+
+  void test_fromEnvironment_int_undeclared() {
+    _assertValidUnknown(_check_fromEnvironment_int(null, null));
+  }
+
+  void test_fromEnvironment_int_undeclared_nullDefault() {
+    _assertValidNull(_check_fromEnvironment_int(null, "null"));
+  }
+
+  void test_fromEnvironment_string_default_overridden() {
+    expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")),
+        "abc");
+  }
+
+  void test_fromEnvironment_string_default_undeclared() {
+    expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")),
+        "def");
+  }
+
+  void test_fromEnvironment_string_empty() {
+    expect(_assertValidString(_check_fromEnvironment_string("", null)), "");
+  }
+
+  void test_fromEnvironment_string_ok() {
+    expect(
+        _assertValidString(_check_fromEnvironment_string("abc", null)), "abc");
+  }
+
+  void test_fromEnvironment_string_undeclared() {
+    _assertValidUnknown(_check_fromEnvironment_string(null, null));
+  }
+
+  void test_fromEnvironment_string_undeclared_nullDefault() {
+    _assertValidNull(_check_fromEnvironment_string(null, "null"));
+  }
+
+  void test_instanceCreationExpression_computedField() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(4, 5);
+class A {
+  const A(int i, int j) : k = 2 * i + j;
+  final int k;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "k", 13);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_namedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(false, true, true);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(false, true, false);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(false, false, true);
+  }
+
+  void
+      test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(false, false, false);
+  }
+
+  void test_instanceCreationExpression_computedField_usesConstConstructor() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+class A {
+  const A(int i) : b = const B(4);
+  final int b;
+}
+class B {
+  const B(this.k);
+  final int k;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A");
+    expect(fieldsOfA, hasLength(1));
+    Map<String, DartObjectImpl> fieldsOfB =
+        _assertFieldType(fieldsOfA, "b", "B");
+    expect(fieldsOfB, hasLength(1));
+    _assertIntField(fieldsOfB, "k", 4);
+  }
+
+  void test_instanceCreationExpression_computedField_usesStaticConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+class A {
+  const A(int i) : k = i + B.bar;
+  final int k;
+}
+class B {
+  static const bar = 4;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "k", 7);
+  }
+
+  void test_instanceCreationExpression_computedField_usesToplevelConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+const bar = 4;
+class A {
+  const A(int i) : k = i + bar;
+  final int k;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "k", 7);
+  }
+
+  void test_instanceCreationExpression_explicitSuper() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const B(4, 5);
+class A {
+  const A(this.x);
+  final int x;
+}
+class B extends A {
+  const B(int x, this.y) : super(x * 2);
+  final int y;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B");
+    expect(fields, hasLength(2));
+    _assertIntField(fields, "y", 5);
+    Map<String, DartObjectImpl> superclassFields =
+        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
+    expect(superclassFields, hasLength(1));
+    _assertIntField(superclassFields, "x", 8);
+  }
+
+  void test_instanceCreationExpression_fieldFormalParameter() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(42);
+class A {
+  int x;
+  const A(this.x)
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "x", 42);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(true, true, true);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(true, true, false);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() {
+    _checkInstanceCreationOptionalParams(true, false, true);
+  }
+
+  void
+      test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() {
+    _checkInstanceCreationOptionalParams(true, false, false);
+  }
+
+  void test_instanceCreationExpression_implicitSuper() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const B(4);
+class A {
+  const A() : x = 3;
+  final int x;
+}
+class B extends A {
+  const B(this.y);
+  final int y;
+}''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B");
+    expect(fields, hasLength(2));
+    _assertIntField(fields, "y", 4);
+    Map<String, DartObjectImpl> superclassFields =
+        _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
+    expect(superclassFields, hasLength(1));
+    _assertIntField(superclassFields, "x", 3);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+  const A.a2() : x = 5;
+  final int x;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'x', 5);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_arg() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1(1);
+class A {
+  const A.a1(x) : this.a2(x + 100);
+  const A.a2(x) : y = x + 10;
+  final int y;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'y', 111);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_cycle() {
+    // It is an error to have a cycle in non-factory redirects; however, we
+    // need to make sure that even if the error occurs, attempting to evaluate
+    // the constant will terminate.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const A() : this.b();
+  const A.b() : this();
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+  const A.a2([x = 100]) : y = x + 10;
+  final int y;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'y', 110);
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_toMissing() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+}''');
+    // We don't care what value foo evaluates to (since there is a compile
+    // error), but we shouldn't crash, and we should figure
+    // out that it evaluates to an instance of class A.
+    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this.a2();
+  A.a2();
+}''');
+    // We don't care what value foo evaluates to (since there is a compile
+    // error), but we shouldn't crash, and we should figure
+    // out that it evaluates to an instance of class A.
+    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+  }
+
+  void test_instanceCreationExpression_nonFactoryRedirect_unnamed() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+  const A.a1() : this();
+  const A() : x = 5;
+  final int x;
+}''');
+    Map<String, DartObjectImpl> aFields =
+        _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+    _assertIntField(aFields, 'x', 5);
+  }
+
+  void test_instanceCreationExpression_redirect() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const factory A() = B;
+}
+class B implements A {
+  const B();
+}''');
+    _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B");
+  }
+
+  void test_instanceCreationExpression_redirect_cycle() {
+    // It is an error to have a cycle in factory redirects; however, we need
+    // to make sure that even if the error occurs, attempting to evaluate the
+    // constant will terminate.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const factory A() = A.b;
+  const factory A.b() = A;
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_redirect_extern() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  external const factory A();
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_redirect_nonConst() {
+    // It is an error for a const factory constructor redirect to a non-const
+    // constructor; however, we need to make sure that even if the error
+    // attempting to evaluate the constant won't cause a crash.
+    CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+  const factory A() = A.b;
+  A.b();
+}''');
+    _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+  }
+
+  void test_instanceCreationExpression_redirectWithTypeParams() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+  const factory A(var a) = B<int>;
+}
+
+class B<T> implements A {
+  final T x;
+  const B(this.x);
+}
+
+const A a = const A(10);''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "a");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "x", 10);
+  }
+
+  void test_instanceCreationExpression_redirectWithTypeSubstitution() {
+    // To evaluate the redirection of A<int>,
+    // A's template argument (T=int) must be substituted
+    // into B's template argument (B<U> where U=T) to get B<int>.
+    CompilationUnit compilationUnit = resolveSource(r'''
+class A<T> {
+  const factory A(var a) = B<T>;
+}
+
+class B<U> implements A {
+  final U x;
+  const B(this.x);
+}
+
+const A<int> a = const A<int>(10);''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, "a");
+    Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "x", 10);
+  }
+
+  void test_instanceCreationExpression_symbol() {
+    CompilationUnit compilationUnit =
+        resolveSource("const foo = const Symbol('a');");
+    EvaluationResultImpl evaluationResult =
+        _evaluateTopLevelVariable(compilationUnit, "foo");
+    expect(evaluationResult.value, isNotNull);
+    DartObjectImpl value = evaluationResult.value;
+    expect(value.type, typeProvider.symbolType);
+    expect(value.toSymbolValue(), "a");
+  }
+
+  void test_instanceCreationExpression_withSupertypeParams_explicit() {
+    _checkInstanceCreation_withSupertypeParams(true);
+  }
+
+  void test_instanceCreationExpression_withSupertypeParams_implicit() {
+    _checkInstanceCreation_withSupertypeParams(false);
+  }
+
+  void test_instanceCreationExpression_withTypeParams() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+class C<E> {
+  const C();
+}
+const c_int = const C<int>();
+const c_num = const C<num>();''');
+    EvaluationResultImpl c_int =
+        _evaluateTopLevelVariable(compilationUnit, "c_int");
+    _assertType(c_int, "C<int>");
+    DartObjectImpl c_int_value = c_int.value;
+    EvaluationResultImpl c_num =
+        _evaluateTopLevelVariable(compilationUnit, "c_num");
+    _assertType(c_num, "C<num>");
+    DartObjectImpl c_num_value = c_num.value;
+    expect(c_int_value == c_num_value, isFalse);
+  }
+
+  void test_isValidSymbol() {
+    expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse);
+    expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse);
+  }
+
+  void test_length_of_improperly_typed_string_expression() {
+    // Since type annotations are ignored in unchecked mode, the improper
+    // types on s1 and s2 shouldn't prevent us from evaluating i to
+    // 'alpha'.length.
+    CompilationUnit compilationUnit = resolveSource('''
+const int s1 = 'alpha';
+const int s2 = 'beta';
+const int i = (true ? s1 : s2).length;
+''');
+    ConstTopLevelVariableElementImpl element =
+        findTopLevelDeclaration(compilationUnit, 'i').element;
+    EvaluationResultImpl result = element.evaluationResult;
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_length_of_improperly_typed_string_identifier() {
+    // Since type annotations are ignored in unchecked mode, the improper type
+    // on s shouldn't prevent us from evaluating i to 'alpha'.length.
+    CompilationUnit compilationUnit = resolveSource('''
+const int s = 'alpha';
+const int i = s.length;
+''');
+    ConstTopLevelVariableElementImpl element =
+        findTopLevelDeclaration(compilationUnit, 'i').element;
+    EvaluationResultImpl result = element.evaluationResult;
+    expect(_assertValidInt(result), 5);
+  }
+
+  void test_non_static_const_initialized_at_declaration() {
+    // Even though non-static consts are not allowed by the language, we need
+    // to handle them for error recovery purposes.
+    CompilationUnit compilationUnit = resolveSource('''
+class A {
+  const int i = 123;
+  const A();
+}
+
+const A a = const A();
+''');
+    EvaluationResultImpl result =
+        _evaluateTopLevelVariable(compilationUnit, 'a');
+    Map<String, DartObjectImpl> fields = _assertType(result, "A");
+    expect(fields, hasLength(1));
+    _assertIntField(fields, "i", 123);
+  }
+
+  void test_symbolLiteral_void() {
+    CompilationUnit compilationUnit =
+        resolveSource("const voidSymbol = #void;");
+    VariableDeclaration voidSymbol =
+        findTopLevelDeclaration(compilationUnit, "voidSymbol");
+    EvaluationResultImpl voidSymbolResult =
+        (voidSymbol.element as VariableElementImpl).evaluationResult;
+    DartObjectImpl value = voidSymbolResult.value;
+    expect(value.type, typeProvider.symbolType);
+    expect(value.toSymbolValue(), "void");
+  }
+
+  Map<String, DartObjectImpl> _assertFieldType(
+      Map<String, DartObjectImpl> fields,
+      String fieldName,
+      String expectedType) {
+    DartObjectImpl field = fields[fieldName];
+    expect(field.type.displayName, expectedType);
+    return field.fields;
+  }
+
+  void _assertIntField(
+      Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) {
+    DartObjectImpl field = fields[fieldName];
+    expect(field.type.name, "int");
+    expect(field.toIntValue(), expectedValue);
+  }
+
+  void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) {
+    DartObjectImpl field = fields[fieldName];
+    expect(field.isNull, isTrue);
+  }
+
+  void _assertProperDependencies(String sourceText,
+      [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
+    Source source = addSource(sourceText);
+    LibraryElement element = resolve2(source);
+    CompilationUnit unit =
+        analysisContext.resolveCompilationUnit(source, element);
+    expect(unit, isNotNull);
+    ConstantValueComputer computer = _makeConstantValueComputer();
+    computer.add(unit, source, source);
+    computer.computeValues();
+    assertErrors(source, expectedErrorCodes);
+  }
+
+  Map<String, DartObjectImpl> _assertType(
+      EvaluationResultImpl result, String typeName) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type.displayName, typeName);
+    return value.fields;
+  }
+
+  bool _assertValidBool(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.boolType);
+    bool boolValue = value.toBoolValue();
+    expect(boolValue, isNotNull);
+    return boolValue;
+  }
+
+  int _assertValidInt(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.intType);
+    return value.toIntValue();
+  }
+
+  void _assertValidNull(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.nullType);
+  }
+
+  String _assertValidString(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.type, typeProvider.stringType);
+    return value.toStringValue();
+  }
+
+  void _assertValidUnknown(EvaluationResultImpl result) {
+    expect(result.value, isNotNull);
+    DartObjectImpl value = result.value;
+    expect(value.isUnknown, isTrue);
+  }
+
+  EvaluationResultImpl _check_fromEnvironment_bool(
+      String valueInEnvironment, String defaultExpr) {
+    String envVarName = "x";
+    String varName = "foo";
+    if (valueInEnvironment != null) {
+      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+    }
+    String defaultArg =
+        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+    CompilationUnit compilationUnit = resolveSource(
+        "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);");
+    return _evaluateTopLevelVariable(compilationUnit, varName);
+  }
+
+  EvaluationResultImpl _check_fromEnvironment_int(
+      String valueInEnvironment, String defaultExpr) {
+    String envVarName = "x";
+    String varName = "foo";
+    if (valueInEnvironment != null) {
+      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+    }
+    String defaultArg =
+        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+    CompilationUnit compilationUnit = resolveSource(
+        "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);");
+    return _evaluateTopLevelVariable(compilationUnit, varName);
+  }
+
+  EvaluationResultImpl _check_fromEnvironment_string(
+      String valueInEnvironment, String defaultExpr) {
+    String envVarName = "x";
+    String varName = "foo";
+    if (valueInEnvironment != null) {
+      analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+    }
+    String defaultArg =
+        defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+    CompilationUnit compilationUnit = resolveSource(
+        "const $varName = const String.fromEnvironment('$envVarName'$defaultArg);");
+    return _evaluateTopLevelVariable(compilationUnit, varName);
+  }
+
+  void _checkInstanceCreation_withSupertypeParams(bool isExplicit) {
+    String superCall = isExplicit ? " : super()" : "";
+    CompilationUnit compilationUnit = resolveSource("""
+class A<T> {
+  const A();
+}
+class B<T, U> extends A<T> {
+  const B()$superCall;
+}
+class C<T, U> extends A<U> {
+  const C()$superCall;
+}
+const b_int_num = const B<int, num>();
+const c_int_num = const C<int, num>();""");
+    EvaluationResultImpl b_int_num =
+        _evaluateTopLevelVariable(compilationUnit, "b_int_num");
+    Map<String, DartObjectImpl> b_int_num_fields =
+        _assertType(b_int_num, "B<int, num>");
+    _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>");
+    EvaluationResultImpl c_int_num =
+        _evaluateTopLevelVariable(compilationUnit, "c_int_num");
+    Map<String, DartObjectImpl> c_int_num_fields =
+        _assertType(c_int_num, "C<int, num>");
+    _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>");
+  }
+
+  void _checkInstanceCreationOptionalParams(
+      bool isFieldFormal, bool isNamed, bool hasDefault) {
+    String fieldName = "j";
+    String paramName = isFieldFormal ? fieldName : "i";
+    String formalParam =
+        "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : ""}";
+    CompilationUnit compilationUnit = resolveSource("""
+const x = const A();
+const y = const A(${isNamed ? '$paramName: ' : ''}10);
+class A {
+  const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"};
+  final int $fieldName;
+}""");
+    EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x");
+    Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A");
+    expect(fieldsOfX, hasLength(1));
+    if (hasDefault) {
+      _assertIntField(fieldsOfX, fieldName, 3);
+    } else {
+      _assertNullField(fieldsOfX, fieldName);
+    }
+    EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y");
+    Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A");
+    expect(fieldsOfY, hasLength(1));
+    _assertIntField(fieldsOfY, fieldName, 10);
+  }
+
+  /**
+   * Search [compilationUnit] for a class named [className], containing a
+   * method [methodName], with exactly one annotation.  Return the constant
+   * value of the annotation.
+   */
+  EvaluationResultImpl _evaluateAnnotation(
+      CompilationUnit compilationUnit, String className, String memberName) {
+    for (CompilationUnitMember member in compilationUnit.declarations) {
+      if (member is ClassDeclaration && member.name.name == className) {
+        for (ClassMember classMember in member.members) {
+          if (classMember is MethodDeclaration &&
+              classMember.name.name == memberName) {
+            expect(classMember.metadata, hasLength(1));
+            ElementAnnotationImpl elementAnnotation =
+                classMember.metadata[0].elementAnnotation;
+            return elementAnnotation.evaluationResult;
+          }
+        }
+      }
+    }
+    fail('Class member not found');
+    return null;
+  }
+
+  EvaluationResultImpl _evaluateTopLevelVariable(
+      CompilationUnit compilationUnit, String name) {
+    VariableDeclaration varDecl =
+        findTopLevelDeclaration(compilationUnit, name);
+    ConstTopLevelVariableElementImpl varElement = varDecl.element;
+    return varElement.evaluationResult;
+  }
+
+  ConstantValueComputer _makeConstantValueComputer() {
+    ConstantEvaluationValidator_ForTest validator =
+        new ConstantEvaluationValidator_ForTest(analysisContext2);
+    validator.computer = new ConstantValueComputer(
+        analysisContext2,
+        analysisContext2.typeProvider,
+        analysisContext2.declaredVariables,
+        validator,
+        analysisContext2.typeSystem);
+    return validator.computer;
+  }
+
+  void _validate(bool shouldBeValid, VariableDeclarationList declarationList) {
+    for (VariableDeclaration declaration in declarationList.variables) {
+      VariableElementImpl element = declaration.element as VariableElementImpl;
+      expect(element, isNotNull);
+      EvaluationResultImpl result = element.evaluationResult;
+      if (shouldBeValid) {
+        expect(result.value, isNotNull);
+      } else {
+        expect(result.value, isNull);
+      }
+    }
+  }
+}
+
+@reflectiveTest
+class ConstantVisitorTest extends ResolverTestCase {
+  void test_visitBinaryExpression_questionQuestion_notNull_notNull() {
+    Expression left = AstFactory.string2('a');
+    Expression right = AstFactory.string2('b');
+    Expression expression =
+        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNotNull);
+    expect(result.isNull, isFalse);
+    expect(result.toStringValue(), 'a');
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitBinaryExpression_questionQuestion_null_notNull() {
+    Expression left = AstFactory.nullLiteral();
+    Expression right = AstFactory.string2('b');
+    Expression expression =
+        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNotNull);
+    expect(result.isNull, isFalse);
+    expect(result.toStringValue(), 'b');
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitBinaryExpression_questionQuestion_null_null() {
+    Expression left = AstFactory.nullLiteral();
+    Expression right = AstFactory.nullLiteral();
+    Expression expression =
+        AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNotNull);
+    expect(result.isNull, isTrue);
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitConditionalExpression_false() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.integer(0);
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(false), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    _assertValue(0, _evaluate(expression, errorReporter));
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitConditionalExpression_nonBooleanCondition() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.integer(0);
+    NullLiteral conditionExpression = AstFactory.nullLiteral();
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        conditionExpression, thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNull);
+    errorListener
+        .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
+  }
+
+  void test_visitConditionalExpression_nonConstantElse() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.identifier3("x");
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNull);
+    errorListener
+        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  void test_visitConditionalExpression_nonConstantThen() {
+    Expression thenExpression = AstFactory.identifier3("x");
+    Expression elseExpression = AstFactory.integer(0);
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    DartObjectImpl result = _evaluate(expression, errorReporter);
+    expect(result, isNull);
+    errorListener
+        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  void test_visitConditionalExpression_true() {
+    Expression thenExpression = AstFactory.integer(1);
+    Expression elseExpression = AstFactory.integer(0);
+    ConditionalExpression expression = AstFactory.conditionalExpression(
+        AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter =
+        new ErrorReporter(errorListener, _dummySource());
+    _assertValue(1, _evaluate(expression, errorReporter));
+    errorListener.assertNoErrors();
+  }
+
+  void test_visitSimpleIdentifier_className() {
+    CompilationUnit compilationUnit = resolveSource('''
+const a = C;
+class C {}
+''');
+    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+    expect(result.type, typeProvider.typeType);
+    expect(result.toTypeValue().name, 'C');
+  }
+
+  void test_visitSimpleIdentifier_dynamic() {
+    CompilationUnit compilationUnit = resolveSource('''
+const a = dynamic;
+''');
+    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+    expect(result.type, typeProvider.typeType);
+    expect(result.toTypeValue(), typeProvider.dynamicType);
+  }
+
+  void test_visitSimpleIdentifier_inEnvironment() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
+    DartObjectImpl six =
+        new DartObjectImpl(typeProvider.intType, new IntState(6));
+    environment["b"] = six;
+    _assertValue(6, _evaluateConstant(compilationUnit, "a", environment));
+  }
+
+  void test_visitSimpleIdentifier_notInEnvironment() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
+    DartObjectImpl six =
+        new DartObjectImpl(typeProvider.intType, new IntState(6));
+    environment["c"] = six;
+    _assertValue(3, _evaluateConstant(compilationUnit, "a", environment));
+  }
+
+  void test_visitSimpleIdentifier_withoutEnvironment() {
+    CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+    _assertValue(3, _evaluateConstant(compilationUnit, "a", null));
+  }
+
+  void _assertValue(int expectedValue, DartObjectImpl result) {
+    expect(result, isNotNull);
+    expect(result.type.name, "int");
+    expect(result.toIntValue(), expectedValue);
+  }
+
+  NonExistingSource _dummySource() {
+    String path = '/test.dart';
+    return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
+  }
+
+  DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) {
+    return expression.accept(new ConstantVisitor(
+        new ConstantEvaluationEngine(
+            new TestTypeProvider(), new DeclaredVariables(),
+            typeSystem: new TypeSystemImpl()),
+        errorReporter));
+  }
+
+  DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
+      Map<String, DartObjectImpl> lexicalEnvironment) {
+    Source source = compilationUnit.element.source;
+    Expression expression =
+        findTopLevelConstantExpression(compilationUnit, name);
+    GatheringErrorListener errorListener = new GatheringErrorListener();
+    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
+    DartObjectImpl result = expression.accept(new ConstantVisitor(
+        new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
+            typeSystem: typeSystem),
+        errorReporter,
+        lexicalEnvironment: lexicalEnvironment));
+    errorListener.assertNoErrors();
+    return result;
+  }
+}
+
+@reflectiveTest
+class ReferenceFinderTest {
+  DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
+  VariableElement _head;
+  Element _tail;
+
+  void setUp() {
+    _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
+    _head = ElementFactory.topLevelVariableElement2("v1");
+  }
+
+  void test_visitSimpleIdentifier_const() {
+    _visitNode(_makeTailVariable("v2", true));
+    _assertOneArc(_tail);
+  }
+
+  void test_visitSuperConstructorInvocation_const() {
+    _visitNode(_makeTailSuperConstructorInvocation("A", true));
+    _assertOneArc(_tail);
+  }
+
+  void test_visitSuperConstructorInvocation_nonConst() {
+    _visitNode(_makeTailSuperConstructorInvocation("A", false));
+    _assertOneArc(_tail);
+  }
+
+  void test_visitSuperConstructorInvocation_unresolved() {
+    SuperConstructorInvocation superConstructorInvocation =
+        AstFactory.superConstructorInvocation();
+    _visitNode(superConstructorInvocation);
+    _assertNoArcs();
+  }
+
+  void _assertNoArcs() {
+    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
+    expect(tails, hasLength(0));
+  }
+
+  void _assertOneArc(Element tail) {
+    Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
+    expect(tails, hasLength(1));
+    expect(tails.first, same(tail));
+  }
+
+  ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
+      new ReferenceFinder((ConstantEvaluationTarget dependency) {
+        _referenceGraph.addEdge(source, dependency);
+      });
+  SuperConstructorInvocation _makeTailSuperConstructorInvocation(
+      String name, bool isConst) {
+    List<ConstructorInitializer> initializers =
+        new List<ConstructorInitializer>();
+    ConstructorDeclaration constructorDeclaration =
+        AstFactory.constructorDeclaration(AstFactory.identifier3(name), null,
+            AstFactory.formalParameterList(), initializers);
+    if (isConst) {
+      constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
+    }
+    ClassElementImpl classElement = ElementFactory.classElement2(name);
+    SuperConstructorInvocation superConstructorInvocation =
+        AstFactory.superConstructorInvocation();
+    ConstructorElementImpl constructorElement =
+        ElementFactory.constructorElement(classElement, name, isConst);
+    _tail = constructorElement;
+    superConstructorInvocation.staticElement = constructorElement;
+    return superConstructorInvocation;
+  }
+
+  SimpleIdentifier _makeTailVariable(String name, bool isConst) {
+    VariableDeclaration variableDeclaration =
+        AstFactory.variableDeclaration(name);
+    ConstLocalVariableElementImpl variableElement =
+        ElementFactory.constLocalVariableElement(name);
+    _tail = variableElement;
+    variableElement.const3 = isConst;
+    AstFactory.variableDeclarationList2(
+        isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
+    SimpleIdentifier identifier = AstFactory.identifier3(name);
+    identifier.staticElement = variableElement;
+    return identifier;
+  }
+
+  void _visitNode(AstNode node) {
+    node.accept(_createReferenceFinder(_head));
+  }
+}
+
+class _TestAnalysisContext extends TestAnalysisContext {
+  @override
+  InternalAnalysisContext getContextFor(Source source) => this;
+}
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 3dfae2b..188cc26 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -4,8 +4,9 @@
 
 library engine.declaration_resolver_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:unittest/unittest.dart';
@@ -35,6 +36,27 @@
 
 @reflectiveTest
 class DeclarationResolverTest extends ResolverTestCase {
+  void fail_visitMethodDeclaration_setter_duplicate() {
+    // https://github.com/dart-lang/sdk/issues/25601
+    String code = r'''
+class C {
+  set zzz(x) {}
+  set zzz(y) {}
+}
+''';
+    CompilationUnit unit = resolveSource(code);
+    PropertyAccessorElement firstElement =
+        _findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
+    PropertyAccessorElement secondElement =
+        _findSimpleIdentifier(unit, code, 'zzz(y)').staticElement;
+    // re-resolve
+    CompilationUnit unit2 = _cloneResolveUnit(unit);
+    SimpleIdentifier firstName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
+    SimpleIdentifier secondName = _findSimpleIdentifier(unit2, code, 'zzz(y)');
+    expect(firstName.staticElement, same(firstElement));
+    expect(secondName.staticElement, same(secondElement));
+  }
+
   @override
   void setUp() {
     super.setUp();
@@ -97,6 +119,47 @@
     SimpleIdentifier setterName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
     expect(setterName.staticElement, same(setterElement));
   }
+
+  void test_visitMethodDeclaration_getter_duplicate() {
+    String code = r'''
+class C {
+  int get zzz => 1;
+  String get zzz => null;
+}
+''';
+    CompilationUnit unit = resolveSource(code);
+    PropertyAccessorElement firstElement =
+        _findSimpleIdentifier(unit, code, 'zzz => 1').staticElement;
+    PropertyAccessorElement secondElement =
+        _findSimpleIdentifier(unit, code, 'zzz => null').staticElement;
+    // re-resolve
+    CompilationUnit unit2 = _cloneResolveUnit(unit);
+    SimpleIdentifier firstName = _findSimpleIdentifier(unit2, code, 'zzz => 1');
+    SimpleIdentifier secondName =
+        _findSimpleIdentifier(unit2, code, 'zzz => null');
+    expect(firstName.staticElement, same(firstElement));
+    expect(secondName.staticElement, same(secondElement));
+  }
+
+  void test_visitMethodDeclaration_method_duplicate() {
+    String code = r'''
+class C {
+  void zzz(x) {}
+  void zzz(y) {}
+}
+''';
+    CompilationUnit unit = resolveSource(code);
+    MethodElement firstElement =
+        _findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
+    MethodElement secondElement =
+        _findSimpleIdentifier(unit, code, 'zzz(y)').staticElement;
+    // re-resolve
+    CompilationUnit unit2 = _cloneResolveUnit(unit);
+    SimpleIdentifier firstName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
+    SimpleIdentifier secondName = _findSimpleIdentifier(unit2, code, 'zzz(y)');
+    expect(firstName.staticElement, same(firstElement));
+    expect(secondName.staticElement, same(secondElement));
+  }
 }
 
 /**
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index e2b20b3..ce630b1 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -6,10 +6,11 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -192,6 +193,9 @@
  */
 class TestAnalysisContext implements InternalAnalysisContext {
   @override
+  ResultProvider resultProvider;
+
+  @override
   AnalysisCache get analysisCache {
     fail("Unexpected invocation of analysisCache");
     return null;
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 6a52fce..3f3390b 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -4,13 +4,14 @@
 
 library analyzer.test.generated.incremental_resolver_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/incremental_logger.dart' as log;
+import 'package:analyzer/src/generated/incremental_logger.dart' as logging;
 import 'package:analyzer/src/generated/incremental_resolution_validator.dart';
 import 'package:analyzer/src/generated/incremental_resolver.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -495,6 +496,20 @@
 ''');
   }
 
+  void test_false_constructor_parameters_name() {
+    _assertDoesNotMatch(
+        r'''
+class A {
+  A(int a);
+}
+''',
+        r'''
+class A {
+  A(int b);
+}
+''');
+  }
+
   void test_false_constructor_parameters_type_edit() {
     _assertDoesNotMatch(
         r'''
@@ -835,6 +850,22 @@
 ''');
   }
 
+  void test_false_fieldFormalParameter_changeName_wasUnresolvedField() {
+    _assertDoesNotMatch(
+        r'''
+class A {
+  final fff;
+  A(this.unresolved);
+}
+''',
+        r'''
+class A {
+  final fff;
+  A(this.fff);
+}
+''');
+  }
+
   void test_false_fieldFormalParameter_differentField() {
     _assertDoesNotMatch(
         r'''
@@ -2506,22 +2537,6 @@
 ''');
   }
 
-  void test_true_fieldFormalParameter_changeName_wasUnresolvedField() {
-    _assertMatches(
-        r'''
-class A {
-  final fff;
-  A(this.unresolved);
-}
-''',
-        r'''
-class A {
-  final fff;
-  A(this.fff);
-}
-''');
-  }
-
   void test_true_fieldFormalParameter_function() {
     _assertMatches(
         r'''
@@ -3092,7 +3107,7 @@
   void setUp() {
     super.setUp();
     test_resolveApiChanges = true;
-    log.logger = log.NULL_LOGGER;
+    logging.logger = logging.NULL_LOGGER;
   }
 
   void test_classMemberAccessor_body() {
@@ -3170,15 +3185,6 @@
     _resolve(_editString('+', '*'), _isExpression);
   }
 
-  void test_fieldFormalParameter() {
-    _resolveUnit(r'''
-class A {
-  int xy;
-  A(this.x);
-}''');
-    _resolve(_editString('this.x', 'this.xy'), _isDeclaration);
-  }
-
   void test_function_localFunction_add() {
     _resolveUnit(r'''
 int main() {
@@ -3523,6 +3529,8 @@
  */
 @reflectiveTest
 class PoorMansIncrementalResolutionTest extends ResolverTestCase {
+  final _TestLogger logger = new _TestLogger();
+
   Source source;
   String code;
   LibraryElement oldLibrary;
@@ -3800,23 +3808,6 @@
 ''');
   }
 
-  void test_endOfLineComment_localFunction_inTopLevelVariable() {
-    _resolveUnit(r'''
-typedef int Binary(one, two, three);
-
-int Global = f((a, b, c) {
-  return 0; // Some comment
-});
-''');
-    _updateAndValidate(r'''
-typedef int Binary(one, two, three);
-
-int Global = f((a, b, c) {
-  return 0; // Some  comment
-});
-''');
-  }
-
   void test_endOfLineComment_outBody_add() {
     _resolveUnit(r'''
 main() {
@@ -3886,6 +3877,25 @@
 ''');
   }
 
+  void test_endOfLineComment_toDartDoc() {
+    _resolveUnit(r'''
+class A {
+  // text
+  main() {
+    print(42);
+  }
+}''');
+    _updateAndValidate(
+        r'''
+class A {
+  /// text
+  main() {
+    print(42);
+  }
+}''',
+        expectedSuccess: false);
+  }
+
   void test_false_constConstructor_initializer() {
     _resolveUnit(r'''
 class C {
@@ -3911,6 +3921,74 @@
         expectedSuccess: false);
   }
 
+  void test_false_constructor_initializer_damage() {
+    _resolveUnit(r'''
+class Problem {
+  final Map location;
+  final String message;
+
+  Problem(Map json)
+      : location = json["location"],
+        message = json["message"];
+}''');
+    _updateAndValidate(
+        r'''
+class Problem {
+  final Map location;
+  final String message;
+
+  Problem(Map json)
+      : location = json["location],
+        message = json["message"];
+}''',
+        expectedSuccess: false);
+  }
+
+  void test_false_constructor_initializer_remove() {
+    _resolveUnit(r'''
+class Problem {
+  final String severity;
+  final Map location;
+  final String message;
+
+  Problem(Map json)
+      : severity = json["severity"],
+        location = json["location"],
+        message = json["message"];
+}''');
+    _updateAndValidate(
+        r'''
+class Problem {
+  final String severity;
+  final Map location;
+  final String message;
+
+  Problem(Map json)
+      : severity = json["severity"],
+        message = json["message"];
+}''',
+        expectedSuccess: false);
+  }
+
+  void test_false_endOfLineComment_localFunction_inTopLevelVariable() {
+    _resolveUnit(r'''
+typedef int Binary(one, two, three);
+
+int Global = f((a, b, c) {
+  return 0; // Some comment
+});
+''');
+    _updateAndValidate(
+        r'''
+typedef int Binary(one, two, three);
+
+int Global = f((a, b, c) {
+  return 0; // Some  comment
+});
+''',
+        expectedSuccess: false);
+  }
+
   void test_false_expressionBody() {
     _resolveUnit(r'''
 class A {
@@ -3926,6 +4004,44 @@
         expectedSuccess: false);
   }
 
+  void test_false_expressionBody2() {
+    _resolveUnit(r'''
+class A {
+  int m() => 10 * 10;
+}
+''');
+    _updateAndValidate(
+        r'''
+class A {
+  int m() => 10 * 100;
+}
+''',
+        expectedSuccess: false);
+  }
+
+  void test_false_inBody_functionExpression() {
+    _resolveUnit(r'''
+class C extends D {
+  static final f = () {
+    var x = 0;
+  }();
+}
+
+class D {}
+''');
+    _updateAndValidate(
+        r'''
+class C extends D {
+  static final f = () {
+    var x = 01;
+  }();
+}
+
+class D {}
+''',
+        expectedSuccess: false);
+  }
+
   void test_false_topLevelFunction_name() {
     _resolveUnit(r'''
 a() {}
@@ -3995,6 +4111,25 @@
         expectedSuccess: false);
   }
 
+  void test_false_wholeConstructor() {
+    _resolveUnit(r'''
+class A {
+  A(int a) {
+    print(a);
+  }
+}
+''');
+    _updateAndValidate(
+        r'''
+class A {
+  A(int b) {
+    print(b);
+  }
+}
+''',
+        expectedSuccess: false);
+  }
+
   void test_fieldClassField_propagatedType() {
     _resolveUnit(r'''
 class A {
@@ -4045,27 +4180,6 @@
 ''');
   }
 
-  void test_inBody_functionExpression() {
-    _resolveUnit(r'''
-class C extends D {
-  static final f = () {
-    var x = 0;
-  }();
-}
-
-class D {}
-''');
-    _updateAndValidate(r'''
-class C extends D {
-  static final f = () {
-    var x = 01;
-  }();
-}
-
-class D {}
-''');
-  }
-
   void test_inBody_insertStatement() {
     _resolveUnit(r'''
 main() {
@@ -4238,23 +4352,6 @@
     _assertEqualErrors(newErrors, oldErrors);
   }
 
-  void test_true_wholeConstructor() {
-    _resolveUnit(r'''
-class A {
-  A(int a) {
-    print(a);
-  }
-}
-''');
-    _updateAndValidate(r'''
-class A {
-  A(int b) {
-    print(b);
-  }
-}
-''');
-  }
-
   void test_true_wholeConstructor_addInitializer() {
     _resolveUnit(r'''
 class A {
@@ -4697,8 +4794,7 @@
     AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
     analysisOptions.incremental = enable;
     analysisOptions.incrementalApi = enable;
-//    log.logger = log.PRINT_LOGGER;
-    log.logger = log.NULL_LOGGER;
+    logging.logger = logger;
     analysisContext2.analysisOptions = analysisOptions;
   }
 
@@ -4730,6 +4826,7 @@
     _resetWithIncremental(true);
     analysisContext2.setContents(source, newCode);
     CompilationUnit newUnit = resolveCompilationUnit(source, oldLibrary);
+    expect(logger.hasError, isFalse);
     List<AnalysisError> newErrors = analysisContext.computeErrors(source);
     LineInfo newLineInfo = analysisContext.getLineInfo(source);
     // check for expected failure
@@ -5022,3 +5119,26 @@
   final String replacement;
   _Edit(this.offset, this.length, this.replacement);
 }
+
+class _TestLogger implements logging.Logger {
+  bool hasError = false;
+
+  @override
+  void enter(String name) {}
+
+  @override
+  void exit() {}
+
+  @override
+  void log(Object obj) {}
+
+  @override
+  void logException(Object exception, [Object stackTrace]) {
+    hasError = true;
+  }
+
+  @override
+  logging.LoggingTimer startTimer() {
+    return new logging.LoggingTimer(this);
+  }
+}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 6792467..9ce75c6 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -4,8 +4,8 @@
 
 library analyzer.test.generated.non_error_resolver_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
@@ -35,24 +35,6 @@
     verify([source]);
   }
 
-  void test_class_type_alias_documentationComment() {
-    Source source = addSource('''
-/**
- * Documentation
- */
-class C = D with E;
-
-class D {}
-class E {}''');
-    computeLibrarySourceErrors(source);
-    computeLibrarySourceErrors(source);
-    assertNoErrors(source);
-    verify([source]);
-    CompilationUnit unit = _getResolvedLibraryUnit(source);
-    ClassElement classC = unit.element.getType('C');
-    expect(classC.documentationComment, isNotNull);
-  }
-
   void test_ambiguousExport() {
     Source source = addSource(r'''
 library L;
@@ -932,6 +914,24 @@
     verify([source]);
   }
 
+  void test_class_type_alias_documentationComment() {
+    Source source = addSource('''
+/**
+ * Documentation
+ */
+class C = D with E;
+
+class D {}
+class E {}''');
+    computeLibrarySourceErrors(source);
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+    CompilationUnit unit = _getResolvedLibraryUnit(source);
+    ClassElement classC = unit.element.getType('C');
+    expect(classC.documentationComment, isNotNull);
+  }
+
   void test_commentReference_beforeConstructor() {
     String code = r'''
 abstract class A {
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 5d304c7..2855c21 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -4,10 +4,12 @@
 
 library analyzer.test.generated.parser_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/incremental_scanner.dart';
@@ -937,21 +939,42 @@
         [ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT]);
   }
 
+  void test_emptyEnumBody() {
+    parse3("parseEnumDeclaration", <Object>[emptyCommentAndMetadata()],
+        "enum E {}", [ParserErrorCode.EMPTY_ENUM_BODY]);
+  }
+
   void test_enableAsync_false_1() {
     parseAsync = false;
-    parse4("parseFunctionDeclarationStatement",
-        "foo() async {}", [ParserErrorCode.ASYNC_NOT_SUPPORTED]);
+    FunctionDeclarationStatement stmt = parse4(
+        "parseFunctionDeclarationStatement",
+        "foo() async {}",
+        [ParserErrorCode.ASYNC_NOT_SUPPORTED]);
+    FunctionExpression expr = stmt.functionDeclaration.functionExpression;
+    expect(expr.body.isAsynchronous, isTrue);
+    expect(expr.body.isGenerator, isFalse);
   }
 
   void test_enableAsync_false_2() {
     parseAsync = false;
-    parse4("parseFunctionDeclarationStatement",
-        "foo() sync* {}", [ParserErrorCode.ASYNC_NOT_SUPPORTED]);
+    FunctionDeclarationStatement stmt = parse4(
+        "parseFunctionDeclarationStatement",
+        "foo() async => 0;",
+        [ParserErrorCode.ASYNC_NOT_SUPPORTED]);
+    FunctionExpression expr = stmt.functionDeclaration.functionExpression;
+    expect(expr.body.isAsynchronous, isTrue);
+    expect(expr.body.isGenerator, isFalse);
   }
 
-  void test_emptyEnumBody() {
-    parse3("parseEnumDeclaration", <Object>[emptyCommentAndMetadata()],
-        "enum E {}", [ParserErrorCode.EMPTY_ENUM_BODY]);
+  void test_enableAsync_false_3() {
+    parseAsync = false;
+    FunctionDeclarationStatement stmt = parse4(
+        "parseFunctionDeclarationStatement",
+        "foo() sync* {}",
+        [ParserErrorCode.ASYNC_NOT_SUPPORTED]);
+    FunctionExpression expr = stmt.functionDeclaration.functionExpression;
+    expect(expr.body.isAsynchronous, isFalse);
+    expect(expr.body.isGenerator, isTrue);
   }
 
   void test_enumInClass() {
@@ -3687,6 +3710,55 @@
     expect(statement.toSource(), 'List<String> v;');
   }
 
+  void test_incompleteTypeArguments_field() {
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
+        r'''
+class C {
+  final List<int f;
+}''',
+        [ParserErrorCode.EXPECTED_TOKEN]);
+    // one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+    // one field declaration
+    List<ClassMember> members = classDecl.members;
+    expect(members, hasLength(1));
+    FieldDeclaration fieldDecl = members[0] as FieldDeclaration;
+    // one field
+    VariableDeclarationList fieldList = fieldDecl.fields;
+    List<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.name, 'f');
+    // validate the type
+    TypeArgumentList typeArguments = fieldList.type.typeArguments;
+    expect(typeArguments.arguments, hasLength(1));
+    // synthetic '>'
+    Token token = typeArguments.endToken;
+    expect(token.type, TokenType.GT);
+    expect(token.isSynthetic, isTrue);
+  }
+
+  void test_incompleteTypeParameters() {
+    CompilationUnit unit = ParserTestCase.parseCompilationUnit(
+        r'''
+class C<K {
+}''',
+        [ParserErrorCode.EXPECTED_TOKEN]);
+    // one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+    // validate the type parameters
+    TypeParameterList typeParameters = classDecl.typeParameters;
+    expect(typeParameters.typeParameters, hasLength(1));
+    // synthetic '>'
+    Token token = typeParameters.endToken;
+    expect(token.type, TokenType.GT);
+    expect(token.isSynthetic, isTrue);
+  }
+
   void test_invalidFunctionBodyModifier() {
     ParserTestCase.parseCompilationUnit(
         "f() sync {}", [ParserErrorCode.MISSING_STAR_AFTER_SYNC]);
@@ -7334,6 +7406,16 @@
     expect(literal.rightBracket, isNotNull);
   }
 
+  void test_parseConstExpression_listLiteral_typed_genericComment() {
+    enableGenericMethodComments = true;
+    ListLiteral literal = parse4("parseConstExpression", "const /*<A>*/ []");
+    expect(literal.constKeyword, isNotNull);
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
   void test_parseConstExpression_listLiteral_untyped() {
     ListLiteral literal = parse4("parseConstExpression", "const []");
     expect(literal.constKeyword, isNotNull);
@@ -7351,6 +7433,15 @@
     expect(literal.typeArguments, isNotNull);
   }
 
+  void test_parseConstExpression_mapLiteral_typed_genericComment() {
+    enableGenericMethodComments = true;
+    MapLiteral literal = parse4("parseConstExpression", "const /*<A, B>*/ {}");
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.entries, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+    expect(literal.typeArguments, isNotNull);
+  }
+
   void test_parseConstExpression_mapLiteral_untyped() {
     MapLiteral literal = parse4("parseConstExpression", "const {}");
     expect(literal.leftBracket, isNotNull);
@@ -9856,6 +9947,13 @@
     expect(literal.typeArguments.arguments, hasLength(1));
   }
 
+  void test_parsePrimaryExpression_listLiteral_typed_genericComment() {
+    enableGenericMethodComments = true;
+    ListLiteral literal = parse4("parsePrimaryExpression", "/*<A>*/[ ]");
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.typeArguments.arguments, hasLength(1));
+  }
+
   void test_parsePrimaryExpression_mapLiteral() {
     MapLiteral literal = parse4("parsePrimaryExpression", "{}");
     expect(literal, isNotNull);
@@ -9867,6 +9965,13 @@
     expect(literal.typeArguments.arguments, hasLength(2));
   }
 
+  void test_parsePrimaryExpression_mapLiteral_typed_genericComment() {
+    enableGenericMethodComments = true;
+    MapLiteral literal = parse4("parsePrimaryExpression", "/*<A, B>*/{}");
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.typeArguments.arguments, hasLength(2));
+  }
+
   void test_parsePrimaryExpression_new() {
     InstanceCreationExpression expression =
         parse4("parsePrimaryExpression", "new A()");
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 4722a65..fe755ed8 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -6,13 +6,14 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/context/context.dart';
 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/ast.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
@@ -43,6 +44,7 @@
   initializeTestEnvironment();
   runReflectiveTests(AnalysisDeltaTest);
   runReflectiveTests(ChangeSetTest);
+  runReflectiveTests(DisableAsyncTestCase);
   runReflectiveTests(EnclosedScopeTest);
   runReflectiveTests(LibraryImportScopeTest);
   runReflectiveTests(LibraryScopeTest);
@@ -108,11 +110,14 @@
   static InternalAnalysisContext initContextWithCore(
       InternalAnalysisContext context) {
     DirectoryBasedDartSdk sdk = new _AnalysisContextFactory_initContextWithCore(
-        new JavaFile("/fake/sdk"));
+        new JavaFile("/fake/sdk"),
+        enableAsync: context.analysisOptions.enableAsync);
     SourceFactory sourceFactory =
         new SourceFactory([new DartUriResolver(sdk), new FileUriResolver()]);
     context.sourceFactory = sourceFactory;
     AnalysisContext coreContext = sdk.context;
+    (coreContext.analysisOptions as AnalysisOptionsImpl).strongMode =
+        context.analysisOptions.strongMode;
     //
     // dart:core
     //
@@ -124,8 +129,9 @@
     coreUnit.librarySource = coreUnit.source = coreSource;
     ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy");
     proxyClassElement.constructors = <ConstructorElement>[
-      ElementFactory.constructorElement(proxyClassElement, null, true)
+      ElementFactory.constructorElement(proxyClassElement, '', true)
         ..isCycleFree = true
+        ..constantInitializers = <ConstructorInitializer>[]
     ];
     ClassElement objectClassElement = provider.objectType.element;
     coreUnit.types = <ClassElement>[
@@ -158,11 +164,18 @@
     ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt =
         ElementFactory.topLevelVariableElement3(
             "deprecated", true, false, provider.deprecatedType);
-    deprecatedTopLevelVariableElt.constantInitializer = AstFactory
-        .instanceCreationExpression2(
-            Keyword.CONST,
-            AstFactory.typeName(provider.deprecatedType.element),
-            [AstFactory.string2('next release')]);
+    {
+      ClassElement deprecatedElement = provider.deprecatedType.element;
+      InstanceCreationExpression initializer = AstFactory
+          .instanceCreationExpression2(
+              Keyword.CONST,
+              AstFactory.typeName(deprecatedElement),
+              [AstFactory.string2('next release')]);
+      ConstructorElement constructor = deprecatedElement.constructors.single;
+      initializer.staticElement = constructor;
+      initializer.constructorName.staticElement = constructor;
+      deprecatedTopLevelVariableElt.constantInitializer = initializer;
+    }
     coreUnit.accessors = <PropertyAccessorElement>[
       proxyTopLevelVariableElt.getter,
       deprecatedTopLevelVariableElt.getter
@@ -177,89 +190,97 @@
     //
     // dart:async
     //
-    CompilationUnitElementImpl asyncUnit =
-        new CompilationUnitElementImpl("async.dart");
-    Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
-    coreContext.setContents(asyncSource, "");
-    asyncUnit.librarySource = asyncUnit.source = asyncSource;
-    // Future
-    ClassElementImpl futureElement =
-        ElementFactory.classElement2("Future", ["T"]);
-    //   factory Future.value([value])
-    ConstructorElementImpl futureConstructor =
-        ElementFactory.constructorElement2(futureElement, "value");
-    futureConstructor.parameters = <ParameterElement>[
-      ElementFactory.positionalParameter2("value", provider.dynamicType)
-    ];
-    futureConstructor.factory = true;
-    futureElement.constructors = <ConstructorElement>[futureConstructor];
-    //   Future then(onValue(T value), { Function onError });
-    TypeDefiningElement futureThenR = DynamicElementImpl.instance;
-    if (context.analysisOptions.strongMode) {
-      futureThenR = ElementFactory.typeParameterWithType('R');
+    Source asyncSource;
+    LibraryElementImpl asyncLibrary;
+    if (context.analysisOptions.enableAsync) {
+      asyncLibrary = new LibraryElementImpl.forNode(
+          coreContext, AstFactory.libraryIdentifier2(["dart", "async"]));
+      CompilationUnitElementImpl asyncUnit =
+          new CompilationUnitElementImpl("async.dart");
+      asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
+      coreContext.setContents(asyncSource, "");
+      asyncUnit.librarySource = asyncUnit.source = asyncSource;
+      asyncLibrary.definingCompilationUnit = asyncUnit;
+      // Future
+      ClassElementImpl futureElement =
+          ElementFactory.classElement2("Future", ["T"]);
+      futureElement.enclosingElement = asyncUnit;
+      //   factory Future.value([value])
+      ConstructorElementImpl futureConstructor =
+          ElementFactory.constructorElement2(futureElement, "value");
+      futureConstructor.parameters = <ParameterElement>[
+        ElementFactory.positionalParameter2("value", provider.dynamicType)
+      ];
+      futureConstructor.factory = true;
+      futureElement.constructors = <ConstructorElement>[futureConstructor];
+      //   Future then(onValue(T value), { Function onError });
+      TypeDefiningElement futureThenR = DynamicElementImpl.instance;
+      if (context.analysisOptions.strongMode) {
+        futureThenR = ElementFactory.typeParameterWithType('R');
+      }
+      FunctionElementImpl thenOnValue = ElementFactory.functionElement3(
+          'onValue', futureThenR, [futureElement.typeParameters[0]], null);
+
+      DartType futureRType = futureElement.type.substitute4([futureThenR.type]);
+      MethodElementImpl thenMethod = ElementFactory
+          .methodElementWithParameters(futureElement, "then", futureRType, [
+        ElementFactory.requiredParameter2("onValue", thenOnValue.type),
+        ElementFactory.namedParameter2("onError", provider.functionType)
+      ]);
+      if (!futureThenR.type.isDynamic) {
+        thenMethod.typeParameters = [futureThenR];
+      }
+      thenOnValue.enclosingElement = thenMethod;
+      thenOnValue.type = new FunctionTypeImpl(thenOnValue);
+      (thenMethod.parameters[0] as ParameterElementImpl).type =
+          thenOnValue.type;
+      thenMethod.type = new FunctionTypeImpl(thenMethod);
+
+      futureElement.methods = <MethodElement>[thenMethod];
+      // Completer
+      ClassElementImpl completerElement =
+          ElementFactory.classElement2("Completer", ["T"]);
+      ConstructorElementImpl completerConstructor =
+          ElementFactory.constructorElement2(completerElement, null);
+      completerElement.constructors = <ConstructorElement>[
+        completerConstructor
+      ];
+      // StreamSubscription
+      ClassElementImpl streamSubscriptionElement =
+          ElementFactory.classElement2("StreamSubscription", ["T"]);
+      // Stream
+      ClassElementImpl streamElement =
+          ElementFactory.classElement2("Stream", ["T"]);
+      streamElement.constructors = <ConstructorElement>[
+        ElementFactory.constructorElement2(streamElement, null)
+      ];
+      DartType returnType = streamSubscriptionElement.type
+          .substitute4(streamElement.type.typeArguments);
+      List<DartType> parameterTypes = <DartType>[
+        ElementFactory
+            .functionElement3('onData', VoidTypeImpl.instance.element,
+                <TypeDefiningElement>[streamElement.typeParameters[0]], null)
+            .type,
+      ];
+      // TODO(brianwilkerson) This is missing the optional parameters.
+      MethodElementImpl listenMethod =
+          ElementFactory.methodElement('listen', returnType, parameterTypes);
+      streamElement.methods = <MethodElement>[listenMethod];
+      listenMethod.type = new FunctionTypeImpl(listenMethod);
+
+      FunctionElementImpl listenParamFunction = parameterTypes[0].element;
+      listenParamFunction.enclosingElement = listenMethod;
+      listenParamFunction.type = new FunctionTypeImpl(listenParamFunction);
+      ParameterElementImpl listenParam = listenMethod.parameters[0];
+      listenParam.type = listenParamFunction.type;
+
+      asyncUnit.types = <ClassElement>[
+        completerElement,
+        futureElement,
+        streamElement,
+        streamSubscriptionElement
+      ];
     }
-    FunctionElementImpl thenOnValue = ElementFactory.functionElement3(
-        'onValue', futureThenR, [futureElement.typeParameters[0]], null);
-
-    DartType futureRType = futureElement.type.substitute4([futureThenR.type]);
-    MethodElementImpl thenMethod = ElementFactory
-        .methodElementWithParameters(futureElement, "then", futureRType, [
-      ElementFactory.requiredParameter2("onValue", thenOnValue.type),
-      ElementFactory.namedParameter2("onError", provider.functionType)
-    ]);
-    if (!futureThenR.type.isDynamic) {
-      thenMethod.typeParameters = [futureThenR];
-    }
-    thenOnValue.enclosingElement = thenMethod;
-    thenOnValue.type = new FunctionTypeImpl(thenOnValue);
-    (thenMethod.parameters[0] as ParameterElementImpl).type = thenOnValue.type;
-    thenMethod.type = new FunctionTypeImpl(thenMethod);
-
-    futureElement.methods = <MethodElement>[thenMethod];
-    // Completer
-    ClassElementImpl completerElement =
-        ElementFactory.classElement2("Completer", ["T"]);
-    ConstructorElementImpl completerConstructor =
-        ElementFactory.constructorElement2(completerElement, null);
-    completerElement.constructors = <ConstructorElement>[completerConstructor];
-    // StreamSubscription
-    ClassElementImpl streamSubscriptionElement =
-        ElementFactory.classElement2("StreamSubscription", ["T"]);
-    // Stream
-    ClassElementImpl streamElement =
-        ElementFactory.classElement2("Stream", ["T"]);
-    streamElement.constructors = <ConstructorElement>[
-      ElementFactory.constructorElement2(streamElement, null)
-    ];
-    DartType returnType = streamSubscriptionElement.type
-        .substitute4(streamElement.type.typeArguments);
-    List<DartType> parameterTypes = <DartType>[
-      ElementFactory
-          .functionElement3('onData', VoidTypeImpl.instance.element,
-              <TypeDefiningElement>[streamElement.typeParameters[0]], null)
-          .type,
-    ];
-    // TODO(brianwilkerson) This is missing the optional parameters.
-    MethodElementImpl listenMethod =
-        ElementFactory.methodElement('listen', returnType, parameterTypes);
-    streamElement.methods = <MethodElement>[listenMethod];
-    listenMethod.type = new FunctionTypeImpl(listenMethod);
-
-    FunctionElementImpl listenParamFunction = parameterTypes[0].element;
-    listenParamFunction.enclosingElement = listenMethod;
-    listenParamFunction.type = new FunctionTypeImpl(listenParamFunction);
-    ParameterElementImpl listenParam = listenMethod.parameters[0];
-    listenParam.type = listenParamFunction.type;
-
-    asyncUnit.types = <ClassElement>[
-      completerElement,
-      futureElement,
-      streamElement,
-      streamSubscriptionElement
-    ];
-    LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
-        coreContext, AstFactory.libraryIdentifier2(["dart", "async"]));
-    asyncLibrary.definingCompilationUnit = asyncUnit;
     //
     // dart:html
     //
@@ -395,7 +416,9 @@
     HashMap<Source, LibraryElement> elementMap =
         new HashMap<Source, LibraryElement>();
     elementMap[coreSource] = coreLibrary;
-    elementMap[asyncSource] = asyncLibrary;
+    if (asyncSource != null) {
+      elementMap[asyncSource] = asyncLibrary;
+    }
     elementMap[htmlSource] = htmlLibrary;
     elementMap[mathSource] = mathLibrary;
     //
@@ -407,6 +430,10 @@
           library.publicNamespace = new PublicNamespaceBuilder().build(library);
     }
     context.recordLibraryElements(elementMap);
+    // Create the synthetic element for `loadLibrary`.
+    for (LibraryElementImpl library in elementMap.values) {
+      library.createLoadLibraryFunction(context.typeProvider);
+    }
     return context;
   }
 }
@@ -1206,6 +1233,51 @@
 }
 
 @reflectiveTest
+class DisableAsyncTestCase extends ResolverTestCase {
+  @override
+  void setUp() {
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableAsync = false;
+    resetWithOptions(options);
+  }
+
+  void test_resolve() {
+    Source source = addSource(r'''
+class C {
+  foo() {
+    bar();
+  }
+  bar() {
+    //
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, []);
+  }
+
+  void test_resolve_async() {
+    Source source = addSource(r'''
+class C {
+  Future foo() async {
+    await bar();
+    return null;
+  }
+  Future bar() {
+    return new Future.delayed(new Duration(milliseconds: 10));
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [
+      StaticWarningCode.UNDEFINED_CLASS,
+      StaticWarningCode.UNDEFINED_CLASS,
+      StaticWarningCode.UNDEFINED_CLASS,
+      StaticWarningCode.UNDEFINED_CLASS,
+      ParserErrorCode.ASYNC_NOT_SUPPORTED
+    ]);
+  }
+}
+
+@reflectiveTest
 class ElementResolverTest extends EngineTestCase {
   /**
    * The error listener to which errors will be reported.
@@ -2272,6 +2344,44 @@
   }
 }
 
+/**
+ * Tests for generic method and function resolution that do not use strong mode.
+ */
+@reflectiveTest
+class GenericMethodResolverTest extends _StaticTypeAnalyzer2TestShared {
+  void setUp() {
+    super.setUp();
+    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+    options.enableGenericMethods = true;
+    resetWithOptions(options);
+  }
+
+  void test_genericMethod_propagatedType_promotion() {
+    // Regression test for:
+    // https://github.com/dart-lang/sdk/issues/25340
+    //
+    // Note, after https://github.com/dart-lang/sdk/issues/25486 the original
+    // strong mode example won't work, as we now compute a static type and
+    // therefore discard the propagated type.
+    //
+    // So this test does not use strong mode.
+    _resolveTestUnit(r'''
+abstract class Iter {
+  List<S> map<S>(S f(x));
+}
+class C {}
+C toSpan(dynamic element) {
+  if (element is Iter) {
+    var y = element.map(toSpan);
+  }
+  return null;
+}''');
+    SimpleIdentifier y = _findIdentifier('y = ');
+    expect(y.staticType.toString(), 'dynamic');
+    expect(y.propagatedType.toString(), 'List<dynamic>');
+  }
+}
+
 @reflectiveTest
 class HintCodeTest extends ResolverTestCase {
   void fail_deadCode_statementAfterRehrow() {
@@ -6546,6 +6656,18 @@
     verify([source]);
   }
 
+  void test_deprecatedAnnotationUse_classWithConstructor() {
+    Source source = addSource(r'''
+@deprecated
+class C {
+  C();
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_divisionOptimization() {
     Source source = addSource(r'''
 f(int x, int y) {
@@ -9274,14 +9396,30 @@
   void test_isValidMixin_badSuperclass() {
     Source source = addSource(r'''
 class A extends B {}
-class B {}''');
+class B {}
+class C = Object with A;''');
     LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(2));
-    expect(classes[0].isValidMixin, isFalse);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isFalse);
+    assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+    verify([source]);
+  }
+
+  void test_isValidMixin_badSuperclass_withSuperMixins() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+    Source source = addSource(r'''
+class A extends B {}
+class B {}
+class C = Object with A;''');
+    LibraryElement library = resolve2(source);
+    expect(library, isNotNull);
+    CompilationUnitElement unit = library.definingCompilationUnit;
+    expect(unit, isNotNull);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isTrue);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9290,14 +9428,64 @@
     Source source = addSource(r'''
 class A {
   A() {}
-}''');
+}
+class C = Object with A;''');
     LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(1));
-    expect(classes[0].isValidMixin, isFalse);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isFalse);
+    assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
+    verify([source]);
+  }
+
+  void test_isValidMixin_constructor_withSuperMixins() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+    Source source = addSource(r'''
+class A {
+  A() {}
+}
+class C = Object with A;''');
+    LibraryElement library = resolve2(source);
+    expect(library, isNotNull);
+    CompilationUnitElement unit = library.definingCompilationUnit;
+    expect(unit, isNotNull);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isFalse);
+    assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]);
+    verify([source]);
+  }
+
+  void test_isValidMixin_factoryConstructor() {
+    Source source = addSource(r'''
+class A {
+  factory A() => null;
+}
+class C = Object with A;''');
+    LibraryElement library = resolve2(source);
+    expect(library, isNotNull);
+    CompilationUnitElement unit = library.definingCompilationUnit;
+    expect(unit, isNotNull);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isTrue);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_isValidMixin_factoryConstructor_withSuperMixins() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+    Source source = addSource(r'''
+class A {
+  factory A() => null;
+}
+class C = Object with A;''');
+    LibraryElement library = resolve2(source);
+    expect(library, isNotNull);
+    CompilationUnitElement unit = library.definingCompilationUnit;
+    expect(unit, isNotNull);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isTrue);
     assertNoErrors(source);
     verify([source]);
   }
@@ -9308,27 +9496,62 @@
   toString() {
     return super.toString();
   }
-}''');
+}
+class C = Object with A;''');
     LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(1));
-    expect(classes[0].isValidMixin, isFalse);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isFalse);
+    assertErrors(source, [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
+    verify([source]);
+  }
+
+  void test_isValidMixin_super_withSuperMixins() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+    Source source = addSource(r'''
+class A {
+  toString() {
+    return super.toString();
+  }
+}
+class C = Object with A;''');
+    LibraryElement library = resolve2(source);
+    expect(library, isNotNull);
+    CompilationUnitElement unit = library.definingCompilationUnit;
+    expect(unit, isNotNull);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isTrue);
     assertNoErrors(source);
     verify([source]);
   }
 
   void test_isValidMixin_valid() {
-    Source source = addSource("class A {}");
+    Source source = addSource('''
+class A {}
+class C = Object with A;''');
     LibraryElement library = resolve2(source);
     expect(library, isNotNull);
     CompilationUnitElement unit = library.definingCompilationUnit;
     expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(1));
-    expect(classes[0].isValidMixin, isTrue);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isTrue);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
+  void test_isValidMixin_valid_withSuperMixins() {
+    resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true);
+    Source source = addSource('''
+class A {}
+class C = Object with A;''');
+    LibraryElement library = resolve2(source);
+    expect(library, isNotNull);
+    CompilationUnitElement unit = library.definingCompilationUnit;
+    expect(unit, isNotNull);
+    ClassElement a = unit.getType('A');
+    expect(a.isValidMixin, isTrue);
     assertNoErrors(source);
     verify([source]);
   }
@@ -10019,6 +10242,11 @@
    */
   TestTypeProvider _typeProvider;
 
+  /**
+   * The type system used to analyze the test cases.
+   */
+  TypeSystem get _typeSystem => _visitor.typeSystem;
+
   void fail_visitFunctionExpressionInvocation() {
     fail("Not yet tested");
     _listener.assertNoErrors();
@@ -10038,7 +10266,6 @@
   void setUp() {
     super.setUp();
     _listener = new GatheringErrorListener();
-    _typeProvider = new TestTypeProvider();
     _analyzer = _createAnalyzer();
   }
 
@@ -11304,6 +11531,7 @@
     LibraryElementImpl definingLibrary =
         new LibraryElementImpl.forNode(context, null);
     definingLibrary.definingCompilationUnit = definingCompilationUnit;
+    _typeProvider = new TestTypeProvider(context);
     _visitor = new ResolverVisitor(
         definingLibrary, source, _typeProvider, _listener,
         nameScope: new LibraryScope(definingLibrary, _listener));
@@ -11316,8 +11544,7 @@
     }
   }
 
-  DartType _flatten(DartType type) =>
-      StaticTypeAnalyzer.flattenFutures(_typeProvider, type);
+  DartType _flatten(DartType type) => type.flattenFutures(_typeSystem);
 
   /**
    * Return a simple identifier that has been resolved to a variable element with the given type.
@@ -13030,105 +13257,6 @@
  */
 @reflectiveTest
 class StrongModeStaticTypeAnalyzer2Test extends _StaticTypeAnalyzer2TestShared {
-  void test_genericMethod_functionExpressionInvocation_explicit() {
-    _resolveTestUnit(r'''
-class C<E> {
-  /*=T*/ f/*<T>*/(/*=T*/ e) => null;
-  static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
-  static final h = g;
-}
-
-/*=T*/ topF/*<T>*/(/*=T*/ e) => null;
-var topG = topF;
-void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
-  var c = new C<int>();
-  /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
-
-  var lambdaCall = (/*<E>*/(/*=E*/ e) => e)/*<int>*/(3);
-  var methodCall = (c.f)/*<int>*/(3);
-  var staticCall = (C.g)/*<int>*/(3);
-  var staticFieldCall = (C.h)/*<int>*/(3);
-  var topFunCall = (topF)/*<int>*/(3);
-  var topFieldCall = (topG)/*<int>*/(3);
-  var localCall = (lf)/*<int>*/(3);
-  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");
-  }
-
-  void fail_genericMethod_functionExpressionInvocation_inferred() {
-    _resolveTestUnit(r'''
-class C<E> {
-  /*=T*/ f/*<T>*/(/*=T*/ e) => null;
-  static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
-  static final h = g;
-}
-
-/*=T*/ topF/*<T>*/(/*=T*/ e) => null;
-var topG = topF;
-void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
-  var c = new C<int>();
-  /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
-
-  var lambdaCall = (/*<E>*/(/*=E*/ e) => e)(3);
-  var methodCall = (c.f)(3);
-  var staticCall = (C.g)(3);
-  var staticFieldCall = (C.h)(3);
-  var topFunCall = (topF)(3);
-  var topFieldCall = (topG)(3);
-  var localCall = (lf)(3);
-  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");
-  }
-
-  void fail_genericMethod_functionInvocation_inferred() {
-    _resolveTestUnit(r'''
-class C<E> {
-  /*=T*/ f/*<T>*/(/*=T*/ e) => null;
-  static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
-  static final h = g;
-}
-
-/*=T*/ topF/*<T>*/(/*=T*/ e) => null;
-var topG = topF;
-void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
-  var c = new C<int>();
-  /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
-  var methodCall = c.f(3);
-  var staticCall = C.g(3);
-  var staticFieldCall = C.h(3);
-  var topFunCall = topF(3);
-  var topFieldCall = topG(3);
-  var localCall = lf(3);
-  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");
-  }
-
   void fail_genericMethod_tearoff_instantiated() {
     _resolveTestUnit(r'''
 class C<E> {
@@ -13384,6 +13512,74 @@
         typeProvider.listType.substitute4([typeProvider.intType]));
   }
 
+  void test_genericMethod_functionExpressionInvocation_explicit() {
+    _resolveTestUnit(r'''
+class C<E> {
+  /*=T*/ f/*<T>*/(/*=T*/ e) => null;
+  static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
+  static final h = g;
+}
+
+/*=T*/ topF/*<T>*/(/*=T*/ e) => null;
+var topG = topF;
+void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
+  var c = new C<int>();
+  /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
+
+  var lambdaCall = (/*<E>*/(/*=E*/ e) => e)/*<int>*/(3);
+  var methodCall = (c.f)/*<int>*/(3);
+  var staticCall = (C.g)/*<int>*/(3);
+  var staticFieldCall = (C.h)/*<int>*/(3);
+  var topFunCall = (topF)/*<int>*/(3);
+  var topFieldCall = (topG)/*<int>*/(3);
+  var localCall = (lf)/*<int>*/(3);
+  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");
+  }
+
+  void test_genericMethod_functionExpressionInvocation_inferred() {
+    _resolveTestUnit(r'''
+class C<E> {
+  /*=T*/ f/*<T>*/(/*=T*/ e) => null;
+  static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
+  static final h = g;
+}
+
+/*=T*/ topF/*<T>*/(/*=T*/ e) => null;
+var topG = topF;
+void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
+  var c = new C<int>();
+  /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
+
+  var lambdaCall = (/*<E>*/(/*=E*/ e) => e)(3);
+  var methodCall = (c.f)(3);
+  var staticCall = (C.g)(3);
+  var staticFieldCall = (C.h)(3);
+  var topFunCall = (topF)(3);
+  var topFieldCall = (topG)(3);
+  var localCall = (lf)(3);
+  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");
+  }
+
   void test_genericMethod_functionInvocation_explicit() {
     _resolveTestUnit(r'''
 class C<E> {
@@ -13415,6 +13611,37 @@
     expect(_findIdentifier('paramCall').staticType.toString(), "int");
   }
 
+  void test_genericMethod_functionInvocation_inferred() {
+    _resolveTestUnit(r'''
+class C<E> {
+  /*=T*/ f/*<T>*/(/*=T*/ e) => null;
+  static /*=T*/ g/*<T>*/(/*=T*/ e) => null;
+  static final h = g;
+}
+
+/*=T*/ topF/*<T>*/(/*=T*/ e) => null;
+var topG = topF;
+void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) {
+  var c = new C<int>();
+  /*=T*/ lf/*<T>*/(/*=T*/ e) => null;
+  var methodCall = c.f(3);
+  var staticCall = C.g(3);
+  var staticFieldCall = C.h(3);
+  var topFunCall = topF(3);
+  var topFieldCall = topG(3);
+  var localCall = lf(3);
+  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");
+  }
+
   void test_genericMethod_functionTypedParameter() {
     _resolveTestUnit(r'''
 class C<E> {
@@ -13456,15 +13683,95 @@
     SimpleIdentifier map1 = _findIdentifier('map((e) => e);');
     MethodInvocation m1 = map1.parent;
     expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
-    expect(map1.staticType, isNull);
+    expect(map1.staticType.toString(), '<T>((dynamic) → T) → T');
     expect(map1.propagatedType, isNull);
     SimpleIdentifier map2 = _findIdentifier('map((e) => 3);');
     MethodInvocation m2 = map2.parent;
     expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int');
-    expect(map2.staticType, isNull);
+    expect(map2.staticType.toString(), '<T>((dynamic) → T) → T');
     expect(map2.propagatedType, isNull);
   }
 
+  void test_genericMethod_max_doubleDouble() {
+    String code = r'''
+import 'dart:math';
+main() {
+  var foo = max(1.0, 2.0);
+}
+''';
+    _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);
+  }
+
+  void test_genericMethod_max_doubleDouble_prefixed() {
+    String code = r'''
+import 'dart:math' as math;
+main() {
+  var foo = math.max(1.0, 2.0);
+}
+''';
+    _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);
+  }
+
+  void test_genericMethod_max_doubleInt() {
+    String code = r'''
+import 'dart:math';
+main() {
+  var foo = max(1.0, 2);
+}
+''';
+    _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);
+  }
+
+  void test_genericMethod_max_intDouble() {
+    String code = r'''
+import 'dart:math';
+main() {
+  var foo = max(1, 2.0);
+}
+''';
+    _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);
+  }
+
+  void test_genericMethod_max_intInt() {
+    String code = r'''
+import 'dart:math';
+main() {
+  var foo = max(1, 2);
+}
+''';
+    _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);
+  }
+
   void test_genericMethod_nestedCapture() {
     _resolveTestUnit(r'''
 class C<T> {
@@ -13564,10 +13871,11 @@
     // TODO(jmesserly): this is modified code from assertErrors, which we can't
     // use directly because STRONG_MODE_* errors don't have working equality.
     List<AnalysisError> errors = analysisContext2.computeErrors(source);
-    expect(errors.map((e) => e.errorCode.name), [
-      'STRONG_MODE_INVALID_METHOD_OVERRIDE',
-      'INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND'
-    ]);
+    List errorNames = errors.map((e) => e.errorCode.name).toList();
+    expect(errorNames, hasLength(2));
+    expect(errorNames, contains('STRONG_MODE_INVALID_METHOD_OVERRIDE'));
+    expect(
+        errorNames, contains('INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND'));
     verify([source]);
   }
 
@@ -13589,6 +13897,30 @@
     verify([source]);
   }
 
+  void test_genericMethod_propagatedType_promotion() {
+    // Regression test for:
+    // https://github.com/dart-lang/sdk/issues/25340
+
+    // Note, after https://github.com/dart-lang/sdk/issues/25486 the original
+    // example won't work, as we now compute a static type and therefore discard
+    // the propagated type. So a new test was created that doesn't run under
+    // strong mode.
+    _resolveTestUnit(r'''
+abstract class Iter {
+  List/*<S>*/ map/*<S>*/(/*=S*/ f(x));
+}
+class C {}
+C toSpan(dynamic element) {
+  if (element is Iter) {
+    var y = element.map(toSpan);
+  }
+  return null;
+}''');
+    SimpleIdentifier y = _findIdentifier('y = ');
+    expect(y.staticType.toString(), 'List<C>');
+    expect(y.propagatedType, isNull);
+  }
+
   void test_genericMethod_tearoff() {
     _resolveTestUnit(r'''
 class C<E> {
@@ -13625,87 +13957,7 @@
     expect(_findIdentifier('paramTearOff').staticType.toString(), "<T>(T) → T");
   }
 
-  void test_pseudoGeneric_max_doubleDouble() {
-    String code = r'''
-import 'dart:math';
-main() {
-  var foo = max(1.0, 2.0);
-}
-''';
-    _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);
-  }
-
-  void test_pseudoGeneric_max_doubleDouble_prefixed() {
-    String code = r'''
-import 'dart:math' as math;
-main() {
-  var foo = math.max(1.0, 2.0);
-}
-''';
-    _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);
-  }
-
-  void test_pseudoGeneric_max_doubleInt() {
-    String code = r'''
-import 'dart:math';
-main() {
-  var foo = max(1.0, 2);
-}
-''';
-    _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);
-  }
-
-  void test_pseudoGeneric_max_intDouble() {
-    String code = r'''
-import 'dart:math';
-main() {
-  var foo = max(1, 2.0);
-}
-''';
-    _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);
-  }
-
-  void test_pseudoGeneric_max_intInt() {
-    String code = r'''
-import 'dart:math';
-main() {
-  var foo = max(1, 2);
-}
-''';
-    _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);
-  }
-
-  void test_pseudoGeneric_then() {
+  void test_genericMethod_then() {
     String code = r'''
 import 'dart:async';
 String toString(int x) => x.toString();
@@ -13724,7 +13976,7 @@
     expect(declaration.initializer.propagatedType, isNull);
   }
 
-  void test_pseudoGeneric_then_prefixed() {
+  void test_genericMethod_then_prefixed() {
     String code = r'''
 import 'dart:async' as async;
 String toString(int x) => x.toString();
@@ -13743,6 +13995,22 @@
     expect(declaration.initializer.propagatedType, isNull);
   }
 
+  void test_genericMethod_then_propagatedType() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25482.
+    String code = r'''
+import 'dart:async';
+void main() {
+  Future<String> p;
+  var foo = p.then((r) => new Future<String>.value(3));
+}
+''';
+    // 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);
+  }
+
   void test_setterWithDynamicTypeIsError() {
     Source source = addSource(r'''
 class A {
@@ -15747,7 +16015,7 @@
 }''';
     SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker");
     MethodInvocation methodInvoke = methodName.parent;
-    expect(methodName.staticType, null, reason: 'library prefix has no type');
+    expect(methodName.staticType, typeProvider.dynamicType);
     expect(methodInvoke.staticType, typeProvider.dynamicType);
   }
 
@@ -15953,11 +16221,81 @@
     expect(provider.mapType, same(mapType));
     expect(provider.objectType, same(objectType));
     expect(provider.stackTraceType, same(stackTraceType));
+    expect(provider.streamType, same(streamType));
     expect(provider.stringType, same(stringType));
     expect(provider.symbolType, same(symbolType));
     expect(provider.typeType, same(typeType));
   }
 
+  void test_creation_no_async() {
+    //
+    // Create a mock library element with the types expected to be in dart:core.
+    // We cannot use either ElementFactory or TestTypeProvider (which uses
+    // ElementFactory) because we side-effect the elements in ways that would
+    // break other tests.
+    //
+    InterfaceType objectType = _classElement("Object", null).type;
+    InterfaceType boolType = _classElement("bool", objectType).type;
+    InterfaceType numType = _classElement("num", objectType).type;
+    InterfaceType doubleType = _classElement("double", numType).type;
+    InterfaceType functionType = _classElement("Function", objectType).type;
+    InterfaceType intType = _classElement("int", numType).type;
+    InterfaceType iterableType =
+        _classElement("Iterable", objectType, ["T"]).type;
+    InterfaceType listType = _classElement("List", objectType, ["E"]).type;
+    InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type;
+    InterfaceType stackTraceType = _classElement("StackTrace", objectType).type;
+    InterfaceType stringType = _classElement("String", objectType).type;
+    InterfaceType symbolType = _classElement("Symbol", objectType).type;
+    InterfaceType typeType = _classElement("Type", objectType).type;
+    CompilationUnitElementImpl coreUnit =
+        new CompilationUnitElementImpl("core.dart");
+    coreUnit.types = <ClassElement>[
+      boolType.element,
+      doubleType.element,
+      functionType.element,
+      intType.element,
+      iterableType.element,
+      listType.element,
+      mapType.element,
+      objectType.element,
+      stackTraceType.element,
+      stringType.element,
+      symbolType.element,
+      typeType.element
+    ];
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+    LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
+        context, AstFactory.libraryIdentifier2(["dart.core"]));
+    coreLibrary.definingCompilationUnit = coreUnit;
+
+    LibraryElementImpl mockAsyncLib =
+        (context as AnalysisContextImpl).createMockAsyncLib(coreLibrary);
+    expect(mockAsyncLib.publicNamespace, isNotNull);
+
+    //
+    // Create a type provider and ensure that it can return the expected types.
+    //
+    TypeProviderImpl provider = new TypeProviderImpl(coreLibrary, mockAsyncLib);
+    expect(provider.boolType, same(boolType));
+    expect(provider.bottomType, isNotNull);
+    expect(provider.doubleType, same(doubleType));
+    expect(provider.dynamicType, isNotNull);
+    expect(provider.functionType, same(functionType));
+    InterfaceType mockFutureType = mockAsyncLib.getType('Future').type;
+    expect(provider.futureType, same(mockFutureType));
+    expect(provider.intType, same(intType));
+    expect(provider.listType, same(listType));
+    expect(provider.mapType, same(mapType));
+    expect(provider.objectType, same(objectType));
+    expect(provider.stackTraceType, same(stackTraceType));
+    expect(provider.stringType, same(stringType));
+    expect(provider.symbolType, same(symbolType));
+    InterfaceType mockStreamType = mockAsyncLib.getType('Stream').type;
+    expect(provider.streamType, same(mockStreamType));
+    expect(provider.typeType, same(typeType));
+  }
+
   ClassElement _classElement(String typeName, InterfaceType superclassType,
       [List<String> parameterNames]) {
     ClassElementImpl element =
@@ -16612,12 +16950,17 @@
 
 class _AnalysisContextFactory_initContextWithCore
     extends DirectoryBasedDartSdk {
-  _AnalysisContextFactory_initContextWithCore(JavaFile arg0) : super(arg0);
+  final bool enableAsync;
+  _AnalysisContextFactory_initContextWithCore(JavaFile arg0,
+      {this.enableAsync: true})
+      : super(arg0);
 
   @override
   LibraryMap initialLibraryMap(bool useDart2jsPaths) {
     LibraryMap map = new LibraryMap();
-    _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart");
+    if (enableAsync) {
+      _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart");
+    }
     _addLibrary(map, DartSdk.DART_CORE, false, "core.dart");
     _addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart");
     _addLibrary(map, AnalysisContextFactory._DART_MATH, false, "math.dart");
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index e737b56..8a0b3d2 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -8,8 +8,8 @@
 
 import '../utils.dart';
 import 'all_the_rest_test.dart' as all_the_rest;
-import 'ast_test.dart' as ast_test;
 import 'compile_time_error_code_test.dart' as compile_time_error_code_test;
+import 'constant_test.dart' as constant_test;
 import 'declaration_resolver_test.dart' as declaration_resolver_test;
 import 'engine_test.dart' as engine_test;
 import 'incremental_resolver_test.dart' as incremental_resolver_test;
@@ -31,8 +31,8 @@
   initializeTestEnvironment();
   group('generated tests', () {
     all_the_rest.main();
-    ast_test.main();
     compile_time_error_code_test.main();
+    constant_test.main();
     declaration_resolver_test.main();
     engine_test.main();
     incremental_resolver_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 87b1282..adccead 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -6,10 +6,11 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart'
+    show AstNode, NodeLocator, SimpleIdentifier;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart'
-    show AstNode, NodeLocator, SimpleIdentifier;
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_core.dart';
@@ -423,9 +424,9 @@
    */
   bool _equalErrors(AnalysisError firstError, AnalysisError secondError) =>
       identical(firstError.errorCode, secondError.errorCode) &&
-          firstError.offset == secondError.offset &&
-          firstError.length == secondError.length &&
-          _equalSources(firstError.source, secondError.source);
+      firstError.offset == secondError.offset &&
+      firstError.length == secondError.length &&
+      _equalSources(firstError.source, secondError.source);
 
   /**
    * Return `true` if the two sources are equivalent.
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index bd5876b..d07f422 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -6,7 +6,8 @@
 
 import 'dart:collection';
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/scanner.dart';
@@ -1506,8 +1507,8 @@
   }
 
   void test_visitSwitchCase_noLabels() {
-    _assertClone(AstFactory.switchCase(
-        AstFactory.identifier3("a"), [AstFactory.block()]));
+    _assertClone(AstFactory
+        .switchCase(AstFactory.identifier3("a"), [AstFactory.block()]));
   }
 
   void test_visitSwitchCase_singleLabel() {
@@ -1531,8 +1532,8 @@
   }
 
   void test_visitSwitchDefault_singleLabel() {
-    _assertClone(AstFactory.switchDefault(
-        [AstFactory.label2("l1")], [AstFactory.block()]));
+    _assertClone(AstFactory
+        .switchDefault([AstFactory.label2("l1")], [AstFactory.block()]));
   }
 
   void test_visitSwitchStatement() {
@@ -3534,8 +3535,8 @@
         AstFactory.extendsClause(AstFactory.typeName4("B")),
         AstFactory.withClause([AstFactory.typeName4("C")]),
         AstFactory.implementsClause([AstFactory.typeName4("D")]), [
-      AstFactory.fieldDeclaration2(
-          false, null, [AstFactory.variableDeclaration("f")])
+      AstFactory
+          .fieldDeclaration2(false, null, [AstFactory.variableDeclaration("f")])
     ]);
     node.documentationComment =
         Comment.createEndOfLineComment(EMPTY_TOKEN_LIST);
@@ -3981,8 +3982,8 @@
   }
 
   void test_labeledStatement() {
-    LabeledStatement node = AstFactory.labeledStatement(
-        [AstFactory.label2("l")], AstFactory.block());
+    LabeledStatement node = AstFactory
+        .labeledStatement([AstFactory.label2("l")], AstFactory.block());
     _assertReplace(
         node, new ListGetter_NodeReplacerTest_test_labeledStatement(0));
     _assertReplace(node, new Getter_NodeReplacerTest_test_labeledStatement());
@@ -4181,8 +4182,8 @@
   }
 
   void test_switchDefault() {
-    SwitchDefault node = AstFactory.switchDefault(
-        [AstFactory.label2("l")], [AstFactory.block()]);
+    SwitchDefault node = AstFactory
+        .switchDefault([AstFactory.label2("l")], [AstFactory.block()]);
     _testSwitchMember(node);
   }
 
@@ -4235,8 +4236,8 @@
   }
 
   void test_typeName() {
-    TypeName node = AstFactory.typeName4(
-        "T", [AstFactory.typeName4("E"), AstFactory.typeName4("F")]);
+    TypeName node = AstFactory
+        .typeName4("T", [AstFactory.typeName4("E"), AstFactory.typeName4("F")]);
     _assertReplace(node, new Getter_NodeReplacerTest_test_typeName_2());
     _assertReplace(node, new Getter_NodeReplacerTest_test_typeName());
   }
diff --git a/pkg/analyzer/test/reflective_tests.dart b/pkg/analyzer/test/reflective_tests.dart
index 24c36cb..970743d 100644
--- a/pkg/analyzer/test/reflective_tests.dart
+++ b/pkg/analyzer/test/reflective_tests.dart
@@ -73,14 +73,15 @@
 
 Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) {
   var invocationResult = null;
+  InstanceMirror closure;
   try {
-    invocationResult = instanceMirror.invoke(symbol, []).reflectee;
+    closure = instanceMirror.getField(symbol);
   } on NoSuchMethodError {}
-  if (invocationResult is Future) {
-    return invocationResult;
-  } else {
-    return new Future.value(invocationResult);
+
+  if (closure is ClosureMirror) {
+    invocationResult = closure.apply([]).reflectee;
   }
+  return new Future.value(invocationResult);
 }
 
 /**
diff --git a/pkg/analyzer/test/source/embedder_test.dart b/pkg/analyzer/test/source/embedder_test.dart
index c152773..cf96040 100644
--- a/pkg/analyzer/test/source/embedder_test.dart
+++ b/pkg/analyzer/test/source/embedder_test.dart
@@ -6,6 +6,8 @@
 
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/embedder.dart';
+import 'package:analyzer/src/generated/java_io.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:unittest/unittest.dart';
 
 import '../utils.dart';
@@ -34,13 +36,20 @@
         'fox': [resourceProvider.getResource('/tmp')]
       });
       var resolver = new EmbedderUriResolver(locator.embedderYamls);
+
+      expectResolved(dartUri, filePath) {
+        Source source = resolver.resolveAbsolute(Uri.parse(dartUri));
+        expect(source, isNotNull, reason: dartUri);
+        expect(source.fullName, filePath.replaceAll('/', JavaFile.separator));
+      }
+
       // We have four mappings.
       expect(resolver.length, equals(4));
       // Check that they map to the correct paths.
-      expect(resolver['dart:fox'], equals("/tmp/slippy.dart"));
-      expect(resolver['dart:bear'], equals("/tmp/grizzly.dart"));
-      expect(resolver['dart:relative'], equals("/relative.dart"));
-      expect(resolver['dart:deep'], equals("/tmp/deep/directory/file.dart"));
+      expectResolved('dart:fox', '/tmp/slippy.dart');
+      expectResolved('dart:bear', '/tmp/grizzly.dart');
+      expectResolved('dart:relative', '/relative.dart');
+      expectResolved('dart:deep', '/tmp/deep/directory/file.dart');
     });
     test('test_BadYAML', () {
       var locator = new EmbedderYamlLocator(null);
@@ -52,15 +61,91 @@
         'fox': [resourceProvider.getResource('/tmp')]
       });
       var resolver = new EmbedderUriResolver(locator.embedderYamls);
-      var source = resolver.resolveAbsolute(Uri.parse('dart:fox'));
-      expect(source, isNotNull);
-      // Restore source's uri.
-      var restoreUri = resolver.restoreAbsolute(source);
-      expect(restoreUri, isNotNull);
-      // Verify that it is 'dart:fox'.
-      expect(restoreUri.toString(), equals('dart:fox'));
-      expect(restoreUri.scheme, equals('dart'));
-      expect(restoreUri.path, equals('fox'));
+
+      expectRestore(String dartUri, [String expected]) {
+        var source = resolver.resolveAbsolute(Uri.parse(dartUri));
+        expect(source, isNotNull);
+        // Restore source's uri.
+        var restoreUri = resolver.restoreAbsolute(source);
+        expect(restoreUri, isNotNull, reason: dartUri);
+        // Verify that it is 'dart:fox'.
+        expect(restoreUri.toString(), equals(expected ?? dartUri));
+        List<String> split = (expected ?? dartUri).split(':');
+        expect(restoreUri.scheme, equals(split[0]));
+        expect(restoreUri.path, equals(split[1]));
+      }
+
+      try {
+        expectRestore('dart:deep');
+        expectRestore('dart:deep/file.dart', 'dart:deep');
+        expectRestore('dart:deep/part.dart');
+        expectRestore('dart:deep/deep/file.dart');
+        if (JavaFile.separator == '\\') {
+          // See https://github.com/dart-lang/sdk/issues/25498
+          fail('expected to fail on Windows');
+        }
+      } catch (_) {
+        // Test is broken on Windows, but should run elsewhere
+        if (JavaFile.separator != '\\') {
+          rethrow;
+        }
+      }
+    });
+
+    test('test_EmbedderSdk_fromFileUri', () {
+      var locator = new EmbedderYamlLocator({
+        'fox': [resourceProvider.getResource('/tmp')]
+      });
+      var resolver = new EmbedderUriResolver(locator.embedderYamls);
+      var sdk = resolver.dartSdk;
+
+      expectSource(String filePath, String dartUri) {
+        var uri = Uri.parse(filePath);
+        var source = sdk.fromFileUri(uri);
+        expect(source, isNotNull, reason: filePath);
+        expect(source.uri.toString(), dartUri);
+        expect(source.fullName, filePath.replaceAll('/', JavaFile.separator));
+      }
+
+      //TODO(danrubel) fix embedder on Windows
+      isWindows() => JavaFile.separator == '\\';
+      try {
+        expectSource('/tmp/slippy.dart', 'dart:fox');
+        expectSource('/tmp/deep/directory/file.dart', 'dart:deep');
+        expectSource('/tmp/deep/directory/part.dart', 'dart:deep/part.dart');
+        if (isWindows()) fail('expected to fail on windows');
+      } catch (e) {
+        if (!isWindows()) rethrow;
+      }
+    });
+    test('test_EmbedderSdk_getSdkLibrary', () {
+      var locator = new EmbedderYamlLocator({
+        'fox': [resourceProvider.getResource('/tmp')]
+      });
+      var resolver = new EmbedderUriResolver(locator.embedderYamls);
+      var sdk = resolver.dartSdk;
+      var lib = sdk.getSdkLibrary('dart:fox');
+      expect(lib, isNotNull);
+      expect(lib.path, '/tmp/slippy.dart');
+      expect(lib.shortName, 'fox');
+    });
+    test('test_EmbedderSdk_mapDartUri', () {
+      var locator = new EmbedderYamlLocator({
+        'fox': [resourceProvider.getResource('/tmp')]
+      });
+      var resolver = new EmbedderUriResolver(locator.embedderYamls);
+      var sdk = resolver.dartSdk;
+
+      expectSource(String dartUri, String filePath) {
+        var source = sdk.mapDartUri(dartUri);
+        expect(source, isNotNull, reason: filePath);
+        expect(source.uri.toString(), dartUri);
+        expect(source.fullName, filePath.replaceAll('/', JavaFile.separator));
+      }
+
+      expectSource('dart:fox', '/tmp/slippy.dart');
+      expectSource('dart:deep', '/tmp/deep/directory/file.dart');
+      expectSource('dart:deep/part.dart', '/tmp/deep/directory/part.dart');
     });
   });
 }
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 41feb593..d37179a 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -5,15 +5,17 @@
 library analyzer.test.src.context.context_test;
 
 import 'dart:async';
+import 'dart:collection';
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -2002,6 +2004,72 @@
     _assertNoExceptions();
   }
 
+  void test_resolveCompilationUnit_existingElementModel() {
+    Source source = addSource(
+        '/test.dart',
+        r'''
+library test;
+
+String topLevelVariable;
+int get topLevelGetter => 0;
+void set topLevelSetter(int value) {}
+String topLevelFunction(int i) => '';
+
+typedef String FunctionTypeAlias(int i);
+
+enum EnumeratedType {Invalid, Valid}
+
+class ClassOne {
+  int instanceField;
+  static int staticField;
+
+  ClassOne();
+  ClassOne.named();
+
+  int get instanceGetter => 0;
+  static String get staticGetter => '';
+
+  void set instanceSetter(int value) {}
+  static void set staticSetter(int value) {}
+
+  int instanceMethod(int first, [int second = 0]) {
+    int localVariable;
+    int localFunction(String s) {}
+  }
+  static String staticMethod(int first, {int second: 0}) => '';
+}
+
+class ClassTwo {
+  // Implicit no-argument constructor
+}
+''');
+    context.resolveCompilationUnit2(source, source);
+    LibraryElement firstElement = context.computeLibraryElement(source);
+    _ElementGatherer gatherer = new _ElementGatherer();
+    firstElement.accept(gatherer);
+
+    CacheEntry entry =
+        context.analysisCache.get(new LibrarySpecificUnit(source, source));
+    entry.setState(RESOLVED_UNIT1, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT2, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT3, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT4, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT5, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT6, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT7, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT8, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT9, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
+
+    context.resolveCompilationUnit2(source, source);
+    LibraryElement secondElement = context.computeLibraryElement(source);
+    _ElementComparer comparer = new _ElementComparer(gatherer.elements);
+    secondElement.accept(comparer);
+    comparer.expectNoDifferences();
+  }
+
   void test_resolveCompilationUnit_import_relative() {
     Source sourceA =
         addSource("/libA.dart", "library libA; import 'libB.dart'; class A{}");
@@ -2731,3 +2799,82 @@
   @override
   bool contains(Source source) => source == libB;
 }
+
+/**
+ * A visitor that can be used to compare all of the elements in an element model
+ * with a previously created map of elements. The class [ElementGatherer] can be
+ * used to create the map of elements.
+ */
+class _ElementComparer extends GeneralizingElementVisitor {
+  /**
+   * The previously created map of elements.
+   */
+  final Map<Element, Element> previousElements;
+
+  /**
+   * The number of elements that were found to have been overwritten.
+   */
+  int overwrittenCount = 0;
+
+  /**
+   * A buffer to which a description of the overwritten elements will be written.
+   */
+  final StringBuffer buffer = new StringBuffer();
+
+  /**
+   * Initialize a newly created visitor.
+   */
+  _ElementComparer(this.previousElements);
+
+  /**
+   * Expect that no differences were found, causing the test to fail if that
+   * wasn't the case.
+   */
+  void expectNoDifferences() {
+    if (overwrittenCount > 0) {
+      fail('Found $overwrittenCount overwritten elements.$buffer');
+    }
+  }
+
+  @override
+  void visitElement(Element element) {
+    Element previousElement = previousElements[element];
+    if (!identical(previousElement, element)) {
+      if (overwrittenCount == 0) {
+        buffer.writeln();
+      }
+      overwrittenCount++;
+      buffer.writeln('Overwritten element:');
+      Element currentElement = element;
+      while (currentElement != null) {
+        buffer.write('  ');
+        buffer.writeln(currentElement.toString());
+        currentElement = currentElement.enclosingElement;
+      }
+    }
+    super.visitElement(element);
+  }
+}
+
+/**
+ * A visitor that can be used to collect all of the elements in an element
+ * model.
+ */
+class _ElementGatherer extends GeneralizingElementVisitor {
+  /**
+   * The map in which the elements are collected. The value of each key is the
+   * key itself.
+   */
+  Map<Element, Element> elements = new HashMap<Element, Element>();
+
+  /**
+   * Initialize the visitor.
+   */
+  _ElementGatherer();
+
+  @override
+  void visitElement(Element element) {
+    elements[element] = element;
+    super.visitElement(element);
+  }
+}
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 5cf93dd..b67c4a5 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -228,12 +228,6 @@
       _analysisContext = new _SdkAnalysisContext(this);
       SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
       _analysisContext.sourceFactory = factory;
-      ChangeSet changeSet = new ChangeSet();
-      for (String uri in uris) {
-        Source source = factory.forUri(uri);
-        changeSet.addedSource(source);
-      }
-      _analysisContext.applyChanges(changeSet);
     }
     return _analysisContext;
   }
diff --git a/pkg/analyzer/test/src/dart/ast/test_all.dart b/pkg/analyzer/test/src/dart/ast/test_all.dart
new file mode 100644
index 0000000..f0648c4
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/ast/test_all.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.src.dart.ast.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'utilities_test.dart' as utilities;
+
+/// Utility for manually running all tests.
+main() {
+  initializeTestEnvironment();
+  group('ast tests', () {
+    utilities.main();
+  });
+}
diff --git a/pkg/analyzer/test/generated/ast_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
similarity index 63%
rename from pkg/analyzer/test/generated/ast_test.dart
rename to pkg/analyzer/test/src/dart/ast/utilities_test.dart
index bff9b8b..8531637 100644
--- a/pkg/analyzer/test/generated/ast_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -2,9 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.generated.ast_test;
+library analyzer.test.src.dart.ast.utilities_test;
 
-import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/java_engine.dart' show Predicate;
 import 'package:analyzer/src/generated/java_engine.dart';
@@ -13,211 +14,17 @@
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:unittest/unittest.dart';
 
-import '../reflective_tests.dart';
-import '../utils.dart';
-import 'parser_test.dart' show ParserTestCase;
-import 'test_support.dart';
+import '../../../generated/parser_test.dart' show ParserTestCase;
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
 
 main() {
   initializeTestEnvironment();
-  runReflectiveTests(BreadthFirstVisitorTest);
-  runReflectiveTests(ClassDeclarationTest);
-  runReflectiveTests(ClassTypeAliasTest);
   runReflectiveTests(ConstantEvaluatorTest);
-  runReflectiveTests(ConstructorDeclarationTest);
-  runReflectiveTests(FieldFormalParameterTest);
-  runReflectiveTests(IndexExpressionTest);
-  runReflectiveTests(NodeListTest);
   runReflectiveTests(NodeLocatorTest);
   runReflectiveTests(NodeLocator2Test);
-  runReflectiveTests(SimpleIdentifierTest);
-  runReflectiveTests(SimpleStringLiteralTest);
-  runReflectiveTests(StringInterpolationTest);
   runReflectiveTests(ToSourceVisitorTest);
-  runReflectiveTests(VariableDeclarationTest);
-}
-
-class AssignmentKind extends Enum<AssignmentKind> {
-  static const AssignmentKind BINARY = const AssignmentKind('BINARY', 0);
-
-  static const AssignmentKind COMPOUND_LEFT =
-      const AssignmentKind('COMPOUND_LEFT', 1);
-
-  static const AssignmentKind COMPOUND_RIGHT =
-      const AssignmentKind('COMPOUND_RIGHT', 2);
-
-  static const AssignmentKind POSTFIX_INC =
-      const AssignmentKind('POSTFIX_INC', 3);
-
-  static const AssignmentKind PREFIX_DEC =
-      const AssignmentKind('PREFIX_DEC', 4);
-
-  static const AssignmentKind PREFIX_INC =
-      const AssignmentKind('PREFIX_INC', 5);
-
-  static const AssignmentKind PREFIX_NOT =
-      const AssignmentKind('PREFIX_NOT', 6);
-
-  static const AssignmentKind SIMPLE_LEFT =
-      const AssignmentKind('SIMPLE_LEFT', 7);
-
-  static const AssignmentKind SIMPLE_RIGHT =
-      const AssignmentKind('SIMPLE_RIGHT', 8);
-
-  static const AssignmentKind NONE = const AssignmentKind('NONE', 9);
-
-  static const List<AssignmentKind> values = const [
-    BINARY,
-    COMPOUND_LEFT,
-    COMPOUND_RIGHT,
-    POSTFIX_INC,
-    PREFIX_DEC,
-    PREFIX_INC,
-    PREFIX_NOT,
-    SIMPLE_LEFT,
-    SIMPLE_RIGHT,
-    NONE
-  ];
-
-  const AssignmentKind(String name, int ordinal) : super(name, ordinal);
-}
-
-class BreadthFirstVisitor_BreadthFirstVisitorTest_testIt
-    extends BreadthFirstVisitor<Object> {
-  List<AstNode> nodes;
-
-  BreadthFirstVisitor_BreadthFirstVisitorTest_testIt(this.nodes) : super();
-
-  @override
-  Object visitNode(AstNode node) {
-    nodes.add(node);
-    return super.visitNode(node);
-  }
-}
-
-@reflectiveTest
-class BreadthFirstVisitorTest extends ParserTestCase {
-  void test_it() {
-    String source = r'''
-class A {
-  bool get g => true;
-}
-class B {
-  int f() {
-    num q() {
-      return 3;
-    }
-  return q() + 4;
-  }
-}
-A f(var p) {
-  if ((p as A).g) {
-    return p;
-  } else {
-    return null;
-  }
-}''';
-    CompilationUnit unit = ParserTestCase.parseCompilationUnit(source);
-    List<AstNode> nodes = new List<AstNode>();
-    BreadthFirstVisitor<Object> visitor =
-        new BreadthFirstVisitor_BreadthFirstVisitorTest_testIt(nodes);
-    visitor.visitAllNodes(unit);
-    expect(nodes, hasLength(59));
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is CompilationUnit, CompilationUnit, nodes[0]);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is ClassDeclaration, ClassDeclaration, nodes[2]);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is FunctionDeclaration, FunctionDeclaration, nodes[3]);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is FunctionDeclarationStatement,
-        FunctionDeclarationStatement,
-        nodes[27]);
-    EngineTestCase.assertInstanceOf(
-        (obj) => obj is IntegerLiteral, IntegerLiteral, nodes[58]);
-    //3
-  }
-}
-
-@reflectiveTest
-class ClassDeclarationTest extends ParserTestCase {
-  void test_getConstructor() {
-    List<ConstructorInitializer> initializers =
-        new List<ConstructorInitializer>();
-    ConstructorDeclaration defaultConstructor = AstFactory
-        .constructorDeclaration(AstFactory.identifier3("Test"), null,
-            AstFactory.formalParameterList(), initializers);
-    ConstructorDeclaration aConstructor = AstFactory.constructorDeclaration(
-        AstFactory.identifier3("Test"),
-        "a",
-        AstFactory.formalParameterList(),
-        initializers);
-    ConstructorDeclaration bConstructor = AstFactory.constructorDeclaration(
-        AstFactory.identifier3("Test"),
-        "b",
-        AstFactory.formalParameterList(),
-        initializers);
-    ClassDeclaration clazz = AstFactory.classDeclaration(null, "Test", null,
-        null, null, null, [defaultConstructor, aConstructor, bConstructor]);
-    expect(clazz.getConstructor(null), same(defaultConstructor));
-    expect(clazz.getConstructor("a"), same(aConstructor));
-    expect(clazz.getConstructor("b"), same(bConstructor));
-    expect(clazz.getConstructor("noSuchConstructor"), same(null));
-  }
-
-  void test_getField() {
-    VariableDeclaration aVar = AstFactory.variableDeclaration("a");
-    VariableDeclaration bVar = AstFactory.variableDeclaration("b");
-    VariableDeclaration cVar = AstFactory.variableDeclaration("c");
-    ClassDeclaration clazz =
-        AstFactory.classDeclaration(null, "Test", null, null, null, null, [
-      AstFactory.fieldDeclaration2(false, null, [aVar]),
-      AstFactory.fieldDeclaration2(false, null, [bVar, cVar])
-    ]);
-    expect(clazz.getField("a"), same(aVar));
-    expect(clazz.getField("b"), same(bVar));
-    expect(clazz.getField("c"), same(cVar));
-    expect(clazz.getField("noSuchField"), same(null));
-  }
-
-  void test_getMethod() {
-    MethodDeclaration aMethod = AstFactory.methodDeclaration(null, null, null,
-        null, AstFactory.identifier3("a"), AstFactory.formalParameterList());
-    MethodDeclaration bMethod = AstFactory.methodDeclaration(null, null, null,
-        null, AstFactory.identifier3("b"), AstFactory.formalParameterList());
-    ClassDeclaration clazz = AstFactory.classDeclaration(
-        null, "Test", null, null, null, null, [aMethod, bMethod]);
-    expect(clazz.getMethod("a"), same(aMethod));
-    expect(clazz.getMethod("b"), same(bMethod));
-    expect(clazz.getMethod("noSuchMethod"), same(null));
-  }
-
-  void test_isAbstract() {
-    expect(
-        AstFactory
-            .classDeclaration(null, "A", null, null, null, null)
-            .isAbstract,
-        isFalse);
-    expect(
-        AstFactory
-            .classDeclaration(Keyword.ABSTRACT, "B", null, null, null, null)
-            .isAbstract,
-        isTrue);
-  }
-}
-
-@reflectiveTest
-class ClassTypeAliasTest extends ParserTestCase {
-  void test_isAbstract() {
-    expect(
-        AstFactory.classTypeAlias("A", null, null, null, null, null).isAbstract,
-        isFalse);
-    expect(
-        AstFactory
-            .classTypeAlias("B", null, Keyword.ABSTRACT, null, null, null)
-            .isAbstract,
-        isTrue);
-  }
 }
 
 @reflectiveTest
@@ -525,427 +332,6 @@
 }
 
 @reflectiveTest
-class ConstructorDeclarationTest extends EngineTestCase {
-  void test_firstTokenAfterCommentAndMetadata_all_inverted() {
-    Token externalKeyword = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-    externalKeyword.offset = 14;
-    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
-        Keyword.CONST,
-        Keyword.FACTORY,
-        AstFactory.identifier3('int'),
-        null,
-        null,
-        null,
-        null);
-    declaration.externalKeyword = externalKeyword;
-    declaration.constKeyword.offset = 8;
-    Token factoryKeyword = declaration.factoryKeyword;
-    factoryKeyword.offset = 0;
-    expect(declaration.firstTokenAfterCommentAndMetadata, factoryKeyword);
-  }
-
-  void test_firstTokenAfterCommentAndMetadata_all_normal() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-    token.offset = 0;
-    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
-        Keyword.CONST,
-        Keyword.FACTORY,
-        AstFactory.identifier3('int'),
-        null,
-        null,
-        null,
-        null);
-    declaration.externalKeyword = token;
-    declaration.constKeyword.offset = 9;
-    declaration.factoryKeyword.offset = 15;
-    expect(declaration.firstTokenAfterCommentAndMetadata, token);
-  }
-
-  void test_firstTokenAfterCommentAndMetadata_constOnly() {
-    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
-        Keyword.CONST,
-        null,
-        AstFactory.identifier3('int'),
-        null,
-        null,
-        null,
-        null);
-    expect(declaration.firstTokenAfterCommentAndMetadata,
-        declaration.constKeyword);
-  }
-
-  void test_firstTokenAfterCommentAndMetadata_externalOnly() {
-    Token externalKeyword = TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
-        null, null, AstFactory.identifier3('int'), null, null, null, null);
-    declaration.externalKeyword = externalKeyword;
-    expect(declaration.firstTokenAfterCommentAndMetadata, externalKeyword);
-  }
-
-  void test_firstTokenAfterCommentAndMetadata_factoryOnly() {
-    ConstructorDeclaration declaration = AstFactory.constructorDeclaration2(
-        null,
-        Keyword.FACTORY,
-        AstFactory.identifier3('int'),
-        null,
-        null,
-        null,
-        null);
-    expect(declaration.firstTokenAfterCommentAndMetadata,
-        declaration.factoryKeyword);
-  }
-}
-
-@reflectiveTest
-class FieldFormalParameterTest extends EngineTestCase {
-  void test_endToken_noParameters() {
-    FieldFormalParameter parameter = AstFactory.fieldFormalParameter2('field');
-    expect(parameter.endToken, parameter.identifier.endToken);
-  }
-
-  void test_endToken_parameters() {
-    FieldFormalParameter parameter = AstFactory.fieldFormalParameter(
-        null, null, 'field', AstFactory.formalParameterList([]));
-    expect(parameter.endToken, parameter.parameters.endToken);
-  }
-}
-
-@reflectiveTest
-class IndexExpressionTest extends EngineTestCase {
-  void test_inGetterContext_assignment_compound_left() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // a[b] += c
-    AstFactory.assignmentExpression(
-        expression, TokenType.PLUS_EQ, AstFactory.identifier3("c"));
-    expect(expression.inGetterContext(), isTrue);
-  }
-
-  void test_inGetterContext_assignment_simple_left() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // a[b] = c
-    AstFactory.assignmentExpression(
-        expression, TokenType.EQ, AstFactory.identifier3("c"));
-    expect(expression.inGetterContext(), isFalse);
-  }
-
-  void test_inGetterContext_nonAssignment() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // a[b] + c
-    AstFactory.binaryExpression(
-        expression, TokenType.PLUS, AstFactory.identifier3("c"));
-    expect(expression.inGetterContext(), isTrue);
-  }
-
-  void test_inSetterContext_assignment_compound_left() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // a[b] += c
-    AstFactory.assignmentExpression(
-        expression, TokenType.PLUS_EQ, AstFactory.identifier3("c"));
-    expect(expression.inSetterContext(), isTrue);
-  }
-
-  void test_inSetterContext_assignment_compound_right() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // c += a[b]
-    AstFactory.assignmentExpression(
-        AstFactory.identifier3("c"), TokenType.PLUS_EQ, expression);
-    expect(expression.inSetterContext(), isFalse);
-  }
-
-  void test_inSetterContext_assignment_simple_left() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // a[b] = c
-    AstFactory.assignmentExpression(
-        expression, TokenType.EQ, AstFactory.identifier3("c"));
-    expect(expression.inSetterContext(), isTrue);
-  }
-
-  void test_inSetterContext_assignment_simple_right() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // c = a[b]
-    AstFactory.assignmentExpression(
-        AstFactory.identifier3("c"), TokenType.EQ, expression);
-    expect(expression.inSetterContext(), isFalse);
-  }
-
-  void test_inSetterContext_nonAssignment() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    AstFactory.binaryExpression(
-        expression, TokenType.PLUS, AstFactory.identifier3("c"));
-    // a[b] + cc
-    expect(expression.inSetterContext(), isFalse);
-  }
-
-  void test_inSetterContext_postfix() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    AstFactory.postfixExpression(expression, TokenType.PLUS_PLUS);
-    // a[b]++
-    expect(expression.inSetterContext(), isTrue);
-  }
-
-  void test_inSetterContext_prefix_bang() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // !a[b]
-    AstFactory.prefixExpression(TokenType.BANG, expression);
-    expect(expression.inSetterContext(), isFalse);
-  }
-
-  void test_inSetterContext_prefix_minusMinus() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // --a[b]
-    AstFactory.prefixExpression(TokenType.MINUS_MINUS, expression);
-    expect(expression.inSetterContext(), isTrue);
-  }
-
-  void test_inSetterContext_prefix_plusPlus() {
-    IndexExpression expression = AstFactory.indexExpression(
-        AstFactory.identifier3("a"), AstFactory.identifier3("b"));
-    // ++a[b]
-    AstFactory.prefixExpression(TokenType.PLUS_PLUS, expression);
-    expect(expression.inSetterContext(), isTrue);
-  }
-}
-
-@reflectiveTest
-class NodeListTest extends EngineTestCase {
-  void test_add() {
-    AstNode parent = AstFactory.argumentList();
-    AstNode firstNode = AstFactory.booleanLiteral(true);
-    AstNode secondNode = AstFactory.booleanLiteral(false);
-    NodeList<AstNode> list = new NodeList<AstNode>(parent);
-    list.insert(0, secondNode);
-    list.insert(0, firstNode);
-    expect(list, hasLength(2));
-    expect(list[0], same(firstNode));
-    expect(list[1], same(secondNode));
-    expect(firstNode.parent, same(parent));
-    expect(secondNode.parent, same(parent));
-    AstNode thirdNode = AstFactory.booleanLiteral(false);
-    list.insert(1, thirdNode);
-    expect(list, hasLength(3));
-    expect(list[0], same(firstNode));
-    expect(list[1], same(thirdNode));
-    expect(list[2], same(secondNode));
-    expect(firstNode.parent, same(parent));
-    expect(secondNode.parent, same(parent));
-    expect(thirdNode.parent, same(parent));
-  }
-
-  void test_add_negative() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      list.insert(-1, AstFactory.booleanLiteral(true));
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_add_tooBig() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      list.insert(1, AstFactory.booleanLiteral(true));
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_addAll() {
-    AstNode parent = AstFactory.argumentList();
-    List<AstNode> firstNodes = new List<AstNode>();
-    AstNode firstNode = AstFactory.booleanLiteral(true);
-    AstNode secondNode = AstFactory.booleanLiteral(false);
-    firstNodes.add(firstNode);
-    firstNodes.add(secondNode);
-    NodeList<AstNode> list = new NodeList<AstNode>(parent);
-    list.addAll(firstNodes);
-    expect(list, hasLength(2));
-    expect(list[0], same(firstNode));
-    expect(list[1], same(secondNode));
-    expect(firstNode.parent, same(parent));
-    expect(secondNode.parent, same(parent));
-    List<AstNode> secondNodes = new List<AstNode>();
-    AstNode thirdNode = AstFactory.booleanLiteral(true);
-    AstNode fourthNode = AstFactory.booleanLiteral(false);
-    secondNodes.add(thirdNode);
-    secondNodes.add(fourthNode);
-    list.addAll(secondNodes);
-    expect(list, hasLength(4));
-    expect(list[0], same(firstNode));
-    expect(list[1], same(secondNode));
-    expect(list[2], same(thirdNode));
-    expect(list[3], same(fourthNode));
-    expect(firstNode.parent, same(parent));
-    expect(secondNode.parent, same(parent));
-    expect(thirdNode.parent, same(parent));
-    expect(fourthNode.parent, same(parent));
-  }
-
-  void test_creation() {
-    AstNode owner = AstFactory.argumentList();
-    NodeList<AstNode> list = new NodeList<AstNode>(owner);
-    expect(list, isNotNull);
-    expect(list, hasLength(0));
-    expect(list.owner, same(owner));
-  }
-
-  void test_get_negative() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      list[-1];
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_get_tooBig() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      list[1];
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_getBeginToken_empty() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    expect(list.beginToken, isNull);
-  }
-
-  void test_getBeginToken_nonEmpty() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    AstNode node =
-        AstFactory.parenthesizedExpression(AstFactory.booleanLiteral(true));
-    list.add(node);
-    expect(list.beginToken, same(node.beginToken));
-  }
-
-  void test_getEndToken_empty() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    expect(list.endToken, isNull);
-  }
-
-  void test_getEndToken_nonEmpty() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    AstNode node =
-        AstFactory.parenthesizedExpression(AstFactory.booleanLiteral(true));
-    list.add(node);
-    expect(list.endToken, same(node.endToken));
-  }
-
-  void test_indexOf() {
-    List<AstNode> nodes = new List<AstNode>();
-    AstNode firstNode = AstFactory.booleanLiteral(true);
-    AstNode secondNode = AstFactory.booleanLiteral(false);
-    AstNode thirdNode = AstFactory.booleanLiteral(true);
-    AstNode fourthNode = AstFactory.booleanLiteral(false);
-    nodes.add(firstNode);
-    nodes.add(secondNode);
-    nodes.add(thirdNode);
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    list.addAll(nodes);
-    expect(list, hasLength(3));
-    expect(list.indexOf(firstNode), 0);
-    expect(list.indexOf(secondNode), 1);
-    expect(list.indexOf(thirdNode), 2);
-    expect(list.indexOf(fourthNode), -1);
-    expect(list.indexOf(null), -1);
-  }
-
-  void test_remove() {
-    List<AstNode> nodes = new List<AstNode>();
-    AstNode firstNode = AstFactory.booleanLiteral(true);
-    AstNode secondNode = AstFactory.booleanLiteral(false);
-    AstNode thirdNode = AstFactory.booleanLiteral(true);
-    nodes.add(firstNode);
-    nodes.add(secondNode);
-    nodes.add(thirdNode);
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    list.addAll(nodes);
-    expect(list, hasLength(3));
-    expect(list.removeAt(1), same(secondNode));
-    expect(list, hasLength(2));
-    expect(list[0], same(firstNode));
-    expect(list[1], same(thirdNode));
-  }
-
-  void test_remove_negative() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      list.removeAt(-1);
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_remove_tooBig() {
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      list.removeAt(1);
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_set() {
-    List<AstNode> nodes = new List<AstNode>();
-    AstNode firstNode = AstFactory.booleanLiteral(true);
-    AstNode secondNode = AstFactory.booleanLiteral(false);
-    AstNode thirdNode = AstFactory.booleanLiteral(true);
-    nodes.add(firstNode);
-    nodes.add(secondNode);
-    nodes.add(thirdNode);
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    list.addAll(nodes);
-    expect(list, hasLength(3));
-    AstNode fourthNode = AstFactory.integer(0);
-    expect(javaListSet(list, 1, fourthNode), same(secondNode));
-    expect(list, hasLength(3));
-    expect(list[0], same(firstNode));
-    expect(list[1], same(fourthNode));
-    expect(list[2], same(thirdNode));
-  }
-
-  void test_set_negative() {
-    AstNode node = AstFactory.booleanLiteral(true);
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      javaListSet(list, -1, node);
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-
-  void test_set_tooBig() {
-    AstNode node = AstFactory.booleanLiteral(true);
-    NodeList<AstNode> list = new NodeList<AstNode>(AstFactory.argumentList());
-    try {
-      javaListSet(list, 1, node);
-      fail("Expected IndexOutOfBoundsException");
-    } on RangeError {
-      // Expected
-    }
-  }
-}
-
-@reflectiveTest
 class NodeLocator2Test extends ParserTestCase {
   void test_onlyStartOffset() {
     String code = ' int vv; ';
@@ -1042,659 +428,6 @@
 }
 
 @reflectiveTest
-class SimpleIdentifierTest extends ParserTestCase {
-  void test_inDeclarationContext_catch_exception() {
-    SimpleIdentifier identifier =
-        AstFactory.catchClause("e").exceptionParameter;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_catch_stack() {
-    SimpleIdentifier identifier =
-        AstFactory.catchClause2("e", "s").stackTraceParameter;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_classDeclaration() {
-    SimpleIdentifier identifier =
-        AstFactory.classDeclaration(null, "C", null, null, null, null).name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_classTypeAlias() {
-    SimpleIdentifier identifier =
-        AstFactory.classTypeAlias("C", null, null, null, null, null).name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_constructorDeclaration() {
-    SimpleIdentifier identifier = AstFactory
-        .constructorDeclaration(AstFactory.identifier3("C"), "c", null, null)
-        .name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_declaredIdentifier() {
-    DeclaredIdentifier declaredIdentifier = AstFactory.declaredIdentifier3("v");
-    SimpleIdentifier identifier = declaredIdentifier.identifier;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_enumConstantDeclaration() {
-    EnumDeclaration enumDeclaration =
-        AstFactory.enumDeclaration2('MyEnum', ['CONST']);
-    SimpleIdentifier identifier = enumDeclaration.constants[0].name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_enumDeclaration() {
-    EnumDeclaration enumDeclaration =
-        AstFactory.enumDeclaration2('MyEnum', ['A', 'B', 'C']);
-    SimpleIdentifier identifier = enumDeclaration.name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_fieldFormalParameter() {
-    SimpleIdentifier identifier =
-        AstFactory.fieldFormalParameter2("p").identifier;
-    expect(identifier.inDeclarationContext(), isFalse);
-  }
-
-  void test_inDeclarationContext_functionDeclaration() {
-    SimpleIdentifier identifier =
-        AstFactory.functionDeclaration(null, null, "f", null).name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_functionTypeAlias() {
-    SimpleIdentifier identifier =
-        AstFactory.typeAlias(null, "F", null, null).name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_label_false() {
-    SimpleIdentifier identifier =
-        AstFactory.namedExpression2("l", AstFactory.integer(0)).name.label;
-    expect(identifier.inDeclarationContext(), isFalse);
-  }
-
-  void test_inDeclarationContext_label_true() {
-    Label label = AstFactory.label2("l");
-    SimpleIdentifier identifier = label.label;
-    AstFactory.labeledStatement([label], AstFactory.emptyStatement());
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_methodDeclaration() {
-    SimpleIdentifier identifier = AstFactory.identifier3("m");
-    AstFactory.methodDeclaration2(
-        null, null, null, null, identifier, null, null);
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_prefix() {
-    SimpleIdentifier identifier =
-        AstFactory.importDirective3("uri", "pref").prefix;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_simpleFormalParameter() {
-    SimpleIdentifier identifier =
-        AstFactory.simpleFormalParameter3("p").identifier;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_typeParameter_bound() {
-    TypeName bound = AstFactory.typeName4("A");
-    SimpleIdentifier identifier = bound.name as SimpleIdentifier;
-    AstFactory.typeParameter2("E", bound);
-    expect(identifier.inDeclarationContext(), isFalse);
-  }
-
-  void test_inDeclarationContext_typeParameter_name() {
-    SimpleIdentifier identifier = AstFactory.typeParameter("E").name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inDeclarationContext_variableDeclaration() {
-    SimpleIdentifier identifier = AstFactory.variableDeclaration("v").name;
-    expect(identifier.inDeclarationContext(), isTrue);
-  }
-
-  void test_inGetterContext() {
-    for (WrapperKind wrapper in WrapperKind.values) {
-      for (AssignmentKind assignment in AssignmentKind.values) {
-        SimpleIdentifier identifier = _createIdentifier(wrapper, assignment);
-        if (assignment == AssignmentKind.SIMPLE_LEFT &&
-            wrapper != WrapperKind.PREFIXED_LEFT &&
-            wrapper != WrapperKind.PROPERTY_LEFT) {
-          if (identifier.inGetterContext()) {
-            fail("Expected ${_topMostNode(identifier).toSource()} to be false");
-          }
-        } else {
-          if (!identifier.inGetterContext()) {
-            fail("Expected ${_topMostNode(identifier).toSource()} to be true");
-          }
-        }
-      }
-    }
-  }
-
-  void test_inGetterContext_forEachLoop() {
-    SimpleIdentifier identifier = AstFactory.identifier3("a");
-    Expression iterator = AstFactory.listLiteral();
-    Statement body = AstFactory.block();
-    AstFactory.forEachStatement2(identifier, iterator, body);
-    expect(identifier.inGetterContext(), isFalse);
-  }
-
-  void test_inReferenceContext() {
-    SimpleIdentifier identifier = AstFactory.identifier3("id");
-    AstFactory.namedExpression(
-        AstFactory.label(identifier), AstFactory.identifier3("_"));
-    expect(identifier.inGetterContext(), isFalse);
-    expect(identifier.inSetterContext(), isFalse);
-  }
-
-  void test_inSetterContext() {
-    for (WrapperKind wrapper in WrapperKind.values) {
-      for (AssignmentKind assignment in AssignmentKind.values) {
-        SimpleIdentifier identifier = _createIdentifier(wrapper, assignment);
-        if (wrapper == WrapperKind.PREFIXED_LEFT ||
-            wrapper == WrapperKind.PROPERTY_LEFT ||
-            assignment == AssignmentKind.BINARY ||
-            assignment == AssignmentKind.COMPOUND_RIGHT ||
-            assignment == AssignmentKind.PREFIX_NOT ||
-            assignment == AssignmentKind.SIMPLE_RIGHT ||
-            assignment == AssignmentKind.NONE) {
-          if (identifier.inSetterContext()) {
-            fail("Expected ${_topMostNode(identifier).toSource()} to be false");
-          }
-        } else {
-          if (!identifier.inSetterContext()) {
-            fail("Expected ${_topMostNode(identifier).toSource()} to be true");
-          }
-        }
-      }
-    }
-  }
-
-  void test_inSetterContext_forEachLoop() {
-    SimpleIdentifier identifier = AstFactory.identifier3("a");
-    Expression iterator = AstFactory.listLiteral();
-    Statement body = AstFactory.block();
-    AstFactory.forEachStatement2(identifier, iterator, body);
-    expect(identifier.inSetterContext(), isTrue);
-  }
-
-  void test_isQualified_inMethodInvocation_noTarget() {
-    MethodInvocation invocation =
-        AstFactory.methodInvocation2("test", [AstFactory.identifier3("arg0")]);
-    SimpleIdentifier identifier = invocation.methodName;
-    expect(identifier.isQualified, isFalse);
-  }
-
-  void test_isQualified_inMethodInvocation_withTarget() {
-    MethodInvocation invocation = AstFactory.methodInvocation(
-        AstFactory.identifier3("target"),
-        "test",
-        [AstFactory.identifier3("arg0")]);
-    SimpleIdentifier identifier = invocation.methodName;
-    expect(identifier.isQualified, isTrue);
-  }
-
-  void test_isQualified_inPrefixedIdentifier_name() {
-    SimpleIdentifier identifier = AstFactory.identifier3("test");
-    AstFactory.identifier4("prefix", identifier);
-    expect(identifier.isQualified, isTrue);
-  }
-
-  void test_isQualified_inPrefixedIdentifier_prefix() {
-    SimpleIdentifier identifier = AstFactory.identifier3("test");
-    AstFactory.identifier(identifier, AstFactory.identifier3("name"));
-    expect(identifier.isQualified, isFalse);
-  }
-
-  void test_isQualified_inPropertyAccess_name() {
-    SimpleIdentifier identifier = AstFactory.identifier3("test");
-    AstFactory.propertyAccess(AstFactory.identifier3("target"), identifier);
-    expect(identifier.isQualified, isTrue);
-  }
-
-  void test_isQualified_inPropertyAccess_target() {
-    SimpleIdentifier identifier = AstFactory.identifier3("test");
-    AstFactory.propertyAccess(identifier, AstFactory.identifier3("name"));
-    expect(identifier.isQualified, isFalse);
-  }
-
-  void test_isQualified_inReturnStatement() {
-    SimpleIdentifier identifier = AstFactory.identifier3("test");
-    AstFactory.returnStatement2(identifier);
-    expect(identifier.isQualified, isFalse);
-  }
-
-  SimpleIdentifier _createIdentifier(
-      WrapperKind wrapper, AssignmentKind assignment) {
-    SimpleIdentifier identifier = AstFactory.identifier3("a");
-    Expression expression = identifier;
-    while (true) {
-      if (wrapper == WrapperKind.PREFIXED_LEFT) {
-        expression =
-            AstFactory.identifier(identifier, AstFactory.identifier3("_"));
-      } else if (wrapper == WrapperKind.PREFIXED_RIGHT) {
-        expression =
-            AstFactory.identifier(AstFactory.identifier3("_"), identifier);
-      } else if (wrapper == WrapperKind.PROPERTY_LEFT) {
-        expression = AstFactory.propertyAccess2(expression, "_");
-      } else if (wrapper == WrapperKind.PROPERTY_RIGHT) {
-        expression =
-            AstFactory.propertyAccess(AstFactory.identifier3("_"), identifier);
-      } else if (wrapper == WrapperKind.NONE) {}
-      break;
-    }
-    while (true) {
-      if (assignment == AssignmentKind.BINARY) {
-        AstFactory.binaryExpression(
-            expression, TokenType.PLUS, AstFactory.identifier3("_"));
-      } else if (assignment == AssignmentKind.COMPOUND_LEFT) {
-        AstFactory.assignmentExpression(
-            expression, TokenType.PLUS_EQ, AstFactory.identifier3("_"));
-      } else if (assignment == AssignmentKind.COMPOUND_RIGHT) {
-        AstFactory.assignmentExpression(
-            AstFactory.identifier3("_"), TokenType.PLUS_EQ, expression);
-      } else if (assignment == AssignmentKind.POSTFIX_INC) {
-        AstFactory.postfixExpression(expression, TokenType.PLUS_PLUS);
-      } else if (assignment == AssignmentKind.PREFIX_DEC) {
-        AstFactory.prefixExpression(TokenType.MINUS_MINUS, expression);
-      } else if (assignment == AssignmentKind.PREFIX_INC) {
-        AstFactory.prefixExpression(TokenType.PLUS_PLUS, expression);
-      } else if (assignment == AssignmentKind.PREFIX_NOT) {
-        AstFactory.prefixExpression(TokenType.BANG, expression);
-      } else if (assignment == AssignmentKind.SIMPLE_LEFT) {
-        AstFactory.assignmentExpression(
-            expression, TokenType.EQ, AstFactory.identifier3("_"));
-      } else if (assignment == AssignmentKind.SIMPLE_RIGHT) {
-        AstFactory.assignmentExpression(
-            AstFactory.identifier3("_"), TokenType.EQ, expression);
-      } else if (assignment == AssignmentKind.NONE) {}
-      break;
-    }
-    return identifier;
-  }
-
-  /**
-   * Return the top-most node in the AST structure containing the given identifier.
-   *
-   * @param identifier the identifier in the AST structure being traversed
-   * @return the root of the AST structure containing the identifier
-   */
-  AstNode _topMostNode(SimpleIdentifier identifier) {
-    AstNode child = identifier;
-    AstNode parent = identifier.parent;
-    while (parent != null) {
-      child = parent;
-      parent = parent.parent;
-    }
-    return child;
-  }
-}
-
-@reflectiveTest
-class SimpleStringLiteralTest extends ParserTestCase {
-  void test_contentsEnd() {
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X")
-            .contentsEnd,
-        2);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString('"X"'), "X")
-            .contentsEnd,
-        2);
-
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString('"""X"""'), "X")
-            .contentsEnd,
-        4);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
-            .contentsEnd,
-        4);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("'''  \nX'''"), "X").contentsEnd,
-        7);
-
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
-            .contentsEnd,
-        3);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString('r"X"'), "X")
-            .contentsEnd,
-        3);
-
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString('r"""X"""'), "X")
-            .contentsEnd,
-        5);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
-            .contentsEnd,
-        5);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("r'''  \nX'''"), "X").contentsEnd,
-        8);
-  }
-
-  void test_contentsOffset() {
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X")
-            .contentsOffset,
-        1);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("\"X\""), "X")
-            .contentsOffset,
-        1);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X").contentsOffset,
-        3);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
-            .contentsOffset,
-        3);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
-            .contentsOffset,
-        2);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r\"X\""), "X")
-            .contentsOffset,
-        2);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X").contentsOffset,
-        4);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
-            .contentsOffset,
-        4);
-    // leading whitespace
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("''' \ \nX''"), "X").contentsOffset,
-        6);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString('r""" \ \nX"""'), "X").contentsOffset,
-        7);
-  }
-
-  void test_isMultiline() {
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X")
-            .isMultiline,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
-            .isMultiline,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("\"X\""), "X")
-            .isMultiline,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r\"X\""), "X")
-            .isMultiline,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
-            .isMultiline,
-        isTrue);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
-            .isMultiline,
-        isTrue);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X").isMultiline,
-        isTrue);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X").isMultiline,
-        isTrue);
-  }
-
-  void test_isRaw() {
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'X'"), "X").isRaw,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("\"X\""), "X")
-            .isRaw,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("\"\"\"X\"\"\""), "X").isRaw,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("'''X'''"), "X")
-            .isRaw,
-        isFalse);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'X'"), "X")
-            .isRaw,
-        isTrue);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r\"X\""), "X")
-            .isRaw,
-        isTrue);
-    expect(
-        new SimpleStringLiteral(
-            TokenFactory.tokenFromString("r\"\"\"X\"\"\""), "X").isRaw,
-        isTrue);
-    expect(
-        new SimpleStringLiteral(TokenFactory.tokenFromString("r'''X'''"), "X")
-            .isRaw,
-        isTrue);
-  }
-
-  void test_isSingleQuoted() {
-    // '
-    {
-      var token = TokenFactory.tokenFromString("'X'");
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isTrue);
-    }
-    // '''
-    {
-      var token = TokenFactory.tokenFromString("'''X'''");
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isTrue);
-    }
-    // "
-    {
-      var token = TokenFactory.tokenFromString('"X"');
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isFalse);
-    }
-    // """
-    {
-      var token = TokenFactory.tokenFromString('"""X"""');
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isFalse);
-    }
-  }
-
-  void test_isSingleQuoted_raw() {
-    // r'
-    {
-      var token = TokenFactory.tokenFromString("r'X'");
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isTrue);
-    }
-    // r'''
-    {
-      var token = TokenFactory.tokenFromString("r'''X'''");
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isTrue);
-    }
-    // r"
-    {
-      var token = TokenFactory.tokenFromString('r"X"');
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isFalse);
-    }
-    // r"""
-    {
-      var token = TokenFactory.tokenFromString('r"""X"""');
-      var node = new SimpleStringLiteral(token, null);
-      expect(node.isSingleQuoted, isFalse);
-    }
-  }
-
-  void test_simple() {
-    Token token = TokenFactory.tokenFromString("'value'");
-    SimpleStringLiteral stringLiteral = new SimpleStringLiteral(token, "value");
-    expect(stringLiteral.literal, same(token));
-    expect(stringLiteral.beginToken, same(token));
-    expect(stringLiteral.endToken, same(token));
-    expect(stringLiteral.value, "value");
-  }
-}
-
-@reflectiveTest
-class StringInterpolationTest extends ParserTestCase {
-  void test_contentsOffsetEnd() {
-    AstFactory.interpolationExpression(AstFactory.identifier3('bb'));
-    // 'a${bb}ccc'
-    {
-      var ae = AstFactory.interpolationString("'a", "a");
-      var cToken = new StringToken(TokenType.STRING, "ccc'", 10);
-      var cElement = new InterpolationString(cToken, 'ccc');
-      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
-      expect(node.contentsOffset, 1);
-      expect(node.contentsEnd, 10 + 4 - 1);
-    }
-    // '''a${bb}ccc'''
-    {
-      var ae = AstFactory.interpolationString("'''a", "a");
-      var cToken = new StringToken(TokenType.STRING, "ccc'''", 10);
-      var cElement = new InterpolationString(cToken, 'ccc');
-      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
-      expect(node.contentsOffset, 3);
-      expect(node.contentsEnd, 10 + 4 - 1);
-    }
-    // """a${bb}ccc"""
-    {
-      var ae = AstFactory.interpolationString('"""a', "a");
-      var cToken = new StringToken(TokenType.STRING, 'ccc"""', 10);
-      var cElement = new InterpolationString(cToken, 'ccc');
-      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
-      expect(node.contentsOffset, 3);
-      expect(node.contentsEnd, 10 + 4 - 1);
-    }
-    // r'a${bb}ccc'
-    {
-      var ae = AstFactory.interpolationString("r'a", "a");
-      var cToken = new StringToken(TokenType.STRING, "ccc'", 10);
-      var cElement = new InterpolationString(cToken, 'ccc');
-      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
-      expect(node.contentsOffset, 2);
-      expect(node.contentsEnd, 10 + 4 - 1);
-    }
-    // r'''a${bb}ccc'''
-    {
-      var ae = AstFactory.interpolationString("r'''a", "a");
-      var cToken = new StringToken(TokenType.STRING, "ccc'''", 10);
-      var cElement = new InterpolationString(cToken, 'ccc');
-      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
-      expect(node.contentsOffset, 4);
-      expect(node.contentsEnd, 10 + 4 - 1);
-    }
-    // r"""a${bb}ccc"""
-    {
-      var ae = AstFactory.interpolationString('r"""a', "a");
-      var cToken = new StringToken(TokenType.STRING, 'ccc"""', 10);
-      var cElement = new InterpolationString(cToken, 'ccc');
-      StringInterpolation node = AstFactory.string([ae, ae, cElement]);
-      expect(node.contentsOffset, 4);
-      expect(node.contentsEnd, 10 + 4 - 1);
-    }
-  }
-
-  void test_isMultiline() {
-    var b = AstFactory.interpolationExpression(AstFactory.identifier3('bb'));
-    // '
-    {
-      var a = AstFactory.interpolationString("'a", "a");
-      var c = AstFactory.interpolationString("ccc'", "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isMultiline, isFalse);
-    }
-    // '''
-    {
-      var a = AstFactory.interpolationString("'''a", "a");
-      var c = AstFactory.interpolationString("ccc'''", "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isMultiline, isTrue);
-    }
-    // "
-    {
-      var a = AstFactory.interpolationString('"a', "a");
-      var c = AstFactory.interpolationString('ccc"', "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isMultiline, isFalse);
-    }
-    // """
-    {
-      var a = AstFactory.interpolationString('"""a', "a");
-      var c = AstFactory.interpolationString('ccc"""', "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isMultiline, isTrue);
-    }
-  }
-
-  void test_isRaw() {
-    StringInterpolation node = AstFactory.string();
-    expect(node.isRaw, isFalse);
-  }
-
-  void test_isSingleQuoted() {
-    var b = AstFactory.interpolationExpression(AstFactory.identifier3('bb'));
-    // "
-    {
-      var a = AstFactory.interpolationString('"a', "a");
-      var c = AstFactory.interpolationString('ccc"', "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isSingleQuoted, isFalse);
-    }
-    // """
-    {
-      var a = AstFactory.interpolationString('"""a', "a");
-      var c = AstFactory.interpolationString('ccc"""', "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isSingleQuoted, isFalse);
-    }
-    // '
-    {
-      var a = AstFactory.interpolationString("'a", "a");
-      var c = AstFactory.interpolationString("ccc'", "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isSingleQuoted, isTrue);
-    }
-    // '''
-    {
-      var a = AstFactory.interpolationString("'''a", "a");
-      var c = AstFactory.interpolationString("ccc'''", "ccc");
-      StringInterpolation node = AstFactory.string([a, b, c]);
-      expect(node.isSingleQuoted, isTrue);
-    }
-  }
-}
-
-@reflectiveTest
 class ToSourceVisitorTest extends EngineTestCase {
   void test_visitAdjacentStrings() {
     _assertSource(
@@ -3648,8 +2381,8 @@
   void test_visitSwitchCase_noLabels() {
     _assertSource(
         "case a: {}",
-        AstFactory.switchCase(
-            AstFactory.identifier3("a"), [AstFactory.block()]));
+        AstFactory
+            .switchCase(AstFactory.identifier3("a"), [AstFactory.block()]));
   }
 
   void test_visitSwitchCase_singleLabel() {
@@ -3680,8 +2413,8 @@
   void test_visitSwitchDefault_singleLabel() {
     _assertSource(
         "l1: default: {}",
-        AstFactory.switchDefault(
-            [AstFactory.label2("l1")], [AstFactory.block()]));
+        AstFactory
+            .switchDefault([AstFactory.label2("l1")], [AstFactory.block()]));
   }
 
   void test_visitSwitchStatement() {
@@ -3932,50 +2665,3 @@
     expect(writer.toString(), expectedSource);
   }
 }
-
-@reflectiveTest
-class VariableDeclarationTest extends ParserTestCase {
-  void test_getDocumentationComment_onGrandParent() {
-    VariableDeclaration varDecl = AstFactory.variableDeclaration("a");
-    TopLevelVariableDeclaration decl =
-        AstFactory.topLevelVariableDeclaration2(Keyword.VAR, [varDecl]);
-    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
-    expect(varDecl.documentationComment, isNull);
-    decl.documentationComment = comment;
-    expect(varDecl.documentationComment, isNotNull);
-    expect(decl.documentationComment, isNotNull);
-  }
-
-  void test_getDocumentationComment_onNode() {
-    VariableDeclaration decl = AstFactory.variableDeclaration("a");
-    Comment comment = Comment.createDocumentationComment(new List<Token>(0));
-    decl.documentationComment = comment;
-    expect(decl.documentationComment, isNotNull);
-  }
-}
-
-class WrapperKind extends Enum<WrapperKind> {
-  static const WrapperKind PREFIXED_LEFT =
-      const WrapperKind('PREFIXED_LEFT', 0);
-
-  static const WrapperKind PREFIXED_RIGHT =
-      const WrapperKind('PREFIXED_RIGHT', 1);
-
-  static const WrapperKind PROPERTY_LEFT =
-      const WrapperKind('PROPERTY_LEFT', 2);
-
-  static const WrapperKind PROPERTY_RIGHT =
-      const WrapperKind('PROPERTY_RIGHT', 3);
-
-  static const WrapperKind NONE = const WrapperKind('NONE', 4);
-
-  static const List<WrapperKind> values = const [
-    PREFIXED_LEFT,
-    PREFIXED_RIGHT,
-    PROPERTY_LEFT,
-    PROPERTY_RIGHT,
-    NONE
-  ];
-
-  const WrapperKind(String name, int ordinal) : super(name, ordinal);
-}
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index bf01506..3f0aa84 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.generated.element_test;
+library analyzer.test.src.dart.element.element_test;
 
+import 'package:analyzer/dart/ast/ast.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/ast.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/java_core.dart';
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index c401919..1997466 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.generated.test_all;
+library analyzer.test.src.dart.element.test_all;
 
 import 'package:unittest/unittest.dart';
 
diff --git a/pkg/analyzer/test/src/dart/test_all.dart b/pkg/analyzer/test/src/dart/test_all.dart
index f0c4598..ec4f182 100644
--- a/pkg/analyzer/test/src/dart/test_all.dart
+++ b/pkg/analyzer/test/src/dart/test_all.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library analyzer.test.generated.test_all;
+library analyzer.test.src.dart.test_all;
 
 import 'package:unittest/unittest.dart';
 
diff --git a/pkg/analyzer/test/src/mock_sdk.dart b/pkg/analyzer/test/src/mock_sdk.dart
index b08e293..bfef108 100644
--- a/pkg/analyzer/test/src/mock_sdk.dart
+++ b/pkg/analyzer/test/src/mock_sdk.dart
@@ -184,6 +184,10 @@
     LIB_HTML,
   ];
 
+  static const List<SdkLibrary> LIBRARIES_NO_ASYNC = const [
+    LIB_CORE,
+  ];
+
   final resource.MemoryResourceProvider provider =
       new resource.MemoryResourceProvider();
 
@@ -192,8 +196,9 @@
    */
   InternalAnalysisContext _analysisContext;
 
-  MockSdk() {
-    LIBRARIES.forEach((_MockSdkLibrary library) {
+  MockSdk({bool dartAsync: true}) {
+    List<SdkLibrary> libraries = dartAsync ? LIBRARIES : LIBRARIES_NO_ASYNC;
+    libraries.forEach((_MockSdkLibrary library) {
       provider.newFile(library.path, library.content);
     });
   }
@@ -204,12 +209,6 @@
       _analysisContext = new SdkAnalysisContext();
       SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
       _analysisContext.sourceFactory = factory;
-      ChangeSet changeSet = new ChangeSet();
-      for (String uri in uris) {
-        Source source = factory.forUri(uri);
-        changeSet.addedSource(source);
-      }
-      _analysisContext.applyChanges(changeSet);
     }
     return _analysisContext;
   }
diff --git a/pkg/analyzer/test/src/summary/flat_buffers_test.dart b/pkg/analyzer/test/src/summary/flat_buffers_test.dart
index e7b7804..7ceed57 100644
--- a/pkg/analyzer/test/src/summary/flat_buffers_test.dart
+++ b/pkg/analyzer/test/src/summary/flat_buffers_test.dart
@@ -97,6 +97,7 @@
       builder.addInt32(2, 20);
       builder.addOffset(3, stringOffset);
       builder.addInt32(4, 40);
+      builder.addUint32(5, 0x9ABCDEF0);
       Offset offset = builder.endTable();
       byteList = builder.finish(offset);
     }
@@ -107,6 +108,23 @@
     expect(const Int32Reader().vTableGet(object, 2), 20);
     expect(const StringReader().vTableGet(object, 3), '12345');
     expect(const Int32Reader().vTableGet(object, 4), 40);
+    expect(const Uint32Reader().vTableGet(object, 5), 0x9ABCDEF0);
+  }
+
+  void test_writeList_ofFloat64() {
+    List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
+    // write
+    List<int> byteList;
+    {
+      Builder builder = new Builder(initialSize: 0);
+      Offset offset = builder.writeListFloat64(values);
+      byteList = builder.finish(offset);
+    }
+    // read and verify
+    BufferPointer root = new BufferPointer.fromBytes(byteList);
+    List<double> items = const Float64ListReader().read(root);
+    expect(items, hasLength(5));
+    expect(items, orderedEquals(values));
   }
 
   void test_writeList_ofInt32() {
@@ -195,6 +213,20 @@
     expect(items, contains('12345'));
     expect(items, contains('ABC'));
   }
+
+  void test_writeList_ofUint32() {
+    List<int> byteList;
+    {
+      Builder builder = new Builder(initialSize: 0);
+      Offset offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
+      byteList = builder.finish(offset);
+    }
+    // read and verify
+    BufferPointer root = new BufferPointer.fromBytes(byteList);
+    List<int> items = const ListReader<int>(const Uint32Reader()).read(root);
+    expect(items, hasLength(3));
+    expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
+  }
 }
 
 class StringListWrapperImpl {
diff --git a/pkg/analyzer/test/src/summary/name_filter_test.dart b/pkg/analyzer/test/src/summary/name_filter_test.dart
index a3c9ae5..5f5ca4f 100644
--- a/pkg/analyzer/test/src/summary/name_filter_test.dart
+++ b/pkg/analyzer/test/src/summary/name_filter_test.dart
@@ -14,28 +14,11 @@
   runReflectiveTests(NameFilterTest);
 }
 
-class MockUnlinkedCombinator implements UnlinkedCombinator {
-  @override
-  final List<String> hides;
-
-  @override
-  final List<String> shows;
-
-  MockUnlinkedCombinator(
-      {this.hides: const <String>[], this.shows: const <String>[]});
-
-  @override
-  Map<String, Object> toMap() {
-    fail('toMap() called unexpectedly');
-    return null;
-  }
-}
-
 @reflectiveTest
 class NameFilterTest {
   test_accepts_accessors_hide() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(hides: ['bar']));
+        new UnlinkedCombinatorBuilder(hides: ['bar']));
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('foo='), isTrue);
     expect(filter.accepts('bar'), isFalse);
@@ -44,7 +27,7 @@
 
   test_accepts_accessors_show() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(shows: ['foo']));
+        new UnlinkedCombinatorBuilder(shows: ['foo']));
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('foo='), isTrue);
     expect(filter.accepts('bar'), isFalse);
@@ -88,7 +71,7 @@
 
   test_forUnlinkedCombinator_hide() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(hides: ['foo', 'bar']));
+        new UnlinkedCombinatorBuilder(hides: ['foo', 'bar']));
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isFalse);
     expect(filter.accepts('baz'), isTrue);
@@ -99,7 +82,7 @@
 
   test_forUnlinkedCombinator_show() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(shows: ['foo', 'bar']));
+        new UnlinkedCombinatorBuilder(shows: ['foo', 'bar']));
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('bar'), isTrue);
     expect(filter.accepts('baz'), isFalse);
@@ -110,8 +93,8 @@
 
   test_forUnlinkedCombinators() {
     NameFilter filter = new NameFilter.forUnlinkedCombinators([
-      new MockUnlinkedCombinator(hides: ['foo']),
-      new MockUnlinkedCombinator(hides: ['bar'])
+      new UnlinkedCombinatorBuilder(hides: ['foo']),
+      new UnlinkedCombinatorBuilder(hides: ['bar'])
     ]);
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isFalse);
@@ -130,9 +113,9 @@
 
   test_merge_hides_hides() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(hides: ['foo'])).merge(
+        new UnlinkedCombinatorBuilder(hides: ['foo'])).merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(hides: ['bar'])));
+            new UnlinkedCombinatorBuilder(hides: ['bar'])));
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isFalse);
     expect(filter.accepts('baz'), isTrue);
@@ -143,7 +126,7 @@
 
   test_merge_hides_identity() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(hides: ['foo', 'bar']))
+            new UnlinkedCombinatorBuilder(hides: ['foo', 'bar']))
         .merge(NameFilter.identity);
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isFalse);
@@ -155,9 +138,9 @@
 
   test_merge_hides_shows() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(hides: ['bar', 'baz'])).merge(
+        new UnlinkedCombinatorBuilder(hides: ['bar', 'baz'])).merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(shows: ['foo', 'bar'])));
+            new UnlinkedCombinatorBuilder(shows: ['foo', 'bar'])));
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('bar'), isFalse);
     expect(filter.accepts('baz'), isFalse);
@@ -169,7 +152,7 @@
   test_merge_identity_hides() {
     NameFilter filter = NameFilter.identity.merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(hides: ['foo', 'bar'])));
+            new UnlinkedCombinatorBuilder(hides: ['foo', 'bar'])));
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isFalse);
     expect(filter.accepts('baz'), isTrue);
@@ -189,7 +172,7 @@
   test_merge_identity_shows() {
     NameFilter filter = NameFilter.identity.merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(shows: ['foo', 'bar'])));
+            new UnlinkedCombinatorBuilder(shows: ['foo', 'bar'])));
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('bar'), isTrue);
     expect(filter.accepts('baz'), isFalse);
@@ -200,9 +183,9 @@
 
   test_merge_shows_hides() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(shows: ['foo', 'bar'])).merge(
+        new UnlinkedCombinatorBuilder(shows: ['foo', 'bar'])).merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(hides: ['bar', 'baz'])));
+            new UnlinkedCombinatorBuilder(hides: ['bar', 'baz'])));
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('bar'), isFalse);
     expect(filter.accepts('baz'), isFalse);
@@ -213,7 +196,7 @@
 
   test_merge_shows_identity() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(shows: ['foo', 'bar']))
+            new UnlinkedCombinatorBuilder(shows: ['foo', 'bar']))
         .merge(NameFilter.identity);
     expect(filter.accepts('foo'), isTrue);
     expect(filter.accepts('bar'), isTrue);
@@ -225,9 +208,9 @@
 
   test_merge_shows_shows() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(shows: ['foo', 'bar'])).merge(
+        new UnlinkedCombinatorBuilder(shows: ['foo', 'bar'])).merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(shows: ['bar', 'baz'])));
+            new UnlinkedCombinatorBuilder(shows: ['bar', 'baz'])));
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isTrue);
     expect(filter.accepts('baz'), isFalse);
@@ -238,9 +221,9 @@
 
   test_merge_shows_shows_emptyResult() {
     NameFilter filter = new NameFilter.forUnlinkedCombinator(
-        new MockUnlinkedCombinator(shows: ['foo'])).merge(
+        new UnlinkedCombinatorBuilder(shows: ['foo'])).merge(
         new NameFilter.forUnlinkedCombinator(
-            new MockUnlinkedCombinator(shows: ['bar'])));
+            new UnlinkedCombinatorBuilder(shows: ['bar'])));
     expect(filter.accepts('foo'), isFalse);
     expect(filter.accepts('bar'), isFalse);
     expect(filter.accepts('baz'), isFalse);
diff --git a/pkg/analyzer/test/src/summary/prelinker_test.dart b/pkg/analyzer/test/src/summary/prelinker_test.dart
new file mode 100644
index 0000000..39e43bd
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/prelinker_test.dart
@@ -0,0 +1,92 @@
+// 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 analyzer.test.src.summary.prelinker_test;
+
+import 'package:analyzer/dart/element/element.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/prelink.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import 'summarize_elements_test.dart';
+import 'summary_common.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(PrelinkerTest);
+}
+
+/**
+ * Override of [SummaryTest] which verifies the correctness of the prelinker by
+ * creating summaries from the element model, discarding their prelinked
+ * information, and then recreating it using the prelinker.
+ */
+@reflectiveTest
+class PrelinkerTest extends SummarizeElementsTest {
+  final Map<String, UnlinkedPublicNamespace> uriToPublicNamespace =
+      <String, UnlinkedPublicNamespace>{};
+
+  @override
+  bool get expectAbsoluteUrisInDependencies => false;
+
+  @override
+  bool get skipFullyLinkedData => true;
+
+  @override
+  bool get strongMode => false;
+
+  @override
+  Source addNamedSource(String filePath, String contents) {
+    Source source = super.addNamedSource(filePath, contents);
+    uriToPublicNamespace[absUri(filePath)] =
+        computePublicNamespaceFromText(contents, source);
+    return source;
+  }
+
+  String resolveToAbsoluteUri(LibraryElement library, String relativeUri) {
+    Source resolvedSource =
+        analysisContext.sourceFactory.resolveUri(library.source, relativeUri);
+    if (resolvedSource == null) {
+      fail('Failed to resolve relative uri "$relativeUri"');
+    }
+    return resolvedSource.uri.toString();
+  }
+
+  @override
+  void serializeLibraryElement(LibraryElement library) {
+    super.serializeLibraryElement(library);
+    Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
+    expect(unlinkedUnits.length, unitUris.length);
+    for (int i = 1; i < unlinkedUnits.length; i++) {
+      uriToUnit[unitUris[i]] = unlinkedUnits[i];
+    }
+    UnlinkedUnit getPart(String relativeUri) {
+      String absoluteUri = resolveToAbsoluteUri(library, relativeUri);
+      UnlinkedUnit unit = uriToUnit[absoluteUri];
+      if (unit == null) {
+        fail('Prelinker unexpectedly requested unit for "$relativeUri"'
+            ' (resolves to "$absoluteUri").');
+      }
+      return unit;
+    }
+    UnlinkedPublicNamespace getImport(String relativeUri) {
+      String absoluteUri = resolveToAbsoluteUri(library, relativeUri);
+      UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri];
+      if (namespace == null) {
+        namespace = uriToPublicNamespace[absoluteUri];
+      }
+      if (namespace == null && !allowMissingFiles) {
+        fail('Prelinker unexpectedly requested namespace for "$relativeUri"'
+            ' (resolves to "$absoluteUri").'
+            '  Namespaces available: ${uriToPublicNamespace.keys}');
+      }
+      return namespace;
+    }
+    linked = new LinkedLibrary.fromBuffer(
+        prelink(unlinkedUnits[0], getPart, getImport).toBuffer());
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_strong_test.dart b/pkg/analyzer/test/src/summary/resynthesize_strong_test.dart
new file mode 100644
index 0000000..b6a9258
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/resynthesize_strong_test.dart
@@ -0,0 +1,22 @@
+// 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 analyzer.test.src.summary.resynthesize_strong_test;
+
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import 'resynthesize_test.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(ResynthStrongTest);
+}
+
+@reflectiveTest
+class ResynthStrongTest extends ResynthTest {
+  @override
+  AnalysisOptionsImpl get options => super.options..strongMode = true;
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index c27b507..c4692fc 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -4,9 +4,14 @@
 
 library test.src.serialization.elements_test;
 
-import 'package:analyzer/src/generated/element.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/element_handle.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart' show Namespace;
+import 'package:analyzer/src/generated/resolver.dart'
+    show Namespace, TypeProvider;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
@@ -25,6 +30,12 @@
 class ResynthTest extends ResolverTestCase {
   Set<Source> otherLibrarySources = new Set<Source>();
 
+  /**
+   * Determine the analysis options that should be used for this test.
+   */
+  AnalysisOptionsImpl get options =>
+      new AnalysisOptionsImpl()..enableGenericMethods = true;
+
   void addLibrary(String uri) {
     otherLibrarySources.add(analysisContext2.sourceFactory.forUri(uri));
   }
@@ -33,13 +44,12 @@
     otherLibrarySources.add(addNamedSource(filePath, contents));
   }
 
-  void checkLibrary(String text,
-      {bool allowErrors: false, int resynthesisCount: 1}) {
+  void checkLibrary(String text, {bool allowErrors: false}) {
     Source source = addSource(text);
     LibraryElementImpl original = resolve2(source);
-    LibraryElementImpl resynthesized = resynthesizeLibrary(
-        source, original, allowErrors,
-        resynthesisCount: resynthesisCount);
+    LibraryElementImpl resynthesized = resynthesizeLibraryElement(
+        encodeLibrary(original, allowErrors: allowErrors),
+        source.uri.toString());
     checkLibraryElements(original, resynthesized);
   }
 
@@ -67,6 +77,10 @@
           'export ${original.exports[i].uri}');
     }
     expect(resynthesized.nameLength, original.nameLength);
+    compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
+        '(public namespace)');
+    compareNamespaces(resynthesized.exportNamespace, original.exportNamespace,
+        '(export namespace)');
     if (original.entryPoint == null) {
       expect(resynthesized.entryPoint, isNull);
     } else {
@@ -74,10 +88,14 @@
       compareFunctionElements(
           resynthesized.entryPoint, original.entryPoint, '(entry point)');
     }
-    compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
-        '(public namespace)');
-    compareNamespaces(resynthesized.exportNamespace, original.exportNamespace,
-        '(export namespace)');
+    // The libraries `dart:core` and `dart:async` cannot create their
+    // `loadLibrary` functions until after both are created.
+    if (original.name != 'dart.core' && original.name != 'dart.async') {
+      compareExecutableElements(
+          resynthesized.loadLibraryFunction as ExecutableElementImpl,
+          original.loadLibraryFunction as ExecutableElementImpl,
+          '(loadLibraryFunction)');
+    }
     // TODO(paulberry): test metadata.
   }
 
@@ -88,8 +106,8 @@
         reason: '$desc fields.length');
     for (int i = 0; i < resynthesized.fields.length; i++) {
       String name = original.fields[i].name;
-      compareFieldElements(resynthesized.getField(name), original.fields[i],
-          '$desc.field $name');
+      compareFieldElements(
+          resynthesized.fields[i], original.fields[i], '$desc.field $name');
     }
     compareTypes(
         resynthesized.supertype, original.supertype, '$desc supertype');
@@ -120,18 +138,10 @@
     }
     expect(resynthesized.accessors.length, original.accessors.length);
     for (int i = 0; i < resynthesized.accessors.length; i++) {
-      String name = original.accessors[i].name;
-      if (name.endsWith('=')) {
-        comparePropertyAccessorElements(
-            resynthesized.getSetter(name),
-            original.accessors[i],
-            '$desc setter ${original.accessors[i].name}');
-      } else {
-        comparePropertyAccessorElements(
-            resynthesized.getGetter(name),
-            original.accessors[i],
-            '$desc getter ${original.accessors[i].name}');
-      }
+      comparePropertyAccessorElements(
+          resynthesized.accessors[i],
+          original.accessors[i],
+          '$desc accessor ${original.accessors[i].name}');
     }
     expect(resynthesized.methods.length, original.methods.length);
     for (int i = 0; i < resynthesized.methods.length; i++) {
@@ -197,8 +207,7 @@
     // TODO(paulberry): test redirectedConstructor and constantInitializers
   }
 
-  void compareElements(
-      ElementImpl resynthesized, ElementImpl original, String desc) {
+  void compareElements(Element resynthesized, Element original, String desc) {
     expect(resynthesized, isNotNull);
     expect(resynthesized.kind, original.kind);
     expect(resynthesized.location, original.location, reason: desc);
@@ -207,20 +216,20 @@
     expect(resynthesized.documentationComment, original.documentationComment,
         reason: desc);
     expect(resynthesized.docRange, original.docRange, reason: desc);
+    // Modifiers are a pain to test via handles.  So just test them via the
+    // actual element.
+    ElementImpl actualResynthesized = getActualElement(resynthesized, desc);
+    ElementImpl actualOriginal = getActualElement(original, desc);
     for (Modifier modifier in Modifier.values) {
-      if (modifier == Modifier.MIXIN) {
-        // Skipping for now.  TODO(paulberry): fix.
-        continue;
-      }
-      bool got = resynthesized.hasModifier(modifier);
-      bool want = original.hasModifier(modifier);
+      bool got = actualResynthesized.hasModifier(modifier);
+      bool want = actualOriginal.hasModifier(modifier);
       expect(got, want,
           reason: 'Mismatch in $desc.$modifier: got $got, want $want');
     }
   }
 
-  void compareExecutableElements(ExecutableElementImpl resynthesized,
-      ExecutableElementImpl original, String desc) {
+  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++) {
@@ -252,8 +261,8 @@
     // TODO(paulberry): test evaluationResult
   }
 
-  void compareFunctionElements(FunctionElementImpl resynthesized,
-      FunctionElementImpl original, String desc) {
+  void compareFunctionElements(
+      FunctionElement resynthesized, FunctionElement original, String desc) {
     compareExecutableElements(resynthesized, original, desc);
   }
 
@@ -286,6 +295,7 @@
     compareUriReferencedElements(resynthesized, original, desc);
     expect(resynthesized.importedLibrary.location,
         original.importedLibrary.location);
+    expect(resynthesized.prefixOffset, original.prefixOffset);
     if (original.prefix == null) {
       expect(resynthesized.prefix, isNull);
     } else {
@@ -347,6 +357,20 @@
           '$desc parameter ${original.parameters[i].name}');
     }
     expect(resynthesized.parameterKind, original.parameterKind);
+    expect(resynthesized.isInitializingFormal, original.isInitializingFormal,
+        reason: desc);
+    expect(resynthesized is FieldFormalParameterElementImpl,
+        original is FieldFormalParameterElementImpl);
+    if (resynthesized is FieldFormalParameterElementImpl &&
+        original is FieldFormalParameterElementImpl) {
+      if (original.field == null) {
+        expect(resynthesized.field, isNull, reason: '$desc field');
+      } else {
+        expect(resynthesized.field, isNotNull, reason: '$desc field');
+        compareFieldElements(
+            resynthesized.field, original.field, '$desc field');
+      }
+    }
   }
 
   void comparePrefixElements(PrefixElementImpl resynthesized,
@@ -371,6 +395,7 @@
       PropertyInducingElementImpl original,
       String desc) {
     compareVariableElements(resynthesized, original, desc);
+    compareTypes(resynthesized.propagatedType, original.propagatedType, desc);
     if (original.getter == null) {
       expect(resynthesized.getter, isNull);
     } else {
@@ -487,75 +512,106 @@
     // TODO(paulberry): test initializer
   }
 
-  fail_library_hasExtUri() {
-    checkLibrary('import "dart-ext:doesNotExist.dart";');
-  }
-
-  LibraryElementImpl resynthesizeLibrary(
-      Source source, LibraryElementImpl original, bool allowErrors,
-      {int resynthesisCount: 1}) {
+  /**
+   * Serialize the given [library] into a summary.  Then create a
+   * [_TestSummaryResynthesizer] which can deserialize it, along with any
+   * references it makes to `dart:core`.
+   *
+   * Errors will lead to a test failure unless [allowErrors] is `true`.
+   */
+  _TestSummaryResynthesizer encodeLibrary(LibraryElementImpl library,
+      {bool allowErrors: false}) {
     if (!allowErrors) {
-      assertNoErrors(source);
+      assertNoErrors(library.source);
     }
-    String uri = source.uri.toString();
     addLibrary('dart:core');
-    return resynthesizeLibraryElement(uri, original,
-        resynthesisCount: resynthesisCount);
+    return encodeLibraryElement(library);
   }
 
-  LibraryElementImpl resynthesizeLibraryElement(
-      String uri, LibraryElementImpl original,
-      {int resynthesisCount: 1}) {
+  /**
+   * Convert the library element [library] into a summary, and then create a
+   * [_TestSummaryResynthesizer] which can deserialize it.
+   *
+   * Caller is responsible for checking the library for errors, and adding any
+   * dependent libraries using [addLibrary].
+   */
+  _TestSummaryResynthesizer encodeLibraryElement(LibraryElementImpl library) {
     Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
-    PrelinkedLibrary getPrelinkedSummaryFor(LibraryElement lib) {
-      LibrarySerializationResult serialized =
-          serializeLibrary(lib, typeProvider);
+    LinkedLibrary getLinkedSummaryFor(LibraryElement lib) {
+      LibrarySerializationResult serialized = serializeLibrary(
+          lib, typeProvider, analysisContext.analysisOptions.strongMode);
       for (int i = 0; i < serialized.unlinkedUnits.length; i++) {
         unlinkedSummaries[serialized.unitUris[i]] =
             new UnlinkedUnit.fromBuffer(serialized.unlinkedUnits[i].toBuffer());
       }
-      return new PrelinkedLibrary.fromBuffer(serialized.prelinked.toBuffer());
+      return new LinkedLibrary.fromBuffer(serialized.linked.toBuffer());
     }
-    Map<String, PrelinkedLibrary> prelinkedSummaries =
-        <String, PrelinkedLibrary>{uri: getPrelinkedSummaryFor(original)};
+    Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{
+      library.source.uri.toString(): getLinkedSummaryFor(library)
+    };
     for (Source source in otherLibrarySources) {
       LibraryElement original = resolve2(source);
       String uri = source.uri.toString();
-      prelinkedSummaries[uri] = getPrelinkedSummaryFor(original);
+      linkedSummaries[uri] = getLinkedSummaryFor(original);
     }
-    PrelinkedLibrary getPrelinkedSummary(String uri) {
-      PrelinkedLibrary serializedLibrary = prelinkedSummaries[uri];
-      if (serializedLibrary == null) {
-        fail('Unexpectedly tried to get prelinked summary for $uri');
-      }
-      return serializedLibrary;
-    }
-    UnlinkedUnit getUnlinkedSummary(String uri) {
-      UnlinkedUnit serializedUnit = unlinkedSummaries[uri];
-      if (serializedUnit == null) {
-        fail('Unexpectedly tried to get unlinked summary for $uri');
-      }
-      return serializedUnit;
-    }
-    SummaryResynthesizer resynthesizer = new SummaryResynthesizer(
+    return new _TestSummaryResynthesizer(
+        null,
         analysisContext,
         analysisContext.typeProvider,
-        getPrelinkedSummary,
-        getUnlinkedSummary,
-        analysisContext.sourceFactory);
+        analysisContext.sourceFactory,
+        unlinkedSummaries,
+        linkedSummaries,
+        options.strongMode);
+  }
+
+  fail_library_hasExtUri() {
+    checkLibrary('import "dart-ext:doesNotExist.dart";');
+  }
+
+  ElementImpl getActualElement(Element element, String desc) {
+    if (element is ElementHandle) {
+      return element.actualElement;
+    } else if (element is ElementImpl) {
+      return element;
+    } else {
+      fail('Unexpected type for resynthesized ($desc):'
+          ' ${element.runtimeType}');
+      return null;
+    }
+  }
+
+  /**
+   * Resynthesize the library element associated with [uri] using
+   * [resynthesizer], and verify that it only had to consult one summary in
+   * order to do so.
+   */
+  LibraryElementImpl resynthesizeLibraryElement(
+      _TestSummaryResynthesizer resynthesizer, String uri) {
     LibraryElementImpl resynthesized = resynthesizer.getLibraryElement(uri);
     // Check that no other summaries needed to be resynthesized to resynthesize
     // the library element.
-    // TODO(paulberry): once export namespaces are resynthesized from
-    // prelinked data, resynthesisCount should be hardcoded to 1.
-    expect(resynthesizer.resynthesisCount, resynthesisCount);
+    expect(resynthesizer.resynthesisCount, 1);
     return resynthesized;
   }
 
+  @override
+  void setUp() {
+    super.setUp();
+    resetWithOptions(options);
+  }
+
+  test_class_abstract() {
+    checkLibrary('abstract class C {}');
+  }
+
   test_class_alias() {
     checkLibrary('class C = D with E, F; class D {} class E {} class F {}');
   }
 
+  test_class_alias_abstract() {
+    checkLibrary('abstract class C = D with E; class D {} class E {}');
+  }
+
   test_class_alias_documented() {
     checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -662,8 +718,18 @@
     checkLibrary('class C { dynamic x; C(this.x); }');
   }
 
+  test_class_constructor_field_formal_multiple_matching_fields() {
+    // This is a compile-time error but it should still analyze consistently.
+    checkLibrary('class C { C(this.x); int x; String x; }', allowErrors: true);
+  }
+
+  test_class_constructor_field_formal_no_matching_field() {
+    // This is a compile-time error but it should still analyze consistently.
+    checkLibrary('class C { C(this.x); }', allowErrors: true);
+  }
+
   test_class_constructor_field_formal_typed_dynamic() {
-    checkLibrary('class C { num x; C(dynamic this.x); }');
+    checkLibrary('class C { num x; C(dynamic this.x); }', allowErrors: true);
   }
 
   test_class_constructor_field_formal_typed_typed() {
@@ -742,6 +808,10 @@
     checkLibrary('class C { int i; int j; }');
   }
 
+  test_class_getter_abstract() {
+    checkLibrary('abstract class C { int get x; }');
+  }
+
   test_class_getter_external() {
     checkLibrary('class C { external int get x; }');
   }
@@ -770,6 +840,10 @@
     checkLibrary('class C implements D, E {} class D {} class E {}');
   }
 
+  test_class_method_abstract() {
+    checkLibrary('abstract class C { f(); }');
+  }
+
   test_class_method_external() {
     checkLibrary('class C { external f(); }');
   }
@@ -790,6 +864,10 @@
     checkLibrary('class C extends Object with D, E {} class D {} class E {}');
   }
 
+  test_class_setter_abstract() {
+    checkLibrary('abstract class C { void set x(int value); }');
+  }
+
   test_class_setter_external() {
     checkLibrary('class C { external void set x(int value); }');
   }
@@ -849,7 +927,7 @@
     LibraryElementImpl original =
         resolve2(analysisContext2.sourceFactory.forUri(uri));
     LibraryElementImpl resynthesized =
-        resynthesizeLibraryElement(uri, original);
+        resynthesizeLibraryElement(encodeLibraryElement(original), uri);
     checkLibraryElements(original, resynthesized);
   }
 
@@ -880,28 +958,71 @@
     checkLibrary('enum E1 { v1 } enum E2 { v2 }');
   }
 
+  test_export_class() {
+    addLibrarySource('/a.dart', 'class C {}');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_export_class_type_alias() {
+    addLibrarySource(
+        '/a.dart', 'class C {} exends _D with _E; class _D {} class _E {}');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_export_function() {
+    addLibrarySource('/a.dart', 'f() {}');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_export_getter() {
+    addLibrarySource('/a.dart', 'get f() => null;');
+    checkLibrary('export "a.dart";');
+  }
+
   test_export_hide() {
     addLibrary('dart:async');
-    checkLibrary('export "dart:async" hide Stream, Future;',
-        resynthesisCount: 2);
+    checkLibrary('export "dart:async" hide Stream, Future;');
   }
 
   test_export_multiple_combinators() {
     addLibrary('dart:async');
-    checkLibrary('export "dart:async" hide Stream show Future;',
-        resynthesisCount: 2);
+    checkLibrary('export "dart:async" hide Stream show Future;');
+  }
+
+  test_export_setter() {
+    addLibrarySource('/a.dart', 'void set f(value) {}');
+    checkLibrary('export "a.dart";');
   }
 
   test_export_show() {
     addLibrary('dart:async');
-    checkLibrary('export "dart:async" show Future, Stream;',
-        resynthesisCount: 2);
+    checkLibrary('export "dart:async" show Future, Stream;');
+  }
+
+  test_export_typedef() {
+    addLibrarySource('/a.dart', 'typedef F();');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_export_variable() {
+    addLibrarySource('/a.dart', 'var x;');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_export_variable_const() {
+    addLibrarySource('/a.dart', 'const x = 0;');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_export_variable_final() {
+    addLibrarySource('/a.dart', 'final x = 0;');
+    checkLibrary('export "a.dart";');
   }
 
   test_exports() {
     addLibrarySource('/a.dart', 'library a;');
     addLibrarySource('/b.dart', 'library b;');
-    checkLibrary('export "a.dart"; export "b.dart";', resynthesisCount: 3);
+    checkLibrary('export "a.dart"; export "b.dart";');
   }
 
   test_field_documented() {
@@ -914,6 +1035,68 @@
 }''');
   }
 
+  test_field_formal_param_inferred_type_implicit() {
+    checkLibrary('class C extends D { var v; C(this.v); }'
+        ' abstract class D { int get v; }');
+  }
+
+  test_field_inferred_type_nonstatic_explicit_initialized() {
+    checkLibrary('class C { num v = 0; }');
+  }
+
+  test_field_inferred_type_nonstatic_implicit_initialized() {
+    checkLibrary('class C { var v = 0; }');
+  }
+
+  test_field_inferred_type_nonstatic_implicit_uninitialized() {
+    checkLibrary(
+        'class C extends D { var v; } abstract class D { int get v; }');
+  }
+
+  test_field_inferred_type_static_implicit_initialized() {
+    checkLibrary('class C { static var v = 0; }');
+  }
+
+  test_field_propagatedType_const_noDep() {
+    checkLibrary('''
+class C {
+  static const x = 0;
+}''');
+  }
+
+  test_field_propagatedType_final_dep_inLib() {
+    addNamedSource('/a.dart', 'final a = 1;');
+    checkLibrary('''
+import "a.dart";
+class C {
+  final b = a / 2;
+}''');
+  }
+
+  test_field_propagatedType_final_dep_inPart() {
+    addNamedSource('/a.dart', 'part of lib; final a = 1;');
+    checkLibrary('''
+library lib;
+part "a.dart";
+class C {
+  final b = a / 2;
+}''');
+  }
+
+  test_field_propagatedType_final_noDep_instance() {
+    checkLibrary('''
+class C {
+  final x = 0;
+}''');
+  }
+
+  test_field_propagatedType_final_noDep_static() {
+    checkLibrary('''
+class C {
+  static final x = 0;
+}''');
+  }
+
   test_function_documented() {
     checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -929,12 +1112,12 @@
 
   test_function_entry_point_in_export() {
     addLibrarySource('/a.dart', 'library a; main() {}');
-    checkLibrary('export "a.dart";', resynthesisCount: 2);
+    checkLibrary('export "a.dart";');
   }
 
   test_function_entry_point_in_export_hidden() {
     addLibrarySource('/a.dart', 'library a; main() {}');
-    checkLibrary('export "a.dart" hide main;', resynthesisCount: 2);
+    checkLibrary('export "a.dart" hide main;');
   }
 
   test_function_entry_point_in_part() {
@@ -1006,6 +1189,69 @@
     checkLibrary('f() {} g() {}');
   }
 
+  test_getElement_constructor_named() {
+    ConstructorElement original = resolve2(addSource('class C { C.named(); }'))
+        .getType('C')
+        .getNamedConstructor('named');
+    expect(original, isNotNull);
+    ConstructorElement resynthesized = validateGetElement(original);
+    compareConstructorElements(resynthesized, original, 'C.constructor named');
+  }
+
+  test_getElement_constructor_unnamed() {
+    ConstructorElement original =
+        resolve2(addSource('class C { C(); }')).getType('C').unnamedConstructor;
+    expect(original, isNotNull);
+    ConstructorElement resynthesized = validateGetElement(original);
+    compareConstructorElements(resynthesized, original, 'C.constructor');
+  }
+
+  test_getElement_field() {
+    FieldElement original =
+        resolve2(addSource('class C { var f; }')).getType('C').getField('f');
+    expect(original, isNotNull);
+    FieldElement resynthesized = validateGetElement(original);
+    compareFieldElements(resynthesized, original, 'C.field f');
+  }
+
+  test_getElement_getter() {
+    PropertyAccessorElement original =
+        resolve2(addSource('class C { get f => null; }'))
+            .getType('C')
+            .getGetter('f');
+    expect(original, isNotNull);
+    PropertyAccessorElement resynthesized = validateGetElement(original);
+    comparePropertyAccessorElements(resynthesized, original, 'C.getter f');
+  }
+
+  test_getElement_method() {
+    MethodElement original =
+        resolve2(addSource('class C { f() {} }')).getType('C').getMethod('f');
+    expect(original, isNotNull);
+    MethodElement resynthesized = validateGetElement(original);
+    compareMethodElements(resynthesized, original, 'C.method f');
+  }
+
+  test_getElement_operator() {
+    MethodElement original =
+        resolve2(addSource('class C { operator+(x) => null; }'))
+            .getType('C')
+            .getMethod('+');
+    expect(original, isNotNull);
+    MethodElement resynthesized = validateGetElement(original);
+    compareMethodElements(resynthesized, original, 'C.operator+');
+  }
+
+  test_getElement_setter() {
+    PropertyAccessorElement original =
+        resolve2(addSource('class C { void set f(value) {} }'))
+            .getType('C')
+            .getSetter('f');
+    expect(original, isNotNull);
+    PropertyAccessorElement resynthesized = validateGetElement(original);
+    comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
+  }
+
   test_getter_documented() {
     checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -1019,6 +1265,11 @@
     checkLibrary('external int get x;');
   }
 
+  test_getter_inferred_type_nonstatic_implicit_return() {
+    checkLibrary(
+        'class C extends D { get f => null; } abstract class D { int get f; }');
+  }
+
   test_getters() {
     checkLibrary('int get x => null; get y => null;');
   }
@@ -1031,6 +1282,11 @@
     checkLibrary('void set x(int value) {} int get x => 0;');
   }
 
+  test_import_deferred() {
+    addLibrarySource('/a.dart', 'f() {}');
+    checkLibrary('import "a.dart" deferred as p; main() { p.f(); }');
+  }
+
   test_import_hide() {
     addLibrary('dart:async');
     checkLibrary('import "dart:async" hide Stream, Completer; Future f;');
@@ -1057,6 +1313,26 @@
     checkLibrary('import "a.dart"; import "b.dart"; C c; D d;');
   }
 
+  test_inferred_type_is_typedef() {
+    checkLibrary('typedef int F(String s);'
+        ' class C extends D { var v; }'
+        ' abstract class D { F get v; }');
+  }
+
+  test_inferred_type_refers_to_bound_type_param() {
+    checkLibrary('class C<T> extends D<int, T> { var v; }'
+        ' abstract class D<U, V> { Map<V, U> get v; }');
+  }
+
+  test_inferred_type_via_function_typed_param() {
+    if (options.strongMode) {
+      // TODO(paulberry): get this test to pass.
+      return;
+    }
+    checkLibrary('class C extends D { f(g) {} }'
+        ' abstract class D { void f(int g(String)); }');
+  }
+
   test_library() {
     checkLibrary('');
   }
@@ -1078,6 +1354,51 @@
     checkLibrary('library foo.bar;');
   }
 
+  test_main_class() {
+    checkLibrary('class main {}');
+  }
+
+  test_main_class_alias() {
+    checkLibrary('class main = C with D; class C {} class D {}');
+  }
+
+  test_main_class_alias_via_export() {
+    addLibrarySource('/a.dart', 'class main = C with D; class C {} class D {}');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_main_class_via_export() {
+    addLibrarySource('/a.dart', 'class main {}');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_main_getter() {
+    checkLibrary('get main => null;');
+  }
+
+  test_main_getter_via_export() {
+    addLibrarySource('/a.dart', 'get main => null;');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_main_typedef() {
+    checkLibrary('typedef main();');
+  }
+
+  test_main_typedef_via_export() {
+    addLibrarySource('/a.dart', 'typedef main();');
+    checkLibrary('export "a.dart";');
+  }
+
+  test_main_variable() {
+    checkLibrary('var main;');
+  }
+
+  test_main_variable_via_export() {
+    addLibrarySource('/a.dart', 'var main;');
+    checkLibrary('export "a.dart";');
+  }
+
   test_method_documented() {
     checkLibrary('''
 class C {
@@ -1088,6 +1409,16 @@
 }''');
   }
 
+  test_method_inferred_type_nonstatic_implicit_param() {
+    checkLibrary('class C extends D { void f(value) {} }'
+        ' abstract class D { void f(int value); }');
+  }
+
+  test_method_inferred_type_nonstatic_implicit_return() {
+    checkLibrary(
+        'class C extends D { f() => null; } abstract class D { int f(); }');
+  }
+
   test_method_parameter_parameters() {
     checkLibrary('class C { f(g(x, y)) {} }');
   }
@@ -1124,7 +1455,7 @@
   }
 
   test_operator_equal() {
-    checkLibrary('class C { bool operator==(C other) => false; }');
+    checkLibrary('class C { bool operator==(Object other) => false; }');
   }
 
   test_operator_external() {
@@ -1166,11 +1497,36 @@
     checkLibrary('external void set x(int value);');
   }
 
+  test_setter_inferred_type_nonstatic_implicit_param() {
+    checkLibrary('class C extends D { void set f(value) {} }'
+        ' abstract class D { void set f(int value); }');
+  }
+
+  test_setter_inferred_type_static_implicit_return() {
+    checkLibrary('class C { static set f(int value) {} }');
+  }
+
+  test_setter_inferred_type_top_level_implicit_return() {
+    checkLibrary('set f(int value) {}');
+  }
+
   test_setters() {
     checkLibrary('void set x(int value) {} set y(value) {}');
   }
 
-  test_type_arguments_explicit() {
+  test_type_arguments_explicit_dynamic_dynamic() {
+    checkLibrary('Map<dynamic, dynamic> m;');
+  }
+
+  test_type_arguments_explicit_dynamic_int() {
+    checkLibrary('Map<dynamic, int> m;');
+  }
+
+  test_type_arguments_explicit_String_dynamic() {
+    checkLibrary('Map<String, dynamic> m;');
+  }
+
+  test_type_arguments_explicit_String_int() {
     checkLibrary('Map<String, int> m;');
   }
 
@@ -1386,11 +1742,120 @@
 var x;''');
   }
 
+  test_variable_final() {
+    checkLibrary('final int x = 0;');
+  }
+
+  test_variable_getterInLib_setterInPart() {
+    addNamedSource('/a.dart', 'part of my.lib; void set x(int _) {}');
+    checkLibrary('library my.lib; part "a.dart"; int get x => 42;');
+  }
+
+  test_variable_getterInPart_setterInLib() {
+    addNamedSource('/a.dart', 'part of my.lib; int get x => 42;');
+    checkLibrary('library my.lib; part "a.dart"; void set x(int _) {}');
+  }
+
+  test_variable_getterInPart_setterInPart() {
+    addNamedSource('/a.dart', 'part of my.lib; int get x => 42;');
+    addNamedSource('/b.dart', 'part of my.lib; void set x(int _) {}');
+    checkLibrary('library my.lib; part "a.dart"; part "b.dart";');
+  }
+
   test_variable_implicit_type() {
     checkLibrary('var x;');
   }
 
+  test_variable_inferred_type_implicit_initialized() {
+    checkLibrary('var v = 0;');
+  }
+
+  test_variable_propagatedType_const_noDep() {
+    checkLibrary('const i = 0;');
+  }
+
+  test_variable_propagatedType_final_dep_inLib() {
+    addNamedSource('/a.dart', 'final a = 1;');
+    checkLibrary('import "a.dart"; final b = a / 2;');
+  }
+
+  test_variable_propagatedType_final_dep_inPart() {
+    addNamedSource('/a.dart', 'part of lib; final a = 1;');
+    checkLibrary('library lib; part "a.dart"; final b = a / 2;');
+  }
+
+  test_variable_propagatedType_final_noDep() {
+    checkLibrary('final i = 0;');
+  }
+
+  test_variable_propagatedType_implicit_dep() {
+    // The propagated type is defined in a library that is not imported.
+    addNamedSource('/a.dart', 'class C {}');
+    addNamedSource('/b.dart', 'import "a.dart"; C f() => null;');
+    checkLibrary('import "b.dart"; final x = f();');
+  }
+
+  test_variable_setterInPart_getterInPart() {
+    addNamedSource('/a.dart', 'part of my.lib; void set x(int _) {}');
+    addNamedSource('/b.dart', 'part of my.lib; int get x => 42;');
+    checkLibrary('library my.lib; part "a.dart"; part "b.dart";');
+  }
+
   test_variables() {
     checkLibrary('int i; int j;');
   }
+
+  /**
+   * Encode the library containing [original] into a summary and then use
+   * [_TestSummaryResynthesizer.getElement] to retrieve just the original
+   * element from the resynthesized summary.
+   */
+  Element validateGetElement(Element original) {
+    _TestSummaryResynthesizer resynthesizer = encodeLibrary(original.library);
+    ElementLocationImpl location = original.location;
+    Element result = resynthesizer.getElement(location);
+    // Check that no other summaries needed to be resynthesized to resynthesize
+    // the library element.
+    expect(resynthesizer.resynthesisCount, 1);
+    expect(result.location, location);
+    return result;
+  }
+}
+
+class _TestSummaryResynthesizer extends SummaryResynthesizer {
+  final Map<String, UnlinkedUnit> unlinkedSummaries;
+  final Map<String, LinkedLibrary> linkedSummaries;
+
+  _TestSummaryResynthesizer(
+      SummaryResynthesizer parent,
+      AnalysisContext context,
+      TypeProvider typeProvider,
+      SourceFactory sourceFactory,
+      this.unlinkedSummaries,
+      this.linkedSummaries,
+      bool strongMode)
+      : super(parent, context, typeProvider, sourceFactory, strongMode);
+
+  @override
+  LinkedLibrary getLinkedSummary(String uri) {
+    LinkedLibrary serializedLibrary = linkedSummaries[uri];
+    if (serializedLibrary == null) {
+      fail('Unexpectedly tried to get linked summary for $uri');
+    }
+    return serializedLibrary;
+  }
+
+  @override
+  UnlinkedUnit getUnlinkedSummary(String uri) {
+    UnlinkedUnit serializedUnit = unlinkedSummaries[uri];
+    if (serializedUnit == null) {
+      fail('Unexpectedly tried to get unlinked summary for $uri');
+    }
+    return serializedUnit;
+  }
+
+  @override
+  bool hasLibrarySummary(String uri) {
+    return true;
+  }
 }
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
new file mode 100644
index 0000000..aa7dff0
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -0,0 +1,117 @@
+// 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 analyzer.test.src.summary.summarize_ast_test;
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/prelink.dart';
+import 'package:analyzer/src/summary/summarize_ast.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import 'summary_common.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(UnlinkedSummarizeAstTest);
+}
+
+/**
+ * Override of [SummaryTest] which creates unlinked summaries directly from the
+ * AST.
+ */
+@reflectiveTest
+class UnlinkedSummarizeAstTest extends Object with SummaryTest {
+  @override
+  LinkedLibrary linked;
+
+  @override
+  List<UnlinkedUnit> unlinkedUnits;
+
+  /**
+   * Map from absolute URI to the [UnlinkedUnit] for each compilation unit
+   * passed to [addNamedSource].
+   */
+  Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
+
+  @override
+  bool get checkAstDerivedData => true;
+
+  @override
+  bool get expectAbsoluteUrisInDependencies => false;
+
+  @override
+  bool get skipFullyLinkedData => true;
+
+  @override
+  bool get strongMode => false;
+
+  @override
+  addNamedSource(String filePath, String contents) {
+    CompilationUnit unit = _parseText(contents);
+    UnlinkedUnit unlinkedUnit =
+        new UnlinkedUnit.fromBuffer(serializeAstUnlinked(unit).toBuffer());
+    uriToUnit[absUri(filePath)] = unlinkedUnit;
+  }
+
+  @override
+  void serializeLibraryText(String text, {bool allowErrors: false}) {
+    Uri testDartUri = Uri.parse(absUri('/test.dart'));
+    String resolveToAbsoluteUri(String relativeUri) =>
+        testDartUri.resolve(relativeUri).toString();
+    CompilationUnit unit = _parseText(text);
+    UnlinkedUnit definingUnit =
+        new UnlinkedUnit.fromBuffer(serializeAstUnlinked(unit).toBuffer());
+    UnlinkedUnit getPart(String relativeUri) {
+      String absoluteUri = resolveToAbsoluteUri(relativeUri);
+      UnlinkedUnit unit = uriToUnit[absoluteUri];
+      if (unit == null && !allowMissingFiles) {
+        fail('Prelinker unexpectedly requested unit for "$relativeUri"'
+            ' (resolves to "$absoluteUri").');
+      }
+      return unit;
+    }
+    UnlinkedPublicNamespace getImport(String relativeUri) {
+      String absoluteUri = resolveToAbsoluteUri(relativeUri);
+      UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri];
+      if (namespace == null) {
+        namespace = uriToUnit[absoluteUri]?.publicNamespace;
+      }
+      if (namespace == null && !allowMissingFiles) {
+        fail('Prelinker unexpectedly requested namespace for "$relativeUri"'
+            ' (resolves to "$absoluteUri").'
+            '  Namespaces available: ${uriToUnit.keys}');
+      }
+      return namespace;
+    }
+    linked = new LinkedLibrary.fromBuffer(
+        prelink(definingUnit, getPart, getImport).toBuffer());
+    unlinkedUnits = <UnlinkedUnit>[definingUnit];
+    for (String relativeUri in definingUnit.publicNamespace.parts) {
+      UnlinkedUnit unit = uriToUnit[resolveToAbsoluteUri(relativeUri)];
+      if (unit == null) {
+        if (!allowMissingFiles) {
+          fail('Test referred to unknown unit $relativeUri');
+        }
+      } else {
+        unlinkedUnits.add(unit);
+      }
+    }
+  }
+
+  CompilationUnit _parseText(String text) {
+    CharSequenceReader reader = new CharSequenceReader(text);
+    Scanner scanner =
+        new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER);
+    Token token = scanner.tokenize();
+    Parser parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
+    parser.parseGenericMethods = true;
+    return parser.parseCompilationUnit(token);
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/summarize_elements_strong_test.dart b/pkg/analyzer/test/src/summary/summarize_elements_strong_test.dart
new file mode 100644
index 0000000..8a8bfe6
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/summarize_elements_strong_test.dart
@@ -0,0 +1,30 @@
+// 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 analyzer.test.src.summary.summarize_elements_strong_test;
+
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import 'summarize_elements_test.dart';
+import 'summary_common.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(SummarizeElementsStrongTest);
+}
+
+/**
+ * Override of [SummaryTest] which creates summaries from the element model
+ * using strong mode.
+ */
+@reflectiveTest
+class SummarizeElementsStrongTest extends SummarizeElementsTest {
+  @override
+  AnalysisOptionsImpl get options => super.options..strongMode = true;
+
+  @override
+  bool get strongMode => true;
+}
diff --git a/pkg/analyzer/test/src/summary/summarize_elements_test.dart b/pkg/analyzer/test/src/summary/summarize_elements_test.dart
new file mode 100644
index 0000000..7b679b9
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/summarize_elements_test.dart
@@ -0,0 +1,155 @@
+// 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 analyzer.test.src.summary.summarize_elements_test;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.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/public_namespace_computer.dart'
+    as public_namespace;
+import 'package:analyzer/src/summary/summarize_elements.dart'
+    as summarize_elements;
+import 'package:unittest/unittest.dart';
+
+import '../../generated/resolver_test.dart';
+import '../../reflective_tests.dart';
+import 'summary_common.dart';
+
+main() {
+  groupSep = ' | ';
+  runReflectiveTests(SummarizeElementsTest);
+}
+
+/**
+ * Override of [SummaryTest] which creates summaries from the element model.
+ */
+@reflectiveTest
+class SummarizeElementsTest extends ResolverTestCase with SummaryTest {
+  /**
+   * The list of absolute unit URIs corresponding to the compilation units in
+   * [unlinkedUnits].
+   */
+  List<String> unitUris;
+
+  /**
+   * Map containing all source files in this test, and their corresponding file
+   * contents.
+   */
+  final Map<Source, String> _fileContents = <Source, String>{};
+
+  @override
+  LinkedLibrary linked;
+
+  @override
+  List<UnlinkedUnit> unlinkedUnits;
+
+  @override
+  bool get checkAstDerivedData => false;
+
+  @override
+  bool get expectAbsoluteUrisInDependencies => true;
+
+  /**
+   * Determine the analysis options that should be used for this test.
+   */
+  AnalysisOptionsImpl get options =>
+      new AnalysisOptionsImpl()..enableGenericMethods = true;
+
+  @override
+  bool get skipFullyLinkedData => false;
+
+  @override
+  bool get strongMode => false;
+
+  @override
+  Source addNamedSource(String filePath, String contents) {
+    Source source = super.addNamedSource(filePath, contents);
+    _fileContents[source] = contents;
+    return source;
+  }
+
+  /**
+   * Serialize the library containing the given class [element], then
+   * deserialize it and return the summary of the class.
+   */
+  UnlinkedClass serializeClassElement(ClassElement element) {
+    serializeLibraryElement(element.library);
+    return findClass(element.name, failIfAbsent: true);
+  }
+
+  /**
+   * Serialize the given [library] element, then deserialize it and store the
+   * resulting summary in [linked] and [unlinkedUnits].
+   */
+  void serializeLibraryElement(LibraryElement library) {
+    summarize_elements.LibrarySerializationResult serializedLib =
+        summarize_elements.serializeLibrary(
+            library, typeProvider, analysisContext.analysisOptions.strongMode);
+    {
+      List<int> buffer = serializedLib.linked.toBuffer();
+      linked = new LinkedLibrary.fromBuffer(buffer);
+    }
+    unlinkedUnits = serializedLib.unlinkedUnits.map((UnlinkedUnitBuilder b) {
+      List<int> buffer = b.toBuffer();
+      return new UnlinkedUnit.fromBuffer(buffer);
+    }).toList();
+    unitUris = serializedLib.unitUris;
+  }
+
+  @override
+  void serializeLibraryText(String text, {bool allowErrors: false}) {
+    Source source = addSource(text);
+    _fileContents[source] = text;
+    LibraryElement library = resolve2(source);
+    if (!allowErrors) {
+      assertNoErrors(source);
+    }
+    serializeLibraryElement(library);
+    expect(unlinkedUnits[0].imports.length, linked.importDependencies.length);
+    expect(linked.units.length, unlinkedUnits.length);
+    for (int i = 0; i < linked.units.length; i++) {
+      expect(unlinkedUnits[i].references.length,
+          lessThanOrEqualTo(linked.units[i].references.length));
+    }
+    verifyPublicNamespace();
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    resetWithOptions(options);
+  }
+
+  test_class_no_superclass() {
+    UnlinkedClass cls = serializeClassElement(typeProvider.objectType.element);
+    expect(cls.supertype, isNull);
+    expect(cls.hasNoSupertype, isTrue);
+  }
+
+  /**
+   * Verify that [public_namespace.computePublicNamespace] produces data that's
+   * equivalent to that produced by [summarize_elements.serializeLibrary].
+   */
+  void verifyPublicNamespace() {
+    for (int i = 0; i < unlinkedUnits.length; i++) {
+      Source source = analysisContext.sourceFactory.forUri(unitUris[i]);
+      String text = _fileContents[source];
+      if (text == null) {
+        if (!allowMissingFiles) {
+          fail('Could not find file while verifying public namespace: '
+              '${unitUris[i]}');
+        }
+      } else {
+        UnlinkedPublicNamespace namespace =
+            computePublicNamespaceFromText(text, source);
+        expect(canonicalize(namespace),
+            canonicalize(unlinkedUnits[i].publicNamespace),
+            reason: 'publicNamespace(${unitUris[i]})');
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
new file mode 100644
index 0000000..2122771
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -0,0 +1,5002 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.src.summary.summary_common;
+
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_engine_io.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/scanner.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/summary/base.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/public_namespace_computer.dart'
+    as public_namespace;
+import 'package:analyzer/src/summary/summarize_elements.dart'
+    as summarize_elements;
+import 'package:unittest/unittest.dart';
+
+import '../../generated/resolver_test.dart';
+
+/**
+ * The public namespaces of the sdk are computed once so that we don't bog
+ * down the test.  Structured as a map from absolute URI to the corresponding
+ * public namespace.
+ *
+ * Note: should an exception occur during computation of this variable, it
+ * will silently be set to null to allow other tests to run.
+ */
+final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () {
+  try {
+    AnalysisContext analysisContext = AnalysisContextFactory.contextWithCore();
+    Map<String, UnlinkedPublicNamespace> uriToNamespace =
+        <String, UnlinkedPublicNamespace>{};
+    List<LibraryElement> libraries = [
+      analysisContext.typeProvider.objectType.element.library,
+      analysisContext.typeProvider.futureType.element.library
+    ];
+    for (LibraryElement library in libraries) {
+      summarize_elements.LibrarySerializationResult serializedLibrary =
+          summarize_elements.serializeLibrary(
+              library, analysisContext.typeProvider, false);
+      for (int i = 0; i < serializedLibrary.unlinkedUnits.length; i++) {
+        uriToNamespace[serializedLibrary.unitUris[i]] =
+            new UnlinkedUnit.fromBuffer(
+                    serializedLibrary.unlinkedUnits[i].toBuffer())
+                .publicNamespace;
+      }
+    }
+    return uriToNamespace;
+  } catch (_) {
+    return null;
+  }
+}();
+
+/**
+ * Convert a summary object (or a portion of one) into a canonical form that
+ * can be easily compared using [expect].  If [orderByName] is true, and the
+ * object is a [List], it is sorted by the `name` field of its elements.
+ */
+Object canonicalize(Object obj, {bool orderByName: false}) {
+  if (obj is SummaryClass) {
+    Map<String, Object> result = <String, Object>{};
+    obj.toMap().forEach((String key, Object value) {
+      bool orderByName = false;
+      if (obj is UnlinkedPublicNamespace && key == 'names') {
+        orderByName = true;
+      }
+      result[key] = canonicalize(value, orderByName: orderByName);
+    });
+    return result;
+  } else if (obj is List) {
+    List<Object> result = <Object>[];
+    for (Object item in obj) {
+      result.add(canonicalize(item));
+    }
+    if (orderByName) {
+      result.sort((Object a, Object b) {
+        if (a is Map && b is Map) {
+          return Comparable.compare(a['name'], b['name']);
+        } else {
+          return 0;
+        }
+      });
+    }
+    return result;
+  } else if (obj is String || obj is num || obj is bool) {
+    return obj;
+  } else {
+    return obj.toString();
+  }
+}
+
+UnlinkedPublicNamespace computePublicNamespaceFromText(
+    String text, Source source) {
+  CharacterReader reader = new CharSequenceReader(text);
+  Scanner scanner =
+      new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
+  Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
+  parser.parseGenericMethods = true;
+  CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
+  UnlinkedPublicNamespace namespace = new UnlinkedPublicNamespace.fromBuffer(
+      public_namespace.computePublicNamespace(unit).toBuffer());
+  return namespace;
+}
+
+/**
+ * Type of a function that validates an [EntityRef].
+ */
+typedef void _EntityRefValidator(EntityRef entityRef);
+
+/**
+ * Base class containing most summary tests.  This allows summary tests to be
+ * re-used to exercise all the different ways in which summaries can be
+ * generated (e.g. direct from the AST, from the element model, from a
+ * "relinking" process, etc.)
+ */
+abstract class SummaryTest {
+  /**
+   * A test will set this to `true` if it contains `import`, `export`, or
+   * `part` declarations that deliberately refer to non-existent files.
+   */
+  bool allowMissingFiles = false;
+
+  /**
+   * `true` if the summary was created directly from the AST (and hence
+   * contains information that is not obtainable from the element model alone).
+   * TODO(paulberry): modify the element model so that it contains all the data
+   * that summaries need, so that this flag is no longer needed.
+   */
+  bool get checkAstDerivedData;
+
+  /**
+   * Get access to the linked defining compilation unit.
+   */
+  LinkedUnit get definingUnit => linked.units[0];
+
+  /**
+   * `true` if the linked portion of the summary is expected to contain
+   * absolute URIs.  This happens because the element model doesn't (yet) store
+   * enough information to recover relative URIs, TODO(paulberry): fix this.
+   */
+  bool get expectAbsoluteUrisInDependencies;
+
+  /**
+   * Get access to the linked summary that results from serializing and
+   * then deserializing the library under test.
+   */
+  LinkedLibrary get linked;
+
+  /**
+   * `true` if the linked portion of the summary only contains prelinked data.
+   * This happens because we don't yet have a full linker; only a prelinker.
+   */
+  bool get skipFullyLinkedData;
+
+  /**
+   * `true` if the linked portion of the summary contains the result of strong
+   * mode analysis.
+   */
+  bool get strongMode;
+
+  /**
+   * Get access to the unlinked compilation unit summaries that result from
+   * serializing and deserializing the library under test.
+   */
+  List<UnlinkedUnit> get unlinkedUnits;
+
+  /**
+   * Convert [path] to a suitably formatted absolute path URI for the current
+   * platform.
+   */
+  String absUri(String path) {
+    return FileUtilities2.createFile(path).toURI().toString();
+  }
+
+  /**
+   * Add the given source file so that it may be referenced by the file under
+   * test.
+   */
+  Source addNamedSource(String filePath, String contents);
+
+  /**
+   * Verify that the [dependency]th element of the dependency table represents
+   * a file reachable via the given [absoluteUri] and [relativeUri].
+   */
+  void checkDependency(int dependency, String absoluteUri, String relativeUri) {
+    if (expectAbsoluteUrisInDependencies) {
+      // The element model doesn't (yet) store enough information to recover
+      // relative URIs, so we have to use the absolute URI.
+      // TODO(paulberry): fix this.
+      relativeUri = absoluteUri;
+    }
+    expect(dependency, new isInstanceOf<int>());
+    expect(linked.dependencies[dependency].uri, relativeUri);
+  }
+
+  /**
+   * Verify that the given [dependency] lists the given [absoluteUris] or
+   * [relativeUris] as its parts.
+   */
+  void checkDependencyParts(LinkedDependency dependency,
+      List<String> absoluteUris, List<String> relativeUris) {
+    if (expectAbsoluteUrisInDependencies) {
+      // The element model doesn't (yet) store enough information to recover
+      // relative URIs, so we have to use the absolute URI.
+      // TODO(paulberry): fix this.
+      relativeUris = absoluteUris;
+    }
+    expect(dependency.parts, relativeUris);
+  }
+
+  /**
+   * Check that the given [documentationComment] matches the first
+   * Javadoc-style comment found in [text].
+   *
+   * Note that the algorithm for finding the Javadoc-style comment in [text] is
+   * a simple-minded text search; it is easily confused by corner cases such as
+   * strings containing comments, nested comments, etc.
+   */
+  void checkDocumentationComment(
+      UnlinkedDocumentationComment documentationComment, String text) {
+    expect(documentationComment, isNotNull);
+    int commentStart = text.indexOf('/*');
+    expect(commentStart, isNot(-1));
+    int commentEnd = text.indexOf('*/');
+    expect(commentEnd, isNot(-1));
+    commentEnd += 2;
+    String expectedCommentText =
+        text.substring(commentStart, commentEnd).replaceAll('\r\n', '\n');
+    expect(documentationComment.text, expectedCommentText);
+    expect(documentationComment.offset, commentStart);
+    expect(documentationComment.length, commentEnd - commentStart);
+  }
+
+  /**
+   * Verify that the given [typeRef] represents the type `dynamic`.
+   */
+  void checkDynamicTypeRef(EntityRef typeRef) {
+    checkTypeRef(typeRef, null, null, 'dynamic');
+  }
+
+  /**
+   * Verify that the given [exportName] represents a reference to an entity
+   * declared in a file reachable via [absoluteUri] and [relativeUri], having
+   * name [expectedName].  [expectedKind] is the kind of object referenced.
+   * [expectedTargetUnit] is the index of the compilation unit in which the
+   * target of the [exportName] is expected to appear; if not specified it is
+   * assumed to be the defining compilation unit.
+   */
+  void checkExportName(LinkedExportName exportName, String absoluteUri,
+      String relativeUri, String expectedName, ReferenceKind expectedKind,
+      {int expectedTargetUnit: 0}) {
+    expect(exportName, new isInstanceOf<LinkedExportName>());
+    // Exported names must come from other libraries.
+    expect(exportName.dependency, isNot(0));
+    checkDependency(exportName.dependency, absoluteUri, relativeUri);
+    expect(exportName.name, expectedName);
+    expect(exportName.kind, expectedKind);
+    expect(exportName.unit, expectedTargetUnit);
+  }
+
+  /**
+   * Verify that the dependency table contains an entry for a file reachable
+   * via the given [absoluteUri] and [relativeUri].  If [fullyLinked] is
+   * `true`, then the dependency should be a fully-linked dependency; otherwise
+   * it should be a prelinked dependency.
+   *
+   * The index of the [LinkedDependency] is returned.
+   */
+  int checkHasDependency(String absoluteUri, String relativeUri,
+      {bool fullyLinked: false}) {
+    if (expectAbsoluteUrisInDependencies) {
+      // The element model doesn't (yet) store enough information to recover
+      // relative URIs, so we have to use the absolute URI.
+      // TODO(paulberry): fix this.
+      relativeUri = absoluteUri;
+    }
+    List<String> found = <String>[];
+    for (int i = 0; i < linked.dependencies.length; i++) {
+      LinkedDependency dep = linked.dependencies[i];
+      if (dep.uri == relativeUri) {
+        if (fullyLinked) {
+          expect(i, greaterThanOrEqualTo(linked.numPrelinkedDependencies));
+        } else {
+          expect(i, lessThan(linked.numPrelinkedDependencies));
+        }
+        return i;
+      }
+      found.add(dep.uri);
+    }
+    fail('Did not find dependency $relativeUri.  Found: $found');
+    return null;
+  }
+
+  /**
+   * 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].
+   */
+  void checkInferredTypeSlot(
+      int slotId, String absoluteUri, String relativeUri, String expectedName,
+      {bool allowTypeParameters: false,
+      ReferenceKind expectedKind: ReferenceKind.classOrEnum,
+      int expectedTargetUnit: 0,
+      LinkedUnit linkedSourceUnit,
+      UnlinkedUnit unlinkedSourceUnit,
+      int numTypeParameters: 0}) {
+    if (strongMode) {
+      checkLinkedTypeSlot(slotId, absoluteUri, relativeUri, expectedName,
+          allowTypeParameters: allowTypeParameters,
+          expectedKind: expectedKind,
+          expectedTargetUnit: expectedTargetUnit,
+          linkedSourceUnit: linkedSourceUnit,
+          unlinkedSourceUnit: unlinkedSourceUnit,
+          numTypeParameters: numTypeParameters);
+    } else {
+      // A slot id should have been assigned but it should not be associated
+      // with any type.
+      expect(slotId, isNot(0));
+      expect(getTypeRefForSlot(slotId, linkedSourceUnit: linkedSourceUnit),
+          isNull);
+    }
+  }
+
+  /**
+   * Verify that the dependency table *does not* contain any entries for a file
+   * reachable via the given [absoluteUri] and [relativeUri].
+   */
+  void checkLacksDependency(String absoluteUri, String relativeUri) {
+    if (expectAbsoluteUrisInDependencies) {
+      // The element model doesn't (yet) store enough information to recover
+      // relative URIs, so we have to use the absolute URI.
+      // TODO(paulberry): fix this.
+      relativeUri = absoluteUri;
+    }
+    for (LinkedDependency dep in linked.dependencies) {
+      if (dep.uri == relativeUri) {
+        fail('Unexpected dependency found: $relativeUri');
+      }
+    }
+  }
+
+  /**
+   * Verify that the given [typeRef] represents a reference to a type declared
+   * in a file reachable via [absoluteUri] and [relativeUri], having name
+   * [expectedName].  If [allowTypeParameters] is true, allow the type
+   * reference to supply type parameters.  [expectedKind] is the kind of object
+   * referenced.  [linkedSourceUnit] and [unlinkedSourceUnit] refer to the
+   * compilation unit within which the [typeRef] appears; if not specified they
+   * are assumed to refer to the defining compilation unit.
+   * [expectedTargetUnit] is the index of the compilation unit in which the
+   * target of the [typeRef] is expected to appear; if not specified it is
+   * assumed to be the defining compilation unit.  [numTypeParameters] is the
+   * number of type parameters of the thing being referred to.
+   */
+  void checkLinkedTypeRef(EntityRef typeRef, String absoluteUri,
+      String relativeUri, String expectedName,
+      {bool allowTypeParameters: false,
+      ReferenceKind expectedKind: ReferenceKind.classOrEnum,
+      int expectedTargetUnit: 0,
+      LinkedUnit linkedSourceUnit,
+      UnlinkedUnit unlinkedSourceUnit,
+      int numTypeParameters: 0}) {
+    linkedSourceUnit ??= definingUnit;
+    expect(typeRef, isNotNull,
+        reason: 'No entry in linkedSourceUnit.types matching slotId');
+    expect(typeRef.paramReference, 0);
+    int index = typeRef.reference;
+    if (!allowTypeParameters) {
+      expect(typeRef.typeArguments, isEmpty);
+    }
+    checkTypeRefCommonElements(
+        index,
+        absoluteUri,
+        relativeUri,
+        expectedName,
+        expectedKind,
+        expectedTargetUnit,
+        linkedSourceUnit,
+        unlinkedSourceUnit,
+        numTypeParameters);
+  }
+
+  /**
+   * Verify that the given [slotId] represents a reference to a type declared
+   * in a file reachable via [absoluteUri] and [relativeUri], having name
+   * [expectedName].  If [allowTypeParameters] is true, allow the type
+   * reference to supply type parameters.  [expectedKind] is the kind of object
+   * referenced.  [linkedSourceUnit] and [unlinkedSourceUnit] refer to the
+   * compilation unit within which the [typeRef] appears; if not specified they
+   * are assumed to refer to the defining compilation unit.
+   * [expectedTargetUnit] is the index of the compilation unit in which the
+   * target of the [typeRef] is expected to appear; if not specified it is
+   * assumed to be the defining compilation unit.  [numTypeParameters] is the
+   * number of type parameters of the thing being referred to.
+   */
+  void checkLinkedTypeSlot(
+      int slotId, String absoluteUri, String relativeUri, String expectedName,
+      {bool allowTypeParameters: false,
+      ReferenceKind expectedKind: ReferenceKind.classOrEnum,
+      int expectedTargetUnit: 0,
+      LinkedUnit linkedSourceUnit,
+      UnlinkedUnit unlinkedSourceUnit,
+      int numTypeParameters: 0}) {
+    // Slot ids should be nonzero, since zero means "no associated slot".
+    expect(slotId, isNot(0));
+    if (skipFullyLinkedData) {
+      return;
+    }
+    linkedSourceUnit ??= definingUnit;
+    checkLinkedTypeRef(
+        getTypeRefForSlot(slotId, linkedSourceUnit: linkedSourceUnit),
+        absoluteUri,
+        relativeUri,
+        expectedName,
+        allowTypeParameters: allowTypeParameters,
+        expectedKind: expectedKind,
+        expectedTargetUnit: expectedTargetUnit,
+        linkedSourceUnit: linkedSourceUnit,
+        unlinkedSourceUnit: unlinkedSourceUnit,
+        numTypeParameters: numTypeParameters);
+  }
+
+  /**
+   * Verify that the given [typeRef] represents a reference to a type parameter
+   * having the given [deBruijnIndex].
+   */
+  void checkParamTypeRef(EntityRef typeRef, int deBruijnIndex) {
+    expect(typeRef, new isInstanceOf<EntityRef>());
+    expect(typeRef.reference, 0);
+    expect(typeRef.typeArguments, isEmpty);
+    expect(typeRef.paramReference, deBruijnIndex);
+  }
+
+  /**
+   * Verify that [prefixReference] is a valid reference to a prefix having the
+   * given [name].
+   */
+  void checkPrefix(int prefixReference, String name) {
+    expect(prefixReference, isNot(0));
+    expect(unlinkedUnits[0].references[prefixReference].prefixReference, 0);
+    expect(unlinkedUnits[0].references[prefixReference].name, name);
+    expect(definingUnit.references[prefixReference].dependency, 0);
+    expect(definingUnit.references[prefixReference].kind, ReferenceKind.prefix);
+    expect(definingUnit.references[prefixReference].unit, 0);
+  }
+
+  /**
+   * Verify that the given [typeRef] represents a reference to a type declared
+   * in a file reachable via [absoluteUri] and [relativeUri], having name
+   * [expectedName].  If [expectedPrefix] is supplied, verify that the type is
+   * reached via the given prefix.  If [allowTypeParameters] is true, allow the
+   * type reference to supply type parameters.  [expectedKind] is the kind of
+   * object referenced.  [linkedSourceUnit] and [unlinkedSourceUnit] refer
+   * to the compilation unit within which the [typeRef] appears; if not
+   * specified they are assumed to refer to the defining compilation unit.
+   * [expectedTargetUnit] is the index of the compilation unit in which the
+   * target of the [typeRef] is expected to appear; if not specified it is
+   * assumed to be the defining compilation unit.  [numTypeParameters] is the
+   * number of type parameters of the thing being referred to.
+   */
+  void checkTypeRef(EntityRef typeRef, String absoluteUri, String relativeUri,
+      String expectedName,
+      {String expectedPrefix,
+      List<_PrefixExpectation> prefixExpectations,
+      bool allowTypeParameters: false,
+      ReferenceKind expectedKind: ReferenceKind.classOrEnum,
+      int expectedTargetUnit: 0,
+      LinkedUnit linkedSourceUnit,
+      UnlinkedUnit unlinkedSourceUnit,
+      int numTypeParameters: 0}) {
+    linkedSourceUnit ??= definingUnit;
+    expect(typeRef, new isInstanceOf<EntityRef>());
+    expect(typeRef.paramReference, 0);
+    int index = typeRef.reference;
+    if (!allowTypeParameters) {
+      expect(typeRef.typeArguments, isEmpty);
+    }
+    UnlinkedReference reference = checkTypeRefCommonElements(
+        index,
+        absoluteUri,
+        relativeUri,
+        expectedName,
+        expectedKind,
+        expectedTargetUnit,
+        linkedSourceUnit,
+        unlinkedSourceUnit,
+        numTypeParameters);
+    expect(reference, isNotNull,
+        reason: 'Unlinked type refs must refer to an explicit reference');
+    if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
+      // summarize_elements.dart isn't yet able to record the prefix of
+      // unresolved references.  TODO(paulberry): fix this.
+      expect(reference.prefixReference, 0);
+    } else if (expectedPrefix != null) {
+      checkPrefix(reference.prefixReference, expectedPrefix);
+    } else if (prefixExpectations != null) {
+      for (_PrefixExpectation expectation in prefixExpectations) {
+        expect(reference.prefixReference, isNot(0));
+        reference = checkTypeRefCommonElements(
+            reference.prefixReference,
+            expectation.inLibraryDefiningUnit
+                ? null
+                : expectation.absoluteUri ?? absoluteUri,
+            expectation.inLibraryDefiningUnit
+                ? null
+                : expectation.relativeUri ?? relativeUri,
+            expectation.name,
+            expectation.kind,
+            expectedTargetUnit,
+            linkedSourceUnit,
+            unlinkedSourceUnit,
+            expectation.numTypeParameters);
+      }
+      expect(reference.prefixReference, 0);
+    } else {
+      expect(reference.prefixReference, 0);
+    }
+  }
+
+  /**
+   * Check the data structures that are common between [checkTypeRef] and
+   * [checkLinkedTypeRef].  If the type reference in question is an explicit
+   * reference, return the [UnlinkedReference] that is used to make the
+   * explicit reference.  If the type reference in question is an implicit
+   * reference, return `null`.
+   */
+  UnlinkedReference checkTypeRefCommonElements(
+      int referenceIndex,
+      String absoluteUri,
+      String relativeUri,
+      String expectedName,
+      ReferenceKind expectedKind,
+      int expectedTargetUnit,
+      LinkedUnit linkedSourceUnit,
+      UnlinkedUnit unlinkedSourceUnit,
+      int numTypeParameters) {
+    unlinkedSourceUnit ??= unlinkedUnits[0];
+    LinkedReference referenceResolution =
+        linkedSourceUnit.references[referenceIndex];
+    String name;
+    UnlinkedReference reference;
+    if (referenceIndex < unlinkedSourceUnit.references.length) {
+      // This is an explicit reference, so its name and prefix should be in
+      // [UnlinkedUnit.references].
+      expect(referenceResolution.name, isEmpty);
+      reference = unlinkedSourceUnit.references[referenceIndex];
+      name = reference.name;
+      if (reference.prefixReference != 0) {
+        // Prefixes should appear in the references table before any reference
+        // that uses them.
+        expect(reference.prefixReference, lessThan(referenceIndex));
+      }
+    } else {
+      // This is an implicit reference, so its name should be in
+      // [LinkedUnit.references].
+      name = referenceResolution.name;
+    }
+    // Index 0 is reserved.
+    expect(referenceIndex, isNot(0));
+    if (absoluteUri == null) {
+      expect(referenceResolution.dependency, 0);
+    } else {
+      checkDependency(referenceResolution.dependency, absoluteUri, relativeUri);
+    }
+    if (expectedKind == ReferenceKind.unresolved && !checkAstDerivedData) {
+      // summarize_elements.dart isn't yet able to record the name of
+      // unresolved references.  TODO(paulberry): fix this.
+      expect(name, '*unresolved*');
+    } else {
+      if (expectedName == null) {
+        expect(name, isEmpty);
+      } else {
+        expect(name, expectedName);
+      }
+    }
+    expect(referenceResolution.kind, expectedKind);
+    expect(referenceResolution.unit, expectedTargetUnit);
+    expect(referenceResolution.numTypeParameters, numTypeParameters);
+    return reference;
+  }
+
+  /**
+   * Verify that the given [typeRef] represents a reference to an unresolved
+   * type.
+   */
+  void checkUnresolvedTypeRef(
+      EntityRef typeRef, String expectedPrefix, String expectedName,
+      {LinkedUnit linkedSourceUnit, UnlinkedUnit unlinkedSourceUnit}) {
+    // When serializing from the element model, unresolved type refs lose their
+    // name.
+    checkTypeRef(typeRef, null, null, checkAstDerivedData ? expectedName : null,
+        expectedPrefix: expectedPrefix,
+        expectedKind: ReferenceKind.unresolved,
+        linkedSourceUnit: linkedSourceUnit,
+        unlinkedSourceUnit: unlinkedSourceUnit);
+  }
+
+  /**
+   * Verify that the given [typeRef] represents the type `void`.
+   */
+  void checkVoidTypeRef(EntityRef typeRef) {
+    checkTypeRef(typeRef, null, null, 'void');
+  }
+
+  fail_enum_value_documented() {
+    // TODO(paulberry): currently broken because of dartbug.com/25385
+    String text = '''
+enum E {
+  /**
+   * Docs
+   */
+  v
+}''';
+    UnlinkedEnumValue value = serializeEnumText(text).values[0];
+    expect(value.documentationComment, isNotNull);
+    checkDocumentationComment(value.documentationComment, text);
+  }
+
+  /**
+   * Find the class with the given [className] in the summary, and return its
+   * [UnlinkedClass] data structure.  If [unit] is not given, the class is
+   * looked for in the defining compilation unit.
+   */
+  UnlinkedClass findClass(String className,
+      {bool failIfAbsent: false, UnlinkedUnit unit}) {
+    unit ??= unlinkedUnits[0];
+    UnlinkedClass result;
+    for (UnlinkedClass cls in unit.classes) {
+      if (cls.name == className) {
+        if (result != null) {
+          fail('Duplicate class $className');
+        }
+        result = cls;
+      }
+    }
+    if (result == null && failIfAbsent) {
+      fail('Class $className not found in serialized output');
+    }
+    return result;
+  }
+
+  /**
+   * Find the enum with the given [enumName] in the summary, and return its
+   * [UnlinkedEnum] data structure.  If [unit] is not given, the enum is looked
+   * for in the defining compilation unit.
+   */
+  UnlinkedEnum findEnum(String enumName,
+      {bool failIfAbsent: false, UnlinkedUnit unit}) {
+    unit ??= unlinkedUnits[0];
+    UnlinkedEnum result;
+    for (UnlinkedEnum e in unit.enums) {
+      if (e.name == enumName) {
+        if (result != null) {
+          fail('Duplicate enum $enumName');
+        }
+        result = e;
+      }
+    }
+    if (result == null && failIfAbsent) {
+      fail('Enum $enumName not found in serialized output');
+    }
+    return result;
+  }
+
+  /**
+   * Find the executable with the given [executableName] in the summary, and
+   * return its [UnlinkedExecutable] data structure.  If [executables] is not
+   * given, then the executable is searched for in the defining compilation
+   * unit.
+   */
+  UnlinkedExecutable findExecutable(String executableName,
+      {List<UnlinkedExecutable> executables, bool failIfAbsent: false}) {
+    executables ??= unlinkedUnits[0].executables;
+    UnlinkedExecutable result;
+    for (UnlinkedExecutable executable in executables) {
+      if (executable.name == executableName) {
+        if (result != null) {
+          fail('Duplicate executable $executableName');
+        }
+        result = executable;
+      }
+    }
+    if (result == null && failIfAbsent) {
+      fail('Executable $executableName not found in serialized output');
+    }
+    return result;
+  }
+
+  /**
+   * Find the typedef with the given [typedefName] in the summary, and return
+   * its [UnlinkedTypedef] data structure.  If [unit] is not given, the typedef
+   * is looked for in the defining compilation unit.
+   */
+  UnlinkedTypedef findTypedef(String typedefName,
+      {bool failIfAbsent: false, UnlinkedUnit unit}) {
+    unit ??= unlinkedUnits[0];
+    UnlinkedTypedef result;
+    for (UnlinkedTypedef type in unit.typedefs) {
+      if (type.name == typedefName) {
+        if (result != null) {
+          fail('Duplicate typedef $typedefName');
+        }
+        result = type;
+      }
+    }
+    if (result == null && failIfAbsent) {
+      fail('Typedef $typedefName not found in serialized output');
+    }
+    return result;
+  }
+
+  /**
+   * Find the top level variable with the given [variableName] in the summary,
+   * and return its [UnlinkedVariable] data structure.  If [variables] is not
+   * specified, the variable is looked for in the defining compilation unit.
+   */
+  UnlinkedVariable findVariable(String variableName,
+      {List<UnlinkedVariable> variables, bool failIfAbsent: false}) {
+    variables ??= unlinkedUnits[0].variables;
+    UnlinkedVariable result;
+    for (UnlinkedVariable variable in variables) {
+      if (variable.name == variableName) {
+        if (result != null) {
+          fail('Duplicate variable $variableName');
+        }
+        result = variable;
+      }
+    }
+    if (result == null && failIfAbsent) {
+      fail('Variable $variableName not found in serialized output');
+    }
+    return result;
+  }
+
+  /**
+   * Find the entry in [linkedSourceUnit.types] matching [slotId].
+   */
+  EntityRef getTypeRefForSlot(int slotId, {LinkedUnit linkedSourceUnit}) {
+    linkedSourceUnit ??= definingUnit;
+    for (EntityRef typeRef in linkedSourceUnit.types) {
+      if (typeRef.slot == slotId) {
+        return typeRef;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Serialize the given library [text] and return the summary of the class
+   * with the given [className].
+   */
+  UnlinkedClass serializeClassText(String text,
+      {String className: 'C', bool allowErrors: false}) {
+    serializeLibraryText(text, allowErrors: allowErrors);
+    return findClass(className, failIfAbsent: true);
+  }
+
+  /**
+   * Serialize the given library [text] and return the summary of the enum with
+   * the given [enumName].
+   */
+  UnlinkedEnum serializeEnumText(String text, [String enumName = 'E']) {
+    serializeLibraryText(text);
+    return findEnum(enumName, failIfAbsent: true);
+  }
+
+  /**
+   * Serialize the given library [text] and return the summary of the
+   * executable with the given [executableName].
+   */
+  UnlinkedExecutable serializeExecutableText(String text,
+      [String executableName = 'f']) {
+    serializeLibraryText(text);
+    return findExecutable(executableName, failIfAbsent: true);
+  }
+
+  /**
+   * Serialize the given library [text], then deserialize it and store its
+   * summary in [lib].
+   */
+  void serializeLibraryText(String text, {bool allowErrors: false});
+
+  /**
+   * Serialize the given method [text] and return the summary of the executable
+   * with the given [executableName].
+   */
+  UnlinkedExecutable serializeMethodText(String text,
+      [String executableName = 'f']) {
+    serializeLibraryText('class C { $text }');
+    return findExecutable(executableName,
+        executables: findClass('C', failIfAbsent: true).executables,
+        failIfAbsent: true);
+  }
+
+  /**
+   * Serialize the given library [text] and return the summary of the typedef
+   * with the given [typedefName].
+   */
+  UnlinkedTypedef serializeTypedefText(String text,
+      [String typedefName = 'F']) {
+    serializeLibraryText(text);
+    return findTypedef(typedefName, failIfAbsent: true);
+  }
+
+  /**
+   * Serialize a type declaration using the given [text] as a type name, and
+   * return a summary of the corresponding [EntityRef].  If the type
+   * declaration needs to refer to types that are not available in core, those
+   * types may be declared in [otherDeclarations].
+   */
+  EntityRef serializeTypeText(String text,
+      {String otherDeclarations: '', bool allowErrors: false}) {
+    return serializeVariableText('$otherDeclarations\n$text v;',
+            allowErrors: allowErrors)
+        .type;
+  }
+
+  /**
+   * Serialize the given library [text] and return the summary of the variable
+   * with the given [variableName].
+   */
+  UnlinkedVariable serializeVariableText(String text,
+      {String variableName: 'v', bool allowErrors: false}) {
+    serializeLibraryText(text, allowErrors: allowErrors);
+    return findVariable(variableName, failIfAbsent: true);
+  }
+
+  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 {}');
+    serializeLibraryText(
+        '''
+import 'lib1.dart';
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(
+        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_export_hide_show() {
+    addNamedSource('/lib1.dart', 'export "lib2.dart" hide C show A, C;');
+    addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib1.dart';
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(
+        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_export_show_hide() {
+    addNamedSource('/lib1.dart', 'export "lib2.dart" show A, B hide B, C;');
+    addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib1.dart';
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(
+        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_export_show_show() {
+    addNamedSource('/lib1.dart', 'export "lib2.dart" show A, B show A, C;');
+    addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib1.dart';
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(
+        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_import_hide_hide() {
+    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib.dart' hide C hide B, C;
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_import_hide_show() {
+    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib.dart' hide C show A, C;
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_import_show_hide() {
+    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib.dart' show A, B hide B, C;
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_cascaded_import_show_show() {
+    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
+    serializeLibraryText(
+        '''
+import 'lib.dart' show A, B show A, C;
+A a;
+B b;
+C c;
+    ''',
+        allowErrors: true);
+    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
+    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
+    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
+  }
+
+  test_class_abstract() {
+    UnlinkedClass cls = serializeClassText('abstract class C {}');
+    expect(cls.isAbstract, true);
+  }
+
+  test_class_alias_abstract() {
+    UnlinkedClass cls = serializeClassText(
+        'abstract class C = D with E; class D {} class E {}');
+    expect(cls.isAbstract, true);
+  }
+
+  test_class_alias_concrete() {
+    UnlinkedClass cls =
+        serializeClassText('class C = _D with _E; class _D {} class _E {}');
+    expect(cls.isAbstract, false);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.classOrEnum);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
+  }
+
+  test_class_alias_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+class C = D with E;
+
+class D {}
+class E {}''';
+    UnlinkedClass cls = serializeClassText(text);
+    expect(cls.documentationComment, isNotNull);
+    checkDocumentationComment(cls.documentationComment, text);
+  }
+
+  test_class_alias_flag() {
+    UnlinkedClass cls =
+        serializeClassText('class C = D with E; class D {} class E {}');
+    expect(cls.isMixinApplication, true);
+  }
+
+  test_class_alias_generic() {
+    serializeClassText('class C<A, B> = _D with _E; class _D {} class _E {}');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 2);
+  }
+
+  test_class_alias_mixin_order() {
+    UnlinkedClass cls = serializeClassText('''
+class C = D with E, F;
+class D {}
+class E {}
+class F {}
+''');
+    expect(cls.mixins, hasLength(2));
+    checkTypeRef(cls.mixins[0], null, null, 'E');
+    checkTypeRef(cls.mixins[1], null, null, 'F');
+  }
+
+  test_class_alias_no_implicit_constructors() {
+    UnlinkedClass cls = serializeClassText('''
+class C = D with E;
+class D {
+  D.foo();
+  D.bar();
+}
+class E {}
+''');
+    expect(cls.executables, isEmpty);
+  }
+
+  test_class_alias_private() {
+    serializeClassText('class _C = _D with _E; class _D {} class _E {}',
+        className: '_C');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_class_alias_reference_generic() {
+    EntityRef typeRef = serializeTypeText('C',
+        otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}');
+    checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
+  }
+
+  test_class_alias_reference_generic_imported() {
+    addNamedSource(
+        '/lib.dart', 'class C<D, E> = F with G; class F {} class G {}');
+    EntityRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
+    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
+        numTypeParameters: 2);
+  }
+
+  test_class_alias_supertype() {
+    UnlinkedClass cls =
+        serializeClassText('class C = D with E; class D {} class E {}');
+    checkTypeRef(cls.supertype, null, null, 'D');
+    expect(cls.hasNoSupertype, isFalse);
+  }
+
+  test_class_concrete() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.isAbstract, false);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.classOrEnum);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
+  }
+
+  test_class_constMembers() {
+    UnlinkedClass cls = serializeClassText('''
+class C {
+  int fieldInstance = 0;
+  final int fieldInstanceFinal = 0;
+  static int fieldStatic = 0;
+  static final int fieldStaticFinal = 0;
+  static const int fieldStaticConst = 0;
+  static const int _fieldStaticConstPrivate = 0;
+  static void methodStaticPublic() {}
+  static void _methodStaticPrivate() {}
+  void methodInstancePublic() {}
+  C operator+(C c) => null;
+}
+''');
+    expect(cls.isAbstract, false);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    UnlinkedPublicName className = unlinkedUnits[0].publicNamespace.names[0];
+    expect(className.kind, ReferenceKind.classOrEnum);
+    expect(className.name, 'C');
+    expect(className.numTypeParameters, 0);
+    // executables
+    Map<String, UnlinkedPublicName> executablesMap =
+        <String, UnlinkedPublicName>{};
+    className.constMembers.forEach((e) => executablesMap[e.name] = e);
+    expect(executablesMap, hasLength(2));
+    {
+      UnlinkedPublicName executable = executablesMap['fieldStaticConst'];
+      expect(executable.kind, ReferenceKind.constField);
+      expect(executable.constMembers, isEmpty);
+    }
+    {
+      UnlinkedPublicName executable = executablesMap['methodStaticPublic'];
+      expect(executable.kind, ReferenceKind.staticMethod);
+      expect(executable.constMembers, isEmpty);
+    }
+  }
+
+  test_class_constMembers_constructors() {
+    UnlinkedClass cls = serializeClassText('''
+class C {
+  const C();
+  const C.constructorNamedPublicConst();
+  C.constructorNamedPublic();
+  C._constructorNamedPrivate();
+}
+''');
+    expect(cls.isAbstract, false);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    UnlinkedPublicName className = unlinkedUnits[0].publicNamespace.names[0];
+    expect(className.kind, ReferenceKind.classOrEnum);
+    expect(className.name, 'C');
+    expect(className.numTypeParameters, 0);
+    // executables
+    Map<String, UnlinkedPublicName> executablesMap =
+        <String, UnlinkedPublicName>{};
+    className.constMembers.forEach((e) => executablesMap[e.name] = e);
+    expect(executablesMap, hasLength(2));
+    {
+      UnlinkedPublicName executable = executablesMap[''];
+      expect(executable.kind, ReferenceKind.constructor);
+      expect(executable.constMembers, isEmpty);
+    }
+    {
+      UnlinkedPublicName executable =
+          executablesMap['constructorNamedPublicConst'];
+      expect(executable.kind, ReferenceKind.constructor);
+      expect(executable.constMembers, isEmpty);
+    }
+  }
+
+  test_class_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+class C {}''';
+    UnlinkedClass cls = serializeClassText(text);
+    expect(cls.documentationComment, isNotNull);
+    checkDocumentationComment(cls.documentationComment, text);
+  }
+
+  test_class_documented_with_references() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs referring to [D] and [E]
+ */
+class C {}
+
+class D {}
+class E {}''';
+    UnlinkedClass cls = serializeClassText(text);
+    expect(cls.documentationComment, isNotNull);
+    checkDocumentationComment(cls.documentationComment, text);
+  }
+
+  test_class_documented_with_with_windows_line_endings() {
+    String text = '/**\r\n * Docs\r\n */\r\nclass C {}';
+    UnlinkedClass cls = serializeClassText(text);
+    expect(cls.documentationComment, isNotNull);
+    checkDocumentationComment(cls.documentationComment, text);
+  }
+
+  test_class_interface() {
+    UnlinkedClass cls = serializeClassText('''
+class C implements D {}
+class D {}
+''');
+    expect(cls.interfaces, hasLength(1));
+    checkTypeRef(cls.interfaces[0], null, null, 'D');
+  }
+
+  test_class_interface_order() {
+    UnlinkedClass cls = serializeClassText('''
+class C implements D, E {}
+class D {}
+class E {}
+''');
+    expect(cls.interfaces, hasLength(2));
+    checkTypeRef(cls.interfaces[0], null, null, 'D');
+    checkTypeRef(cls.interfaces[1], null, null, 'E');
+  }
+
+  test_class_mixin() {
+    UnlinkedClass cls = serializeClassText('''
+class C extends Object with D {}
+class D {}
+''');
+    expect(cls.mixins, hasLength(1));
+    checkTypeRef(cls.mixins[0], null, null, 'D');
+  }
+
+  test_class_mixin_order() {
+    UnlinkedClass cls = serializeClassText('''
+class C extends Object with D, E {}
+class D {}
+class E {}
+''');
+    expect(cls.mixins, hasLength(2));
+    checkTypeRef(cls.mixins[0], null, null, 'D');
+    checkTypeRef(cls.mixins[1], null, null, 'E');
+  }
+
+  test_class_name() {
+    var classText = 'class C {}';
+    UnlinkedClass cls = serializeClassText(classText);
+    expect(cls.name, 'C');
+    expect(cls.nameOffset, classText.indexOf('C'));
+  }
+
+  test_class_no_flags() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.isAbstract, false);
+    expect(cls.isMixinApplication, false);
+  }
+
+  test_class_no_interface() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.interfaces, isEmpty);
+  }
+
+  test_class_no_mixins() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.mixins, isEmpty);
+  }
+
+  test_class_no_type_param() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.typeParameters, isEmpty);
+  }
+
+  test_class_non_alias_flag() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.isMixinApplication, false);
+  }
+
+  test_class_private() {
+    serializeClassText('class _C {}', className: '_C');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_class_reference_generic() {
+    EntityRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'class C<D, E> {}');
+    checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
+  }
+
+  test_class_reference_generic_imported() {
+    addNamedSource('/lib.dart', 'class C<D, E> {}');
+    EntityRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
+    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
+        numTypeParameters: 2);
+  }
+
+  test_class_superclass() {
+    UnlinkedClass cls = serializeClassText('class C {}');
+    expect(cls.supertype, isNull);
+    expect(cls.hasNoSupertype, isFalse);
+  }
+
+  test_class_superclass_explicit() {
+    UnlinkedClass cls = serializeClassText('class C extends D {} class D {}');
+    expect(cls.supertype, isNotNull);
+    checkTypeRef(cls.supertype, null, null, 'D');
+    expect(cls.hasNoSupertype, isFalse);
+  }
+
+  test_class_type_param_bound() {
+    UnlinkedClass cls = serializeClassText('class C<T extends List> {}');
+    expect(cls.typeParameters, hasLength(1));
+    expect(cls.typeParameters[0].name, 'T');
+    expect(cls.typeParameters[0].bound, isNotNull);
+    checkTypeRef(cls.typeParameters[0].bound, 'dart:core', 'dart:core', 'List',
+        allowTypeParameters: true, numTypeParameters: 1);
+  }
+
+  test_class_type_param_f_bound() {
+    UnlinkedClass cls = serializeClassText('class C<T, U extends List<T>> {}');
+    EntityRef typeArgument = cls.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 2);
+  }
+
+  test_class_type_param_f_bound_self_ref() {
+    UnlinkedClass cls = serializeClassText('class C<T, U extends List<U>> {}');
+    EntityRef typeArgument = cls.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 1);
+  }
+
+  test_class_type_param_no_bound() {
+    String text = 'class C<T> {}';
+    UnlinkedClass cls = serializeClassText(text);
+    expect(cls.typeParameters, hasLength(1));
+    expect(cls.typeParameters[0].name, 'T');
+    expect(cls.typeParameters[0].nameOffset, text.indexOf('T'));
+    expect(cls.typeParameters[0].bound, isNull);
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
+  }
+
+  test_constExpr_binary_add() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 + 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.add
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_and() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = true && false;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushTrue,
+      UnlinkedConstOperation.pushFalse,
+      UnlinkedConstOperation.and
+    ]);
+  }
+
+  test_constExpr_binary_bitAnd() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 & 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.bitAnd
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_bitOr() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 | 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.bitOr
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_bitShiftLeft() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 << 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.bitShiftLeft
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_bitShiftRight() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 >> 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.bitShiftRight
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_bitXor() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 ^ 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.bitXor
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_divide() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 / 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.divide
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_equal() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 == 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.equal
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_equal_not() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 != 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.equal,
+      UnlinkedConstOperation.not
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_floorDivide() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 ~/ 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.floorDivide
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_greater() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 > 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.greater
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_greaterEqual() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 >= 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.greaterEqual
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_less() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 < 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.less
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_lessEqual() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 <= 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.lessEqual
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_modulo() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 % 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.modulo
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_multiply() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 * 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.multiply
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_binary_or() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = false || true;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushFalse,
+      UnlinkedConstOperation.pushTrue,
+      UnlinkedConstOperation.or
+    ]);
+  }
+
+  test_constExpr_binary_subtract() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1 - 2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.subtract
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_conditional() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = true ? 1 : 2;', allowErrors: true);
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushTrue,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.conditional
+    ], ints: [
+      1,
+      2
+    ]);
+  }
+
+  test_constExpr_identical() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = identical(42, null);');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushNull,
+      UnlinkedConstOperation.identical
+    ], ints: [
+      42
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_named() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  const C.named();
+}
+const v = const C.named();
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'named',
+              expectedKind: ReferenceKind.constructor,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_named_imported() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  const C.named();
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = const C.named();
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'named',
+              expectedKind: ReferenceKind.constructor,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_named_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  const C.named();
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = const p.C.named();
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'named',
+              expectedKind: ReferenceKind.constructor,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unnamed() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  const C(a, b, c, d, {e, f, g});
+}
+const v = const C(11, 22, 3.3, '444', e: 55, g: '777', f: 66);
+''');
+    // Stack: 11 22 3.3 '444' 55 '777' 66 ^head
+    // Ints: ^pointer 3 4
+    // Doubles: ^pointer
+    // Strings: ^pointer 'e' 'g' 'f' ''
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushDouble,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      11,
+      22,
+      55,
+      66,
+      3,
+      4,
+    ], doubles: [
+      3.3
+    ], strings: [
+      '444',
+      '777',
+      'e',
+      'g',
+      'f'
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'C',
+          expectedKind: ReferenceKind.classOrEnum)
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unnamed_imported() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  const C();
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = const C();
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'C',
+          expectedKind: ReferenceKind.classOrEnum)
+    ]);
+  }
+
+  test_constExpr_invokeConstructor_unnamed_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  const C();
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = const p.C();
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.invokeConstructor,
+    ], ints: [
+      0,
+      0
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'C',
+              expectedKind: ReferenceKind.classOrEnum,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_length_classConstField() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  static const int length = 0;
+}
+const int v = C.length;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'length',
+              expectedKind: ReferenceKind.constField,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_length_classConstField_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static const int length = 0;
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const int v = p.C.length;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'length',
+              expectedKind: ReferenceKind.constField,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_length_identifierTarget() {
+    UnlinkedVariable variable = serializeVariableText('''
+const String a = 'aaa';
+const int v = a.length;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'length',
+              expectedKind: ReferenceKind.length,
+              prefixExpectations: [
+                new _PrefixExpectation(
+                    ReferenceKind.topLevelPropertyAccessor, 'a')
+              ])
+    ]);
+  }
+
+  test_constExpr_length_identifierTarget_classConstField() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  static const String F = '';
+}
+const int v = C.F.length;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'length',
+              expectedKind: ReferenceKind.length,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.constField, 'F'),
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C'),
+              ])
+    ]);
+  }
+
+  test_constExpr_length_identifierTarget_imported() {
+    addNamedSource(
+        '/a.dart',
+        '''
+const String a = 'aaa';
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const int v = a.length;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'length',
+              expectedKind: ReferenceKind.length,
+              prefixExpectations: [
+                new _PrefixExpectation(
+                    ReferenceKind.topLevelPropertyAccessor, 'a',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart')
+              ])
+    ]);
+  }
+
+  test_constExpr_length_identifierTarget_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+const String a = 'aaa';
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const int v = p.a.length;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'length',
+              expectedKind: ReferenceKind.length,
+              prefixExpectations: [
+                new _PrefixExpectation(
+                    ReferenceKind.topLevelPropertyAccessor, 'a',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_length_parenthesizedBinaryTarget() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = ("abc" + "edf").length;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.add,
+      UnlinkedConstOperation.length
+    ], strings: [
+      'abc',
+      'edf'
+    ]);
+  }
+
+  test_constExpr_length_parenthesizedStringTarget() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = ("abc").length;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.length
+    ], strings: [
+      'abc'
+    ]);
+  }
+
+  test_constExpr_length_stringLiteralTarget() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = "abc".length;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.length
+    ], strings: [
+      'abc'
+    ]);
+  }
+
+  test_constExpr_makeSymbol() {
+    UnlinkedVariable variable = serializeVariableText('const v = #a.bb.ccc;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.makeSymbol
+    ], strings: [
+      'a.bb.ccc'
+    ]);
+  }
+
+  test_constExpr_makeTypedList() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = const <int>[11, 22, 33];');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.makeTypedList
+    ], ints: [
+      11,
+      22,
+      33,
+      3
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'dart:core', 'int',
+          expectedKind: ReferenceKind.classOrEnum)
+    ]);
+  }
+
+  test_constExpr_makeTypedList_dynamic() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = const <dynamic>[11, 22, 33];');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.makeTypedList
+    ], ints: [
+      11,
+      22,
+      33,
+      3
+    ], referenceValidators: [
+      (EntityRef r) => checkDynamicTypeRef(r)
+    ]);
+  }
+
+  test_constExpr_makeTypedMap() {
+    UnlinkedVariable variable = serializeVariableText(
+        'const v = const <int, String>{11: "aaa", 22: "bbb", 33: "ccc"};');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.makeTypedMap
+    ], ints: [
+      11,
+      22,
+      33,
+      3
+    ], strings: [
+      'aaa',
+      'bbb',
+      'ccc'
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'dart:core', 'int',
+          expectedKind: ReferenceKind.classOrEnum),
+      (EntityRef r) => checkTypeRef(r, 'dart:core', 'dart:core', 'String',
+          expectedKind: ReferenceKind.classOrEnum)
+    ]);
+  }
+
+  test_constExpr_makeTypedMap_dynamic() {
+    UnlinkedVariable variable = serializeVariableText(
+        'const v = const <dynamic, dynamic>{11: "aaa", 22: "bbb", 33: "ccc"};');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.makeTypedMap
+    ], ints: [
+      11,
+      22,
+      33,
+      3
+    ], strings: [
+      'aaa',
+      'bbb',
+      'ccc'
+    ], referenceValidators: [
+      (EntityRef r) => checkDynamicTypeRef(r),
+      (EntityRef r) => checkDynamicTypeRef(r)
+    ]);
+  }
+
+  test_constExpr_makeUntypedList() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = const [11, 22, 33];');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.makeUntypedList
+    ], ints: [
+      11,
+      22,
+      33,
+      3
+    ]);
+  }
+
+  test_constExpr_makeUntypedMap() {
+    UnlinkedVariable variable = serializeVariableText(
+        'const v = const {11: "aaa", 22: "bbb", 33: "ccc"};');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.makeUntypedMap
+    ], ints: [
+      11,
+      22,
+      33,
+      3
+    ], strings: [
+      'aaa',
+      'bbb',
+      'ccc'
+    ]);
+  }
+
+  test_constExpr_parenthesized() {
+    UnlinkedVariable variable = serializeVariableText('const v = (1 + 2) * 3;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.add,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.multiply,
+    ], ints: [
+      1,
+      2,
+      3
+    ]);
+  }
+
+  test_constExpr_prefix_complement() {
+    UnlinkedVariable variable = serializeVariableText('const v = ~2;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.complement
+    ], ints: [
+      2
+    ]);
+  }
+
+  test_constExpr_prefix_negate() {
+    UnlinkedVariable variable = serializeVariableText('const v = -(2);');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.negate
+    ], ints: [
+      2
+    ]);
+  }
+
+  test_constExpr_prefix_not() {
+    UnlinkedVariable variable = serializeVariableText('const v = !true;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushTrue,
+      UnlinkedConstOperation.not
+    ]);
+  }
+
+  test_constExpr_pushDouble() {
+    UnlinkedVariable variable = serializeVariableText('const v = 123.4567;');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushDouble], doubles: [123.4567]);
+  }
+
+  test_constExpr_pushFalse() {
+    UnlinkedVariable variable = serializeVariableText('const v = false;');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushFalse]);
+  }
+
+  test_constExpr_pushInt() {
+    UnlinkedVariable variable = serializeVariableText('const v = 1;');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+  }
+
+  test_constExpr_pushInt_max() {
+    UnlinkedVariable variable = serializeVariableText('const v = 0xFFFFFFFF;');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushInt,], ints: [0xFFFFFFFF]);
+  }
+
+  test_constExpr_pushInt_negative() {
+    UnlinkedVariable variable = serializeVariableText('const v = -5;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.negate
+    ], ints: [
+      5
+    ]);
+  }
+
+  test_constExpr_pushInt_shiftOr_long() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = 0xA123456789ABCDEF012345678;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.shiftOr,
+      UnlinkedConstOperation.shiftOr,
+      UnlinkedConstOperation.shiftOr
+    ], ints: [
+      0xA,
+      0x12345678,
+      0x9ABCDEF0,
+      0x12345678
+    ]);
+  }
+
+  test_constExpr_pushInt_shiftOr_min() {
+    UnlinkedVariable variable = serializeVariableText('const v = 0x100000000;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.shiftOr,
+    ], ints: [
+      1,
+      0,
+    ]);
+  }
+
+  test_constExpr_pushInt_shiftOr_min2() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = 0x10000000000000000;');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.shiftOr,
+      UnlinkedConstOperation.shiftOr,
+    ], ints: [
+      1,
+      0,
+      0,
+    ]);
+  }
+
+  test_constExpr_pushNull() {
+    UnlinkedVariable variable = serializeVariableText('const v = null;');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushNull]);
+  }
+
+  test_constExpr_pushReference_class() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {}
+const v = C;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'C',
+          expectedKind: ReferenceKind.classOrEnum)
+    ]);
+  }
+
+  test_constExpr_pushReference_enum() {
+    UnlinkedVariable variable = serializeVariableText('''
+enum C {V1, V2, V3}
+const v = C;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'C',
+          expectedKind: ReferenceKind.classOrEnum)
+    ]);
+  }
+
+  test_constExpr_pushReference_field() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  static const int F = 1;
+}
+const v = C.F;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'F',
+              expectedKind: ReferenceKind.constField,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_field_imported() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static const int F = 1;
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = C.F;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'F',
+              expectedKind: ReferenceKind.constField,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_field_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static const int F = 1;
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = p.C.F;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'F',
+              expectedKind: ReferenceKind.constField,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true),
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_staticMethod() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  static m() {}
+}
+const v = C.m;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'm',
+              expectedKind: ReferenceKind.staticMethod,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_staticMethod_imported() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static m() {}
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = C.m;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'm',
+              expectedKind: ReferenceKind.staticMethod,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_staticMethod_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static m() {}
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = p.C.m;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'm',
+              expectedKind: ReferenceKind.staticMethod,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p',
+                    inLibraryDefiningUnit: true)
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_topLevelVariable() {
+    UnlinkedVariable variable = serializeVariableText('''
+const int a = 1;
+const v = a;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'a',
+          expectedKind: ReferenceKind.topLevelPropertyAccessor)
+    ]);
+  }
+
+  test_constExpr_pushReference_topLevelVariable_imported() {
+    addNamedSource('/a.dart', 'const int a = 1;');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = a;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'a',
+          expectedKind: ReferenceKind.topLevelPropertyAccessor)
+    ]);
+  }
+
+  test_constExpr_pushReference_topLevelVariable_imported_withPrefix() {
+    addNamedSource('/a.dart', 'const int a = 1;');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = p.a;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) {
+        return checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'a',
+            expectedKind: ReferenceKind.topLevelPropertyAccessor,
+            expectedPrefix: 'p');
+      }
+    ]);
+  }
+
+  test_constExpr_pushString_adjacent() {
+    UnlinkedVariable variable =
+        serializeVariableText('const v = "aaa" "b" "ccc";');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushString], strings: ['aaabccc']);
+  }
+
+  test_constExpr_pushString_adjacent_interpolation() {
+    UnlinkedVariable variable =
+        serializeVariableText(r'const v = "aaa" "bb ${42} bbb" "cccc";');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.concatenate,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.concatenate,
+    ], ints: [
+      42,
+      3,
+      3,
+    ], strings: [
+      'aaa',
+      'bb ',
+      ' bbb',
+      'cccc'
+    ]);
+  }
+
+  test_constExpr_pushString_interpolation() {
+    UnlinkedVariable variable =
+        serializeVariableText(r'const v = "aaa ${42} bbb";');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.pushInt,
+      UnlinkedConstOperation.pushString,
+      UnlinkedConstOperation.concatenate
+    ], ints: [
+      42,
+      3
+    ], strings: [
+      'aaa ',
+      ' bbb'
+    ]);
+  }
+
+  test_constExpr_pushString_simple() {
+    UnlinkedVariable variable = serializeVariableText('const v = "abc";');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushString], strings: ['abc']);
+  }
+
+  test_constExpr_pushTrue() {
+    UnlinkedVariable variable = serializeVariableText('const v = true;');
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushTrue]);
+  }
+
+  test_constructor() {
+    String text = 'class C { C(); }';
+    UnlinkedExecutable executable =
+        findExecutable('', executables: serializeClassText(text).executables);
+    expect(executable.kind, UnlinkedExecutableKind.constructor);
+    expect(executable.returnType, isNull);
+    expect(executable.isExternal, isFalse);
+    expect(executable.nameOffset, text.indexOf('C();'));
+  }
+
+  test_constructor_anonymous() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(); }').executables);
+    expect(executable.name, isEmpty);
+  }
+
+  test_constructor_const() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { const C(); }').executables);
+    expect(executable.isConst, isTrue);
+    expect(executable.isExternal, isFalse);
+  }
+
+  test_constructor_const_external() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { external const C(); }').executables);
+    expect(executable.isConst, isTrue);
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_constructor_documented() {
+    String text = '''
+class C {
+  /**
+   * Docs
+   */
+  C();
+}''';
+    UnlinkedExecutable executable = serializeClassText(text).executables[0];
+    expect(executable.documentationComment, isNotNull);
+    checkDocumentationComment(executable.documentationComment, text);
+  }
+
+  test_constructor_external() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { external C(); }').executables);
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_constructor_factory() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { factory C() => null; }').executables);
+    expect(executable.isFactory, isTrue);
+  }
+
+  test_constructor_implicit() {
+    // Implicit constructors are not serialized.
+    UnlinkedExecutable executable = findExecutable(null,
+        executables: serializeClassText('class C { C(); }').executables,
+        failIfAbsent: false);
+    expect(executable, isNull);
+  }
+
+  test_constructor_initializing_formal() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { C(this.x); final x; }').executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.isInitializingFormal, isTrue);
+  }
+
+  test_constructor_initializing_formal_explicit_type() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(int this.x); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    checkTypeRef(parameter.type, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_constructor_initializing_formal_function_typed() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(this.x()); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.isFunctionTyped, isTrue);
+  }
+
+  test_constructor_initializing_formal_function_typed_explicit_return_type() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { C(int this.x()); Function x; }')
+                .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    checkTypeRef(parameter.type, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_constructor_initializing_formal_function_typed_implicit_return_type() {
+    if (!checkAstDerivedData) {
+      // TODO(paulberry): this test fails when building the summary from the
+      // element model because the elment model doesn't record whether a
+      // function-typed parameter's return type is implicit.
+      return;
+    }
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(this.x()); Function x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.isFunctionTyped, isTrue);
+    expect(parameter.type, isNull);
+  }
+
+  test_constructor_initializing_formal_function_typed_no_parameters() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(this.x()); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.parameters, isEmpty);
+  }
+
+  test_constructor_initializing_formal_function_typed_parameter() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(this.x(a)); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.parameters, hasLength(1));
+  }
+
+  test_constructor_initializing_formal_function_typed_parameter_order() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(this.x(a, b)); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.parameters, hasLength(2));
+    expect(parameter.parameters[0].name, 'a');
+    expect(parameter.parameters[1].name, 'b');
+  }
+
+  test_constructor_initializing_formal_implicit_type() {
+    // Note: the implicit type of an initializing formal is the type of the
+    // field.
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { C(this.x); int x; }').executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.type, isNull);
+  }
+
+  test_constructor_initializing_formal_name() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { C(this.x); final x; }').executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.name, 'x');
+  }
+
+  test_constructor_initializing_formal_named() {
+    // TODO(paulberry): also test default value
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C({this.x}); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.kind, UnlinkedParamKind.named);
+  }
+
+  test_constructor_initializing_formal_non_function_typed() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { C(this.x); final x; }').executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.isFunctionTyped, isFalse);
+  }
+
+  test_constructor_initializing_formal_positional() {
+    // TODO(paulberry): also test default value
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C([this.x]); final x; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.kind, UnlinkedParamKind.positional);
+  }
+
+  test_constructor_initializing_formal_required() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables:
+            serializeClassText('class C { C(this.x); final x; }').executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.kind, UnlinkedParamKind.required);
+  }
+
+  test_constructor_initializing_formal_typedef() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText(
+                'typedef F<T>(T x); class C<X> { C(this.f); F<X> f; }')
+            .executables);
+    UnlinkedParam parameter = executable.parameters[0];
+    expect(parameter.isFunctionTyped, isFalse);
+    expect(parameter.parameters, isEmpty);
+  }
+
+  test_constructor_named() {
+    String text = 'class C { C.foo(); }';
+    UnlinkedExecutable executable = findExecutable('foo',
+        executables: serializeClassText(text).executables);
+    expect(executable.name, 'foo');
+    expect(executable.nameOffset, text.indexOf('foo'));
+  }
+
+  test_constructor_non_const() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(); }').executables);
+    expect(executable.isConst, isFalse);
+  }
+
+  test_constructor_non_factory() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(); }').executables);
+    expect(executable.isFactory, isFalse);
+  }
+
+  test_constructor_param_inferred_type_explicit() {
+    UnlinkedExecutable ctor =
+        serializeClassText('class C { C(int v); }').executables[0];
+    expect(ctor.kind, UnlinkedExecutableKind.constructor);
+    expect(ctor.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_constructor_param_inferred_type_implicit() {
+    UnlinkedExecutable ctor =
+        serializeClassText('class C { C(v); }').executables[0];
+    expect(ctor.kind, UnlinkedExecutableKind.constructor);
+    expect(ctor.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_constructor_return_type() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C { C(); }').executables);
+    expect(executable.returnType, isNull);
+  }
+
+  test_constructor_return_type_parameterized() {
+    UnlinkedExecutable executable = findExecutable('',
+        executables: serializeClassText('class C<T, U> { C(); }').executables);
+    expect(executable.returnType, isNull);
+  }
+
+  test_dependencies_export_to_export_unused() {
+    addNamedSource('/a.dart', 'export "b.dart";');
+    addNamedSource('/b.dart', '');
+    serializeLibraryText('export "a.dart";');
+    // The main test library depends on b.dart, even though it doesn't
+    // re-export any names defined in b.dart, because a change to b.dart might
+    // cause it to start exporting a name that the main test library *does*
+    // use.
+    checkHasDependency(absUri('/b.dart'), 'b.dart');
+  }
+
+  test_dependencies_export_unused() {
+    addNamedSource('/a.dart', '');
+    serializeLibraryText('export "a.dart";');
+    // The main test library depends on a.dart, even though it doesn't
+    // re-export any names defined in a.dart, because a change to a.dart might
+    // cause it to start exporting a name that the main test library *will*
+    // re-export.
+    checkHasDependency(absUri('/a.dart'), 'a.dart');
+  }
+
+  test_dependencies_import_to_export() {
+    addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
+    addNamedSource('/b.dart', 'library b;');
+    serializeLibraryText('import "a.dart"; A a;');
+    checkHasDependency(absUri('/a.dart'), 'a.dart');
+    // The main test library depends on b.dart, because names defined in
+    // b.dart are exported by a.dart.
+    checkHasDependency(absUri('/b.dart'), 'b.dart');
+  }
+
+  test_dependencies_import_to_export_in_subdirs_absolute_export() {
+    addNamedSource('/a/a.dart',
+        'library a; export "${absUri('/a/b/b.dart')}"; class A {}');
+    addNamedSource('/a/b/b.dart', 'library b;');
+    serializeLibraryText('import "a/a.dart"; A a;');
+    checkHasDependency(absUri('/a/a.dart'), 'a/a.dart');
+    // The main test library depends on b.dart, because names defined in
+    // b.dart are exported by a.dart.
+    checkHasDependency(absUri('/a/b/b.dart'), absUri('/a/b/b.dart'));
+  }
+
+  test_dependencies_import_to_export_in_subdirs_absolute_import() {
+    addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
+    addNamedSource('/a/b/b.dart', 'library b;');
+    serializeLibraryText('import "${absUri('/a/a.dart')}"; A a;');
+    checkHasDependency(absUri('/a/a.dart'), absUri('/a/a.dart'));
+    // The main test library depends on b.dart, because names defined in
+    // b.dart are exported by a.dart.
+    checkHasDependency(absUri('/a/b/b.dart'), absUri('/a/b/b.dart'));
+  }
+
+  test_dependencies_import_to_export_in_subdirs_relative() {
+    addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
+    addNamedSource('/a/b/b.dart', 'library b;');
+    serializeLibraryText('import "a/a.dart"; A a;');
+    checkHasDependency(absUri('/a/a.dart'), 'a/a.dart');
+    // The main test library depends on b.dart, because names defined in
+    // b.dart are exported by a.dart.
+    checkHasDependency(absUri('/a/b/b.dart'), 'a/b/b.dart');
+  }
+
+  test_dependencies_import_to_export_loop() {
+    addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
+    addNamedSource('/b.dart', 'library b; export "a.dart";');
+    serializeLibraryText('import "a.dart"; A a;');
+    checkHasDependency(absUri('/a.dart'), 'a.dart');
+    // Serialization should have been able to walk the transitive export
+    // dependencies to b.dart without going into an infinite loop.
+    checkHasDependency(absUri('/b.dart'), 'b.dart');
+  }
+
+  test_dependencies_import_to_export_transitive_closure() {
+    addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
+    addNamedSource('/b.dart', 'library b; export "c.dart";');
+    addNamedSource('/c.dart', 'library c;');
+    serializeLibraryText('import "a.dart"; A a;');
+    checkHasDependency(absUri('/a.dart'), 'a.dart');
+    // The main test library depends on c.dart, because names defined in
+    // c.dart are exported by b.dart and then re-exported by a.dart.
+    checkHasDependency(absUri('/c.dart'), 'c.dart');
+  }
+
+  test_dependencies_import_to_export_unused() {
+    addNamedSource('/a.dart', 'export "b.dart";');
+    addNamedSource('/b.dart', '');
+    serializeLibraryText('import "a.dart";', allowErrors: true);
+    // The main test library depends on b.dart, even though it doesn't use any
+    // names defined in b.dart, because a change to b.dart might cause it to
+    // start exporting a name that the main test library *does* use.
+    checkHasDependency(absUri('/b.dart'), 'b.dart');
+  }
+
+  test_dependencies_import_transitive_closure() {
+    addNamedSource(
+        '/a.dart', 'library a; import "b.dart"; class A extends B {}');
+    addNamedSource('/b.dart', 'library b; class B {}');
+    serializeLibraryText('import "a.dart"; A a;');
+    checkHasDependency(absUri('/a.dart'), 'a.dart');
+    // The main test library doesn't depend on b.dart, because no change to
+    // b.dart can possibly affect the serialized element model for it.
+    checkLacksDependency(absUri('/b.dart'), 'b.dart');
+  }
+
+  test_dependencies_import_unused() {
+    addNamedSource('/a.dart', '');
+    serializeLibraryText('import "a.dart";', allowErrors: true);
+    // The main test library depends on a.dart, even though it doesn't use any
+    // names defined in a.dart, because a change to a.dart might cause it to
+    // start exporting a name that the main test library *does* use.
+    checkHasDependency(absUri('/a.dart'), 'a.dart');
+  }
+
+  test_dependencies_parts() {
+    addNamedSource(
+        '/a.dart', 'library a; part "b.dart"; part "c.dart"; class A {}');
+    addNamedSource('/b.dart', 'part of a;');
+    addNamedSource('/c.dart', 'part of a;');
+    serializeLibraryText('import "a.dart"; A a;');
+    int dep = checkHasDependency(absUri('/a.dart'), 'a.dart');
+    checkDependencyParts(linked.dependencies[dep],
+        [absUri('/b.dart'), absUri('/c.dart')], ['b.dart', 'c.dart']);
+  }
+
+  test_dependencies_parts_relative_to_importing_library() {
+    addNamedSource('/a/b.dart', 'export "c/d.dart";');
+    addNamedSource('/a/c/d.dart',
+        'library d; part "e/f.dart"; part "g/h.dart"; class D {}');
+    addNamedSource('/a/c/e/f.dart', 'part of d;');
+    addNamedSource('/a/c/g/h.dart', 'part of d;');
+    serializeLibraryText('import "a/b.dart"; D d;');
+    int dep = checkHasDependency(absUri('/a/c/d.dart'), 'a/c/d.dart');
+    checkDependencyParts(
+        linked.dependencies[dep],
+        [absUri('/a/c/e/f.dart'), absUri('/a/c/g/h.dart')],
+        ['a/c/e/f.dart', 'a/c/g/h.dart']);
+  }
+
+  test_elements_in_part() {
+    addNamedSource(
+        '/part1.dart',
+        '''
+part of my.lib;
+
+class C {}
+enum E { v }
+var v;
+f() {}
+typedef F();
+''');
+    serializeLibraryText('library my.lib; part "part1.dart";');
+    UnlinkedUnit unit = unlinkedUnits[1];
+    expect(findClass('C', unit: unit), isNotNull);
+    expect(findEnum('E', unit: unit), isNotNull);
+    expect(findVariable('v', variables: unit.variables), isNotNull);
+    expect(findExecutable('f', executables: unit.executables), isNotNull);
+    expect(findTypedef('F', unit: unit), isNotNull);
+  }
+
+  test_enum() {
+    String text = 'enum E { v1 }';
+    UnlinkedEnum e = serializeEnumText(text);
+    expect(e.name, 'E');
+    expect(e.nameOffset, text.indexOf('E'));
+    expect(e.values, hasLength(1));
+    expect(e.values[0].name, 'v1');
+    expect(e.values[0].nameOffset, text.indexOf('v1'));
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.classOrEnum);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'E');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
+  }
+
+  test_enum_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+enum E { v }''';
+    UnlinkedEnum enm = serializeEnumText(text);
+    expect(enm.documentationComment, isNotNull);
+    checkDocumentationComment(enm.documentationComment, text);
+  }
+
+  test_enum_order() {
+    UnlinkedEnum e = serializeEnumText('enum E { v1, v2 }');
+    expect(e.values, hasLength(2));
+    expect(e.values[0].name, 'v1');
+    expect(e.values[1].name, 'v2');
+  }
+
+  test_enum_private() {
+    serializeEnumText('enum _E { v1 }', '_E');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_executable_abstract() {
+    UnlinkedExecutable executable =
+        serializeClassText('abstract class C { f(); }').executables[0];
+    expect(executable.isAbstract, isTrue);
+  }
+
+  test_executable_concrete() {
+    UnlinkedExecutable executable =
+        serializeClassText('abstract class C { f() {} }').executables[0];
+    expect(executable.isAbstract, isFalse);
+  }
+
+  test_executable_function() {
+    String text = '  f() {}';
+    UnlinkedExecutable executable = serializeExecutableText(text);
+    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
+    expect(executable.returnType, isNull);
+    expect(executable.isExternal, isFalse);
+    expect(executable.nameOffset, text.indexOf('f'));
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.topLevelFunction);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
+  }
+
+  test_executable_function_explicit_return() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('dynamic f() => null;');
+    checkDynamicTypeRef(executable.returnType);
+  }
+
+  test_executable_function_external() {
+    UnlinkedExecutable executable = serializeExecutableText('external f();');
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_executable_function_private() {
+    serializeExecutableText('_f() {}', '_f');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_executable_getter() {
+    String text = 'int get f => 1;';
+    UnlinkedExecutable executable = serializeExecutableText(text);
+    expect(executable.kind, UnlinkedExecutableKind.getter);
+    expect(executable.returnType, isNotNull);
+    expect(executable.isExternal, isFalse);
+    expect(executable.nameOffset, text.indexOf('f'));
+    expect(findVariable('f'), isNull);
+    expect(findExecutable('f='), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.topLevelPropertyAccessor);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
+  }
+
+  test_executable_getter_external() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('external int get f;');
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_executable_getter_private() {
+    serializeExecutableText('int get _f => 1;', '_f');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_executable_getter_type() {
+    UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
+    checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
+    expect(executable.parameters, isEmpty);
+  }
+
+  test_executable_getter_type_implicit() {
+    UnlinkedExecutable executable = serializeExecutableText('get f => 1;');
+    expect(executable.returnType, isNull);
+    expect(executable.parameters, isEmpty);
+  }
+
+  test_executable_member_function() {
+    UnlinkedExecutable executable = findExecutable('f',
+        executables: serializeClassText('class C { f() {} }').executables);
+    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
+    expect(executable.returnType, isNull);
+    expect(executable.isExternal, isFalse);
+  }
+
+  test_executable_member_function_explicit_return() {
+    UnlinkedExecutable executable = findExecutable('f',
+        executables:
+            serializeClassText('class C { dynamic f() => null; }').executables);
+    expect(executable.returnType, isNotNull);
+  }
+
+  test_executable_member_function_external() {
+    UnlinkedExecutable executable = findExecutable('f',
+        executables:
+            serializeClassText('class C { external f(); }').executables);
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_executable_member_getter() {
+    UnlinkedClass cls = serializeClassText('class C { int get f => 1; }');
+    UnlinkedExecutable executable =
+        findExecutable('f', executables: cls.executables, failIfAbsent: true);
+    expect(executable.kind, UnlinkedExecutableKind.getter);
+    expect(executable.returnType, isNotNull);
+    expect(executable.isExternal, isFalse);
+    expect(findVariable('f', variables: cls.fields), isNull);
+    expect(findExecutable('f=', executables: cls.executables), isNull);
+  }
+
+  test_executable_member_getter_external() {
+    UnlinkedClass cls = serializeClassText('class C { external int get f; }');
+    UnlinkedExecutable executable =
+        findExecutable('f', executables: cls.executables, failIfAbsent: true);
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_executable_member_setter() {
+    UnlinkedClass cls = serializeClassText('class C { void set f(value) {} }');
+    UnlinkedExecutable executable =
+        findExecutable('f=', executables: cls.executables, failIfAbsent: true);
+    expect(executable.kind, UnlinkedExecutableKind.setter);
+    expect(executable.returnType, isNotNull);
+    expect(executable.isExternal, isFalse);
+    expect(findVariable('f', variables: cls.fields), isNull);
+    expect(findExecutable('f', executables: cls.executables), isNull);
+  }
+
+  test_executable_member_setter_external() {
+    UnlinkedClass cls =
+        serializeClassText('class C { external void set f(value); }');
+    UnlinkedExecutable executable =
+        findExecutable('f=', executables: cls.executables, failIfAbsent: true);
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_executable_member_setter_implicit_return() {
+    UnlinkedClass cls = serializeClassText('class C { set f(value) {} }');
+    UnlinkedExecutable executable =
+        findExecutable('f=', executables: cls.executables, failIfAbsent: true);
+    expect(executable.returnType, isNull);
+  }
+
+  test_executable_name() {
+    UnlinkedExecutable executable = serializeExecutableText('f() {}');
+    expect(executable.name, 'f');
+  }
+
+  test_executable_no_flags() {
+    UnlinkedExecutable executable = serializeExecutableText('f() {}');
+    expect(executable.isAbstract, isFalse);
+    expect(executable.isConst, isFalse);
+    expect(executable.isFactory, isFalse);
+    expect(executable.isStatic, isFalse);
+  }
+
+  test_executable_non_static() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { f() {} }').executables[0];
+    expect(executable.isStatic, isFalse);
+  }
+
+  test_executable_non_static_top_level() {
+    // Top level executables are considered non-static.
+    UnlinkedExecutable executable = serializeExecutableText('f() {}');
+    expect(executable.isStatic, isFalse);
+  }
+
+  test_executable_operator() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { C operator+(C c) => null; }').executables[
+            0];
+    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
+    expect(executable.name, '+');
+    expect(executable.returnType, isNotNull);
+    expect(executable.isAbstract, false);
+    expect(executable.isConst, false);
+    expect(executable.isFactory, false);
+    expect(executable.isStatic, false);
+    expect(executable.parameters, hasLength(1));
+    checkTypeRef(executable.returnType, null, null, 'C');
+    expect(executable.typeParameters, isEmpty);
+    expect(executable.isExternal, false);
+  }
+
+  test_executable_operator_equal() {
+    UnlinkedExecutable executable = serializeClassText(
+            'class C { bool operator==(Object other) => false; }')
+        .executables[0];
+    expect(executable.name, '==');
+  }
+
+  test_executable_operator_external() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { external C operator+(C c); }')
+            .executables[0];
+    expect(executable.isExternal, true);
+  }
+
+  test_executable_operator_greater_equal() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { bool operator>=(C other) => false; }')
+            .executables[0];
+    expect(executable.name, '>=');
+  }
+
+  test_executable_operator_index() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { bool operator[](int i) => null; }')
+            .executables[0];
+    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
+    expect(executable.name, '[]');
+    expect(executable.returnType, isNotNull);
+    expect(executable.isAbstract, false);
+    expect(executable.isConst, false);
+    expect(executable.isFactory, false);
+    expect(executable.isStatic, false);
+    expect(executable.parameters, hasLength(1));
+    checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'bool');
+    expect(executable.typeParameters, isEmpty);
+  }
+
+  test_executable_operator_index_set() {
+    UnlinkedExecutable executable = serializeClassText(
+            'class C { void operator[]=(int i, bool v) => null; }')
+        .executables[0];
+    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
+    expect(executable.name, '[]=');
+    expect(executable.returnType, isNotNull);
+    expect(executable.isAbstract, false);
+    expect(executable.isConst, false);
+    expect(executable.isFactory, false);
+    expect(executable.isStatic, false);
+    expect(executable.parameters, hasLength(2));
+    checkVoidTypeRef(executable.returnType);
+    expect(executable.typeParameters, isEmpty);
+  }
+
+  test_executable_operator_less_equal() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { bool operator<=(C other) => false; }')
+            .executables[0];
+    expect(executable.name, '<=');
+  }
+
+  test_executable_param_function_typed() {
+    if (!checkAstDerivedData) {
+      // TODO(paulberry): this test fails when building the summary from the
+      // element model because the elment model doesn't record whether a
+      // function-typed parameter's return type is implicit.
+      return;
+    }
+    UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
+    expect(executable.parameters[0].isFunctionTyped, isTrue);
+    expect(executable.parameters[0].type, isNull);
+  }
+
+  test_executable_param_function_typed_explicit_return_type() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('f(dynamic g()) {}');
+    expect(executable.parameters[0].type, isNotNull);
+  }
+
+  test_executable_param_function_typed_param() {
+    UnlinkedExecutable executable = serializeExecutableText('f(g(x)) {}');
+    expect(executable.parameters[0].parameters, hasLength(1));
+  }
+
+  test_executable_param_function_typed_param_none() {
+    UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
+    expect(executable.parameters[0].parameters, isEmpty);
+  }
+
+  test_executable_param_function_typed_param_order() {
+    UnlinkedExecutable executable = serializeExecutableText('f(g(x, y)) {}');
+    expect(executable.parameters[0].parameters, hasLength(2));
+    expect(executable.parameters[0].parameters[0].name, 'x');
+    expect(executable.parameters[0].parameters[1].name, 'y');
+  }
+
+  test_executable_param_function_typed_return_type() {
+    UnlinkedExecutable executable = serializeExecutableText('f(int g()) {}');
+    checkTypeRef(
+        executable.parameters[0].type, 'dart:core', 'dart:core', 'int');
+  }
+
+  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
+      // function-typed parameter's return type is implicit.
+      return;
+    }
+    UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
+    expect(executable.parameters[0].isFunctionTyped, isTrue);
+    expect(executable.parameters[0].type, isNull);
+  }
+
+  test_executable_param_function_typed_return_type_void() {
+    UnlinkedExecutable executable = serializeExecutableText('f(void g()) {}');
+    checkVoidTypeRef(executable.parameters[0].type);
+  }
+
+  test_executable_param_kind_named() {
+    UnlinkedExecutable executable = serializeExecutableText('f({x}) {}');
+    expect(executable.parameters[0].kind, UnlinkedParamKind.named);
+  }
+
+  test_executable_param_kind_positional() {
+    UnlinkedExecutable executable = serializeExecutableText('f([x]) {}');
+    expect(executable.parameters[0].kind, UnlinkedParamKind.positional);
+  }
+
+  test_executable_param_kind_required() {
+    UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
+    expect(executable.parameters[0].kind, UnlinkedParamKind.required);
+  }
+
+  test_executable_param_name() {
+    String text = 'f(x) {}';
+    UnlinkedExecutable executable = serializeExecutableText(text);
+    expect(executable.parameters, hasLength(1));
+    expect(executable.parameters[0].name, 'x');
+    expect(executable.parameters[0].nameOffset, text.indexOf('x'));
+  }
+
+  test_executable_param_no_flags() {
+    UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
+    expect(executable.parameters[0].isFunctionTyped, isFalse);
+    expect(executable.parameters[0].isInitializingFormal, isFalse);
+  }
+
+  test_executable_param_non_function_typed() {
+    UnlinkedExecutable executable = serializeExecutableText('f(g) {}');
+    expect(executable.parameters[0].isFunctionTyped, isFalse);
+  }
+
+  test_executable_param_none() {
+    UnlinkedExecutable executable = serializeExecutableText('f() {}');
+    expect(executable.parameters, isEmpty);
+  }
+
+  test_executable_param_order() {
+    UnlinkedExecutable executable = serializeExecutableText('f(x, y) {}');
+    expect(executable.parameters, hasLength(2));
+    expect(executable.parameters[0].name, 'x');
+    expect(executable.parameters[1].name, 'y');
+  }
+
+  test_executable_param_type_explicit() {
+    UnlinkedExecutable executable = serializeExecutableText('f(dynamic x) {}');
+    checkDynamicTypeRef(executable.parameters[0].type);
+  }
+
+  test_executable_param_type_implicit() {
+    UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
+    expect(executable.parameters[0].type, isNull);
+  }
+
+  test_executable_return_type() {
+    UnlinkedExecutable executable = serializeExecutableText('int f() => 1;');
+    checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_executable_return_type_implicit() {
+    UnlinkedExecutable executable = serializeExecutableText('f() {}');
+    expect(executable.returnType, isNull);
+  }
+
+  test_executable_return_type_void() {
+    UnlinkedExecutable executable = serializeExecutableText('void f() {}');
+    checkVoidTypeRef(executable.returnType);
+  }
+
+  test_executable_setter() {
+    String text = 'void set f(value) {}';
+    UnlinkedExecutable executable = serializeExecutableText(text, 'f=');
+    expect(executable.kind, UnlinkedExecutableKind.setter);
+    expect(executable.returnType, isNotNull);
+    expect(executable.isExternal, isFalse);
+    expect(executable.nameOffset, text.indexOf('f'));
+    expect(findVariable('f'), isNull);
+    expect(findExecutable('f'), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.topLevelPropertyAccessor);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f=');
+  }
+
+  test_executable_setter_external() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('external void set f(value);', 'f=');
+    expect(executable.isExternal, isTrue);
+  }
+
+  test_executable_setter_implicit_return() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('set f(value) {}', 'f=');
+    expect(executable.returnType, isNull);
+  }
+
+  test_executable_setter_private() {
+    serializeExecutableText('void set _f(value) {}', '_f=');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_executable_setter_type() {
+    UnlinkedExecutable executable =
+        serializeExecutableText('void set f(int value) {}', 'f=');
+    checkVoidTypeRef(executable.returnType);
+    expect(executable.parameters, hasLength(1));
+    expect(executable.parameters[0].name, 'value');
+    checkTypeRef(
+        executable.parameters[0].type, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_executable_static() {
+    UnlinkedExecutable executable =
+        serializeClassText('class C { static f() {} }').executables[0];
+    expect(executable.isStatic, isTrue);
+  }
+
+  test_executable_type_param_f_bound_function() {
+    UnlinkedExecutable ex =
+        serializeExecutableText('void f<T, U extends List<T>>() {}');
+    EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 2);
+  }
+
+  test_executable_type_param_f_bound_method() {
+    UnlinkedExecutable ex =
+        serializeMethodText('void f<T, U extends List<T>>() {}');
+    EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 2);
+  }
+
+  test_executable_type_param_f_bound_self_ref_function() {
+    UnlinkedExecutable ex =
+        serializeExecutableText('void f<T, U extends List<U>>() {}');
+    EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 1);
+  }
+
+  test_executable_type_param_f_bound_self_ref_method() {
+    UnlinkedExecutable ex =
+        serializeMethodText('void f<T, U extends List<U>>() {}');
+    EntityRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
+    checkParamTypeRef(typeArgument, 1);
+  }
+
+  test_executable_type_param_in_parameter_function() {
+    UnlinkedExecutable ex = serializeExecutableText('void f<T>(T t) {}');
+    checkParamTypeRef(ex.parameters[0].type, 1);
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
+  }
+
+  test_executable_type_param_in_parameter_method() {
+    UnlinkedExecutable ex = serializeMethodText('void f<T>(T t) {}');
+    checkParamTypeRef(ex.parameters[0].type, 1);
+  }
+
+  test_executable_type_param_in_return_type_function() {
+    UnlinkedExecutable ex = serializeExecutableText('T f<T>() => null;');
+    checkParamTypeRef(ex.returnType, 1);
+  }
+
+  test_executable_type_param_in_return_type_method() {
+    UnlinkedExecutable ex = serializeMethodText('T f<T>() => null;');
+    checkParamTypeRef(ex.returnType, 1);
+  }
+
+  test_export_class() {
+    addNamedSource('/a.dart', 'class C {}');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'C',
+        ReferenceKind.classOrEnum);
+  }
+
+  test_export_class_alias() {
+    addNamedSource(
+        '/a.dart', 'class C extends _D with _E {} class _D {} class _E {}');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'C',
+        ReferenceKind.classOrEnum);
+  }
+
+  test_export_enum() {
+    addNamedSource('/a.dart', 'enum E { v }');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'E',
+        ReferenceKind.classOrEnum);
+  }
+
+  test_export_from_part() {
+    addNamedSource('/a.dart', 'library foo; part "b.dart";');
+    addNamedSource('/b.dart', 'part of foo; f() {}');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f',
+        ReferenceKind.topLevelFunction,
+        expectedTargetUnit: 1);
+  }
+
+  test_export_function() {
+    addNamedSource('/a.dart', 'f() {}');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f',
+        ReferenceKind.topLevelFunction);
+  }
+
+  test_export_getter() {
+    addNamedSource('/a.dart', 'get f => null');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f',
+        ReferenceKind.topLevelPropertyAccessor);
+  }
+
+  test_export_hide() {
+    addNamedSource('/a.dart', 'f() {} g() {}');
+    serializeLibraryText('export "a.dart" hide g;');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f',
+        ReferenceKind.topLevelFunction);
+  }
+
+  test_export_hide_order() {
+    serializeLibraryText('export "dart:async" hide Future, Stream;');
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(
+        unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
+        isEmpty);
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
+        hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[0],
+        'Future');
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
+        'Stream');
+    expect(linked.exportNames, isNotEmpty);
+  }
+
+  test_export_names_excludes_names_from_library() {
+    addNamedSource('/a.dart', 'part of my.lib; int y; int _y;');
+    serializeLibraryText('library my.lib; part "a.dart"; int x; int _x;');
+    expect(linked.exportNames, isEmpty);
+  }
+
+  test_export_no_combinators() {
+    serializeLibraryText('export "dart:async";');
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators, isEmpty);
+  }
+
+  test_export_not_shadowed_by_prefix() {
+    addNamedSource('/a.dart', 'f() {}');
+    serializeLibraryText('export "a.dart"; import "dart:core" as f; f.int _x;');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f',
+        ReferenceKind.topLevelFunction);
+  }
+
+  test_export_offset() {
+    String libraryText = '    export "dart:async";';
+    serializeLibraryText(libraryText);
+    expect(unlinkedUnits[0].exports[0].uriOffset,
+        libraryText.indexOf('"dart:async"'));
+    expect(unlinkedUnits[0].exports[0].uriEnd, libraryText.indexOf(';'));
+    expect(unlinkedUnits[0].exports[0].offset, libraryText.indexOf('export'));
+  }
+
+  test_export_private() {
+    // Private names should not be exported.
+    addNamedSource('/a.dart', '_f() {}');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, isEmpty);
+  }
+
+  test_export_setter() {
+    addNamedSource('/a.dart', 'void set f(value) {}');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f=',
+        ReferenceKind.topLevelPropertyAccessor);
+  }
+
+  test_export_shadowed() {
+    // f() is not shown in exportNames because it is already defined at top
+    // level in the library.
+    addNamedSource('/a.dart', 'f() {}');
+    serializeLibraryText('export "a.dart"; f() {}');
+    expect(linked.exportNames, isEmpty);
+  }
+
+  test_export_shadowed_variable() {
+    // Neither `v` nor `v=` is shown in exportNames because both are defined at
+    // top level in the library by the declaration `var v;`.
+    addNamedSource('/a.dart', 'var v;');
+    serializeLibraryText('export "a.dart"; var v;');
+    expect(linked.exportNames, isEmpty);
+  }
+
+  test_export_shadowed_variable_const() {
+    // `v=` is shown in exportNames because the top level declaration
+    // `const v = 0;` only shadows `v`, not `v=`.
+    addNamedSource('/a.dart', 'var v;');
+    serializeLibraryText('export "a.dart"; const v = 0;');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'v=',
+        ReferenceKind.topLevelPropertyAccessor);
+  }
+
+  test_export_shadowed_variable_final() {
+    // `v=` is shown in exportNames because the top level declaration
+    // `final v = 0;` only shadows `v`, not `v=`.
+    addNamedSource('/a.dart', 'var v;');
+    serializeLibraryText('export "a.dart"; final v = 0;');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'v=',
+        ReferenceKind.topLevelPropertyAccessor);
+  }
+
+  test_export_show() {
+    addNamedSource('/a.dart', 'f() {} g() {}');
+    serializeLibraryText('export "a.dart" show f;');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'f',
+        ReferenceKind.topLevelFunction);
+  }
+
+  test_export_show_order() {
+    serializeLibraryText('export "dart:async" show Future, Stream;');
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(
+        unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
+        hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
+        isEmpty);
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[0],
+        'Future');
+    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
+        'Stream');
+  }
+
+  test_export_typedef() {
+    addNamedSource('/a.dart', 'typedef F();');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(1));
+    checkExportName(linked.exportNames[0], absUri('/a.dart'), 'a.dart', 'F',
+        ReferenceKind.typedef);
+  }
+
+  test_export_uri() {
+    addNamedSource('/a.dart', 'library my.lib;');
+    String uriString = '"a.dart"';
+    String libraryText = 'export $uriString;';
+    serializeLibraryText(libraryText);
+    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.exports[0].uri, 'a.dart');
+  }
+
+  test_export_variable() {
+    addNamedSource('/a.dart', 'var v;');
+    serializeLibraryText('export "a.dart";');
+    expect(linked.exportNames, hasLength(2));
+    LinkedExportName getter =
+        linked.exportNames.firstWhere((e) => e.name == 'v');
+    expect(getter, isNotNull);
+    checkExportName(getter, absUri('/a.dart'), 'a.dart', 'v',
+        ReferenceKind.topLevelPropertyAccessor);
+    LinkedExportName setter =
+        linked.exportNames.firstWhere((e) => e.name == 'v=');
+    expect(setter, isNotNull);
+    checkExportName(setter, absUri('/a.dart'), 'a.dart', 'v=',
+        ReferenceKind.topLevelPropertyAccessor);
+  }
+
+  test_field() {
+    UnlinkedClass cls = serializeClassText('class C { int i; }');
+    UnlinkedVariable variable = findVariable('i', variables: cls.fields);
+    expect(variable, isNotNull);
+    expect(variable.isConst, isFalse);
+    expect(variable.isStatic, isFalse);
+    expect(variable.isFinal, isFalse);
+    expect(findExecutable('i', executables: cls.executables), isNull);
+    expect(findExecutable('i=', executables: cls.executables), isNull);
+  }
+
+  test_field_const() {
+    UnlinkedVariable variable =
+        serializeClassText('class C { static const int i = 0; }').fields[0];
+    expect(variable.isConst, isTrue);
+    _assertUnlinkedConst(variable.constExpr,
+        operators: [UnlinkedConstOperation.pushInt], ints: [0]);
+  }
+
+  test_field_documented() {
+    String text = '''
+class C {
+  /**
+   * Docs
+   */
+  var v;
+}''';
+    UnlinkedVariable variable = serializeClassText(text).fields[0];
+    expect(variable.documentationComment, isNotNull);
+    checkDocumentationComment(variable.documentationComment, text);
+  }
+
+  test_field_final() {
+    UnlinkedVariable variable =
+        serializeClassText('class C { final int i = 0; }').fields[0];
+    expect(variable.isFinal, isTrue);
+  }
+
+  test_field_formal_param_inferred_type_explicit() {
+    UnlinkedClass cls = serializeClassText(
+        'class C extends D { var v; C(int this.v); }'
+        ' abstract class D { num get v; }',
+        className: 'C');
+    checkInferredTypeSlot(
+        cls.fields[0].inferredTypeSlot, 'dart:core', 'dart:core', 'num');
+    expect(cls.executables[0].kind, UnlinkedExecutableKind.constructor);
+    expect(cls.executables[0].parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_field_formal_param_inferred_type_implicit() {
+    // Both the field `v` and the constructor argument `this.v` will have their
+    // type inferred by strong mode.  But only the field should have its
+    // inferred type stored in the summary, since the standard rules for field
+    // formal parameters will take care of the rest (they implicitly inherit
+    // the type of the associated field).
+    UnlinkedClass cls = serializeClassText(
+        'class C extends D { var v; C(this.v); }'
+        ' abstract class D { int get v; }',
+        className: 'C');
+    checkInferredTypeSlot(
+        cls.fields[0].inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+    expect(cls.executables[0].kind, UnlinkedExecutableKind.constructor);
+    expect(cls.executables[0].parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_field_inferred_type_nonstatic_explicit_initialized() {
+    UnlinkedVariable v = serializeClassText('class C { num v = 0; }').fields[0];
+    expect(v.inferredTypeSlot, 0);
+  }
+
+  test_field_inferred_type_nonstatic_explicit_uninitialized() {
+    UnlinkedVariable v = serializeClassText(
+            'class C extends D { num v; } abstract class D { int get v; }',
+            className: 'C',
+            allowErrors: true)
+        .fields[0];
+    expect(v.inferredTypeSlot, 0);
+  }
+
+  test_field_inferred_type_nonstatic_implicit_initialized() {
+    UnlinkedVariable v = serializeClassText('class C { var v = 0; }').fields[0];
+    checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_field_inferred_type_nonstatic_implicit_uninitialized() {
+    UnlinkedVariable v = serializeClassText(
+            'class C extends D { var v; } abstract class D { int get v; }',
+            className: 'C')
+        .fields[0];
+    checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_field_inferred_type_static_explicit_initialized() {
+    UnlinkedVariable v =
+        serializeClassText('class C { static int v = 0; }').fields[0];
+    expect(v.inferredTypeSlot, 0);
+  }
+
+  test_field_inferred_type_static_implicit_initialized() {
+    UnlinkedVariable v =
+        serializeClassText('class C { static var v = 0; }').fields[0];
+    checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_field_inferred_type_static_implicit_uninitialized() {
+    UnlinkedVariable v =
+        serializeClassText('class C { static var v; }').fields[0];
+    expect(v.inferredTypeSlot, 0);
+  }
+
+  test_field_propagated_type_final_immediate() {
+    UnlinkedVariable v =
+        serializeClassText('class C { final v = 0; }').fields[0];
+    checkLinkedTypeSlot(v.propagatedTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_field_static() {
+    UnlinkedVariable variable =
+        serializeClassText('class C { static int i; }').fields[0];
+    expect(variable.isStatic, isTrue);
+  }
+
+  test_fully_linked_references_follow_other_references() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    serializeLibraryText('final x = 0; String y;');
+    checkLinkedTypeSlot(unlinkedUnits[0].variables[0].propagatedTypeSlot,
+        'dart:core', 'dart:core', 'int');
+    checkTypeRef(
+        unlinkedUnits[0].variables[1].type, 'dart:core', 'dart:core', 'String');
+    // Even though the definition of y follows the definition of x, the linked
+    // type reference for x should use a higher numbered reference than the
+    // unlinked type reference for y.
+    EntityRef propagatedType =
+        getTypeRefForSlot(unlinkedUnits[0].variables[0].propagatedTypeSlot);
+    expect(unlinkedUnits[0].variables[1].type.reference,
+        lessThan(propagatedType.reference));
+  }
+
+  test_function_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+f() {}''';
+    UnlinkedExecutable executable = serializeExecutableText(text);
+    expect(executable.documentationComment, isNotNull);
+    checkDocumentationComment(executable.documentationComment, text);
+  }
+
+  test_function_inferred_type_implicit_param() {
+    UnlinkedExecutable f = serializeExecutableText('void f(value) {}');
+    expect(f.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_function_inferred_type_implicit_return() {
+    UnlinkedExecutable f = serializeExecutableText('f() => null;');
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_generic_method_in_generic_class() {
+    UnlinkedClass cls = serializeClassText(
+        'class C<T, U> { void m<V, W>(T t, U u, V v, W w) {} }');
+    List<UnlinkedParam> params = cls.executables[0].parameters;
+    checkParamTypeRef(params[0].type, 4);
+    checkParamTypeRef(params[1].type, 3);
+    checkParamTypeRef(params[2].type, 2);
+    checkParamTypeRef(params[3].type, 1);
+  }
+
+  test_getter_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+get f => null;''';
+    UnlinkedExecutable executable = serializeExecutableText(text);
+    expect(executable.documentationComment, isNotNull);
+    checkDocumentationComment(executable.documentationComment, text);
+  }
+
+  test_getter_inferred_type_nonstatic_explicit_return() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { num get f => null; }'
+            ' abstract class D { int get f; }',
+            className: 'C',
+            allowErrors: true)
+        .executables[0];
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_getter_inferred_type_nonstatic_implicit_return() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { get f => null; } abstract class D { int get f; }',
+            className: 'C')
+        .executables[0];
+    checkInferredTypeSlot(
+        f.inferredReturnTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_getter_inferred_type_static_implicit_return() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { static get f => null; }'
+            ' class D { static int get f => null; }',
+            className: 'C')
+        .executables[0];
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_implicit_dependencies_follow_other_dependencies() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    addNamedSource('/a.dart', 'import "b.dart"; class C {} D f() => null;');
+    addNamedSource('/b.dart', 'class D {}');
+    serializeLibraryText('import "a.dart"; final x = f(); C y;');
+    // The dependency on b.dart is implicit, so it should be placed at the end
+    // of the dependency list, after a.dart, even though the code that refers
+    // to b.dart comes before the code that refers to a.dart.
+    int aDep =
+        checkHasDependency(absUri('/a.dart'), 'a.dart', fullyLinked: false);
+    int bDep =
+        checkHasDependency(absUri('/b.dart'), 'b.dart', fullyLinked: true);
+    expect(aDep, lessThan(bDep));
+  }
+
+  test_import_deferred() {
+    serializeLibraryText(
+        'import "dart:async" deferred as a; main() { print(a.Future); }');
+    expect(unlinkedUnits[0].imports[0].isDeferred, isTrue);
+  }
+
+  test_import_dependency() {
+    serializeLibraryText('import "dart:async"; Future x;');
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    checkDependency(linked.importDependencies[0], 'dart:async', 'dart:async');
+  }
+
+  test_import_explicit() {
+    serializeLibraryText('import "dart:core"; int i;');
+    expect(unlinkedUnits[0].imports, hasLength(1));
+    expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
+  }
+
+  test_import_hide_order() {
+    serializeLibraryText(
+        'import "dart:async" hide Future, Stream; Completer c;');
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
+    expect(unlinkedUnits[0].imports[0].combinators[0].shows, isEmpty);
+    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');
+  }
+
+  test_import_implicit() {
+    // The implicit import of dart:core is represented in the model.
+    serializeLibraryText('');
+    expect(unlinkedUnits[0].imports, hasLength(1));
+    checkDependency(linked.importDependencies[0], 'dart:core', 'dart:core');
+    expect(unlinkedUnits[0].imports[0].uri, isEmpty);
+    expect(unlinkedUnits[0].imports[0].uriOffset, 0);
+    expect(unlinkedUnits[0].imports[0].uriEnd, 0);
+    expect(unlinkedUnits[0].imports[0].prefixReference, 0);
+    expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
+    expect(unlinkedUnits[0].imports[0].isImplicit, isTrue);
+  }
+
+  test_import_missing() {
+    if (!checkAstDerivedData) {
+      // TODO(paulberry): At the moment unresolved imports are not included in
+      // the element model, so we can't pass this test.
+      return;
+    }
+    // Unresolved imports are included since this is necessary for proper
+    // dependency tracking.
+    allowMissingFiles = true;
+    serializeLibraryText('import "foo.dart";', allowErrors: true);
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    checkDependency(
+        linked.importDependencies[0], absUri('/foo.dart'), 'foo.dart');
+  }
+
+  test_import_no_combinators() {
+    serializeLibraryText('import "dart:async"; Future x;');
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
+  }
+
+  test_import_no_flags() {
+    serializeLibraryText('import "dart:async"; Future x;');
+    expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
+    expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
+  }
+
+  test_import_non_deferred() {
+    serializeLibraryText(
+        'import "dart:async" as a; main() { print(a.Future); }');
+    expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
+  }
+
+  test_import_of_file_with_missing_part() {
+    // Other references in foo.dart should be resolved even though foo.dart's
+    // part declaration for bar.dart refers to a non-existent file.
+    allowMissingFiles = true;
+    addNamedSource('/foo.dart', 'part "bar.dart"; class C {}');
+    serializeLibraryText('import "foo.dart"; C x;');
+    checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C');
+  }
+
+  test_import_of_missing_export() {
+    // Other references in foo.dart should be resolved even though foo.dart's
+    // re-export of bar.dart refers to a non-existent file.
+    allowMissingFiles = true;
+    addNamedSource('/foo.dart', 'export "bar.dart"; class C {}');
+    serializeLibraryText('import "foo.dart"; C x;');
+    checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C');
+  }
+
+  test_import_offset() {
+    String libraryText = '    import "dart:async"; Future x;';
+    serializeLibraryText(libraryText);
+    expect(unlinkedUnits[0].imports[0].offset, libraryText.indexOf('import'));
+    expect(unlinkedUnits[0].imports[0].uriOffset,
+        libraryText.indexOf('"dart:async"'));
+    expect(unlinkedUnits[0].imports[0].uriEnd, libraryText.indexOf('; Future'));
+  }
+
+  test_import_prefix_name() {
+    String libraryText = 'import "dart:async" as a; a.Future x;';
+    serializeLibraryText(libraryText);
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    checkPrefix(unlinkedUnits[0].imports[0].prefixReference, 'a');
+    expect(unlinkedUnits[0].imports[0].prefixOffset, libraryText.indexOf('a;'));
+  }
+
+  test_import_prefix_none() {
+    serializeLibraryText('import "dart:async"; Future x;');
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    expect(unlinkedUnits[0].imports[0].prefixReference, 0);
+  }
+
+  test_import_prefix_not_in_public_namespace() {
+    serializeLibraryText('import "dart:async" as a; a.Future v;');
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'v');
+    expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v=');
+  }
+
+  test_import_prefix_reference() {
+    UnlinkedVariable variable =
+        serializeVariableText('import "dart:async" as a; a.Future v;');
+    checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
+        expectedPrefix: 'a', numTypeParameters: 1);
+  }
+
+  test_import_prefixes_take_precedence_over_imported_names() {
+    addNamedSource('/a.dart', 'class b {} class A');
+    addNamedSource('/b.dart', 'class Cls {}');
+    addNamedSource('/c.dart', 'class Cls {}');
+    addNamedSource('/d.dart', 'class c {} class D');
+    serializeLibraryText('''
+import 'a.dart';
+import 'b.dart' as b;
+import 'c.dart' as c;
+import 'd.dart';
+A aCls;
+b.Cls bCls;
+c.Cls cCls;
+D dCls;
+''');
+    checkTypeRef(findVariable('aCls').type, absUri('/a.dart'), 'a.dart', 'A');
+    checkTypeRef(findVariable('bCls').type, absUri('/b.dart'), 'b.dart', 'Cls',
+        expectedPrefix: 'b');
+    checkTypeRef(findVariable('cCls').type, absUri('/c.dart'), 'c.dart', 'Cls',
+        expectedPrefix: 'c');
+    checkTypeRef(findVariable('dCls').type, absUri('/d.dart'), 'd.dart', 'D');
+  }
+
+  test_import_reference() {
+    UnlinkedVariable variable =
+        serializeVariableText('import "dart:async"; Future v;');
+    checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
+        numTypeParameters: 1);
+  }
+
+  test_import_reference_merged_no_prefix() {
+    serializeLibraryText('''
+import "dart:async" show Future;
+import "dart:async" show Stream;
+
+Future f;
+Stream s;
+''');
+    checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
+        numTypeParameters: 1);
+    checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
+        numTypeParameters: 1);
+  }
+
+  test_import_reference_merged_prefixed() {
+    serializeLibraryText('''
+import "dart:async" as a show Future;
+import "dart:async" as a show Stream;
+
+a.Future f;
+a.Stream s;
+''');
+    checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
+        expectedPrefix: 'a', numTypeParameters: 1);
+    checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
+        expectedPrefix: 'a', numTypeParameters: 1);
+  }
+
+  test_import_reference_merged_prefixed_separate_libraries() {
+    addNamedSource('/a.dart', 'class A {}');
+    addNamedSource('/b.dart', 'class B {}');
+    serializeLibraryText('''
+import 'a.dart' as p;
+import 'b.dart' as p;
+
+p.A a;
+p.B b;
+''');
+    checkTypeRef(findVariable('a').type, absUri('/a.dart'), 'a.dart', 'A',
+        expectedPrefix: 'p');
+    checkTypeRef(findVariable('b').type, absUri('/b.dart'), 'b.dart', 'B',
+        expectedPrefix: 'p');
+  }
+
+  test_import_show_order() {
+    String libraryText =
+        'import "dart:async" show Future, Stream; Future x; Stream y;';
+    serializeLibraryText(libraryText);
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
+    expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2));
+    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');
+  }
+
+  test_import_uri() {
+    String uriString = '"dart:async"';
+    String libraryText = 'import $uriString; Future x;';
+    serializeLibraryText(libraryText);
+    // Second import is the implicit import of dart:core
+    expect(unlinkedUnits[0].imports, hasLength(2));
+    expect(unlinkedUnits[0].imports[0].uri, 'dart:async');
+  }
+
+  test_inferred_type_refers_to_bound_type_param() {
+    if (!strongMode || skipFullyLinkedData) {
+      return;
+    }
+    UnlinkedClass cls = serializeClassText(
+        'class C<T> extends D<int, T> { var v; }'
+        ' abstract class D<U, V> { Map<V, U> get v; }',
+        className: 'C');
+    EntityRef type = getTypeRefForSlot(cls.fields[0].inferredTypeSlot);
+    // Check that v has inferred type Map<T, int>.
+    checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    checkParamTypeRef(type.typeArguments[0], 1);
+    checkLinkedTypeRef(type.typeArguments[1], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_invalid_prefix_dynamic() {
+    if (checkAstDerivedData) {
+      // TODO(paulberry): get this to work properly.
+      return;
+    }
+    checkUnresolvedTypeRef(
+        serializeTypeText('dynamic.T', allowErrors: true), 'dynamic', 'T');
+  }
+
+  test_invalid_prefix_type_parameter() {
+    if (checkAstDerivedData) {
+      // TODO(paulberry): get this to work properly.
+      return;
+    }
+    checkUnresolvedTypeRef(
+        serializeClassText('class C<T> { T.U x; }', allowErrors: true)
+            .fields[0]
+            .type,
+        'T',
+        'U');
+  }
+
+  test_invalid_prefix_void() {
+    if (checkAstDerivedData) {
+      // TODO(paulberry): get this to work properly.
+      return;
+    }
+    checkUnresolvedTypeRef(
+        serializeTypeText('void.T', allowErrors: true), 'void', 'T');
+  }
+
+  test_library_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+library foo;''';
+    serializeLibraryText(text);
+    expect(unlinkedUnits[0].libraryDocumentationComment, isNotNull);
+    checkDocumentationComment(
+        unlinkedUnits[0].libraryDocumentationComment, text);
+  }
+
+  test_library_name_with_spaces() {
+    String text = 'library foo . bar ;';
+    serializeLibraryText(text);
+    expect(unlinkedUnits[0].libraryName, 'foo.bar');
+    expect(unlinkedUnits[0].libraryNameOffset, text.indexOf('foo . bar'));
+    expect(unlinkedUnits[0].libraryNameLength, 'foo . bar'.length);
+  }
+
+  test_library_named() {
+    String text = 'library foo.bar;';
+    serializeLibraryText(text);
+    expect(unlinkedUnits[0].libraryName, 'foo.bar');
+    expect(unlinkedUnits[0].libraryNameOffset, text.indexOf('foo.bar'));
+    expect(unlinkedUnits[0].libraryNameLength, 'foo.bar'.length);
+  }
+
+  test_library_unnamed() {
+    serializeLibraryText('');
+    expect(unlinkedUnits[0].libraryName, isEmpty);
+    expect(unlinkedUnits[0].libraryNameOffset, 0);
+    expect(unlinkedUnits[0].libraryNameLength, 0);
+  }
+
+  test_library_with_missing_part() {
+    // References to other parts should still be resolved.
+    allowMissingFiles = true;
+    addNamedSource('/bar.dart', 'part of my.lib; class C {}');
+    serializeLibraryText(
+        'library my.lib; part "foo.dart"; part "bar.dart"; C c;',
+        allowErrors: true);
+    checkTypeRef(findVariable('c').type, null, null, 'C',
+        expectedTargetUnit: 2);
+  }
+
+  test_linked_reference_reuse() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // When the reference for a linked type is the same as an explicitly
+    // referenced type, the explicit reference should be re-used.
+    addNamedSource('/a.dart', 'class C {}');
+    addNamedSource('/b.dart', 'import "a.dart"; C f() => null;');
+    serializeLibraryText(
+        'import "a.dart"; import "b.dart"; C c1; final c2 = f();');
+    int explicitReference = findVariable('c1').type.reference;
+    expect(getTypeRefForSlot(findVariable('c2').propagatedTypeSlot).reference,
+        explicitReference);
+  }
+
+  test_linked_type_dependency_reuse() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    // When the dependency for a linked type is the same as an explicit
+    // dependency, the explicit dependency should be re-used.
+    addNamedSource('/a.dart', 'class C {} class D {}');
+    addNamedSource('/b.dart', 'import "a.dart"; D f() => null;');
+    serializeLibraryText(
+        'import "a.dart"; import "b.dart"; C c; final d = f();');
+    int cReference = findVariable('c').type.reference;
+    int explicitDependency = linked.units[0].references[cReference].dependency;
+    int dReference =
+        getTypeRefForSlot(findVariable('d').propagatedTypeSlot).reference;
+    expect(
+        linked.units[0].references[dReference].dependency, explicitDependency);
+  }
+
+  test_local_names_take_precedence_over_imported_names() {
+    addNamedSource('/a.dart', 'class C {} class D {}');
+    serializeLibraryText('''
+import 'a.dart';
+class C {}
+C c;
+D d;''');
+    checkTypeRef(findVariable('c').type, null, null, 'C');
+    checkTypeRef(findVariable('d').type, absUri('/a.dart'), 'a.dart', 'D');
+  }
+
+  test_method_documented() {
+    String text = '''
+class C {
+  /**
+   * Docs
+   */
+  f() {}
+}''';
+    UnlinkedExecutable executable = serializeClassText(text).executables[0];
+    expect(executable.documentationComment, isNotNull);
+    checkDocumentationComment(executable.documentationComment, text);
+  }
+
+  test_method_inferred_type_nonstatic_explicit_param() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { void f(num value) {} }'
+            ' abstract class D { void f(int value); }',
+            className: 'C')
+        .executables[0];
+    expect(f.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_method_inferred_type_nonstatic_explicit_return() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { num f() => null; } abstract class D { int f(); }',
+            className: 'C',
+            allowErrors: true)
+        .executables[0];
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_method_inferred_type_nonstatic_implicit_param() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { void f(value) {} }'
+            ' abstract class D { void f(int value); }',
+            className: 'C')
+        .executables[0];
+    checkInferredTypeSlot(
+        f.parameters[0].inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_method_inferred_type_nonstatic_implicit_return() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { f() => null; } abstract class D { int f(); }',
+            className: 'C')
+        .executables[0];
+    checkInferredTypeSlot(
+        f.inferredReturnTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_method_inferred_type_static_implicit_param() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { static void f(value) {} }'
+            ' class D { static void f(int value) {} }',
+            className: 'C')
+        .executables[0];
+    expect(f.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_method_inferred_type_static_implicit_return() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { static f() => null; }'
+            ' class D { static int f() => null; }',
+            className: 'C')
+        .executables[0];
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_part_declaration() {
+    addNamedSource('/a.dart', 'part of my.lib;');
+    String text = 'library my.lib; part "a.dart"; // <-part';
+    serializeLibraryText(text);
+    expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.parts[0], 'a.dart');
+    expect(unlinkedUnits[0].parts, hasLength(1));
+    expect(unlinkedUnits[0].parts[0].uriOffset, text.indexOf('"a.dart"'));
+    expect(unlinkedUnits[0].parts[0].uriEnd, text.indexOf('; // <-part'));
+  }
+
+  test_parts_defining_compilation_unit() {
+    serializeLibraryText('');
+    expect(linked.units, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.parts, isEmpty);
+  }
+
+  test_parts_included() {
+    addNamedSource('/part1.dart', 'part of my.lib;');
+    String partString = '"part1.dart"';
+    String libraryText = 'library my.lib; part $partString;';
+    serializeLibraryText(libraryText);
+    expect(linked.units, hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.parts[0], 'part1.dart');
+  }
+
+  test_public_namespace_of_part() {
+    addNamedSource('/a.dart', 'part of foo; class C {}');
+    serializeLibraryText('library foo; part "a.dart";');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+    expect(unlinkedUnits[1].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[1].publicNamespace.names[0].name, 'C');
+  }
+
+  test_setter_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+void set f(value) {}''';
+    UnlinkedExecutable executable = serializeExecutableText(text, 'f=');
+    expect(executable.documentationComment, isNotNull);
+    checkDocumentationComment(executable.documentationComment, text);
+  }
+
+  test_setter_inferred_type_nonstatic_explicit_param() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { void set f(num value) {} }'
+            ' abstract class D { void set f(int value); }',
+            className: 'C')
+        .executables[0];
+    expect(f.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_setter_inferred_type_nonstatic_explicit_return() {
+    UnlinkedExecutable f =
+        serializeClassText('class C { void set f(int value) {} }').executables[
+            0];
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_setter_inferred_type_nonstatic_implicit_param() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { void set f(value) {} }'
+            ' abstract class D { void set f(int value); }',
+            className: 'C')
+        .executables[0];
+    checkInferredTypeSlot(
+        f.parameters[0].inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_setter_inferred_type_nonstatic_implicit_return() {
+    UnlinkedExecutable f =
+        serializeClassText('class C { set f(int value) {} }').executables[0];
+    checkInferredTypeSlot(f.inferredReturnTypeSlot, null, null, 'void');
+  }
+
+  test_setter_inferred_type_static_implicit_param() {
+    UnlinkedExecutable f = serializeClassText(
+            'class C extends D { static void set f(value) {} }'
+            ' class D { static void set f(int value) {} }',
+            className: 'C')
+        .executables[0];
+    expect(f.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_setter_inferred_type_static_implicit_return() {
+    UnlinkedExecutable f =
+        serializeClassText('class C { static set f(int value) {} }')
+            .executables[0];
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_setter_inferred_type_top_level_implicit_param() {
+    UnlinkedExecutable f =
+        serializeExecutableText('void set f(value) {}', 'f=');
+    expect(f.parameters[0].inferredTypeSlot, 0);
+  }
+
+  test_setter_inferred_type_top_level_implicit_return() {
+    UnlinkedExecutable f = serializeExecutableText('set f(int value) {}', 'f=');
+    expect(f.inferredReturnTypeSlot, 0);
+  }
+
+  test_slot_reuse() {
+    // Different compilation units have independent notions of slot id, so slot
+    // ids should be reused.
+    addNamedSource('/a.dart', 'part of foo; final v = 0;');
+    serializeLibraryText('library foo; part "a.dart"; final w = 0;');
+    expect(unlinkedUnits[0].variables[0].propagatedTypeSlot, 1);
+    expect(unlinkedUnits[1].variables[0].propagatedTypeSlot, 1);
+  }
+
+  test_type_arguments_explicit() {
+    EntityRef typeRef = serializeTypeText('List<int>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
+        allowTypeParameters: true, numTypeParameters: 1);
+    expect(typeRef.typeArguments, hasLength(1));
+    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_type_arguments_explicit_dynamic() {
+    EntityRef typeRef = serializeTypeText('List<dynamic>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
+        allowTypeParameters: true, numTypeParameters: 1);
+    expect(typeRef.typeArguments, isEmpty);
+  }
+
+  test_type_arguments_explicit_dynamic_dynamic() {
+    EntityRef typeRef = serializeTypeText('Map<dynamic, dynamic>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    // Trailing type arguments of type `dynamic` are omitted.
+    expect(typeRef.typeArguments, isEmpty);
+  }
+
+  test_type_arguments_explicit_dynamic_int() {
+    EntityRef typeRef = serializeTypeText('Map<dynamic, int>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    // Leading type arguments of type `dynamic` are not omitted.
+    expect(typeRef.typeArguments.length, 2);
+    checkDynamicTypeRef(typeRef.typeArguments[0]);
+    checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_type_arguments_explicit_dynamic_typedef() {
+    EntityRef typeRef =
+        serializeTypeText('F<dynamic>', otherDeclarations: 'typedef T F<T>();');
+    checkTypeRef(typeRef, null, null, 'F',
+        allowTypeParameters: true,
+        expectedKind: ReferenceKind.typedef,
+        numTypeParameters: 1);
+    expect(typeRef.typeArguments, isEmpty);
+  }
+
+  test_type_arguments_explicit_String_dynamic() {
+    EntityRef typeRef = serializeTypeText('Map<String, dynamic>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    // Trailing type arguments of type `dynamic` are omitted.
+    expect(typeRef.typeArguments.length, 1);
+    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'String');
+  }
+
+  test_type_arguments_explicit_String_int() {
+    EntityRef typeRef = serializeTypeText('Map<String, int>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    expect(typeRef.typeArguments.length, 2);
+    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'String');
+    checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_type_arguments_explicit_typedef() {
+    EntityRef typeRef =
+        serializeTypeText('F<int>', otherDeclarations: 'typedef T F<T>();');
+    checkTypeRef(typeRef, null, null, 'F',
+        allowTypeParameters: true,
+        expectedKind: ReferenceKind.typedef,
+        numTypeParameters: 1);
+    expect(typeRef.typeArguments, hasLength(1));
+    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_type_arguments_implicit() {
+    EntityRef typeRef = serializeTypeText('List');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
+        allowTypeParameters: true, numTypeParameters: 1);
+    expect(typeRef.typeArguments, isEmpty);
+  }
+
+  test_type_arguments_implicit_typedef() {
+    EntityRef typeRef =
+        serializeTypeText('F', otherDeclarations: 'typedef T F<T>();');
+    checkTypeRef(typeRef, null, null, 'F',
+        allowTypeParameters: true,
+        expectedKind: ReferenceKind.typedef,
+        numTypeParameters: 1);
+    expect(typeRef.typeArguments, isEmpty);
+  }
+
+  test_type_arguments_order() {
+    EntityRef typeRef = serializeTypeText('Map<int, Object>');
+    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    expect(typeRef.typeArguments, hasLength(2));
+    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
+    checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'Object');
+  }
+
+  test_type_dynamic() {
+    checkDynamicTypeRef(serializeTypeText('dynamic'));
+  }
+
+  test_type_param_not_shadowed_by_constructor() {
+    UnlinkedClass cls =
+        serializeClassText('class C<D> { D x; C.D(); } class D {}');
+    checkParamTypeRef(cls.fields[0].type, 1);
+  }
+
+  test_type_param_not_shadowed_by_field_in_extends() {
+    UnlinkedClass cls =
+        serializeClassText('class C<T> extends D<T> { T x; } class D<T> {}');
+    checkParamTypeRef(cls.supertype.typeArguments[0], 1);
+  }
+
+  test_type_param_not_shadowed_by_field_in_implements() {
+    UnlinkedClass cls =
+        serializeClassText('class C<T> implements D<T> { T x; } class D<T> {}');
+    checkParamTypeRef(cls.interfaces[0].typeArguments[0], 1);
+  }
+
+  test_type_param_not_shadowed_by_field_in_with() {
+    UnlinkedClass cls = serializeClassText(
+        'class C<T> extends Object with D<T> { T x; } class D<T> {}');
+    checkParamTypeRef(cls.mixins[0].typeArguments[0], 1);
+  }
+
+  test_type_param_not_shadowed_by_method_parameter() {
+    UnlinkedClass cls = serializeClassText('class C<T> { f(int T, T x) {} }');
+    checkParamTypeRef(cls.executables[0].parameters[1].type, 1);
+  }
+
+  test_type_param_not_shadowed_by_setter() {
+    // The code under test should not produce a compile-time error, but it
+    // does.
+    bool workAroundBug25525 = true;
+    UnlinkedClass cls = serializeClassText(
+        'class C<D> { D x; void set D(value) {} } class D {}',
+        allowErrors: workAroundBug25525);
+    checkParamTypeRef(cls.fields[0].type, 1);
+  }
+
+  test_type_param_not_shadowed_by_typedef_parameter() {
+    UnlinkedTypedef typedef =
+        serializeTypedefText('typedef void F<T>(int T, T x);');
+    checkParamTypeRef(typedef.parameters[1].type, 1);
+  }
+
+  test_type_param_shadowed_by_field() {
+    UnlinkedClass cls = serializeClassText(
+        'class C<D> { D x; int D; } class D {}',
+        allowErrors: true);
+    checkDynamicTypeRef(cls.fields[0].type);
+  }
+
+  test_type_param_shadowed_by_getter() {
+    UnlinkedClass cls = serializeClassText(
+        'class C<D> { D x; int get D => null; } class D {}',
+        allowErrors: true);
+    checkDynamicTypeRef(cls.fields[0].type);
+  }
+
+  test_type_param_shadowed_by_method() {
+    UnlinkedClass cls = serializeClassText(
+        'class C<D> { D x; void D() {} } class D {}',
+        allowErrors: true);
+    checkDynamicTypeRef(cls.fields[0].type);
+  }
+
+  test_type_param_shadowed_by_type_param() {
+    UnlinkedClass cls =
+        serializeClassText('class C<T> { T f<T>(T x) => null; }');
+    checkParamTypeRef(cls.executables[0].returnType, 1);
+    checkParamTypeRef(cls.executables[0].parameters[0].type, 1);
+  }
+
+  test_type_reference_from_part() {
+    addNamedSource('/a.dart', 'part of foo; C v;');
+    serializeLibraryText('library foo; part "a.dart"; class C {}');
+    checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
+        null, null, 'C',
+        expectedKind: ReferenceKind.classOrEnum,
+        linkedSourceUnit: linked.units[1],
+        unlinkedSourceUnit: unlinkedUnits[1]);
+  }
+
+  test_type_reference_from_part_withPrefix() {
+    addNamedSource('/a.dart', 'class C {}');
+    addNamedSource('/p.dart', 'part of foo; a.C v;');
+    serializeLibraryText(
+        'library foo; import "a.dart"; import "a.dart" as a; part "p.dart";',
+        allowErrors: true);
+    checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
+        absUri('/a.dart'), 'a.dart', 'C',
+        expectedPrefix: 'a',
+        linkedSourceUnit: linked.units[1],
+        unlinkedSourceUnit: unlinkedUnits[1]);
+  }
+
+  test_type_reference_to_class_argument() {
+    UnlinkedClass cls = serializeClassText('class C<T, U> { T t; U u; }');
+    {
+      EntityRef typeRef =
+          findVariable('t', variables: cls.fields, failIfAbsent: true).type;
+      checkParamTypeRef(typeRef, 2);
+    }
+    {
+      EntityRef typeRef =
+          findVariable('u', variables: cls.fields, failIfAbsent: true).type;
+      checkParamTypeRef(typeRef, 1);
+    }
+  }
+
+  test_type_reference_to_import_of_export() {
+    addNamedSource('/a.dart', 'library a; export "b.dart";');
+    addNamedSource('/b.dart', 'library b; class C {}');
+    checkTypeRef(serializeTypeText('C', otherDeclarations: 'import "a.dart";'),
+        absUri('/b.dart'), 'b.dart', 'C');
+  }
+
+  test_type_reference_to_import_of_export_via_prefix() {
+    addNamedSource('/a.dart', 'library a; export "b.dart";');
+    addNamedSource('/b.dart', 'library b; class C {}');
+    checkTypeRef(
+        serializeTypeText('p.C', otherDeclarations: 'import "a.dart" as p;'),
+        absUri('/b.dart'),
+        'b.dart',
+        'C',
+        expectedPrefix: 'p');
+  }
+
+  test_type_reference_to_imported_part() {
+    addNamedSource('/a.dart', 'library my.lib; part "b.dart";');
+    addNamedSource('/b.dart', 'part of my.lib; class C {}');
+    checkTypeRef(
+        serializeTypeText('C',
+            otherDeclarations: 'library my.lib; import "a.dart";'),
+        absUri('/a.dart'),
+        'a.dart',
+        'C',
+        expectedTargetUnit: 1);
+  }
+
+  test_type_reference_to_imported_part_with_prefix() {
+    addNamedSource('/a.dart', 'library my.lib; part "b.dart";');
+    addNamedSource('/b.dart', 'part of my.lib; class C {}');
+    checkTypeRef(
+        serializeTypeText('p.C',
+            otherDeclarations: 'library my.lib; import "a.dart" as p;'),
+        absUri('/a.dart'),
+        'a.dart',
+        'C',
+        expectedPrefix: 'p',
+        expectedTargetUnit: 1);
+  }
+
+  test_type_reference_to_internal_class() {
+    checkTypeRef(serializeTypeText('C', otherDeclarations: 'class C {}'), null,
+        null, 'C');
+  }
+
+  test_type_reference_to_internal_class_alias() {
+    checkTypeRef(
+        serializeTypeText('C',
+            otherDeclarations: 'class C = D with E; class D {} class E {}'),
+        null,
+        null,
+        'C');
+  }
+
+  test_type_reference_to_internal_enum() {
+    checkTypeRef(serializeTypeText('E', otherDeclarations: 'enum E { value }'),
+        null, null, 'E');
+  }
+
+  test_type_reference_to_local_part() {
+    addNamedSource('/a.dart', 'part of my.lib; class C {}');
+    checkTypeRef(
+        serializeTypeText('C',
+            otherDeclarations: 'library my.lib; part "a.dart";'),
+        null,
+        null,
+        'C',
+        expectedTargetUnit: 1);
+  }
+
+  test_type_reference_to_nonexistent_file_via_prefix() {
+    if (!checkAstDerivedData) {
+      // TODO(paulberry): this test currently fails because there is not enough
+      // information in the element model to figure out that the unresolved
+      // reference `p.C` uses the prefix `p`.
+      return;
+    }
+    allowMissingFiles = true;
+    EntityRef typeRef = serializeTypeText('p.C',
+        otherDeclarations: 'import "foo.dart" as p;', allowErrors: true);
+    checkUnresolvedTypeRef(typeRef, 'p', 'C');
+  }
+
+  test_type_reference_to_part() {
+    addNamedSource('/a.dart', 'part of foo; class C { C(); }');
+    serializeLibraryText('library foo; part "a.dart"; C c;');
+    checkTypeRef(unlinkedUnits[0].variables.single.type, null, null, 'C',
+        expectedKind: ReferenceKind.classOrEnum, expectedTargetUnit: 1);
+  }
+
+  test_type_reference_to_type_visible_via_multiple_import_prefixes() {
+    if (!checkAstDerivedData) {
+      // TODO(paulberry): this test currently fails because the element model
+      // doesn't record enough information to track which prefix is used to
+      // refer to a type.
+      return;
+    }
+    addNamedSource('/lib1.dart', 'class C');
+    addNamedSource('/lib2.dart', 'export "lib1.dart";');
+    addNamedSource('/lib3.dart', 'export "lib1.dart";');
+    addNamedSource('/lib4.dart', 'export "lib1.dart";');
+    serializeLibraryText('''
+import 'lib2.dart';
+import 'lib3.dart' as a;
+import 'lib4.dart' as b;
+C c2;
+a.C c3;
+b.C c4;''');
+    // Note: it is important that each reference to class C records the prefix
+    // used to find it; otherwise it's possible that relinking might produce an
+    // incorrect result after a change to lib2.dart, lib3.dart, or lib4.dart.
+    checkTypeRef(
+        findVariable('c2').type, absUri('/lib1.dart'), 'lib1.dart', 'C');
+    checkTypeRef(
+        findVariable('c3').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
+        expectedPrefix: 'a');
+    checkTypeRef(
+        findVariable('c4').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
+        expectedPrefix: 'b');
+  }
+
+  test_type_reference_to_typedef() {
+    checkTypeRef(serializeTypeText('F', otherDeclarations: 'typedef void F();'),
+        null, null, 'F',
+        expectedKind: ReferenceKind.typedef);
+  }
+
+  test_type_unit_counts_unreferenced_units() {
+    addNamedSource('/a.dart', 'library a; part "b.dart"; part "c.dart";');
+    addNamedSource('/b.dart', 'part of a;');
+    addNamedSource('/c.dart', 'part of a; class C {}');
+    EntityRef typeRef =
+        serializeTypeText('C', otherDeclarations: 'import "a.dart";');
+    // The referenced unit should be 2, since unit 0 is a.dart and unit 1 is
+    // b.dart.  a.dart and b.dart are counted even though nothing is imported
+    // from them.
+    checkTypeRef(typeRef, absUri('/a.dart'), 'a.dart', 'C',
+        expectedTargetUnit: 2);
+  }
+
+  test_type_unresolved() {
+    EntityRef typeRef = serializeTypeText('Foo', allowErrors: true);
+    checkUnresolvedTypeRef(typeRef, null, 'Foo');
+  }
+
+  test_typedef_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+typedef F();''';
+    UnlinkedTypedef typedef = serializeTypedefText(text);
+    expect(typedef.documentationComment, isNotNull);
+    checkDocumentationComment(typedef.documentationComment, text);
+  }
+
+  test_typedef_name() {
+    String text = 'typedef F();';
+    UnlinkedTypedef type = serializeTypedefText(text);
+    expect(type.name, 'F');
+    expect(type.nameOffset, text.indexOf('F'));
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(
+        unlinkedUnits[0].publicNamespace.names[0].kind, ReferenceKind.typedef);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'F');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
+  }
+
+  test_typedef_param_none() {
+    UnlinkedTypedef type = serializeTypedefText('typedef F();');
+    expect(type.parameters, isEmpty);
+  }
+
+  test_typedef_param_order() {
+    UnlinkedTypedef type = serializeTypedefText('typedef F(x, y);');
+    expect(type.parameters, hasLength(2));
+    expect(type.parameters[0].name, 'x');
+    expect(type.parameters[1].name, 'y');
+  }
+
+  test_typedef_private() {
+    serializeTypedefText('typedef _F();', '_F');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_typedef_reference_generic() {
+    EntityRef typeRef =
+        serializeTypeText('F', otherDeclarations: 'typedef void F<A, B>();');
+    checkTypeRef(typeRef, null, null, 'F',
+        numTypeParameters: 2, expectedKind: ReferenceKind.typedef);
+  }
+
+  test_typedef_reference_generic_imported() {
+    addNamedSource('/lib.dart', 'typedef void F<A, B>();');
+    EntityRef typeRef =
+        serializeTypeText('F', otherDeclarations: 'import "lib.dart";');
+    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'F',
+        numTypeParameters: 2, expectedKind: ReferenceKind.typedef);
+  }
+
+  test_typedef_return_type_explicit() {
+    UnlinkedTypedef type = serializeTypedefText('typedef int F();');
+    checkTypeRef(type.returnType, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_typedef_type_param_in_parameter() {
+    UnlinkedTypedef type = serializeTypedefText('typedef F<T>(T t);');
+    checkParamTypeRef(type.parameters[0].type, 1);
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
+  }
+
+  test_typedef_type_param_in_return_type() {
+    UnlinkedTypedef type = serializeTypedefText('typedef T F<T>();');
+    checkParamTypeRef(type.returnType, 1);
+  }
+
+  test_typedef_type_param_none() {
+    UnlinkedTypedef type = serializeTypedefText('typedef F();');
+    expect(type.typeParameters, isEmpty);
+  }
+
+  test_typedef_type_param_order() {
+    UnlinkedTypedef type = serializeTypedefText('typedef F<T, U>();');
+    expect(type.typeParameters, hasLength(2));
+    expect(type.typeParameters[0].name, 'T');
+    expect(type.typeParameters[1].name, 'U');
+  }
+
+  test_unresolved_reference_in_multiple_parts() {
+    addNamedSource('/a.dart', 'part of foo; int x; Unresolved y;');
+    serializeLibraryText('library foo; part "a.dart"; Unresolved z;',
+        allowErrors: true);
+    // The unresolved types in the defining compilation unit and the part
+    // should both work correctly even though they use different reference
+    // indices.
+    checkUnresolvedTypeRef(
+        unlinkedUnits[0].variables[0].type, null, 'Unresolved');
+    checkUnresolvedTypeRef(
+        unlinkedUnits[1].variables[1].type, null, 'Unresolved',
+        linkedSourceUnit: linked.units[1],
+        unlinkedSourceUnit: unlinkedUnits[1]);
+  }
+
+  test_variable() {
+    String text = 'int i;';
+    UnlinkedVariable v = serializeVariableText(text, variableName: 'i');
+    expect(v.nameOffset, text.indexOf('i;'));
+    expect(findExecutable('i'), isNull);
+    expect(findExecutable('i='), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
+    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
+        ReferenceKind.topLevelPropertyAccessor);
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'i');
+    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
+    expect(unlinkedUnits[0].publicNamespace.names[1].kind,
+        ReferenceKind.topLevelPropertyAccessor);
+    expect(unlinkedUnits[0].publicNamespace.names[1].name, 'i=');
+    expect(unlinkedUnits[0].publicNamespace.names[1].numTypeParameters, 0);
+  }
+
+  test_variable_const() {
+    UnlinkedVariable variable =
+        serializeVariableText('const int i = 0;', variableName: 'i');
+    expect(variable.isConst, isTrue);
+  }
+
+  test_variable_documented() {
+    String text = '''
+// Extra comment so doc comment offset != 0
+/**
+ * Docs
+ */
+var v;''';
+    UnlinkedVariable variable = serializeVariableText(text);
+    expect(variable.documentationComment, isNotNull);
+    checkDocumentationComment(variable.documentationComment, text);
+  }
+
+  test_variable_explicit_dynamic() {
+    UnlinkedVariable variable = serializeVariableText('dynamic v;');
+    checkDynamicTypeRef(variable.type);
+  }
+
+  test_variable_final_top_level() {
+    UnlinkedVariable variable =
+        serializeVariableText('final int i = 0;', variableName: 'i');
+    expect(variable.isFinal, isTrue);
+  }
+
+  test_variable_implicit_dynamic() {
+    UnlinkedVariable variable = serializeVariableText('var v;');
+    expect(variable.type, isNull);
+  }
+
+  test_variable_inferred_type_explicit_initialized() {
+    UnlinkedVariable v = serializeVariableText('int v = 0;');
+    expect(v.inferredTypeSlot, 0);
+  }
+
+  test_variable_inferred_type_implicit_initialized() {
+    UnlinkedVariable v = serializeVariableText('var v = 0;');
+    checkInferredTypeSlot(v.inferredTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_variable_inferred_type_implicit_uninitialized() {
+    UnlinkedVariable v = serializeVariableText('var v;');
+    expect(v.inferredTypeSlot, 0);
+  }
+
+  test_variable_name() {
+    UnlinkedVariable variable =
+        serializeVariableText('int i;', variableName: 'i');
+    expect(variable.name, 'i');
+  }
+
+  test_variable_no_flags() {
+    UnlinkedVariable variable =
+        serializeVariableText('int i;', variableName: 'i');
+    expect(variable.isStatic, isFalse);
+    expect(variable.isConst, isFalse);
+    expect(variable.isFinal, isFalse);
+  }
+
+  test_variable_non_const() {
+    UnlinkedVariable variable =
+        serializeVariableText('int i = 0;', variableName: 'i');
+    expect(variable.isConst, isFalse);
+  }
+
+  test_variable_non_final() {
+    UnlinkedVariable variable =
+        serializeVariableText('int i;', variableName: 'i');
+    expect(variable.isFinal, isFalse);
+  }
+
+  test_variable_non_static() {
+    UnlinkedVariable variable =
+        serializeClassText('class C { int i; }').fields[0];
+    expect(variable.isStatic, isFalse);
+  }
+
+  test_variable_non_static_top_level() {
+    // Top level variables are considered non-static.
+    UnlinkedVariable variable =
+        serializeVariableText('int i;', variableName: 'i');
+    expect(variable.isStatic, isFalse);
+  }
+
+  test_variable_private() {
+    serializeVariableText('int _i;', variableName: '_i');
+    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
+  }
+
+  test_variable_propagated_type_final_immediate() {
+    UnlinkedVariable v = serializeVariableText('final v = 0;');
+    checkLinkedTypeSlot(v.propagatedTypeSlot, 'dart:core', 'dart:core', 'int');
+  }
+
+  test_variable_propagated_type_new_reference() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    UnlinkedVariable v = serializeVariableText('final v = 0;');
+    // Since the propagated type of `v` is `int`, and there are no references
+    // to `int` elsewhere in the source file, a new linked reference should
+    // have been created for it, with no associated unlinked reference.
+    expect(v.propagatedTypeSlot, isNot(0));
+    EntityRef type = getTypeRefForSlot(v.propagatedTypeSlot);
+    expect(type, isNotNull);
+    expect(type.reference,
+        greaterThanOrEqualTo(unlinkedUnits[0].references.length));
+  }
+
+  test_variable_propagated_type_omit_dynamic() {
+    if (skipFullyLinkedData) {
+      return;
+    }
+    UnlinkedVariable v = serializeVariableText('final v = <int, dynamic>{};');
+    EntityRef type = getTypeRefForSlot(v.propagatedTypeSlot);
+    checkLinkedTypeRef(type, 'dart:core', 'dart:core', 'Map',
+        allowTypeParameters: true, numTypeParameters: 2);
+    expect(type.typeArguments, hasLength(1));
+    checkLinkedTypeRef(type.typeArguments[0], 'dart:core', 'dart:core', 'int');
+  }
+
+  test_variable_propagatedTypeSlot_const() {
+    // Const variables are propagable so they have a nonzero
+    // propagatedTypeSlot.
+    UnlinkedVariable variable = serializeVariableText('const v = 0;');
+    expect(variable.propagatedTypeSlot, isNot(0));
+  }
+
+  test_variable_propagatedTypeSlot_final() {
+    // Final variables are propagable so they have a nonzero
+    // propagatedTypeSlot.
+    UnlinkedVariable variable = serializeVariableText('final v = 0;');
+    expect(variable.propagatedTypeSlot, isNot(0));
+  }
+
+  test_variable_propagatedTypeSlot_non_propagable() {
+    // Non-final non-const variables aren't propagable so they don't have a
+    // propagatedTypeSlot.
+    UnlinkedVariable variable = serializeVariableText('var v;');
+    expect(variable.propagatedTypeSlot, 0);
+  }
+
+  test_variable_static() {
+    UnlinkedVariable variable =
+        serializeClassText('class C { static int i; }').fields[0];
+    expect(variable.isStatic, isTrue);
+  }
+
+  test_variable_type() {
+    UnlinkedVariable variable =
+        serializeVariableText('int i;', variableName: 'i');
+    checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int');
+  }
+
+  void _assertUnlinkedConst(UnlinkedConst constExpr,
+      {List<UnlinkedConstOperation> operators,
+      List<int> ints: const <int>[],
+      List<double> doubles: const <double>[],
+      List<String> strings: const <String>[],
+      List<_EntityRefValidator> referenceValidators:
+          const <_EntityRefValidator>[]}) {
+    expect(constExpr, isNotNull);
+    expect(constExpr.operations, operators);
+    expect(constExpr.ints, ints);
+    expect(constExpr.doubles, doubles);
+    expect(constExpr.strings, strings);
+    expect(constExpr.references, hasLength(referenceValidators.length));
+    for (int i = 0; i < referenceValidators.length; i++) {
+      referenceValidators[i](constExpr.references[i]);
+    }
+  }
+}
+
+/**
+ * Description of expectations for a prelinked prefix reference.
+ */
+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});
+}
diff --git a/pkg/analyzer/test/src/summary/summary_sdk_test.dart b/pkg/analyzer/test/src/summary/summary_sdk_test.dart
deleted file mode 100644
index 5ec807e..0000000
--- a/pkg/analyzer/test/src/summary/summary_sdk_test.dart
+++ /dev/null
@@ -1,260 +0,0 @@
-// 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 test.src.summary.summary_sdk_test;
-
-import 'dart:io';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisContext, CacheState;
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/format.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' show AnalysisContextTarget;
-import 'package:analyzer/task/model.dart';
-import 'package:path/path.dart' as pathos;
-import 'package:unittest/unittest.dart';
-
-import '../../generated/test_support.dart';
-import '../../reflective_tests.dart';
-
-main() {
-  groupSep = ' | ';
-  runReflectiveTests(SummarySdkAnalysisContextTest);
-}
-
-@reflectiveTest
-class SummarySdkAnalysisContextTest {
-  static String _analyzerPackagePath;
-  static bool _analyzerPackagePathInitialized = false;
-
-  static SdkBundle sdkBundle;
-
-  SummarySdkAnalysisContext context;
-
-  void setUp() {
-    _initializeSdkContext();
-  }
-
-  test_libraryResults() {
-    if (context == null) {
-      return;
-    }
-    // verify that there are at least some interesting libraries in the bundle
-    expect(sdkBundle.prelinkedLibraryUris, contains('dart:core'));
-    expect(sdkBundle.prelinkedLibraryUris, contains('dart:async'));
-    expect(sdkBundle.prelinkedLibraryUris, contains('dart:html'));
-    // verify every library
-    for (String uri in sdkBundle.prelinkedLibraryUris) {
-      // TODO(scheglov) breaks at _LibraryResynthesizer.buildImplicitTopLevelVariable
-      if (uri == 'dart:io' || uri == 'dart:_isolate_helper') {
-        continue;
-      }
-      _assertLibraryResults(uri);
-    }
-  }
-
-  test_sourceKind() {
-    if (context == null) {
-      return;
-    }
-    // libraries
-    _assertHasSourceKind('dart:core', SourceKind.LIBRARY);
-    _assertHasSourceKind('dart:async', SourceKind.LIBRARY);
-    _assertHasSourceKind('dart:math', SourceKind.LIBRARY);
-    // parts
-    _assertHasSourceKind('dart:core/bool.dart', SourceKind.PART);
-    _assertHasSourceKind('dart:async/future.dart', SourceKind.PART);
-    // unknown
-    _assertHasSourceKind('dart:no_such_library.dart', null);
-    _assertHasSourceKind('dart:core/no_such_part.dart', null);
-  }
-
-  test_typeProvider() {
-    if (context == null) {
-      return;
-    }
-    AnalysisContextTarget target = AnalysisContextTarget.request;
-    CacheEntry cacheEntry = context.getCacheEntry(target);
-    bool hasResult = context.aboutToComputeResult(cacheEntry, TYPE_PROVIDER);
-    expect(hasResult, isTrue);
-    expect(cacheEntry.getState(TYPE_PROVIDER), CacheState.VALID);
-    TypeProvider typeProvider = cacheEntry.getValue(TYPE_PROVIDER);
-    expect(typeProvider.objectType, isNotNull);
-    expect(typeProvider.boolType, isNotNull);
-    expect(typeProvider.intType, isNotNull);
-    expect(typeProvider.futureType, isNotNull);
-    expect(typeProvider.futureDynamicType, isNotNull);
-    expect(typeProvider.streamType, isNotNull);
-    expect(typeProvider.streamDynamicType, isNotNull);
-  }
-
-  void _assertHasLibraryElement(CacheEntry cacheEntry,
-      ResultDescriptor<LibraryElement> resultDescriptor) {
-    bool hasResult = context.aboutToComputeResult(cacheEntry, resultDescriptor);
-    expect(hasResult, isTrue);
-    expect(cacheEntry.getState(resultDescriptor), CacheState.VALID);
-    LibraryElement library = cacheEntry.getValue(resultDescriptor);
-    expect(library, isNotNull);
-  }
-
-  void _assertHasSourceKind(String uri, SourceKind expectedValue) {
-    Source target = context.sourceFactory.forUri(uri);
-    CacheEntry cacheEntry = context.getCacheEntry(target);
-    ResultDescriptor<SourceKind> resultDescriptor = SOURCE_KIND;
-    bool hasResult = context.aboutToComputeResult(cacheEntry, resultDescriptor);
-    if (expectedValue == null) {
-      expect(hasResult, isFalse);
-      expect(cacheEntry.getState(resultDescriptor), CacheState.INVALID);
-    } else {
-      expect(hasResult, isTrue);
-      expect(cacheEntry.getState(resultDescriptor), CacheState.VALID);
-      SourceKind value = cacheEntry.getValue(resultDescriptor);
-      expect(value, expectedValue);
-    }
-  }
-
-  void _assertIsLibraryElementReady(
-      CacheEntry cacheEntry, ResultDescriptor<bool> resultDescriptor) {
-    bool hasResult = context.aboutToComputeResult(cacheEntry, resultDescriptor);
-    expect(hasResult, isTrue);
-    expect(cacheEntry.getState(resultDescriptor), CacheState.VALID);
-    bool ready = cacheEntry.getValue(resultDescriptor);
-    expect(ready, isTrue);
-  }
-
-  void _assertLibraryResults(String uri) {
-    Source target = context.sourceFactory.forUri(uri);
-    CacheEntry cacheEntry = context.getCacheEntry(target);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT1);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT2);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT3);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT4);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT5);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT6);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT7);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT8);
-    _assertHasLibraryElement(cacheEntry, LIBRARY_ELEMENT);
-    _assertIsLibraryElementReady(cacheEntry, READY_LIBRARY_ELEMENT2);
-    _assertIsLibraryElementReady(cacheEntry, READY_LIBRARY_ELEMENT5);
-    _assertIsLibraryElementReady(cacheEntry, READY_LIBRARY_ELEMENT6);
-  }
-
-  void _initializeSdkBundle() {
-    if (sdkBundle != null) {
-      return;
-    }
-    // prepare analyzer path
-    String analyzerPath = getAnalyzerPackagePath();
-    if (analyzerPath == null) {
-      return;
-    }
-    // prepare summary path
-    String sdkSummaryPath = pathos.join(
-        analyzerPath, 'test', 'src', 'summary', 'sdk_analysis_summary');
-    File file = new File(sdkSummaryPath);
-    if (!file.existsSync()) {
-      return;
-    }
-    // load SdkBundle
-    List<int> bytes = file.readAsBytesSync();
-    sdkBundle = new SdkBundle.fromBuffer(bytes);
-  }
-
-  void _initializeSdkContext() {
-    _initializeSdkBundle();
-    if (sdkBundle == null) {
-      return;
-    }
-    context = new _TestSummarySdkAnalysisContext(sdkBundle);
-    DartSdk sdk = new _TestSummaryDartSdk();
-    context.sourceFactory = new SourceFactory([new DartUriResolver(sdk)]);
-  }
-
-  static String getAnalyzerPackagePath() {
-    if (!_analyzerPackagePathInitialized) {
-      _analyzerPackagePathInitialized = true;
-      _analyzerPackagePath = _computeAnalyzerPackagePath();
-    }
-    return _analyzerPackagePath;
-  }
-
-  /**
-   * Return the path to the `analyzer` package root, or `null` if it cannot
-   * be determined.
-   *
-   * This method expects that one of the `analyzer` tests was run, so
-   * [Platform.script] is inside of the `analyzer/test` folder.
-   */
-  static String _computeAnalyzerPackagePath() {
-    Uri uri = Platform.script;
-    if (uri == null || uri.scheme != 'file') {
-      return null;
-    }
-    String path = pathos.fromUri(uri);
-    List<String> segments = pathos.split(path);
-    while (segments.length > 2) {
-      if (segments[segments.length - 1] == 'test' &&
-          segments[segments.length - 2] == 'analyzer') {
-        segments.removeLast();
-        return pathos.joinAll(segments);
-      }
-      segments.removeLast();
-    }
-    return null;
-  }
-}
-
-class _TestSummaryDartSdk implements DartSdk {
-  @override
-  Source mapDartUri(String uriStr) {
-    Uri uri = Uri.parse(uriStr);
-    List<String> segments = uri.pathSegments;
-    if (segments.length == 1) {
-      String libraryName = segments.first;
-      String path = '/sdk/$libraryName/$libraryName.dart';
-      return new _TestSummarySdkSource(path, uri);
-    } else {
-      String path = '/sdk/' + segments.join('/');
-      return new _TestSummarySdkSource(path, uri);
-    }
-  }
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-/**
- * [SummarySdkAnalysisContext] with simplified cache creation.
- */
-class _TestSummarySdkAnalysisContext extends SummarySdkAnalysisContext {
-  _TestSummarySdkAnalysisContext(SdkBundle bundle) : super(bundle);
-
-  @override
-  AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    return new AnalysisCache(<CachePartition>[new SdkCachePartition(this)]);
-  }
-}
-
-class _TestSummarySdkSource extends TestSourceWithUri {
-  _TestSummarySdkSource(String path, Uri uri) : super(path, uri);
-
-  @override
-  bool get isInSystemLibrary => true;
-
-  @override
-  Uri resolveRelativeUri(Uri relativeUri) {
-    Uri baseUri = uri;
-    if (uri.scheme == 'dart') {
-      String libraryName = uri.path;
-      baseUri = Uri.parse('dart:$libraryName/$libraryName.dart');
-    }
-    return baseUri.resolveUri(relativeUri);
-  }
-}
diff --git a/pkg/analyzer/test/src/summary/summary_test.dart b/pkg/analyzer/test/src/summary/summary_test.dart
deleted file mode 100644
index 8b25e9d..0000000
--- a/pkg/analyzer/test/src/summary/summary_test.dart
+++ /dev/null
@@ -1,2966 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library analyzer.test.src.summary.summary_test;
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_engine_io.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/scanner.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/summary/base.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/prelink.dart';
-import 'package:analyzer/src/summary/public_namespace_computer.dart'
-    as public_namespace;
-import 'package:analyzer/src/summary/summarize_elements.dart'
-    as summarize_elements;
-import 'package:unittest/unittest.dart';
-
-import '../../generated/resolver_test.dart';
-import '../../reflective_tests.dart';
-
-main() {
-  groupSep = ' | ';
-  runReflectiveTests(SummarizeElementsTest);
-  runReflectiveTests(PrelinkerTest);
-}
-
-/**
- * Convert a summary object (or a portion of one) into a canonical form that
- * can be easily compared using [expect].  If [orderByName] is true, and the
- * object is a [List], it is sorted by the `name` field of its elements.
- */
-Object canonicalize(Object obj, {bool orderByName: false}) {
-  if (obj is SummaryClass) {
-    Map<String, Object> result = <String, Object>{};
-    obj.toMap().forEach((String key, Object value) {
-      bool orderByName = false;
-      if (obj is UnlinkedPublicNamespace && key == 'names') {
-        orderByName = true;
-      }
-      result[key] = canonicalize(value, orderByName: orderByName);
-    });
-    return result;
-  } else if (obj is List) {
-    List<Object> result = <Object>[];
-    for (Object item in obj) {
-      result.add(canonicalize(item));
-    }
-    if (orderByName) {
-      result.sort((Object a, Object b) {
-        if (a is Map && b is Map) {
-          return Comparable.compare(a['name'], b['name']);
-        } else {
-          return 0;
-        }
-      });
-    }
-    return result;
-  } else if (obj is String || obj is num || obj is bool) {
-    return obj;
-  } else {
-    return obj.toString();
-  }
-}
-
-UnlinkedPublicNamespace computePublicNamespaceFromText(
-    String text, Source source) {
-  CharacterReader reader = new CharSequenceReader(text);
-  Scanner scanner =
-      new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER);
-  Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
-  parser.parseGenericMethods = true;
-  CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
-  UnlinkedPublicNamespace namespace = new UnlinkedPublicNamespace.fromBuffer(
-      public_namespace.computePublicNamespace(unit).toBuffer());
-  return namespace;
-}
-
-/**
- * Override of [SummaryTest] which verifies the correctness of the prelinker by
- * creating summaries from the element model, discarding their prelinked
- * information, and then recreating it using the prelinker.
- */
-@reflectiveTest
-class PrelinkerTest extends SummarizeElementsTest {
-  /**
-   * The public namespaces of the sdk are computed once so that we don't bog
-   * down the test.  Structured as a map from absolute URI to the corresponding
-   * public namespace.
-   *
-   * Note: should an exception occur during computation of this variable, it
-   * will silently be set to null to allow other tests to run.
-   */
-  static final Map<String, UnlinkedPublicNamespace> sdkPublicNamespace = () {
-    try {
-      AnalysisContext analysisContext =
-          AnalysisContextFactory.contextWithCore();
-      Map<String, UnlinkedPublicNamespace> uriToNamespace =
-          <String, UnlinkedPublicNamespace>{};
-      List<LibraryElement> libraries = [
-        analysisContext.typeProvider.objectType.element.library,
-        analysisContext.typeProvider.futureType.element.library
-      ];
-      for (LibraryElement library in libraries) {
-        summarize_elements.LibrarySerializationResult serializedLibrary =
-            summarize_elements.serializeLibrary(
-                library, analysisContext.typeProvider);
-        for (int i = 0; i < serializedLibrary.unlinkedUnits.length; i++) {
-          uriToNamespace[
-              serializedLibrary.unitUris[i]] = new UnlinkedUnit.fromBuffer(
-              serializedLibrary.unlinkedUnits[i].toBuffer()).publicNamespace;
-        }
-      }
-      return uriToNamespace;
-    } catch (_) {
-      return null;
-    }
-  }();
-
-  final Map<String, UnlinkedPublicNamespace> uriToPublicNamespace =
-      <String, UnlinkedPublicNamespace>{};
-
-  @override
-  bool get expectAbsoluteUrisInDependencies => false;
-
-  @override
-  Source addNamedSource(String filePath, String contents) {
-    Source source = super.addNamedSource(filePath, contents);
-    uriToPublicNamespace[absUri(filePath)] =
-        computePublicNamespaceFromText(contents, source);
-    return source;
-  }
-
-  String resolveToAbsoluteUri(LibraryElement library, String relativeUri) {
-    Source resolvedSource =
-        analysisContext.sourceFactory.resolveUri(library.source, relativeUri);
-    if (resolvedSource == null) {
-      fail('Failed to resolve relative uri "$relativeUri"');
-    }
-    return resolvedSource.uri.toString();
-  }
-
-  @override
-  void serializeLibraryElement(LibraryElement library) {
-    super.serializeLibraryElement(library);
-    Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
-    expect(unlinkedUnits.length, unitUris.length);
-    for (int i = 1; i < unlinkedUnits.length; i++) {
-      uriToUnit[unitUris[i]] = unlinkedUnits[i];
-    }
-    UnlinkedUnit getPart(String relativeUri) {
-      String absoluteUri = resolveToAbsoluteUri(library, relativeUri);
-      UnlinkedUnit unit = uriToUnit[absoluteUri];
-      if (unit == null) {
-        fail('Prelinker unexpectedly requested unit for "$relativeUri"'
-            ' (resolves to "$absoluteUri").');
-      }
-      return unit;
-    }
-    UnlinkedPublicNamespace getImport(String relativeUri) {
-      String absoluteUri = resolveToAbsoluteUri(library, relativeUri);
-      UnlinkedPublicNamespace namespace = sdkPublicNamespace[absoluteUri];
-      if (namespace == null) {
-        namespace = uriToPublicNamespace[absoluteUri];
-      }
-      if (namespace == null && !allowMissingFiles) {
-        fail('Prelinker unexpectedly requested namespace for "$relativeUri"'
-            ' (resolves to "$absoluteUri").'
-            '  Namespaces available: ${uriToPublicNamespace.keys}');
-      }
-      return namespace;
-    }
-    prelinked = new PrelinkedLibrary.fromBuffer(
-        prelink(unlinkedUnits[0], getPart, getImport).toBuffer());
-  }
-}
-
-/**
- * Override of [SummaryTest] which creates summaries from the element model.
- */
-@reflectiveTest
-class SummarizeElementsTest extends ResolverTestCase with SummaryTest {
-  /**
-   * The list of absolute unit URIs corresponding to the compilation units in
-   * [unlinkedUnits].
-   */
-  List<String> unitUris;
-
-  /**
-   * Map containing all source files in this test, and their corresponding file
-   * contents.
-   */
-  final Map<Source, String> _fileContents = <Source, String>{};
-
-  @override
-  bool get checkAstDerivedData => false;
-
-  @override
-  bool get expectAbsoluteUrisInDependencies => true;
-
-  @override
-  Source addNamedSource(String filePath, String contents) {
-    Source source = super.addNamedSource(filePath, contents);
-    _fileContents[source] = contents;
-    return source;
-  }
-
-  /**
-   * Serialize the library containing the given class [element], then
-   * deserialize it and return the summary of the class.
-   */
-  UnlinkedClass serializeClassElement(ClassElement element) {
-    serializeLibraryElement(element.library);
-    return findClass(element.name, failIfAbsent: true);
-  }
-
-  /**
-   * Serialize the given [library] element, then deserialize it and store the
-   * resulting summary in [prelinked] and [unlinkedUnits].
-   */
-  void serializeLibraryElement(LibraryElement library) {
-    summarize_elements.LibrarySerializationResult serializedLib =
-        summarize_elements.serializeLibrary(library, typeProvider);
-    {
-      List<int> buffer = serializedLib.prelinked.toBuffer();
-      prelinked = new PrelinkedLibrary.fromBuffer(buffer);
-    }
-    unlinkedUnits = serializedLib.unlinkedUnits.map((UnlinkedUnitBuilder b) {
-      List<int> buffer = b.toBuffer();
-      return new UnlinkedUnit.fromBuffer(buffer);
-    }).toList();
-    unitUris = serializedLib.unitUris;
-  }
-
-  @override
-  void serializeLibraryText(String text, {bool allowErrors: false}) {
-    Source source = addSource(text);
-    _fileContents[source] = text;
-    LibraryElement library = resolve2(source);
-    if (!allowErrors) {
-      assertNoErrors(source);
-    }
-    serializeLibraryElement(library);
-    expect(
-        unlinkedUnits[0].imports.length, prelinked.importDependencies.length);
-    expect(prelinked.units.length, unlinkedUnits.length);
-    for (int i = 0; i < prelinked.units.length; i++) {
-      expect(unlinkedUnits[i].references.length,
-          prelinked.units[i].references.length);
-    }
-    verifyPublicNamespace();
-  }
-
-  @override
-  void setUp() {
-    super.setUp();
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.enableGenericMethods = true;
-    resetWithOptions(options);
-  }
-
-  test_class_no_superclass() {
-    UnlinkedClass cls = serializeClassElement(typeProvider.objectType.element);
-    expect(cls.supertype, isNull);
-    expect(cls.hasNoSupertype, isTrue);
-  }
-
-  /**
-   * Verify that [public_namespace.computePublicNamespace] produces data that's
-   * equivalent to that produced by [summarize_elements.serializeLibrary].
-   */
-  void verifyPublicNamespace() {
-    for (int i = 0; i < unlinkedUnits.length; i++) {
-      Source source = analysisContext.sourceFactory.forUri(unitUris[i]);
-      String text = _fileContents[source];
-      if (text == null) {
-        if (!allowMissingFiles) {
-          fail('Could not find file while verifying public namespace: '
-              '${unitUris[i]}');
-        }
-      } else {
-        UnlinkedPublicNamespace namespace =
-            computePublicNamespaceFromText(text, source);
-        expect(canonicalize(namespace),
-            canonicalize(unlinkedUnits[i].publicNamespace),
-            reason: 'publicNamespace(${unitUris[i]})');
-      }
-    }
-  }
-}
-
-/**
- * Base class containing most summary tests.  This allows summary tests to be
- * re-used to exercise all the different ways in which summaries can be
- * generated (e.g. direct from the AST, from the element model, from a
- * "relinking" process, etc.)
- */
-abstract class SummaryTest {
-  /**
-   * Prelinked summary that results from serializing and then deserializing the
-   * library under test.
-   */
-  PrelinkedLibrary prelinked;
-
-  /**
-   * Unlinked compilation unit summaries that result from serializing and
-   * deserializing the library under test.
-   */
-  List<UnlinkedUnit> unlinkedUnits;
-
-  /**
-   * A test will set this to `true` if it contains `import`, `export`, or
-   * `part` declarations that deliberately refer to non-existent files.
-   */
-  bool allowMissingFiles = false;
-
-  /**
-   * `true` if the summary was created directly from the AST (and hence
-   * contains information that is not obtainable from the element model alone).
-   * TODO(paulberry): modify the element model so that it contains all the data
-   * that summaries need, so that this flag is no longer needed.
-   */
-  bool get checkAstDerivedData;
-
-  /**
-   * Get access to the prelinked defining compilation unit.
-   */
-  PrelinkedUnit get definingUnit => prelinked.units[0];
-
-  /**
-   * `true` if the prelinked portion of the summary is expected to contain
-   * absolute URIs.  This happens because the element model doesn't (yet) store
-   * enough information to recover relative URIs, TODO(paulberry): fix this.
-   */
-  bool get expectAbsoluteUrisInDependencies;
-
-  /**
-   * Convert [path] to a suitably formatted absolute path URI for the current
-   * platform.
-   */
-  String absUri(String path) {
-    return FileUtilities2.createFile(path).toURI().toString();
-  }
-
-  /**
-   * Add the given source file so that it may be referenced by the file under
-   * test.
-   */
-  Source addNamedSource(String filePath, String contents);
-
-  /**
-   * Verify that the [dependency]th element of the dependency table represents
-   * a file reachable via the given [absoluteUri] and [relativeUri].
-   */
-  void checkDependency(int dependency, String absoluteUri, String relativeUri) {
-    if (expectAbsoluteUrisInDependencies) {
-      // The element model doesn't (yet) store enough information to recover
-      // relative URIs, so we have to use the absolute URI.
-      // TODO(paulberry): fix this.
-      relativeUri = absoluteUri;
-    }
-    expect(dependency, new isInstanceOf<int>());
-    expect(prelinked.dependencies[dependency].uri, relativeUri);
-  }
-
-  /**
-   * Verify that the given [dependency] lists the given [absoluteUris] or
-   * [relativeUris] as its parts.
-   */
-  void checkDependencyParts(PrelinkedDependency dependency,
-      List<String> absoluteUris, List<String> relativeUris) {
-    if (expectAbsoluteUrisInDependencies) {
-      // The element model doesn't (yet) store enough information to recover
-      // relative URIs, so we have to use the absolute URI.
-      // TODO(paulberry): fix this.
-      relativeUris = absoluteUris;
-    }
-    expect(dependency.parts, relativeUris);
-  }
-
-  /**
-   * Check that the given [documentationComment] matches the first
-   * Javadoc-style comment found in [text].
-   *
-   * Note that the algorithm for finding the Javadoc-style comment in [text] is
-   * a simple-minded text search; it is easily confused by corner cases such as
-   * strings containing comments, nested comments, etc.
-   */
-  void checkDocumentationComment(
-      UnlinkedDocumentationComment documentationComment, String text) {
-    expect(documentationComment, isNotNull);
-    int commentStart = text.indexOf('/*');
-    expect(commentStart, isNot(-1));
-    int commentEnd = text.indexOf('*/');
-    expect(commentEnd, isNot(-1));
-    commentEnd += 2;
-    String expectedCommentText =
-        text.substring(commentStart, commentEnd).replaceAll('\r\n', '\n');
-    expect(documentationComment.text, expectedCommentText);
-    expect(documentationComment.offset, commentStart);
-    expect(documentationComment.length, commentEnd - commentStart);
-  }
-
-  /**
-   * Verify that the given [typeRef] represents the type `dynamic`.
-   */
-  void checkDynamicTypeRef(UnlinkedTypeRef typeRef) {
-    checkTypeRef(typeRef, null, null, null);
-  }
-
-  /**
-   * Verify that the dependency table contains an entry for a file reachable
-   * via the given [absoluteUri] and [relativeUri].
-   *
-   * The [PrelinkedDependency] is returned.
-   */
-  PrelinkedDependency checkHasDependency(
-      String absoluteUri, String relativeUri) {
-    if (expectAbsoluteUrisInDependencies) {
-      // The element model doesn't (yet) store enough information to recover
-      // relative URIs, so we have to use the absolute URI.
-      // TODO(paulberry): fix this.
-      relativeUri = absoluteUri;
-    }
-    List<String> found = <String>[];
-    for (PrelinkedDependency dep in prelinked.dependencies) {
-      if (dep.uri == relativeUri) {
-        return dep;
-      }
-      found.add(dep.uri);
-    }
-    fail('Did not find dependency $relativeUri.  Found: $found');
-    return null;
-  }
-
-  /**
-   * Verify that the dependency table *does not* contain any entries for a file
-   * reachable via the given [absoluteUri] and [relativeUri].
-   */
-  void checkLacksDependency(String absoluteUri, String relativeUri) {
-    if (expectAbsoluteUrisInDependencies) {
-      // The element model doesn't (yet) store enough information to recover
-      // relative URIs, so we have to use the absolute URI.
-      // TODO(paulberry): fix this.
-      relativeUri = absoluteUri;
-    }
-    for (PrelinkedDependency dep in prelinked.dependencies) {
-      if (dep.uri == relativeUri) {
-        fail('Unexpected dependency found: $relativeUri');
-      }
-    }
-  }
-
-  /**
-   * Verify that the given [typeRef] represents a reference to a type parameter
-   * having the given [deBruijnIndex].
-   */
-  void checkParamTypeRef(UnlinkedTypeRef typeRef, int deBruijnIndex) {
-    expect(typeRef, new isInstanceOf<UnlinkedTypeRef>());
-    expect(typeRef.reference, 0);
-    expect(typeRef.typeArguments, isEmpty);
-    expect(typeRef.paramReference, deBruijnIndex);
-  }
-
-  /**
-   * Verify that [prefixReference] is a valid reference to a prefix having the
-   * given [name].
-   */
-  void checkPrefix(int prefixReference, String name) {
-    expect(prefixReference, isNot(0));
-    expect(unlinkedUnits[0].references[prefixReference].prefixReference, 0);
-    expect(unlinkedUnits[0].references[prefixReference].name, name);
-    expect(definingUnit.references[prefixReference].dependency, 0);
-    expect(definingUnit.references[prefixReference].kind,
-        PrelinkedReferenceKind.prefix);
-    expect(definingUnit.references[prefixReference].unit, 0);
-  }
-
-  /**
-   * Verify that the given [typeRef] represents a reference to a type declared
-   * in a file reachable via [absoluteUri] and [relativeUri], having name
-   * [expectedName].  If [expectedPrefix] is supplied, verify that the type is
-   * reached via the given prefix.  If [allowTypeParameters] is true, allow the
-   * type reference to supply type parameters.  [expectedKind] is the kind of
-   * object referenced.  [prelinkedSourceUnit] and [unlinkedSourceUnit] refer
-   * to the compilation unit within which the [typeRef] appears; if not
-   * specified they are assumed to refer to the defining compilation unit.
-   * [expectedTargetUnit] is the index of the compilation unit in which the
-   * target of the [typeRef] is expected to appear; if not specified it is
-   * assumed to be the defining compilation unit.  [numTypeParameters] is the
-   * number of type parameters of the thing being referred to.
-   */
-  void checkTypeRef(UnlinkedTypeRef typeRef, String absoluteUri,
-      String relativeUri, String expectedName,
-      {String expectedPrefix,
-      bool allowTypeParameters: false,
-      PrelinkedReferenceKind expectedKind: PrelinkedReferenceKind.classOrEnum,
-      int expectedTargetUnit: 0,
-      PrelinkedUnit prelinkedSourceUnit,
-      UnlinkedUnit unlinkedSourceUnit,
-      int numTypeParameters: 0}) {
-    prelinkedSourceUnit ??= definingUnit;
-    unlinkedSourceUnit ??= unlinkedUnits[0];
-    expect(typeRef, new isInstanceOf<UnlinkedTypeRef>());
-    expect(typeRef.paramReference, 0);
-    int index = typeRef.reference;
-    UnlinkedReference reference = unlinkedSourceUnit.references[index];
-    PrelinkedReference referenceResolution =
-        prelinkedSourceUnit.references[index];
-    if (index == 0) {
-      // Index 0 is reserved for "dynamic".
-      expect(reference.name, isEmpty);
-      expect(reference.prefixReference, 0);
-    }
-    if (absoluteUri == null) {
-      expect(referenceResolution.dependency, 0);
-    } else {
-      checkDependency(referenceResolution.dependency, absoluteUri, relativeUri);
-    }
-    if (!allowTypeParameters) {
-      expect(typeRef.typeArguments, isEmpty);
-    }
-    if (expectedKind == PrelinkedReferenceKind.unresolved) {
-      // summarize_elements.dart isn't yet able to record the name of
-      // unresolved references.  TODO(paulberry): fix this.
-      expect(reference.name, '*unresolved*');
-    } else if (expectedName == null) {
-      expect(reference.name, isEmpty);
-    } else {
-      expect(reference.name, expectedName);
-    }
-    if (expectedPrefix == null) {
-      expect(reference.prefixReference, 0);
-    } else {
-      checkPrefix(reference.prefixReference, expectedPrefix);
-    }
-    expect(referenceResolution.kind, expectedKind);
-    expect(referenceResolution.unit, expectedTargetUnit);
-    expect(referenceResolution.numTypeParameters, numTypeParameters);
-  }
-
-  /**
-   * Verify that the given [typeRef] represents a reference to an unresolved
-   * type.
-   */
-  void checkUnresolvedTypeRef(
-      UnlinkedTypeRef typeRef, String expectedPrefix, String expectedName) {
-    // When serializing from the element model, unresolved type refs lose their
-    // name.
-    checkTypeRef(typeRef, null, null, checkAstDerivedData ? expectedName : null,
-        expectedPrefix: expectedPrefix,
-        expectedKind: PrelinkedReferenceKind.unresolved);
-  }
-
-  fail_enum_value_documented() {
-    // TODO(paulberry): currently broken because of dartbug.com/25385
-    String text = '''
-enum E {
-  /**
-   * Docs
-   */
-  v
-}''';
-    UnlinkedEnumValue value = serializeEnumText(text).values[0];
-    expect(value.documentationComment, isNotNull);
-    checkDocumentationComment(value.documentationComment, text);
-  }
-
-  fail_test_import_missing() {
-    // TODO(paulberry): At the moment unresolved imports are not included in
-    // the element model, so we can't pass this test.
-    // Unresolved imports are included since this is necessary for proper
-    // dependency tracking.
-    allowMissingFiles = true;
-    serializeLibraryText('import "foo.dart";', allowErrors: true);
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    checkDependency(
-        prelinked.importDependencies[0], absUri('/foo.dart'), 'foo.dart');
-  }
-
-  fail_type_reference_to_nonexistent_file_via_prefix() {
-    // TODO(paulberry): this test currently fails because there is not enough
-    // information in the element model to figure out that the unresolved
-    // reference `p.C` uses the prefix `p`.
-    allowMissingFiles = true;
-    UnlinkedTypeRef typeRef = serializeTypeText('p.C',
-        otherDeclarations: 'import "foo.dart" as p;', allowErrors: true);
-    checkUnresolvedTypeRef(typeRef, 'p', 'C');
-  }
-
-  fail_type_reference_to_type_visible_via_multiple_import_prefixes() {
-    // TODO(paulberry): this test currently fails because the element model
-    // doesn't record enough information to track which prefix is used to refer
-    // to a type.
-    addNamedSource('/lib1.dart', 'class C');
-    addNamedSource('/lib2.dart', 'export "lib1.dart";');
-    addNamedSource('/lib3.dart', 'export "lib1.dart";');
-    addNamedSource('/lib4.dart', 'export "lib1.dart";');
-    serializeLibraryText('''
-import 'lib2.dart';
-import 'lib3.dart' as a;
-import 'lib4.dart' as b;
-C c2;
-a.C c3;
-b.C c4;''');
-    // Note: it is important that each reference to class C records the prefix
-    // used to find it; otherwise it's possible that relinking might produce an
-    // incorrect result after a change to lib2.dart, lib3.dart, or lib4.dart.
-    checkTypeRef(
-        findVariable('c2').type, absUri('/lib1.dart'), 'lib1.dart', 'C');
-    checkTypeRef(
-        findVariable('c3').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
-        expectedPrefix: 'a');
-    checkTypeRef(
-        findVariable('c4').type, absUri('/lib1.dart'), 'lib1.dart', 'C',
-        expectedPrefix: 'b');
-  }
-
-  /**
-   * Find the class with the given [className] in the summary, and return its
-   * [UnlinkedClass] data structure.  If [unit] is not given, the class is
-   * looked for in the defining compilation unit.
-   */
-  UnlinkedClass findClass(String className,
-      {bool failIfAbsent: false, UnlinkedUnit unit}) {
-    unit ??= unlinkedUnits[0];
-    UnlinkedClass result;
-    for (UnlinkedClass cls in unit.classes) {
-      if (cls.name == className) {
-        if (result != null) {
-          fail('Duplicate class $className');
-        }
-        result = cls;
-      }
-    }
-    if (result == null && failIfAbsent) {
-      fail('Class $className not found in serialized output');
-    }
-    return result;
-  }
-
-  /**
-   * Find the enum with the given [enumName] in the summary, and return its
-   * [UnlinkedEnum] data structure.  If [unit] is not given, the enum is looked
-   * for in the defining compilation unit.
-   */
-  UnlinkedEnum findEnum(String enumName,
-      {bool failIfAbsent: false, UnlinkedUnit unit}) {
-    unit ??= unlinkedUnits[0];
-    UnlinkedEnum result;
-    for (UnlinkedEnum e in unit.enums) {
-      if (e.name == enumName) {
-        if (result != null) {
-          fail('Duplicate enum $enumName');
-        }
-        result = e;
-      }
-    }
-    if (result == null && failIfAbsent) {
-      fail('Enum $enumName not found in serialized output');
-    }
-    return result;
-  }
-
-  /**
-   * Find the executable with the given [executableName] in the summary, and
-   * return its [UnlinkedExecutable] data structure.  If [executables] is not
-   * given, then the executable is searched for in the defining compilation
-   * unit.
-   */
-  UnlinkedExecutable findExecutable(String executableName,
-      {List<UnlinkedExecutable> executables, bool failIfAbsent: false}) {
-    executables ??= unlinkedUnits[0].executables;
-    UnlinkedExecutable result;
-    for (UnlinkedExecutable executable in executables) {
-      if (executable.name == executableName) {
-        if (result != null) {
-          fail('Duplicate executable $executableName');
-        }
-        result = executable;
-      }
-    }
-    if (result == null && failIfAbsent) {
-      fail('Executable $executableName not found in serialized output');
-    }
-    return result;
-  }
-
-  /**
-   * Find the typedef with the given [typedefName] in the summary, and return
-   * its [UnlinkedTypedef] data structure.  If [unit] is not given, the typedef
-   * is looked for in the defining compilation unit.
-   */
-  UnlinkedTypedef findTypedef(String typedefName,
-      {bool failIfAbsent: false, UnlinkedUnit unit}) {
-    unit ??= unlinkedUnits[0];
-    UnlinkedTypedef result;
-    for (UnlinkedTypedef type in unit.typedefs) {
-      if (type.name == typedefName) {
-        if (result != null) {
-          fail('Duplicate typedef $typedefName');
-        }
-        result = type;
-      }
-    }
-    if (result == null && failIfAbsent) {
-      fail('Typedef $typedefName not found in serialized output');
-    }
-    return result;
-  }
-
-  /**
-   * Find the top level variable with the given [variableName] in the summary,
-   * and return its [UnlinkedVariable] data structure.  If [variables] is not
-   * specified, the variable is looked for in the defining compilation unit.
-   */
-  UnlinkedVariable findVariable(String variableName,
-      {List<UnlinkedVariable> variables, bool failIfAbsent: false}) {
-    variables ??= unlinkedUnits[0].variables;
-    UnlinkedVariable result;
-    for (UnlinkedVariable variable in variables) {
-      if (variable.name == variableName) {
-        if (result != null) {
-          fail('Duplicate variable $variableName');
-        }
-        result = variable;
-      }
-    }
-    if (result == null && failIfAbsent) {
-      fail('Variable $variableName not found in serialized output');
-    }
-    return result;
-  }
-
-  /**
-   * Serialize the given library [text] and return the summary of the class
-   * with the given [className].
-   */
-  UnlinkedClass serializeClassText(String text, [String className = 'C']) {
-    serializeLibraryText(text);
-    return findClass(className, failIfAbsent: true);
-  }
-
-  /**
-   * Serialize the given library [text] and return the summary of the enum with
-   * the given [enumName].
-   */
-  UnlinkedEnum serializeEnumText(String text, [String enumName = 'E']) {
-    serializeLibraryText(text);
-    return findEnum(enumName, failIfAbsent: true);
-  }
-
-  /**
-   * Serialize the given library [text] and return the summary of the
-   * executable with the given [executableName].
-   */
-  UnlinkedExecutable serializeExecutableText(String text,
-      [String executableName = 'f']) {
-    serializeLibraryText(text);
-    return findExecutable(executableName, failIfAbsent: true);
-  }
-
-  /**
-   * Serialize the given library [text], then deserialize it and store its
-   * summary in [lib].
-   */
-  void serializeLibraryText(String text, {bool allowErrors: false});
-
-  /**
-   * Serialize the given method [text] and return the summary of the executable
-   * with the given [executableName].
-   */
-  UnlinkedExecutable serializeMethodText(String text,
-      [String executableName = 'f']) {
-    serializeLibraryText('class C { $text }');
-    return findExecutable(executableName,
-        executables: findClass('C', failIfAbsent: true).executables,
-        failIfAbsent: true);
-  }
-
-  /**
-   * Serialize the given library [text] and return the summary of the typedef
-   * with the given [typedefName].
-   */
-  UnlinkedTypedef serializeTypedefText(String text,
-      [String typedefName = 'F']) {
-    serializeLibraryText(text);
-    return findTypedef(typedefName, failIfAbsent: true);
-  }
-
-  /**
-   * Serialize a type declaration using the given [text] as a type name, and
-   * return a summary of the corresponding [UnlinkedTypeRef].  If the type
-   * declaration needs to refer to types that are not available in core, those
-   * types may be declared in [otherDeclarations].
-   */
-  UnlinkedTypeRef serializeTypeText(String text,
-      {String otherDeclarations: '', bool allowErrors: false}) {
-    return serializeVariableText('$otherDeclarations\n$text v;',
-        allowErrors: allowErrors).type;
-  }
-
-  /**
-   * Serialize the given library [text] and return the summary of the variable
-   * with the given [variableName].
-   */
-  UnlinkedVariable serializeVariableText(String text,
-      {String variableName: 'v', bool allowErrors: false}) {
-    serializeLibraryText(text, allowErrors: allowErrors);
-    return findVariable(variableName, failIfAbsent: true);
-  }
-
-  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 {}');
-    serializeLibraryText(
-        '''
-import 'lib1.dart';
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(
-        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_export_hide_show() {
-    addNamedSource('/lib1.dart', 'export "lib2.dart" hide C show A, C;');
-    addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib1.dart';
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(
-        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_export_show_hide() {
-    addNamedSource('/lib1.dart', 'export "lib2.dart" show A, B hide B, C;');
-    addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib1.dart';
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(
-        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_export_show_show() {
-    addNamedSource('/lib1.dart', 'export "lib2.dart" show A, B show A, C;');
-    addNamedSource('/lib2.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib1.dart';
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(
-        findVariable('a').type, absUri('/lib2.dart'), 'lib2.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_import_hide_hide() {
-    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib.dart' hide C hide B, C;
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_import_hide_show() {
-    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib.dart' hide C show A, C;
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_import_show_hide() {
-    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib.dart' show A, B hide B, C;
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_cascaded_import_show_show() {
-    addNamedSource('/lib.dart', 'class A {} class B {} class C {}');
-    serializeLibraryText(
-        '''
-import 'lib.dart' show A, B show A, C;
-A a;
-B b;
-C c;
-    ''',
-        allowErrors: true);
-    checkTypeRef(findVariable('a').type, absUri('/lib.dart'), 'lib.dart', 'A');
-    checkUnresolvedTypeRef(findVariable('b').type, null, 'B');
-    checkUnresolvedTypeRef(findVariable('c').type, null, 'C');
-  }
-
-  test_class_abstract() {
-    UnlinkedClass cls = serializeClassText('abstract class C {}');
-    expect(cls.isAbstract, true);
-  }
-
-  test_class_alias_abstract() {
-    UnlinkedClass cls = serializeClassText(
-        'abstract class C = D with E; class D {} class E {}');
-    expect(cls.isAbstract, true);
-  }
-
-  test_class_alias_concrete() {
-    UnlinkedClass cls =
-        serializeClassText('class C = _D with _E; class _D {} class _E {}');
-    expect(cls.isAbstract, false);
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.classOrEnum);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
-  }
-
-  test_class_alias_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-class C = D with E;
-
-class D {}
-class E {}''';
-    UnlinkedClass cls = serializeClassText(text);
-    expect(cls.documentationComment, isNotNull);
-    checkDocumentationComment(cls.documentationComment, text);
-  }
-
-  test_class_alias_flag() {
-    UnlinkedClass cls =
-        serializeClassText('class C = D with E; class D {} class E {}');
-    expect(cls.isMixinApplication, true);
-  }
-
-  test_class_alias_generic() {
-    serializeClassText('class C<A, B> = _D with _E; class _D {} class _E {}');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 2);
-  }
-
-  test_class_alias_mixin_order() {
-    UnlinkedClass cls = serializeClassText('''
-class C = D with E, F;
-class D {}
-class E {}
-class F {}
-''');
-    expect(cls.mixins, hasLength(2));
-    checkTypeRef(cls.mixins[0], null, null, 'E');
-    checkTypeRef(cls.mixins[1], null, null, 'F');
-  }
-
-  test_class_alias_no_implicit_constructors() {
-    UnlinkedClass cls = serializeClassText('''
-class C = D with E;
-class D {
-  D.foo();
-  D.bar();
-}
-class E {}
-''');
-    expect(cls.executables, isEmpty);
-  }
-
-  test_class_alias_private() {
-    serializeClassText('class _C = _D with _E; class _D {} class _E {}', '_C');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_class_alias_reference_generic() {
-    UnlinkedTypeRef typeRef = serializeTypeText('C',
-        otherDeclarations: 'class C<D, E> = F with G; class F {} class G {}');
-    checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
-  }
-
-  test_class_alias_reference_generic_imported() {
-    addNamedSource(
-        '/lib.dart', 'class C<D, E> = F with G; class F {} class G {}');
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
-    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
-        numTypeParameters: 2);
-  }
-
-  test_class_alias_supertype() {
-    UnlinkedClass cls =
-        serializeClassText('class C = D with E; class D {} class E {}');
-    checkTypeRef(cls.supertype, null, null, 'D');
-    expect(cls.hasNoSupertype, isFalse);
-  }
-
-  test_class_concrete() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.isAbstract, false);
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.classOrEnum);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
-  }
-
-  test_class_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-class C {}''';
-    UnlinkedClass cls = serializeClassText(text);
-    expect(cls.documentationComment, isNotNull);
-    checkDocumentationComment(cls.documentationComment, text);
-  }
-
-  test_class_documented_with_references() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs referring to [D] and [E]
- */
-class C {}
-
-class D {}
-class E {}''';
-    UnlinkedClass cls = serializeClassText(text);
-    expect(cls.documentationComment, isNotNull);
-    checkDocumentationComment(cls.documentationComment, text);
-  }
-
-  test_class_documented_with_with_windows_line_endings() {
-    String text = '/**\r\n * Docs\r\n */\r\nclass C {}';
-    UnlinkedClass cls = serializeClassText(text);
-    expect(cls.documentationComment, isNotNull);
-    checkDocumentationComment(cls.documentationComment, text);
-  }
-
-  test_class_interface() {
-    UnlinkedClass cls = serializeClassText('''
-class C implements D {}
-class D {}
-''');
-    expect(cls.interfaces, hasLength(1));
-    checkTypeRef(cls.interfaces[0], null, null, 'D');
-  }
-
-  test_class_interface_order() {
-    UnlinkedClass cls = serializeClassText('''
-class C implements D, E {}
-class D {}
-class E {}
-''');
-    expect(cls.interfaces, hasLength(2));
-    checkTypeRef(cls.interfaces[0], null, null, 'D');
-    checkTypeRef(cls.interfaces[1], null, null, 'E');
-  }
-
-  test_class_mixin() {
-    UnlinkedClass cls = serializeClassText('''
-class C extends Object with D {}
-class D {}
-''');
-    expect(cls.mixins, hasLength(1));
-    checkTypeRef(cls.mixins[0], null, null, 'D');
-  }
-
-  test_class_mixin_order() {
-    UnlinkedClass cls = serializeClassText('''
-class C extends Object with D, E {}
-class D {}
-class E {}
-''');
-    expect(cls.mixins, hasLength(2));
-    checkTypeRef(cls.mixins[0], null, null, 'D');
-    checkTypeRef(cls.mixins[1], null, null, 'E');
-  }
-
-  test_class_name() {
-    var classText = 'class C {}';
-    UnlinkedClass cls = serializeClassText(classText);
-    expect(cls.name, 'C');
-    expect(cls.nameOffset, classText.indexOf('C'));
-  }
-
-  test_class_no_flags() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.isAbstract, false);
-    expect(cls.isMixinApplication, false);
-  }
-
-  test_class_no_interface() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.interfaces, isEmpty);
-  }
-
-  test_class_no_mixins() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.mixins, isEmpty);
-  }
-
-  test_class_no_type_param() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.typeParameters, isEmpty);
-  }
-
-  test_class_non_alias_flag() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.isMixinApplication, false);
-  }
-
-  test_class_private() {
-    serializeClassText('class _C {}', '_C');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_class_reference_generic() {
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('C', otherDeclarations: 'class C<D, E> {}');
-    checkTypeRef(typeRef, null, null, 'C', numTypeParameters: 2);
-  }
-
-  test_class_reference_generic_imported() {
-    addNamedSource('/lib.dart', 'class C<D, E> {}');
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('C', otherDeclarations: 'import "lib.dart";');
-    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'C',
-        numTypeParameters: 2);
-  }
-
-  test_class_superclass() {
-    UnlinkedClass cls = serializeClassText('class C {}');
-    expect(cls.supertype, isNull);
-    expect(cls.hasNoSupertype, isFalse);
-  }
-
-  test_class_superclass_explicit() {
-    UnlinkedClass cls = serializeClassText('class C extends D {} class D {}');
-    expect(cls.supertype, isNotNull);
-    checkTypeRef(cls.supertype, null, null, 'D');
-    expect(cls.hasNoSupertype, isFalse);
-  }
-
-  test_class_type_param_bound() {
-    UnlinkedClass cls = serializeClassText('class C<T extends List> {}');
-    expect(cls.typeParameters, hasLength(1));
-    expect(cls.typeParameters[0].name, 'T');
-    expect(cls.typeParameters[0].bound, isNotNull);
-    checkTypeRef(cls.typeParameters[0].bound, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true, numTypeParameters: 1);
-  }
-
-  test_class_type_param_f_bound() {
-    UnlinkedClass cls = serializeClassText('class C<T, U extends List<T>> {}');
-    UnlinkedTypeRef typeArgument = cls.typeParameters[1].bound.typeArguments[0];
-    checkParamTypeRef(typeArgument, 2);
-  }
-
-  test_class_type_param_f_bound_self_ref() {
-    UnlinkedClass cls = serializeClassText('class C<T, U extends List<U>> {}');
-    UnlinkedTypeRef typeArgument = cls.typeParameters[1].bound.typeArguments[0];
-    checkParamTypeRef(typeArgument, 1);
-  }
-
-  test_class_type_param_no_bound() {
-    String text = 'class C<T> {}';
-    UnlinkedClass cls = serializeClassText(text);
-    expect(cls.typeParameters, hasLength(1));
-    expect(cls.typeParameters[0].name, 'T');
-    expect(cls.typeParameters[0].nameOffset, text.indexOf('T'));
-    expect(cls.typeParameters[0].bound, isNull);
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
-  }
-
-  test_constructor() {
-    String text = 'class C { C(); }';
-    UnlinkedExecutable executable =
-        findExecutable('', executables: serializeClassText(text).executables);
-    expect(executable.kind, UnlinkedExecutableKind.constructor);
-    expect(executable.hasImplicitReturnType, isFalse);
-    expect(executable.isExternal, isFalse);
-    expect(executable.nameOffset, text.indexOf('C();'));
-  }
-
-  test_constructor_anonymous() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(); }').executables);
-    expect(executable.name, isEmpty);
-  }
-
-  test_constructor_const() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { const C(); }').executables);
-    expect(executable.isConst, isTrue);
-    expect(executable.isExternal, isFalse);
-  }
-
-  test_constructor_const_external() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { external const C(); }').executables);
-    expect(executable.isConst, isTrue);
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_constructor_documented() {
-    String text = '''
-class C {
-  /**
-   * Docs
-   */
-  C();
-}''';
-    UnlinkedExecutable executable = serializeClassText(text).executables[0];
-    expect(executable.documentationComment, isNotNull);
-    checkDocumentationComment(executable.documentationComment, text);
-  }
-
-  test_constructor_external() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { external C(); }').executables);
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_constructor_factory() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { factory C() => null; }').executables);
-    expect(executable.isFactory, isTrue);
-  }
-
-  test_constructor_implicit() {
-    // Implicit constructors are not serialized.
-    UnlinkedExecutable executable = findExecutable(null,
-        executables: serializeClassText('class C { C(); }').executables,
-        failIfAbsent: false);
-    expect(executable, isNull);
-  }
-
-  test_constructor_initializing_formal() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { C(this.x); final x; }').executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.isInitializingFormal, isTrue);
-  }
-
-  test_constructor_initializing_formal_explicit_type() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(int this.x); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    checkTypeRef(parameter.type, 'dart:core', 'dart:core', 'int');
-  }
-
-  test_constructor_initializing_formal_function_typed() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(this.x()); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.isFunctionTyped, isTrue);
-  }
-
-  test_constructor_initializing_formal_function_typed_explicit_return_type() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { C(int this.x()); Function x; }')
-                .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    checkTypeRef(parameter.type, 'dart:core', 'dart:core', 'int');
-  }
-
-  test_constructor_initializing_formal_function_typed_implicit_return_type() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(this.x()); Function x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    // Since the parameter is function-typed it is considered to have an
-    // explicit type, even though that explicit type itself has an implicit
-    // return type.
-    expect(parameter.hasImplicitType, isFalse);
-    checkDynamicTypeRef(parameter.type);
-  }
-
-  test_constructor_initializing_formal_function_typed_no_parameters() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(this.x()); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.parameters, isEmpty);
-  }
-
-  test_constructor_initializing_formal_function_typed_parameter() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(this.x(a)); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.parameters, hasLength(1));
-  }
-
-  test_constructor_initializing_formal_function_typed_parameter_order() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(this.x(a, b)); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.parameters, hasLength(2));
-    expect(parameter.parameters[0].name, 'a');
-    expect(parameter.parameters[1].name, 'b');
-  }
-
-  test_constructor_initializing_formal_implicit_type() {
-    // Note: the implicit type of an initializing formal is the type of the
-    // field.
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { C(this.x); int x; }').executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    checkTypeRef(parameter.type, 'dart:core', 'dart:core', 'int');
-    expect(parameter.hasImplicitType, isTrue);
-  }
-
-  test_constructor_initializing_formal_name() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { C(this.x); final x; }').executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.name, 'x');
-  }
-
-  test_constructor_initializing_formal_named() {
-    // TODO(paulberry): also test default value
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C({this.x}); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.named);
-  }
-
-  test_constructor_initializing_formal_non_function_typed() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { C(this.x); final x; }').executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.isFunctionTyped, isFalse);
-  }
-
-  test_constructor_initializing_formal_positional() {
-    // TODO(paulberry): also test default value
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C([this.x]); final x; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.positional);
-  }
-
-  test_constructor_initializing_formal_required() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables:
-            serializeClassText('class C { C(this.x); final x; }').executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.kind, UnlinkedParamKind.required);
-  }
-
-  test_constructor_initializing_formal_typedef() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText(
-                'typedef F<T>(T x); class C<X> { C(this.f); F<X> f; }')
-            .executables);
-    UnlinkedParam parameter = executable.parameters[0];
-    expect(parameter.parameters, hasLength(1));
-  }
-
-  test_constructor_named() {
-    String text = 'class C { C.foo(); }';
-    UnlinkedExecutable executable = findExecutable('foo',
-        executables: serializeClassText(text).executables);
-    expect(executable.name, 'foo');
-    expect(executable.nameOffset, text.indexOf('foo'));
-  }
-
-  test_constructor_non_const() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(); }').executables);
-    expect(executable.isConst, isFalse);
-  }
-
-  test_constructor_non_factory() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(); }').executables);
-    expect(executable.isFactory, isFalse);
-  }
-
-  test_constructor_return_type() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C { C(); }').executables);
-    expect(executable.returnType, isNull);
-  }
-
-  test_constructor_return_type_parameterized() {
-    UnlinkedExecutable executable = findExecutable('',
-        executables: serializeClassText('class C<T, U> { C(); }').executables);
-    expect(executable.returnType, isNull);
-  }
-
-  test_dependencies_export_none() {
-    // Exports are not listed as dependencies since no change to the exported
-    // file can change the summary of the exporting file.
-    // TODO(paulberry): this needs to change since the element model for a
-    // library includes its export namespace.
-    addNamedSource('/a.dart', 'library a; export "b.dart";');
-    addNamedSource('/b.dart', 'library b;');
-    serializeLibraryText('export "a.dart";');
-    checkLacksDependency(absUri('/a.dart'), 'a.dart');
-    checkLacksDependency(absUri('/b.dart'), 'b.dart');
-  }
-
-  test_dependencies_import_to_export() {
-    addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
-    addNamedSource('/b.dart', 'library b;');
-    serializeLibraryText('import "a.dart"; A a;');
-    checkHasDependency(absUri('/a.dart'), 'a.dart');
-    // The main test library depends on b.dart, because names defined in
-    // b.dart are exported by a.dart.
-    checkHasDependency(absUri('/b.dart'), 'b.dart');
-  }
-
-  test_dependencies_import_to_export_in_subdirs_absolute_export() {
-    addNamedSource('/a/a.dart',
-        'library a; export "${absUri('/a/b/b.dart')}"; class A {}');
-    addNamedSource('/a/b/b.dart', 'library b;');
-    serializeLibraryText('import "a/a.dart"; A a;');
-    checkHasDependency(absUri('/a/a.dart'), 'a/a.dart');
-    // The main test library depends on b.dart, because names defined in
-    // b.dart are exported by a.dart.
-    checkHasDependency(absUri('/a/b/b.dart'), absUri('/a/b/b.dart'));
-  }
-
-  test_dependencies_import_to_export_in_subdirs_absolute_import() {
-    addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
-    addNamedSource('/a/b/b.dart', 'library b;');
-    serializeLibraryText('import "${absUri('/a/a.dart')}"; A a;');
-    checkHasDependency(absUri('/a/a.dart'), absUri('/a/a.dart'));
-    // The main test library depends on b.dart, because names defined in
-    // b.dart are exported by a.dart.
-    checkHasDependency(absUri('/a/b/b.dart'), absUri('/a/b/b.dart'));
-  }
-
-  test_dependencies_import_to_export_in_subdirs_relative() {
-    addNamedSource('/a/a.dart', 'library a; export "b/b.dart"; class A {}');
-    addNamedSource('/a/b/b.dart', 'library b;');
-    serializeLibraryText('import "a/a.dart"; A a;');
-    checkHasDependency(absUri('/a/a.dart'), 'a/a.dart');
-    // The main test library depends on b.dart, because names defined in
-    // b.dart are exported by a.dart.
-    checkHasDependency(absUri('/a/b/b.dart'), 'a/b/b.dart');
-  }
-
-  test_dependencies_import_to_export_loop() {
-    addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
-    addNamedSource('/b.dart', 'library b; export "a.dart";');
-    serializeLibraryText('import "a.dart"; A a;');
-    checkHasDependency(absUri('/a.dart'), 'a.dart');
-    // Serialization should have been able to walk the transitive export
-    // dependencies to b.dart without going into an infinite loop.
-    checkHasDependency(absUri('/b.dart'), 'b.dart');
-  }
-
-  test_dependencies_import_to_export_transitive_closure() {
-    addNamedSource('/a.dart', 'library a; export "b.dart"; class A {}');
-    addNamedSource('/b.dart', 'library b; export "c.dart";');
-    addNamedSource('/c.dart', 'library c;');
-    serializeLibraryText('import "a.dart"; A a;');
-    checkHasDependency(absUri('/a.dart'), 'a.dart');
-    // The main test library depends on c.dart, because names defined in
-    // c.dart are exported by b.dart and then re-exported by a.dart.
-    checkHasDependency(absUri('/c.dart'), 'c.dart');
-  }
-
-  test_dependencies_import_transitive_closure() {
-    addNamedSource(
-        '/a.dart', 'library a; import "b.dart"; class A extends B {}');
-    addNamedSource('/b.dart', 'library b; class B {}');
-    serializeLibraryText('import "a.dart"; A a;');
-    checkHasDependency(absUri('/a.dart'), 'a.dart');
-    // The main test library doesn't depend on b.dart, because no change to
-    // b.dart can possibly affect the serialized element model for it.
-    checkLacksDependency(absUri('/b.dart'), 'b.dart');
-  }
-
-  test_dependencies_parts() {
-    addNamedSource(
-        '/a.dart', 'library a; part "b.dart"; part "c.dart"; class A {}');
-    addNamedSource('/b.dart', 'part of a;');
-    addNamedSource('/c.dart', 'part of a;');
-    serializeLibraryText('import "a.dart"; A a;');
-    PrelinkedDependency dep = checkHasDependency(absUri('/a.dart'), 'a.dart');
-    checkDependencyParts(
-        dep, [absUri('/b.dart'), absUri('/c.dart')], ['b.dart', 'c.dart']);
-  }
-
-  test_dependencies_parts_relative_to_importing_library() {
-    addNamedSource('/a/b.dart', 'export "c/d.dart";');
-    addNamedSource('/a/c/d.dart',
-        'library d; part "e/f.dart"; part "g/h.dart"; class D {}');
-    addNamedSource('/a/c/e/f.dart', 'part of d;');
-    addNamedSource('/a/c/g/h.dart', 'part of d;');
-    serializeLibraryText('import "a/b.dart"; D d;');
-    PrelinkedDependency dep =
-        checkHasDependency(absUri('/a/c/d.dart'), 'a/c/d.dart');
-    checkDependencyParts(
-        dep,
-        [absUri('/a/c/e/f.dart'), absUri('/a/c/g/h.dart')],
-        ['a/c/e/f.dart', 'a/c/g/h.dart']);
-  }
-
-  test_elements_in_part() {
-    addNamedSource(
-        '/part1.dart',
-        '''
-part of my.lib;
-
-class C {}
-enum E { v }
-var v;
-f() {}
-typedef F();
-''');
-    serializeLibraryText('library my.lib; part "part1.dart";');
-    UnlinkedUnit unit = unlinkedUnits[1];
-    expect(findClass('C', unit: unit), isNotNull);
-    expect(findEnum('E', unit: unit), isNotNull);
-    expect(findVariable('v', variables: unit.variables), isNotNull);
-    expect(findExecutable('f', executables: unit.executables), isNotNull);
-    expect(findTypedef('F', unit: unit), isNotNull);
-  }
-
-  test_enum() {
-    String text = 'enum E { v1 }';
-    UnlinkedEnum e = serializeEnumText(text);
-    expect(e.name, 'E');
-    expect(e.nameOffset, text.indexOf('E'));
-    expect(e.values, hasLength(1));
-    expect(e.values[0].name, 'v1');
-    expect(e.values[0].nameOffset, text.indexOf('v1'));
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.classOrEnum);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'E');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
-  }
-
-  test_enum_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-enum E { v }''';
-    UnlinkedEnum enm = serializeEnumText(text);
-    expect(enm.documentationComment, isNotNull);
-    checkDocumentationComment(enm.documentationComment, text);
-  }
-
-  test_enum_order() {
-    UnlinkedEnum e = serializeEnumText('enum E { v1, v2 }');
-    expect(e.values, hasLength(2));
-    expect(e.values[0].name, 'v1');
-    expect(e.values[1].name, 'v2');
-  }
-
-  test_enum_private() {
-    serializeEnumText('enum _E { v1 }', '_E');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_executable_abstract() {
-    UnlinkedExecutable executable =
-        serializeClassText('abstract class C { f(); }').executables[0];
-    expect(executable.isAbstract, isTrue);
-  }
-
-  test_executable_concrete() {
-    UnlinkedExecutable executable =
-        serializeClassText('abstract class C { f() {} }').executables[0];
-    expect(executable.isAbstract, isFalse);
-  }
-
-  test_executable_function() {
-    String text = '  f() {}';
-    UnlinkedExecutable executable = serializeExecutableText(text);
-    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
-    expect(executable.hasImplicitReturnType, isTrue);
-    checkDynamicTypeRef(executable.returnType);
-    expect(executable.isExternal, isFalse);
-    expect(executable.nameOffset, text.indexOf('f'));
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.other);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
-  }
-
-  test_executable_function_explicit_return() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('dynamic f() => null;');
-    expect(executable.hasImplicitReturnType, isFalse);
-    checkDynamicTypeRef(executable.returnType);
-  }
-
-  test_executable_function_external() {
-    UnlinkedExecutable executable = serializeExecutableText('external f();');
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_executable_function_private() {
-    serializeExecutableText('_f() {}', '_f');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_executable_getter() {
-    String text = 'int get f => 1;';
-    UnlinkedExecutable executable = serializeExecutableText(text);
-    expect(executable.kind, UnlinkedExecutableKind.getter);
-    expect(executable.hasImplicitReturnType, isFalse);
-    expect(executable.isExternal, isFalse);
-    expect(executable.nameOffset, text.indexOf('f'));
-    expect(findVariable('f'), isNull);
-    expect(findExecutable('f='), isNull);
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.other);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f');
-  }
-
-  test_executable_getter_external() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('external int get f;');
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_executable_getter_private() {
-    serializeExecutableText('int get _f => 1;', '_f');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_executable_getter_type() {
-    UnlinkedExecutable executable = serializeExecutableText('int get f => 1;');
-    checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
-    expect(executable.parameters, isEmpty);
-  }
-
-  test_executable_getter_type_implicit() {
-    UnlinkedExecutable executable = serializeExecutableText('get f => 1;');
-    checkDynamicTypeRef(executable.returnType);
-    expect(executable.hasImplicitReturnType, isTrue);
-    expect(executable.parameters, isEmpty);
-  }
-
-  test_executable_member_function() {
-    UnlinkedExecutable executable = findExecutable('f',
-        executables: serializeClassText('class C { f() {} }').executables);
-    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
-    expect(executable.hasImplicitReturnType, isTrue);
-    expect(executable.isExternal, isFalse);
-  }
-
-  test_executable_member_function_explicit_return() {
-    UnlinkedExecutable executable = findExecutable('f',
-        executables:
-            serializeClassText('class C { dynamic f() => null; }').executables);
-    expect(executable.hasImplicitReturnType, isFalse);
-  }
-
-  test_executable_member_function_external() {
-    UnlinkedExecutable executable = findExecutable('f',
-        executables:
-            serializeClassText('class C { external f(); }').executables);
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_executable_member_getter() {
-    UnlinkedClass cls = serializeClassText('class C { int get f => 1; }');
-    UnlinkedExecutable executable =
-        findExecutable('f', executables: cls.executables, failIfAbsent: true);
-    expect(executable.kind, UnlinkedExecutableKind.getter);
-    expect(executable.hasImplicitReturnType, isFalse);
-    expect(executable.isExternal, isFalse);
-    expect(findVariable('f', variables: cls.fields), isNull);
-    expect(findExecutable('f=', executables: cls.executables), isNull);
-  }
-
-  test_executable_member_getter_external() {
-    UnlinkedClass cls = serializeClassText('class C { external int get f; }');
-    UnlinkedExecutable executable =
-        findExecutable('f', executables: cls.executables, failIfAbsent: true);
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_executable_member_setter() {
-    UnlinkedClass cls = serializeClassText('class C { void set f(value) {} }');
-    UnlinkedExecutable executable =
-        findExecutable('f=', executables: cls.executables, failIfAbsent: true);
-    expect(executable.kind, UnlinkedExecutableKind.setter);
-    expect(executable.hasImplicitReturnType, isFalse);
-    expect(executable.isExternal, isFalse);
-    expect(findVariable('f', variables: cls.fields), isNull);
-    expect(findExecutable('f', executables: cls.executables), isNull);
-  }
-
-  test_executable_member_setter_external() {
-    UnlinkedClass cls =
-        serializeClassText('class C { external void set f(value); }');
-    UnlinkedExecutable executable =
-        findExecutable('f=', executables: cls.executables, failIfAbsent: true);
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_executable_member_setter_implicit_return() {
-    UnlinkedClass cls = serializeClassText('class C { set f(value) {} }');
-    UnlinkedExecutable executable =
-        findExecutable('f=', executables: cls.executables, failIfAbsent: true);
-    expect(executable.hasImplicitReturnType, isTrue);
-    checkDynamicTypeRef(executable.returnType);
-  }
-
-  test_executable_name() {
-    UnlinkedExecutable executable = serializeExecutableText('f() {}');
-    expect(executable.name, 'f');
-  }
-
-  test_executable_no_flags() {
-    UnlinkedExecutable executable = serializeExecutableText('f() {}');
-    expect(executable.isAbstract, isFalse);
-    expect(executable.isConst, isFalse);
-    expect(executable.isFactory, isFalse);
-    expect(executable.isStatic, isFalse);
-  }
-
-  test_executable_non_static() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { f() {} }').executables[0];
-    expect(executable.isStatic, isFalse);
-  }
-
-  test_executable_non_static_top_level() {
-    // Top level executables are considered non-static.
-    UnlinkedExecutable executable = serializeExecutableText('f() {}');
-    expect(executable.isStatic, isFalse);
-  }
-
-  test_executable_operator() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { C operator+(C c) => null; }').executables[
-            0];
-    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
-    expect(executable.name, '+');
-    expect(executable.hasImplicitReturnType, false);
-    expect(executable.isAbstract, false);
-    expect(executable.isConst, false);
-    expect(executable.isFactory, false);
-    expect(executable.isStatic, false);
-    expect(executable.parameters, hasLength(1));
-    checkTypeRef(executable.returnType, null, null, 'C');
-    expect(executable.typeParameters, isEmpty);
-    expect(executable.isExternal, false);
-  }
-
-  test_executable_operator_equal() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { bool operator==(C other) => false; }')
-            .executables[0];
-    expect(executable.name, '==');
-  }
-
-  test_executable_operator_external() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { external C operator+(C c); }')
-            .executables[0];
-    expect(executable.isExternal, true);
-  }
-
-  test_executable_operator_greater_equal() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { bool operator>=(C other) => false; }')
-            .executables[0];
-    expect(executable.name, '>=');
-  }
-
-  test_executable_operator_index() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { bool operator[](int i) => null; }')
-            .executables[0];
-    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
-    expect(executable.name, '[]');
-    expect(executable.hasImplicitReturnType, false);
-    expect(executable.isAbstract, false);
-    expect(executable.isConst, false);
-    expect(executable.isFactory, false);
-    expect(executable.isStatic, false);
-    expect(executable.parameters, hasLength(1));
-    checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'bool');
-    expect(executable.typeParameters, isEmpty);
-  }
-
-  test_executable_operator_index_set() {
-    UnlinkedExecutable executable = serializeClassText(
-        'class C { void operator[]=(int i, bool v) => null; }').executables[0];
-    expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
-    expect(executable.name, '[]=');
-    expect(executable.hasImplicitReturnType, false);
-    expect(executable.isAbstract, false);
-    expect(executable.isConst, false);
-    expect(executable.isFactory, false);
-    expect(executable.isStatic, false);
-    expect(executable.parameters, hasLength(2));
-    expect(executable.returnType, isNull);
-    expect(executable.typeParameters, isEmpty);
-  }
-
-  test_executable_operator_less_equal() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { bool operator<=(C other) => false; }')
-            .executables[0];
-    expect(executable.name, '<=');
-  }
-
-  test_executable_param_function_typed() {
-    UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
-    expect(executable.parameters[0].isFunctionTyped, isTrue);
-    // Since the parameter is function-typed it is considered to have an
-    // explicit type, even though that explicit type itself has an implicit
-    // return type.
-    expect(executable.parameters[0].hasImplicitType, isFalse);
-  }
-
-  test_executable_param_function_typed_explicit_return_type() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('f(dynamic g()) {}');
-    expect(executable.parameters[0].hasImplicitType, isFalse);
-  }
-
-  test_executable_param_function_typed_param() {
-    UnlinkedExecutable executable = serializeExecutableText('f(g(x)) {}');
-    expect(executable.parameters[0].parameters, hasLength(1));
-  }
-
-  test_executable_param_function_typed_param_none() {
-    UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
-    expect(executable.parameters[0].parameters, isEmpty);
-  }
-
-  test_executable_param_function_typed_param_order() {
-    UnlinkedExecutable executable = serializeExecutableText('f(g(x, y)) {}');
-    expect(executable.parameters[0].parameters, hasLength(2));
-    expect(executable.parameters[0].parameters[0].name, 'x');
-    expect(executable.parameters[0].parameters[1].name, 'y');
-  }
-
-  test_executable_param_function_typed_return_type() {
-    UnlinkedExecutable executable = serializeExecutableText('f(int g()) {}');
-    checkTypeRef(
-        executable.parameters[0].type, 'dart:core', 'dart:core', 'int');
-  }
-
-  test_executable_param_function_typed_return_type_implicit() {
-    UnlinkedExecutable executable = serializeExecutableText('f(g()) {}');
-    checkDynamicTypeRef(executable.parameters[0].type);
-  }
-
-  test_executable_param_function_typed_return_type_void() {
-    UnlinkedExecutable executable = serializeExecutableText('f(void g()) {}');
-    expect(executable.parameters[0].type, isNull);
-  }
-
-  test_executable_param_kind_named() {
-    UnlinkedExecutable executable = serializeExecutableText('f({x}) {}');
-    expect(executable.parameters[0].kind, UnlinkedParamKind.named);
-  }
-
-  test_executable_param_kind_positional() {
-    UnlinkedExecutable executable = serializeExecutableText('f([x]) {}');
-    expect(executable.parameters[0].kind, UnlinkedParamKind.positional);
-  }
-
-  test_executable_param_kind_required() {
-    UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
-    expect(executable.parameters[0].kind, UnlinkedParamKind.required);
-  }
-
-  test_executable_param_name() {
-    String text = 'f(x) {}';
-    UnlinkedExecutable executable = serializeExecutableText(text);
-    expect(executable.parameters, hasLength(1));
-    expect(executable.parameters[0].name, 'x');
-    expect(executable.parameters[0].nameOffset, text.indexOf('x'));
-  }
-
-  test_executable_param_no_flags() {
-    UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
-    expect(executable.parameters[0].isFunctionTyped, isFalse);
-    expect(executable.parameters[0].isInitializingFormal, isFalse);
-  }
-
-  test_executable_param_non_function_typed() {
-    UnlinkedExecutable executable = serializeExecutableText('f(g) {}');
-    expect(executable.parameters[0].isFunctionTyped, isFalse);
-  }
-
-  test_executable_param_none() {
-    UnlinkedExecutable executable = serializeExecutableText('f() {}');
-    expect(executable.parameters, isEmpty);
-  }
-
-  test_executable_param_order() {
-    UnlinkedExecutable executable = serializeExecutableText('f(x, y) {}');
-    expect(executable.parameters, hasLength(2));
-    expect(executable.parameters[0].name, 'x');
-    expect(executable.parameters[1].name, 'y');
-  }
-
-  test_executable_param_type_explicit() {
-    UnlinkedExecutable executable = serializeExecutableText('f(dynamic x) {}');
-    checkDynamicTypeRef(executable.parameters[0].type);
-    expect(executable.parameters[0].hasImplicitType, isFalse);
-  }
-
-  test_executable_param_type_implicit() {
-    UnlinkedExecutable executable = serializeExecutableText('f(x) {}');
-    checkDynamicTypeRef(executable.parameters[0].type);
-    expect(executable.parameters[0].hasImplicitType, isTrue);
-  }
-
-  test_executable_return_type() {
-    UnlinkedExecutable executable = serializeExecutableText('int f() => 1;');
-    checkTypeRef(executable.returnType, 'dart:core', 'dart:core', 'int');
-    expect(executable.hasImplicitReturnType, isFalse);
-  }
-
-  test_executable_return_type_implicit() {
-    UnlinkedExecutable executable = serializeExecutableText('f() {}');
-    checkDynamicTypeRef(executable.returnType);
-    expect(executable.hasImplicitReturnType, isTrue);
-  }
-
-  test_executable_return_type_void() {
-    UnlinkedExecutable executable = serializeExecutableText('void f() {}');
-    expect(executable.returnType, isNull);
-  }
-
-  test_executable_setter() {
-    String text = 'void set f(value) {}';
-    UnlinkedExecutable executable = serializeExecutableText(text, 'f=');
-    expect(executable.kind, UnlinkedExecutableKind.setter);
-    expect(executable.hasImplicitReturnType, isFalse);
-    expect(executable.isExternal, isFalse);
-    expect(executable.nameOffset, text.indexOf('f'));
-    expect(findVariable('f'), isNull);
-    expect(findExecutable('f'), isNull);
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.other);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'f=');
-  }
-
-  test_executable_setter_external() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('external void set f(value);', 'f=');
-    expect(executable.isExternal, isTrue);
-  }
-
-  test_executable_setter_implicit_return() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('set f(value) {}', 'f=');
-    expect(executable.hasImplicitReturnType, isTrue);
-    checkDynamicTypeRef(executable.returnType);
-  }
-
-  test_executable_setter_private() {
-    serializeExecutableText('void set _f(value) {}', '_f=');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_executable_setter_type() {
-    UnlinkedExecutable executable =
-        serializeExecutableText('void set f(int value) {}', 'f=');
-    expect(executable.returnType, isNull);
-    expect(executable.parameters, hasLength(1));
-    expect(executable.parameters[0].name, 'value');
-    checkTypeRef(
-        executable.parameters[0].type, 'dart:core', 'dart:core', 'int');
-  }
-
-  test_executable_static() {
-    UnlinkedExecutable executable =
-        serializeClassText('class C { static f() {} }').executables[0];
-    expect(executable.isStatic, isTrue);
-  }
-
-  test_executable_type_param_f_bound_function() {
-    UnlinkedExecutable ex =
-        serializeExecutableText('void f<T, U extends List<T>>() {}');
-    UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
-    checkParamTypeRef(typeArgument, 2);
-  }
-
-  test_executable_type_param_f_bound_method() {
-    UnlinkedExecutable ex =
-        serializeMethodText('void f<T, U extends List<T>>() {}');
-    UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
-    checkParamTypeRef(typeArgument, 2);
-  }
-
-  test_executable_type_param_f_bound_self_ref_function() {
-    UnlinkedExecutable ex =
-        serializeExecutableText('void f<T, U extends List<U>>() {}');
-    UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
-    checkParamTypeRef(typeArgument, 1);
-  }
-
-  test_executable_type_param_f_bound_self_ref_method() {
-    UnlinkedExecutable ex =
-        serializeMethodText('void f<T, U extends List<U>>() {}');
-    UnlinkedTypeRef typeArgument = ex.typeParameters[1].bound.typeArguments[0];
-    checkParamTypeRef(typeArgument, 1);
-  }
-
-  test_executable_type_param_in_parameter_function() {
-    UnlinkedExecutable ex = serializeExecutableText('void f<T>(T t) {}');
-    checkParamTypeRef(ex.parameters[0].type, 1);
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
-  }
-
-  test_executable_type_param_in_parameter_method() {
-    UnlinkedExecutable ex = serializeMethodText('void f<T>(T t) {}');
-    checkParamTypeRef(ex.parameters[0].type, 1);
-  }
-
-  test_executable_type_param_in_return_type_function() {
-    UnlinkedExecutable ex = serializeExecutableText('T f<T>() => null;');
-    checkParamTypeRef(ex.returnType, 1);
-  }
-
-  test_executable_type_param_in_return_type_method() {
-    UnlinkedExecutable ex = serializeMethodText('T f<T>() => null;');
-    checkParamTypeRef(ex.returnType, 1);
-  }
-
-  test_export_hide_order() {
-    serializeLibraryText('export "dart:async" hide Future, Stream;');
-    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
-    expect(
-        unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
-        isEmpty);
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
-        hasLength(2));
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[0],
-        'Future');
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
-        'Stream');
-  }
-
-  test_export_no_combinators() {
-    serializeLibraryText('export "dart:async";');
-    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators, isEmpty);
-  }
-
-  test_export_offset() {
-    String libraryText = '    export "dart:async";';
-    serializeLibraryText(libraryText);
-    expect(unlinkedUnits[0].exports[0].uriOffset,
-        libraryText.indexOf('"dart:async"'));
-    expect(unlinkedUnits[0].exports[0].uriEnd, libraryText.indexOf(';'));
-    expect(unlinkedUnits[0].exports[0].offset, libraryText.indexOf('export'));
-  }
-
-  test_export_show_order() {
-    serializeLibraryText('export "dart:async" show Future, Stream;');
-    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
-    expect(
-        unlinkedUnits[0].publicNamespace.exports[0].combinators, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows,
-        hasLength(2));
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides,
-        isEmpty);
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[0],
-        'Future');
-    expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
-        'Stream');
-  }
-
-  test_export_uri() {
-    addNamedSource('/a.dart', 'library my.lib;');
-    String uriString = '"a.dart"';
-    String libraryText = 'export $uriString;';
-    serializeLibraryText(libraryText);
-    expect(unlinkedUnits[0].publicNamespace.exports, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.exports[0].uri, 'a.dart');
-  }
-
-  test_field() {
-    UnlinkedClass cls = serializeClassText('class C { int i; }');
-    UnlinkedVariable variable = findVariable('i', variables: cls.fields);
-    expect(variable, isNotNull);
-    expect(variable.isConst, isFalse);
-    expect(variable.isStatic, isFalse);
-    expect(variable.isFinal, isFalse);
-    expect(findExecutable('i', executables: cls.executables), isNull);
-    expect(findExecutable('i=', executables: cls.executables), isNull);
-  }
-
-  test_field_const() {
-    UnlinkedVariable variable =
-        serializeClassText('class C { static const int i = 0; }').fields[0];
-    expect(variable.isConst, isTrue);
-  }
-
-  test_field_documented() {
-    String text = '''
-class C {
-  /**
-   * Docs
-   */
-  var v;
-}''';
-    UnlinkedVariable variable = serializeClassText(text).fields[0];
-    expect(variable.documentationComment, isNotNull);
-    checkDocumentationComment(variable.documentationComment, text);
-  }
-
-  test_field_final() {
-    UnlinkedVariable variable =
-        serializeClassText('class C { final int i = 0; }').fields[0];
-    expect(variable.isFinal, isTrue);
-  }
-
-  test_field_static() {
-    UnlinkedVariable variable =
-        serializeClassText('class C { static int i; }').fields[0];
-    expect(variable.isStatic, isTrue);
-  }
-
-  test_function_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-f() {}''';
-    UnlinkedExecutable executable = serializeExecutableText(text);
-    expect(executable.documentationComment, isNotNull);
-    checkDocumentationComment(executable.documentationComment, text);
-  }
-
-  test_generic_method_in_generic_class() {
-    UnlinkedClass cls = serializeClassText(
-        'class C<T, U> { void m<V, W>(T t, U u, V v, W w) {} }');
-    List<UnlinkedParam> params = cls.executables[0].parameters;
-    checkParamTypeRef(params[0].type, 4);
-    checkParamTypeRef(params[1].type, 3);
-    checkParamTypeRef(params[2].type, 2);
-    checkParamTypeRef(params[3].type, 1);
-  }
-
-  test_getter_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-get f => null;''';
-    UnlinkedExecutable executable = serializeExecutableText(text);
-    expect(executable.documentationComment, isNotNull);
-    checkDocumentationComment(executable.documentationComment, text);
-  }
-
-  test_import_deferred() {
-    serializeLibraryText(
-        'import "dart:async" deferred as a; main() { print(a.Future); }');
-    expect(unlinkedUnits[0].imports[0].isDeferred, isTrue);
-  }
-
-  test_import_dependency() {
-    serializeLibraryText('import "dart:async"; Future x;');
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    checkDependency(
-        prelinked.importDependencies[0], 'dart:async', 'dart:async');
-  }
-
-  test_import_explicit() {
-    serializeLibraryText('import "dart:core"; int i;');
-    expect(unlinkedUnits[0].imports, hasLength(1));
-    expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
-  }
-
-  test_import_hide_order() {
-    serializeLibraryText(
-        'import "dart:async" hide Future, Stream; Completer c;');
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
-    expect(unlinkedUnits[0].imports[0].combinators[0].shows, isEmpty);
-    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');
-  }
-
-  test_import_implicit() {
-    // The implicit import of dart:core is represented in the model.
-    serializeLibraryText('');
-    expect(unlinkedUnits[0].imports, hasLength(1));
-    checkDependency(prelinked.importDependencies[0], 'dart:core', 'dart:core');
-    expect(unlinkedUnits[0].imports[0].uri, isEmpty);
-    expect(unlinkedUnits[0].imports[0].uriOffset, 0);
-    expect(unlinkedUnits[0].imports[0].uriEnd, 0);
-    expect(unlinkedUnits[0].imports[0].prefixReference, 0);
-    expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
-    expect(unlinkedUnits[0].imports[0].isImplicit, isTrue);
-  }
-
-  test_import_no_combinators() {
-    serializeLibraryText('import "dart:async"; Future x;');
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
-  }
-
-  test_import_no_flags() {
-    serializeLibraryText('import "dart:async"; Future x;');
-    expect(unlinkedUnits[0].imports[0].isImplicit, isFalse);
-    expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
-  }
-
-  test_import_non_deferred() {
-    serializeLibraryText(
-        'import "dart:async" as a; main() { print(a.Future); }');
-    expect(unlinkedUnits[0].imports[0].isDeferred, isFalse);
-  }
-
-  test_import_of_file_with_missing_part() {
-    // Other references in foo.dart should be resolved even though foo.dart's
-    // part declaration for bar.dart refers to a non-existent file.
-    allowMissingFiles = true;
-    addNamedSource('/foo.dart', 'part "bar.dart"; class C {}');
-    serializeLibraryText('import "foo.dart"; C x;');
-    checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C');
-  }
-
-  test_import_of_missing_export() {
-    // Other references in foo.dart should be resolved even though foo.dart's
-    // re-export of bar.dart refers to a non-existent file.
-    allowMissingFiles = true;
-    addNamedSource('/foo.dart', 'export "bar.dart"; class C {}');
-    serializeLibraryText('import "foo.dart"; C x;');
-    checkTypeRef(findVariable('x').type, absUri('/foo.dart'), 'foo.dart', 'C');
-  }
-
-  test_import_offset() {
-    String libraryText = '    import "dart:async"; Future x;';
-    serializeLibraryText(libraryText);
-    expect(unlinkedUnits[0].imports[0].offset, libraryText.indexOf('import'));
-    expect(unlinkedUnits[0].imports[0].uriOffset,
-        libraryText.indexOf('"dart:async"'));
-    expect(unlinkedUnits[0].imports[0].uriEnd, libraryText.indexOf('; Future'));
-  }
-
-  test_import_prefix_name() {
-    String libraryText = 'import "dart:async" as a; a.Future x;';
-    serializeLibraryText(libraryText);
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    checkPrefix(unlinkedUnits[0].imports[0].prefixReference, 'a');
-    expect(unlinkedUnits[0].imports[0].prefixOffset, libraryText.indexOf('a;'));
-  }
-
-  test_import_prefix_none() {
-    serializeLibraryText('import "dart:async"; Future x;');
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    expect(unlinkedUnits[0].imports[0].prefixReference, 0);
-  }
-
-  test_import_prefix_not_in_public_namespace() {
-    serializeLibraryText('import "dart:async" as a; a.Future v;');
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'v');
-    expect(unlinkedUnits[0].publicNamespace.names[1].name, 'v=');
-  }
-
-  test_import_prefix_reference() {
-    UnlinkedVariable variable =
-        serializeVariableText('import "dart:async" as a; a.Future v;');
-    checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
-        expectedPrefix: 'a', numTypeParameters: 1);
-  }
-
-  test_import_prefixes_take_precedence_over_imported_names() {
-    addNamedSource('/a.dart', 'class b {} class A');
-    addNamedSource('/b.dart', 'class Cls {}');
-    addNamedSource('/c.dart', 'class Cls {}');
-    addNamedSource('/d.dart', 'class c {} class D');
-    serializeLibraryText('''
-import 'a.dart';
-import 'b.dart' as b;
-import 'c.dart' as c;
-import 'd.dart';
-A aCls;
-b.Cls bCls;
-c.Cls cCls;
-D dCls;
-''');
-    checkTypeRef(findVariable('aCls').type, absUri('/a.dart'), 'a.dart', 'A');
-    checkTypeRef(findVariable('bCls').type, absUri('/b.dart'), 'b.dart', 'Cls',
-        expectedPrefix: 'b');
-    checkTypeRef(findVariable('cCls').type, absUri('/c.dart'), 'c.dart', 'Cls',
-        expectedPrefix: 'c');
-    checkTypeRef(findVariable('dCls').type, absUri('/d.dart'), 'd.dart', 'D');
-  }
-
-  test_import_reference() {
-    UnlinkedVariable variable =
-        serializeVariableText('import "dart:async"; Future v;');
-    checkTypeRef(variable.type, 'dart:async', 'dart:async', 'Future',
-        numTypeParameters: 1);
-  }
-
-  test_import_reference_merged_no_prefix() {
-    serializeLibraryText('''
-import "dart:async" show Future;
-import "dart:async" show Stream;
-
-Future f;
-Stream s;
-''');
-    checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
-        numTypeParameters: 1);
-    checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
-        numTypeParameters: 1);
-  }
-
-  test_import_reference_merged_prefixed() {
-    serializeLibraryText('''
-import "dart:async" as a show Future;
-import "dart:async" as a show Stream;
-
-a.Future f;
-a.Stream s;
-''');
-    checkTypeRef(findVariable('f').type, 'dart:async', 'dart:async', 'Future',
-        expectedPrefix: 'a', numTypeParameters: 1);
-    checkTypeRef(findVariable('s').type, 'dart:async', 'dart:async', 'Stream',
-        expectedPrefix: 'a', numTypeParameters: 1);
-  }
-
-  test_import_reference_merged_prefixed_separate_libraries() {
-    addNamedSource('/a.dart', 'class A {}');
-    addNamedSource('/b.dart', 'class B {}');
-    serializeLibraryText('''
-import 'a.dart' as p;
-import 'b.dart' as p;
-
-p.A a;
-p.B b;
-''');
-    checkTypeRef(findVariable('a').type, absUri('/a.dart'), 'a.dart', 'A',
-        expectedPrefix: 'p');
-    checkTypeRef(findVariable('b').type, absUri('/b.dart'), 'b.dart', 'B',
-        expectedPrefix: 'p');
-  }
-
-  test_import_show_order() {
-    String libraryText =
-        'import "dart:async" show Future, Stream; Future x; Stream y;';
-    serializeLibraryText(libraryText);
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    expect(unlinkedUnits[0].imports[0].combinators, hasLength(1));
-    expect(unlinkedUnits[0].imports[0].combinators[0].shows, hasLength(2));
-    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');
-  }
-
-  test_import_uri() {
-    String uriString = '"dart:async"';
-    String libraryText = 'import $uriString; Future x;';
-    serializeLibraryText(libraryText);
-    // Second import is the implicit import of dart:core
-    expect(unlinkedUnits[0].imports, hasLength(2));
-    expect(unlinkedUnits[0].imports[0].uri, 'dart:async');
-  }
-
-  test_library_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-library foo;''';
-    serializeLibraryText(text);
-    expect(unlinkedUnits[0].libraryDocumentationComment, isNotNull);
-    checkDocumentationComment(
-        unlinkedUnits[0].libraryDocumentationComment, text);
-  }
-
-  test_library_name_with_spaces() {
-    String text = 'library foo . bar ;';
-    serializeLibraryText(text);
-    expect(unlinkedUnits[0].libraryName, 'foo.bar');
-    expect(unlinkedUnits[0].libraryNameOffset, text.indexOf('foo . bar'));
-    expect(unlinkedUnits[0].libraryNameLength, 'foo . bar'.length);
-  }
-
-  test_library_named() {
-    String text = 'library foo.bar;';
-    serializeLibraryText(text);
-    expect(unlinkedUnits[0].libraryName, 'foo.bar');
-    expect(unlinkedUnits[0].libraryNameOffset, text.indexOf('foo.bar'));
-    expect(unlinkedUnits[0].libraryNameLength, 'foo.bar'.length);
-  }
-
-  test_library_unnamed() {
-    serializeLibraryText('');
-    expect(unlinkedUnits[0].libraryName, isEmpty);
-    expect(unlinkedUnits[0].libraryNameOffset, 0);
-    expect(unlinkedUnits[0].libraryNameLength, 0);
-  }
-
-  test_library_with_missing_part() {
-    // References to other parts should still be resolved.
-    allowMissingFiles = true;
-    addNamedSource('/bar.dart', 'part of my.lib; class C {}');
-    serializeLibraryText(
-        'library my.lib; part "foo.dart"; part "bar.dart"; C c;',
-        allowErrors: true);
-    checkTypeRef(findVariable('c').type, null, null, 'C',
-        expectedTargetUnit: 2);
-  }
-
-  test_local_names_take_precedence_over_imported_names() {
-    addNamedSource('/a.dart', 'class C {} class D {}');
-    serializeLibraryText('''
-import 'a.dart';
-class C {}
-C c;
-D d;''');
-    checkTypeRef(findVariable('c').type, null, null, 'C');
-    checkTypeRef(findVariable('d').type, absUri('/a.dart'), 'a.dart', 'D');
-  }
-
-  test_method_documented() {
-    String text = '''
-class C {
-  /**
-   * Docs
-   */
-  f() {}
-}''';
-    UnlinkedExecutable executable = serializeClassText(text).executables[0];
-    expect(executable.documentationComment, isNotNull);
-    checkDocumentationComment(executable.documentationComment, text);
-  }
-
-  test_part_declaration() {
-    addNamedSource('/a.dart', 'part of my.lib;');
-    String text = 'library my.lib; part "a.dart"; // <-part';
-    serializeLibraryText(text);
-    expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.parts[0], 'a.dart');
-    expect(unlinkedUnits[0].parts, hasLength(1));
-    expect(unlinkedUnits[0].parts[0].uriOffset, text.indexOf('"a.dart"'));
-    expect(unlinkedUnits[0].parts[0].uriEnd, text.indexOf('; // <-part'));
-  }
-
-  test_parts_defining_compilation_unit() {
-    serializeLibraryText('');
-    expect(prelinked.units, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.parts, isEmpty);
-  }
-
-  test_parts_included() {
-    addNamedSource('/part1.dart', 'part of my.lib;');
-    String partString = '"part1.dart"';
-    String libraryText = 'library my.lib; part $partString;';
-    serializeLibraryText(libraryText);
-    expect(prelinked.units, hasLength(2));
-    expect(unlinkedUnits[0].publicNamespace.parts, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.parts[0], 'part1.dart');
-  }
-
-  test_public_namespace_of_part() {
-    addNamedSource('/a.dart', 'part of foo; class C {}');
-    serializeLibraryText('library foo; part "a.dart";');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-    expect(unlinkedUnits[1].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[1].publicNamespace.names[0].name, 'C');
-  }
-
-  test_setter_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-void set f(value) {}''';
-    UnlinkedExecutable executable = serializeExecutableText(text, 'f=');
-    expect(executable.documentationComment, isNotNull);
-    checkDocumentationComment(executable.documentationComment, text);
-  }
-
-  test_type_arguments_explicit() {
-    UnlinkedTypeRef typeRef = serializeTypeText('List<int>');
-    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true, numTypeParameters: 1);
-    expect(typeRef.typeArguments, hasLength(1));
-    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
-  }
-
-  test_type_arguments_explicit_dynamic() {
-    UnlinkedTypeRef typeRef = serializeTypeText('List<dynamic>');
-    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true, numTypeParameters: 1);
-    expect(typeRef.typeArguments, isEmpty);
-  }
-
-  test_type_arguments_explicit_dynamic_typedef() {
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('F<dynamic>', otherDeclarations: 'typedef T F<T>();');
-    checkTypeRef(typeRef, null, null, 'F',
-        allowTypeParameters: true,
-        expectedKind: PrelinkedReferenceKind.typedef,
-        numTypeParameters: 1);
-    expect(typeRef.typeArguments, isEmpty);
-  }
-
-  test_type_arguments_explicit_typedef() {
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('F<int>', otherDeclarations: 'typedef T F<T>();');
-    checkTypeRef(typeRef, null, null, 'F',
-        allowTypeParameters: true,
-        expectedKind: PrelinkedReferenceKind.typedef,
-        numTypeParameters: 1);
-    expect(typeRef.typeArguments, hasLength(1));
-    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
-  }
-
-  test_type_arguments_implicit() {
-    UnlinkedTypeRef typeRef = serializeTypeText('List');
-    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'List',
-        allowTypeParameters: true, numTypeParameters: 1);
-    expect(typeRef.typeArguments, isEmpty);
-  }
-
-  test_type_arguments_implicit_typedef() {
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('F', otherDeclarations: 'typedef T F<T>();');
-    checkTypeRef(typeRef, null, null, 'F',
-        allowTypeParameters: true,
-        expectedKind: PrelinkedReferenceKind.typedef,
-        numTypeParameters: 1);
-    expect(typeRef.typeArguments, isEmpty);
-  }
-
-  test_type_arguments_order() {
-    UnlinkedTypeRef typeRef = serializeTypeText('Map<int, Object>');
-    checkTypeRef(typeRef, 'dart:core', 'dart:core', 'Map',
-        allowTypeParameters: true, numTypeParameters: 2);
-    expect(typeRef.typeArguments, hasLength(2));
-    checkTypeRef(typeRef.typeArguments[0], 'dart:core', 'dart:core', 'int');
-    checkTypeRef(typeRef.typeArguments[1], 'dart:core', 'dart:core', 'Object');
-  }
-
-  test_type_dynamic() {
-    checkDynamicTypeRef(serializeTypeText('dynamic'));
-  }
-
-  test_type_reference_from_part() {
-    addNamedSource('/a.dart', 'part of foo; C v;');
-    serializeLibraryText('library foo; part "a.dart"; class C {}');
-    checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
-        null, null, 'C',
-        expectedKind: PrelinkedReferenceKind.classOrEnum,
-        prelinkedSourceUnit: prelinked.units[1],
-        unlinkedSourceUnit: unlinkedUnits[1]);
-  }
-
-  test_type_reference_from_part_withPrefix() {
-    addNamedSource('/a.dart', 'class C {}');
-    addNamedSource('/p.dart', 'part of foo; a.C v;');
-    serializeLibraryText(
-        'library foo; import "a.dart"; import "a.dart" as a; part "p.dart";',
-        allowErrors: true);
-    checkTypeRef(findVariable('v', variables: unlinkedUnits[1].variables).type,
-        absUri('/a.dart'), 'a.dart', 'C',
-        expectedPrefix: 'a',
-        prelinkedSourceUnit: prelinked.units[1],
-        unlinkedSourceUnit: unlinkedUnits[1]);
-  }
-
-  test_type_reference_to_class_argument() {
-    UnlinkedClass cls = serializeClassText('class C<T, U> { T t; U u; }');
-    {
-      UnlinkedTypeRef typeRef =
-          findVariable('t', variables: cls.fields, failIfAbsent: true).type;
-      checkParamTypeRef(typeRef, 2);
-    }
-    {
-      UnlinkedTypeRef typeRef =
-          findVariable('u', variables: cls.fields, failIfAbsent: true).type;
-      checkParamTypeRef(typeRef, 1);
-    }
-  }
-
-  test_type_reference_to_import_of_export() {
-    addNamedSource('/a.dart', 'library a; export "b.dart";');
-    addNamedSource('/b.dart', 'library b; class C {}');
-    checkTypeRef(serializeTypeText('C', otherDeclarations: 'import "a.dart";'),
-        absUri('/b.dart'), 'b.dart', 'C');
-  }
-
-  test_type_reference_to_import_of_export_via_prefix() {
-    addNamedSource('/a.dart', 'library a; export "b.dart";');
-    addNamedSource('/b.dart', 'library b; class C {}');
-    checkTypeRef(
-        serializeTypeText('p.C', otherDeclarations: 'import "a.dart" as p;'),
-        absUri('/b.dart'),
-        'b.dart',
-        'C',
-        expectedPrefix: 'p');
-  }
-
-  test_type_reference_to_imported_part() {
-    addNamedSource('/a.dart', 'library my.lib; part "b.dart";');
-    addNamedSource('/b.dart', 'part of my.lib; class C {}');
-    checkTypeRef(
-        serializeTypeText('C',
-            otherDeclarations: 'library my.lib; import "a.dart";'),
-        absUri('/a.dart'),
-        'a.dart',
-        'C',
-        expectedTargetUnit: 1);
-  }
-
-  test_type_reference_to_imported_part_with_prefix() {
-    addNamedSource('/a.dart', 'library my.lib; part "b.dart";');
-    addNamedSource('/b.dart', 'part of my.lib; class C {}');
-    checkTypeRef(
-        serializeTypeText('p.C',
-            otherDeclarations: 'library my.lib; import "a.dart" as p;'),
-        absUri('/a.dart'),
-        'a.dart',
-        'C',
-        expectedPrefix: 'p',
-        expectedTargetUnit: 1);
-  }
-
-  test_type_reference_to_internal_class() {
-    checkTypeRef(serializeTypeText('C', otherDeclarations: 'class C {}'), null,
-        null, 'C');
-  }
-
-  test_type_reference_to_internal_class_alias() {
-    checkTypeRef(
-        serializeTypeText('C',
-            otherDeclarations: 'class C = D with E; class D {} class E {}'),
-        null,
-        null,
-        'C');
-  }
-
-  test_type_reference_to_internal_enum() {
-    checkTypeRef(serializeTypeText('E', otherDeclarations: 'enum E { value }'),
-        null, null, 'E');
-  }
-
-  test_type_reference_to_local_part() {
-    addNamedSource('/a.dart', 'part of my.lib; class C {}');
-    checkTypeRef(
-        serializeTypeText('C',
-            otherDeclarations: 'library my.lib; part "a.dart";'),
-        null,
-        null,
-        'C',
-        expectedTargetUnit: 1);
-  }
-
-  test_type_reference_to_part() {
-    addNamedSource('/a.dart', 'part of foo; class C { C(); }');
-    serializeLibraryText('library foo; part "a.dart"; C c;');
-    checkTypeRef(unlinkedUnits[0].variables.single.type, null, null, 'C',
-        expectedKind: PrelinkedReferenceKind.classOrEnum,
-        expectedTargetUnit: 1);
-  }
-
-  test_type_reference_to_typedef() {
-    checkTypeRef(serializeTypeText('F', otherDeclarations: 'typedef void F();'),
-        null, null, 'F',
-        expectedKind: PrelinkedReferenceKind.typedef);
-  }
-
-  test_type_unit_counts_unreferenced_units() {
-    addNamedSource('/a.dart', 'library a; part "b.dart"; part "c.dart";');
-    addNamedSource('/b.dart', 'part of a;');
-    addNamedSource('/c.dart', 'part of a; class C {}');
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('C', otherDeclarations: 'import "a.dart";');
-    // The referenced unit should be 2, since unit 0 is a.dart and unit 1 is
-    // b.dart.  a.dart and b.dart are counted even though nothing is imported
-    // from them.
-    checkTypeRef(typeRef, absUri('/a.dart'), 'a.dart', 'C',
-        expectedTargetUnit: 2);
-  }
-
-  test_type_unresolved() {
-    UnlinkedTypeRef typeRef = serializeTypeText('Foo', allowErrors: true);
-    checkUnresolvedTypeRef(typeRef, null, 'Foo');
-  }
-
-  test_typedef_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-typedef F();''';
-    UnlinkedTypedef typedef = serializeTypedefText(text);
-    expect(typedef.documentationComment, isNotNull);
-    checkDocumentationComment(typedef.documentationComment, text);
-  }
-
-  test_typedef_name() {
-    String text = 'typedef F();';
-    UnlinkedTypedef type = serializeTypedefText(text);
-    expect(type.name, 'F');
-    expect(type.nameOffset, text.indexOf('F'));
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.typedef);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'F');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
-  }
-
-  test_typedef_param_none() {
-    UnlinkedTypedef type = serializeTypedefText('typedef F();');
-    expect(type.parameters, isEmpty);
-  }
-
-  test_typedef_param_order() {
-    UnlinkedTypedef type = serializeTypedefText('typedef F(x, y);');
-    expect(type.parameters, hasLength(2));
-    expect(type.parameters[0].name, 'x');
-    expect(type.parameters[1].name, 'y');
-  }
-
-  test_typedef_private() {
-    serializeTypedefText('typedef _F();', '_F');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-
-  test_typedef_reference_generic() {
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('F', otherDeclarations: 'typedef void F<A, B>();');
-    checkTypeRef(typeRef, null, null, 'F',
-        numTypeParameters: 2, expectedKind: PrelinkedReferenceKind.typedef);
-  }
-
-  test_typedef_reference_generic_imported() {
-    addNamedSource('/lib.dart', 'typedef void F<A, B>();');
-    UnlinkedTypeRef typeRef =
-        serializeTypeText('F', otherDeclarations: 'import "lib.dart";');
-    checkTypeRef(typeRef, absUri('/lib.dart'), 'lib.dart', 'F',
-        numTypeParameters: 2, expectedKind: PrelinkedReferenceKind.typedef);
-  }
-
-  test_typedef_return_type_explicit() {
-    UnlinkedTypedef type = serializeTypedefText('typedef int F();');
-    checkTypeRef(type.returnType, 'dart:core', 'dart:core', 'int');
-  }
-
-  test_typedef_type_param_in_parameter() {
-    UnlinkedTypedef type = serializeTypedefText('typedef F<T>(T t);');
-    checkParamTypeRef(type.parameters[0].type, 1);
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
-  }
-
-  test_typedef_type_param_in_return_type() {
-    UnlinkedTypedef type = serializeTypedefText('typedef T F<T>();');
-    checkParamTypeRef(type.returnType, 1);
-  }
-
-  test_typedef_type_param_none() {
-    UnlinkedTypedef type = serializeTypedefText('typedef F();');
-    expect(type.typeParameters, isEmpty);
-  }
-
-  test_typedef_type_param_order() {
-    UnlinkedTypedef type = serializeTypedefText('typedef F<T, U>();');
-    expect(type.typeParameters, hasLength(2));
-    expect(type.typeParameters[0].name, 'T');
-    expect(type.typeParameters[1].name, 'U');
-  }
-
-  test_variable() {
-    String text = 'int i;';
-    UnlinkedVariable v = serializeVariableText(text, variableName: 'i');
-    expect(v.nameOffset, text.indexOf('i;'));
-    expect(findExecutable('i'), isNull);
-    expect(findExecutable('i='), isNull);
-    expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
-    expect(unlinkedUnits[0].publicNamespace.names[0].kind,
-        PrelinkedReferenceKind.other);
-    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'i');
-    expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
-    expect(unlinkedUnits[0].publicNamespace.names[1].kind,
-        PrelinkedReferenceKind.other);
-    expect(unlinkedUnits[0].publicNamespace.names[1].name, 'i=');
-    expect(unlinkedUnits[0].publicNamespace.names[1].numTypeParameters, 0);
-  }
-
-  test_variable_const() {
-    UnlinkedVariable variable =
-        serializeVariableText('const int i = 0;', variableName: 'i');
-    expect(variable.isConst, isTrue);
-  }
-
-  test_variable_documented() {
-    String text = '''
-// Extra comment so doc comment offset != 0
-/**
- * Docs
- */
-var v;''';
-    UnlinkedVariable variable = serializeVariableText(text);
-    expect(variable.documentationComment, isNotNull);
-    checkDocumentationComment(variable.documentationComment, text);
-  }
-
-  test_variable_explicit_dynamic() {
-    UnlinkedVariable variable = serializeVariableText('dynamic v;');
-    checkDynamicTypeRef(variable.type);
-    expect(variable.hasImplicitType, isFalse);
-  }
-
-  test_variable_final_top_level() {
-    UnlinkedVariable variable =
-        serializeVariableText('final int i = 0;', variableName: 'i');
-    expect(variable.isFinal, isTrue);
-  }
-
-  test_variable_implicit_dynamic() {
-    UnlinkedVariable variable = serializeVariableText('var v;');
-    checkDynamicTypeRef(variable.type);
-    expect(variable.hasImplicitType, isTrue);
-  }
-
-  test_variable_name() {
-    UnlinkedVariable variable =
-        serializeVariableText('int i;', variableName: 'i');
-    expect(variable.name, 'i');
-  }
-
-  test_variable_no_flags() {
-    UnlinkedVariable variable =
-        serializeVariableText('int i;', variableName: 'i');
-    expect(variable.isStatic, isFalse);
-    expect(variable.isConst, isFalse);
-    expect(variable.isFinal, isFalse);
-  }
-
-  test_variable_non_const() {
-    UnlinkedVariable variable =
-        serializeVariableText('int i = 0;', variableName: 'i');
-    expect(variable.isConst, isFalse);
-  }
-
-  test_variable_non_final() {
-    UnlinkedVariable variable =
-        serializeVariableText('int i;', variableName: 'i');
-    expect(variable.isFinal, isFalse);
-  }
-
-  test_variable_non_static() {
-    UnlinkedVariable variable =
-        serializeClassText('class C { int i; }').fields[0];
-    expect(variable.isStatic, isFalse);
-  }
-
-  test_variable_non_static_top_level() {
-    // Top level variables are considered non-static.
-    UnlinkedVariable variable =
-        serializeVariableText('int i;', variableName: 'i');
-    expect(variable.isStatic, isFalse);
-  }
-
-  test_variable_static() {
-    UnlinkedVariable variable =
-        serializeClassText('class C { static int i; }').fields[0];
-    expect(variable.isStatic, isTrue);
-  }
-
-  test_variable_type() {
-    UnlinkedVariable variable =
-        serializeVariableText('int i;', variableName: 'i');
-    checkTypeRef(variable.type, 'dart:core', 'dart:core', 'int');
-  }
-
-  test_varible_private() {
-    serializeVariableText('int _i;', variableName: '_i');
-    expect(unlinkedUnits[0].publicNamespace.names, isEmpty);
-  }
-}
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index 252c95f..d24342f 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -9,9 +9,12 @@
 import '../../utils.dart';
 import 'flat_buffers_test.dart' as flat_buffers_test;
 import 'name_filter_test.dart' as name_filter_test;
+import 'prelinker_test.dart' as prelinker_test;
+import 'resynthesize_strong_test.dart' as resynthesize_strong_test;
 import 'resynthesize_test.dart' as resynthesize_test;
-import 'summary_sdk_test.dart' as summary_sdk_test;
-import 'summary_test.dart' as summary_test;
+import 'summarize_ast_test.dart' as summarize_ast_test;
+import 'summarize_elements_strong_test.dart' as summarize_elements_strong_test;
+import 'summarize_elements_test.dart' as summarize_elements_test;
 
 /// Utility for manually running all tests.
 main() {
@@ -19,8 +22,11 @@
   group('summary tests', () {
     flat_buffers_test.main();
     name_filter_test.main();
+    prelinker_test.main();
+    resynthesize_strong_test.main();
     resynthesize_test.main();
-    summary_sdk_test.main();
-    summary_test.main();
+    summarize_ast_test.main();
+    summarize_elements_strong_test.main();
+    summarize_elements_test.main();
   });
 }
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 23930d8..e351c39 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -4,14 +4,15 @@
 
 library analyzer.test.src.task.dart_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
+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/context/cache.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisOptionsImpl, CacheState;
+    show AnalysisOptions, AnalysisOptionsImpl, CacheState;
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/scanner.dart';
@@ -31,6 +32,7 @@
 import '../../reflective_tests.dart';
 import '../../utils.dart';
 import '../context/abstract_context.dart';
+import '../mock_sdk.dart';
 
 main() {
   initializeTestEnvironment();
@@ -42,6 +44,7 @@
   runReflectiveTests(BuildPublicNamespaceTaskTest);
   runReflectiveTests(BuildSourceExportClosureTaskTest);
   runReflectiveTests(BuildTypeProviderTaskTest);
+  runReflectiveTests(BuildTypeProviderTaskTest_noAsync);
   runReflectiveTests(ComputeConstantDependenciesTaskTest);
   runReflectiveTests(ComputeConstantValueTaskTest);
   runReflectiveTests(ComputeInferableStaticVariableDependenciesTaskTest);
@@ -1005,6 +1008,32 @@
 }
 
 @reflectiveTest
+class BuildTypeProviderTaskTest_noAsync extends _AbstractDartTaskTest {
+  void prepareAnalysisContext([AnalysisOptions options]) {
+    AnalysisOptionsImpl newOptions = new AnalysisOptionsImpl();
+    newOptions.enableAsync = false;
+    super.prepareAnalysisContext(newOptions);
+  }
+
+  void setUp() {
+    sdk = new MockSdk(dartAsync: false);
+    super.setUp();
+  }
+
+  test_perform_noAsync() {
+    expect(context, isNotNull);
+    computeResult(AnalysisContextTarget.request, TYPE_PROVIDER,
+        matcher: isBuildTypeProviderTask);
+    // validate
+    TypeProvider typeProvider = outputs[TYPE_PROVIDER];
+    expect(typeProvider, isNotNull);
+    expect(typeProvider.boolType, isNotNull);
+    expect(typeProvider.intType, isNotNull);
+    expect(typeProvider.futureType, isNotNull);
+  }
+}
+
+@reflectiveTest
 class ComputeConstantDependenciesTaskTest extends _AbstractDartTaskTest {
   Annotation findClassAnnotation(CompilationUnit unit, String className) {
     for (CompilationUnitMember member in unit.declarations) {
@@ -2993,6 +3022,40 @@
     expect(outputs[UNITS], hasLength(1));
   }
 
+  test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
+    // Parse "lib.dart" to let the context know that "test.dart" is included.
+    computeResult(
+        newSource(
+            '/lib.dart',
+            r'''
+library lib;
+part 'test.dart';
+'''),
+        PARSED_UNIT);
+    // If there are no the "part of" directive, then it is not a part.
+    _performParseTask('');
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+  }
+
+  test_perform_computeSourceKind_noDirectives_noContainingLibrary() {
+    _performParseTask('');
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+  }
+
+  test_perform_doesNotExist() {
+    _performParseTask(null);
+    expect(outputs, hasLength(9));
+    expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
+    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
+    _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
+    expect(outputs[INCLUDED_PARTS], hasLength(0));
+    expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
+    expect(outputs[PARSE_ERRORS], hasLength(0));
+    expect(outputs[PARSED_UNIT], isNotNull);
+    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
+    expect(outputs[UNITS], hasLength(1));
+  }
+
   test_perform_enableAsync_false() {
     AnalysisOptionsImpl options = new AnalysisOptionsImpl();
     options.enableAsync = false;
@@ -3028,40 +3091,6 @@
     expect(outputs[UNITS], hasLength(1));
   }
 
-  test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
-    // Parse "lib.dart" to let the context know that "test.dart" is included.
-    computeResult(
-        newSource(
-            '/lib.dart',
-            r'''
-library lib;
-part 'test.dart';
-'''),
-        PARSED_UNIT);
-    // If there are no the "part of" directive, then it is not a part.
-    _performParseTask('');
-    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
-  }
-
-  test_perform_computeSourceKind_noDirectives_noContainingLibrary() {
-    _performParseTask('');
-    expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
-  }
-
-  test_perform_doesNotExist() {
-    _performParseTask(null);
-    expect(outputs, hasLength(9));
-    expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
-    expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
-    _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
-    expect(outputs[INCLUDED_PARTS], hasLength(0));
-    expect(outputs[LIBRARY_SPECIFIC_UNITS], hasLength(1));
-    expect(outputs[PARSE_ERRORS], hasLength(0));
-    expect(outputs[PARSED_UNIT], isNotNull);
-    expect(outputs[SOURCE_KIND], SourceKind.UNKNOWN);
-    expect(outputs[UNITS], hasLength(1));
-  }
-
   test_perform_flushTokenStream() {
     _performParseTask(r'''
 class Test {}
@@ -3133,7 +3162,11 @@
   }
 
   void _performParseTask(String content) {
-    source = newSource('/test.dart', content);
+    if (content == null) {
+      source = resourceProvider.getFile('/test.dart').createSource();
+    } else {
+      source = newSource('/test.dart', content);
+    }
     computeResult(source, PARSED_UNIT, matcher: isParseDartTask);
   }
 
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index 7938cc9..315e061 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -4,8 +4,8 @@
 
 library analyzer.test.src.task.dart_work_manager_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show
         AnalysisErrorInfo,
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index 114a452..8ef225a 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -4,8 +4,8 @@
 
 library analyzer.test.src.task.incremental_element_builder_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/incremental_element_builder.dart';
 import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/test/src/task/model_test.dart b/pkg/analyzer/test/src/task/model_test.dart
index 4db1ee2..a798472 100644
--- a/pkg/analyzer/test/src/task/model_test.dart
+++ b/pkg/analyzer/test/src/task/model_test.dart
@@ -103,7 +103,7 @@
 
 @reflectiveTest
 class TaskDescriptorImplTest extends EngineTestCase {
-  test_create() {
+  test_create_noOptionalArgs() {
     String name = 'name';
     BuildTask buildTask = (context, target) {};
     CreateTaskInputs createTaskInputs = (target) {};
@@ -114,12 +114,30 @@
     expect(descriptor.name, name);
     expect(descriptor.buildTask, equals(buildTask));
     expect(descriptor.createTaskInputs, equals(createTaskInputs));
+    expect(descriptor.suitabilityFor(null), TaskSuitability.LOWEST);
+    expect(descriptor.results, results);
+  }
+
+  test_create_withIsAppropriateFor() {
+    String name = 'name';
+    BuildTask buildTask = (context, target) {};
+    CreateTaskInputs createTaskInputs = (target) {};
+    List<ResultDescriptor> results = <ResultDescriptor>[];
+    SuitabilityFor suitabilityFor = (target) => TaskSuitability.NONE;
+    TaskDescriptorImpl descriptor = new TaskDescriptorImpl(
+        name, buildTask, createTaskInputs, results,
+        suitabilityFor: suitabilityFor);
+    expect(descriptor, isNotNull);
+    expect(descriptor.name, name);
+    expect(descriptor.buildTask, equals(buildTask));
+    expect(descriptor.createTaskInputs, equals(createTaskInputs));
+    expect(descriptor.suitabilityFor(null), TaskSuitability.NONE);
     expect(descriptor.results, results);
   }
 
   test_createTask() {
-    BuildTask buildTask = (context, target) =>
-        new TestAnalysisTask(context, target);
+    BuildTask buildTask =
+        (context, target) => new TestAnalysisTask(context, target);
     CreateTaskInputs createTaskInputs = (target) {};
     List<ResultDescriptor> results = <ResultDescriptor>[];
     TaskDescriptorImpl descriptor =
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 55b73a8..bb8216a 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -964,6 +964,16 @@
    '''
   });
 
+  testChecker('Function subtyping: uninferred closure', {
+    '/main.dart': '''
+      typedef num Num2Num(num x);
+      void main() {
+        Num2Num g = /*info:INFERRED_TYPE_CLOSURE,severe:STATIC_TYPE_ERROR*/(int x) { return x; };
+        print(g(42));
+      }
+    '''
+  });
+
   testChecker('Relaxed casts', {
     '/main.dart': '''
 
@@ -1141,6 +1151,21 @@
        '''
   });
 
+  testChecker('factory constructor downcast', {
+    '/main.dart': r'''
+        class Animal {
+          Animal();
+          factory Animal.cat() => return new Cat();
+        }
+
+        class Cat extends Animal {}
+
+        void main() {
+          Cat c = /*info:ASSIGNMENT_CAST*/new Animal.cat();
+          c = /*severe:STATIC_TYPE_ERROR*/new Animal();
+        }'''
+  });
+
   testChecker('field/field override', {
     '/main.dart': '''
           class A {}
@@ -1389,7 +1414,51 @@
           class DerivedFuture4<A> extends Future<A> {
             /*=B*/ then/*<B>*/(Object onValue(A a)) => null;
           }
-       '''
+      '''
+  });
+
+  testChecker('generic function wrong number of arguments', {
+      '/main.dart': r'''
+          /*=T*/ foo/*<T>*/(/*=T*/ x, /*=T*/ y) => x;
+          /*=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);
+
+            // named arguments
+            bar(y: 1, x: 2, z: 3);
+            String x = bar(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);
+          }
+      '''
+  });
+
+  testChecker('type promotion from dynamic', {
+    '/main.dart': r'''
+          f() {
+            dynamic x;
+            if (x is int) {
+              int y = x;
+              String z = /*severe:STATIC_TYPE_ERROR*/x;
+            }
+          }
+          g() {
+            Object x;
+            if (x is int) {
+              int y = x;
+              String z = /*severe:STATIC_TYPE_ERROR*/x;
+            }
+          }
+    '''
   });
 
   testChecker('unary operators', {
@@ -1642,6 +1711,15 @@
         '''
   });
 
+  testChecker('loadLibrary', {
+    '/lib1.dart': '''library lib1;''',
+    '/main.dart': r'''
+        import 'lib1.dart' deferred as lib1;
+        main() {
+          Future f = lib1.loadLibrary();
+        }'''
+  });
+
   group('invalid overrides', () {
     testChecker('child override', {
       '/main.dart': '''
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 0141e38..f386377 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -6,11 +6,12 @@
 // package:dev_compiler's tests
 library analyzer.test.src.task.strong.strong_test_helper;
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/context/context.dart' show SdkAnalysisContext;
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/error.dart';
 import 'package:analyzer/src/generated/sdk.dart';
@@ -95,6 +96,7 @@
         }
         ''',
   'dart:async': '''
+        library dart.async;
         class Future<T> {
           Future(computation()) {}
           Future.value(T t) {}
diff --git a/pkg/analyzer/test/src/task/strong_mode_test.dart b/pkg/analyzer/test/src/task/strong_mode_test.dart
index 6859d48..097d5d4 100644
--- a/pkg/analyzer/test/src/task/strong_mode_test.dart
+++ b/pkg/analyzer/test/src/task/strong_mode_test.dart
@@ -4,9 +4,9 @@
 
 library analyzer.test.src.task.strong_mode_test;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/strong_mode.dart';
 import 'package:unittest/unittest.dart';
diff --git a/pkg/analyzer/test/src/task/test_all.dart b/pkg/analyzer/test/src/task/test_all.dart
index 41e568e..956a8e5 100644
--- a/pkg/analyzer/test/src/task/test_all.dart
+++ b/pkg/analyzer/test/src/task/test_all.dart
@@ -21,6 +21,7 @@
 import 'options_test.dart' as options_test;
 import 'options_work_manager_test.dart' as options_work_manager_test;
 import 'strong_mode_test.dart' as strong_mode_test;
+import 'yaml_test.dart' as yaml_test;
 
 /// Utility for manually running all tests.
 main() {
@@ -39,5 +40,6 @@
     options_test.main();
     options_work_manager_test.main();
     strong_mode_test.main();
+    yaml_test.main();
   });
 }
diff --git a/pkg/analyzer/test/src/task/yaml_test.dart b/pkg/analyzer/test/src/task/yaml_test.dart
new file mode 100644
index 0000000..5deb5f5
--- /dev/null
+++ b/pkg/analyzer/test/src/task/yaml_test.dart
@@ -0,0 +1,70 @@
+// 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 analyzer.test.src.task.yaml_test;
+
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/yaml.dart';
+import 'package:analyzer/task/general.dart';
+import 'package:analyzer/task/yaml.dart';
+import 'package:unittest/unittest.dart';
+import 'package:yaml/yaml.dart';
+
+import '../../reflective_tests.dart';
+import '../../utils.dart';
+import '../context/abstract_context.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(ParseYamlTaskTest);
+}
+
+isInstanceOf isParseYamlTask = new isInstanceOf<ParseYamlTask>();
+
+@reflectiveTest
+class ParseYamlTaskTest extends AbstractContextTest {
+  Source source;
+
+  test_perform() {
+    _performParseTask(r'''
+rules:
+  style_guide:
+    camel_case_types: false
+''');
+    expect(outputs, hasLength(3));
+    YamlDocument document = outputs[YAML_DOCUMENT];
+    expect(document, isNotNull);
+    var value = document.contents.value;
+    expect(value, new isInstanceOf<Map>());
+    expect(value['rules']['style_guide']['camel_case_types'], isFalse);
+    expect(outputs[YAML_ERRORS], hasLength(0));
+    LineInfo lineInfo = outputs[LINE_INFO];
+    expect(lineInfo, isNotNull);
+    expect(lineInfo.getOffsetOfLine(0), 0);
+    expect(lineInfo.getOffsetOfLine(1), 7);
+    expect(lineInfo.getOffsetOfLine(2), 22);
+    expect(lineInfo.getOffsetOfLine(3), 50);
+  }
+
+  test_perform_doesNotExist() {
+    _performParseTask(null);
+    expect(outputs, hasLength(3));
+    YamlDocument document = outputs[YAML_DOCUMENT];
+    expect(document, isNotNull);
+    expect(document.contents.value, isNull);
+    expect(outputs[YAML_ERRORS], hasLength(1));
+    LineInfo lineInfo = outputs[LINE_INFO];
+    expect(lineInfo, isNotNull);
+    expect(lineInfo.getOffsetOfLine(0), 0);
+  }
+
+  void _performParseTask(String content) {
+    if (content == null) {
+      source = resourceProvider.getFile('/test.yaml').createSource();
+    } else {
+      source = newSource('/test.yaml', content);
+    }
+    computeResult(source, YAML_DOCUMENT, matcher: isParseYamlTask);
+  }
+}
diff --git a/pkg/analyzer/test/utils.dart b/pkg/analyzer/test/utils.dart
index e162219..a8c39a5 100644
--- a/pkg/analyzer/test/utils.dart
+++ b/pkg/analyzer/test/utils.dart
@@ -4,9 +4,9 @@
 
 library analyzer.test.utils;
 
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/ast.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:path/path.dart' as path;
diff --git a/pkg/analyzer/tool/summary/build_sdk_summary.dart b/pkg/analyzer/tool/summary/build_sdk_summary.dart
index db17c57..738e0a1 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summary.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summary.dart
@@ -45,9 +45,8 @@
   //
   // Serialize each SDK library.
   //
-  List<String> prelinkedLibraryUris = <String>[];
-  List<PrelinkedLibraryBuilder> prelinkedLibraries =
-      <PrelinkedLibraryBuilder>[];
+  List<String> linkedLibraryUris = <String>[];
+  List<LinkedLibraryBuilder> linkedLibraries = <LinkedLibraryBuilder>[];
   List<String> unlinkedUnitUris = <String>[];
   List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[];
   for (SdkLibrary lib in sdk.sdkLibraries) {
@@ -55,19 +54,20 @@
     Source librarySource = sdk.mapDartUri(lib.shortName);
     LibraryElement libraryElement =
         context.computeLibraryElement(librarySource);
+    // TODO(paulberry): also build a summary of the SDK in strong mode.
     LibrarySerializationResult libraryResult =
-        serializeLibrary(libraryElement, context.typeProvider);
-    prelinkedLibraryUris.add(lib.shortName);
-    prelinkedLibraries.add(libraryResult.prelinked);
+        serializeLibrary(libraryElement, context.typeProvider, false);
+    linkedLibraryUris.add(lib.shortName);
+    linkedLibraries.add(libraryResult.linked);
     unlinkedUnitUris.addAll(libraryResult.unitUris);
     unlinkedUnits.addAll(libraryResult.unlinkedUnits);
   }
   //
   // Write the whole SDK bundle.
   //
-  SdkBundleBuilder sdkBundle = encodeSdkBundle(
-      prelinkedLibraryUris: prelinkedLibraryUris,
-      prelinkedLibraries: prelinkedLibraries,
+  SdkBundleBuilder sdkBundle = new SdkBundleBuilder(
+      linkedLibraryUris: linkedLibraryUris,
+      linkedLibraries: linkedLibraries,
       unlinkedUnitUris: unlinkedUnitUris,
       unlinkedUnits: unlinkedUnits);
   File file = new File(outputFilePath);
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 1918074..afd790d 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -88,8 +88,12 @@
         if (type.isList) {
           if (_idl.classes.containsKey(type.typeName)) {
             // List of classes is ok
+          } else if (_idl.enums.containsKey(type.typeName)) {
+            // List of enums is ok
           } else if (type.typeName == 'int') {
             // List of ints is ok
+          } else if (type.typeName == 'double') {
+            // List of doubles is ok
           } else if (type.typeName == 'String') {
             // List of strings is ok
           } else {
@@ -116,12 +120,21 @@
   /**
    * Generate a Dart expression representing the default value for a field
    * having the given [type], or `null` if there is no default value.
+   *
+   * If [builder] is `true`, the returned type should be appropriate for use in
+   * a builder class.
    */
-  String defaultValue(idlModel.FieldType type) {
+  String defaultValue(idlModel.FieldType type, bool builder) {
     if (type.isList) {
-      return 'const <${type.typeName}>[]';
+      if (builder) {
+        idlModel.FieldType elementType =
+            new idlModel.FieldType(type.typeName, false);
+        return '<${encodedType(elementType)}>[]';
+      } else {
+        return 'const <${type.typeName}>[]';
+      }
     } else if (_idl.enums.containsKey(type.typeName)) {
-      return '${type.typeName}.${_idl.enums[type.typeName].values[0]}';
+      return '${type.typeName}.${_idl.enums[type.typeName].values[0].name}';
     } else if (type.typeName == 'int') {
       return '0';
     } else if (type.typeName == 'String') {
@@ -200,7 +213,9 @@
             new idlModel.EnumDeclaration(doc, decl.name.name);
         _idl.enums[enm.name] = enm;
         for (EnumConstantDeclaration constDecl in decl.constants) {
-          enm.values.add(constDecl.name.name);
+          String doc = _getNodeDoc(lineInfo, constDecl);
+          enm.values
+              .add(new idlModel.EnumValueDeclaration(doc, constDecl.name.name));
         }
       } else if (decl is TopLevelVariableDeclaration) {
         // Ignore top level variable declarations; they are present just to make
@@ -261,21 +276,14 @@
     out("import 'base.dart' as base;");
     out("import 'flat_buffers.dart' as fb;");
     out();
-    _idl.enums.forEach((String name, idlModel.EnumDeclaration enm) {
-      outDoc(enm.documentation);
-      out('enum $name {');
-      indent(() {
-        for (String value in enm.values) {
-          out('$value,');
-        }
-      });
-      out('}');
+    for (idlModel.EnumDeclaration enm in _idl.enums.values) {
+      _generateEnum(enm);
       out();
-    });
-    for (var cls in _idl.classes.values) {
-      List<String> builderParams = _generateBuilder(cls);
+      _generateEnumReader(enm);
       out();
-      _generateEncodeFunction(cls, builderParams);
+    }
+    for (idlModel.ClassDeclaration cls in _idl.classes.values) {
+      _generateBuilder(cls);
       out();
       _generateInterface(cls);
       out();
@@ -283,6 +291,8 @@
       out();
       _generateImpl(cls);
       out();
+      _generateMixin(cls);
+      out();
     }
   }
 
@@ -293,10 +303,13 @@
     return JSON.encode(s);
   }
 
-  List<String> _generateBuilder(idlModel.ClassDeclaration cls) {
-    String builderName = cls.name + 'Builder';
-    List<String> builderParams = <String>[];
-    out('class $builderName {');
+  void _generateBuilder(idlModel.ClassDeclaration cls) {
+    String name = cls.name;
+    String builderName = name + 'Builder';
+    String mixinName = '_${name}Mixin';
+    List<String> constructorParams = <String>[];
+    out('class $builderName extends Object with $mixinName '
+        'implements $name {');
     indent(() {
       out('bool _finished = false;');
       // Generate fields.
@@ -307,24 +320,45 @@
         String typeStr = encodedType(type);
         out('$typeStr _$fieldName;');
       }
-      // Generate constructor.
-      out();
-      out('$builderName();');
-      // Generate setters.
+      // Generate getters and setters.
       for (idlModel.FieldDeclaration field in cls.fields) {
         String fieldName = field.name;
-        String typeStr = encodedType(field.type);
+        idlModel.FieldType fieldType = field.type;
+        String typeStr = encodedType(fieldType);
+        String def = defaultValue(fieldType, true);
+        String defSuffix = def == null ? '' : ' ??= $def';
+        out();
+        out('@override');
+        out('$typeStr get $fieldName => _$fieldName$defSuffix;');
         out();
         outDoc(field.documentation);
-        builderParams.add('$typeStr $fieldName');
+        constructorParams.add('$typeStr $fieldName');
         out('void set $fieldName($typeStr _value) {');
         indent(() {
           String stateFieldName = '_' + fieldName;
           out('assert(!_finished);');
+          // Validate that int(s) are non-negative.
+          if (fieldType.typeName == 'int') {
+            if (!fieldType.isList) {
+              out('assert(_value == null || _value >= 0);');
+            } else {
+              out('assert(_value == null || _value.every((e) => e >= 0));');
+            }
+          }
+          // Set the value.
           out('$stateFieldName = _value;');
         });
         out('}');
       }
+      // Generate constructor.
+      out();
+      out('$builderName({${constructorParams.join(', ')}})');
+      for (int i = 0; i < cls.fields.length; i++) {
+        idlModel.FieldDeclaration field = cls.fields[i];
+        String prefix = i == 0 ? '  : ' : '    ';
+        String suffix = i == cls.fields.length - 1 ? ';' : ',';
+        out('${prefix}_${field.name} = ${field.name}$suffix');
+      }
       // Generate finish.
       if (cls.isTopLevel) {
         out();
@@ -362,8 +396,16 @@
               String itemCode = 'b.finish(fbBuilder)';
               String listCode = '$valueName.map((b) => $itemCode).toList()';
               writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+            } else if (_idl.enums.containsKey(fieldType.typeName)) {
+              String itemCode = 'b.index';
+              String listCode = '$valueName.map((b) => $itemCode).toList()';
+              writeCode = '$offsetName = fbBuilder.writeListUint32($listCode);';
             } else if (fieldType.typeName == 'int') {
-              writeCode = '$offsetName = fbBuilder.writeListInt32($valueName);';
+              writeCode =
+                  '$offsetName = fbBuilder.writeListUint32($valueName);';
+            } else if (fieldType.typeName == 'double') {
+              writeCode =
+                  '$offsetName = fbBuilder.writeListFloat64($valueName);';
             } else {
               assert(fieldType.typeName == 'String');
               String itemCode = 'fbBuilder.writeString(b)';
@@ -404,11 +446,11 @@
             condition = '$valueName == true';
             writeCode = 'fbBuilder.addBool($index, true);';
           } else if (fieldType.typeName == 'int') {
-            condition += ' && $valueName != ${defaultValue(fieldType)}';
-            writeCode = 'fbBuilder.addInt32($index, $valueName);';
+            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+            writeCode = 'fbBuilder.addUint32($index, $valueName);';
           } else if (_idl.enums.containsKey(fieldType.typeName)) {
-            condition += ' && $valueName != ${defaultValue(fieldType)}';
-            writeCode = 'fbBuilder.addInt32($index, $valueName.index);';
+            condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+            writeCode = 'fbBuilder.addUint32($index, $valueName.index);';
           }
           if (writeCode == null) {
             throw new UnimplementedError('Writing type ${fieldType.typeName}');
@@ -424,21 +466,43 @@
       out('}');
     });
     out('}');
-    return builderParams;
   }
 
-  void _generateEncodeFunction(
-      idlModel.ClassDeclaration cls, List<String> builderParams) {
-    String className = cls.name;
-    String builderName = className + 'Builder';
-    out('$builderName encode$className({${builderParams.join(', ')}}) {');
+  void _generateEnum(idlModel.EnumDeclaration enm) {
+    String name = enm.name;
+    outDoc(enm.documentation);
+    out('enum $name {');
     indent(() {
-      out('$builderName builder = new $builderName();');
-      for (idlModel.FieldDeclaration field in cls.fields) {
-        String fieldName = field.name;
-        out('builder.$fieldName = $fieldName;');
+      for (idlModel.EnumValueDeclaration value in enm.values) {
+        outDoc(value.documentation);
+        if (enm.values.last == value) {
+          out('${value.name}');
+        } else {
+          out('${value.name},');
+          out();
+        }
       }
-      out('return builder;');
+    });
+    out('}');
+  }
+
+  void _generateEnumReader(idlModel.EnumDeclaration enm) {
+    String name = enm.name;
+    String readerName = '_${name}Reader';
+    out('class $readerName extends fb.Reader<$name> {');
+    indent(() {
+      out('const $readerName() : super();');
+      out();
+      out('@override');
+      out('int get size => 4;');
+      out();
+      out('@override');
+      out('$name read(fb.BufferPointer bp) {');
+      indent(() {
+        out('int index = const fb.Uint32Reader().read(bp);');
+        out('return $name.values[index];');
+      });
+      out('}');
     });
     out('}');
   }
@@ -446,7 +510,8 @@
   void _generateImpl(idlModel.ClassDeclaration cls) {
     String name = cls.name;
     String implName = '_${name}Impl';
-    out('class $implName implements $name {');
+    String mixinName = '_${name}Mixin';
+    out('class $implName extends Object with $mixinName implements $name {');
     indent(() {
       out('final fb.BufferPointer _bp;');
       out();
@@ -458,59 +523,50 @@
         String fieldName = field.name;
         out('$returnType _$fieldName;');
       }
-      out();
-      // Write toMap().
-      out('@override');
-      out('Map<String, Object> toMap() => {');
-      indent(() {
-        for (idlModel.FieldDeclaration field in cls.fields) {
-          String fieldName = field.name;
-          out('${quoted(fieldName)}: $fieldName,');
-        }
-      });
-      out('};');
       // Write getters.
       cls.fields.asMap().forEach((index, field) {
         String fieldName = field.name;
         idlModel.FieldType type = field.type;
         String typeName = type.typeName;
-        // Prepare "readExpr" or "readCode" + "def"
-        String readExpr;
+        // Prepare "readCode" + "def"
         String readCode;
-        String def = defaultValue(type);
+        String def = defaultValue(type, false);
         if (type.isList) {
           if (typeName == 'int') {
-            String itemCode = 'const fb.Int32Reader()';
+            String itemCode = 'const fb.Uint32Reader()';
             readCode = 'const fb.ListReader<int>($itemCode)';
+          } else if (typeName == 'double') {
+            readCode = 'const fb.Float64ListReader()';
           } else if (typeName == 'String') {
             String itemCode = 'const fb.StringReader()';
             readCode = 'const fb.ListReader<String>($itemCode)';
-          } else {
+          } else if (_idl.classes.containsKey(typeName)) {
             String itemCode = '$typeName>(const _${typeName}Reader()';
             readCode = 'const fb.ListReader<$itemCode)';
+          } else {
+            assert(_idl.enums.containsKey(typeName));
+            String itemCode = 'const _${typeName}Reader()';
+            readCode = 'const fb.ListReader<$typeName>($itemCode)';
           }
         } else if (typeName == 'bool') {
           readCode = 'const fb.BoolReader()';
         } else if (typeName == 'int') {
-          readCode = 'const fb.Int32Reader()';
+          readCode = 'const fb.Uint32Reader()';
         } else if (typeName == 'String') {
           readCode = 'const fb.StringReader()';
         } else if (_idl.enums.containsKey(typeName)) {
-          readExpr =
-              '$typeName.values[const fb.Int32Reader().vTableGet(_bp, $index, 0)]';
+          readCode = 'const _${typeName}Reader()';
         } else if (_idl.classes.containsKey(typeName)) {
           readCode = 'const _${typeName}Reader()';
         }
-        if (readExpr == null) {
-          assert(readCode != null);
-          readExpr = '$readCode.vTableGet(_bp, $index, $def)';
-        }
+        assert(readCode != null);
         // Write the getter implementation.
         out();
         out('@override');
         String returnType = dartType(type);
         out('$returnType get $fieldName {');
         indent(() {
+          String readExpr = '$readCode.vTableGet(_bp, $index, $def)';
           out('_$fieldName ??= $readExpr;');
           out('return _$fieldName;');
         });
@@ -544,6 +600,25 @@
     out('}');
   }
 
+  void _generateMixin(idlModel.ClassDeclaration cls) {
+    String name = cls.name;
+    String mixinName = '_${name}Mixin';
+    out('abstract class $mixinName implements $name {');
+    indent(() {
+      // Write toMap().
+      out('@override');
+      out('Map<String, Object> toMap() => {');
+      indent(() {
+        for (idlModel.FieldDeclaration field in cls.fields) {
+          String fieldName = field.name;
+          out('${quoted(fieldName)}: $fieldName,');
+        }
+      });
+      out('};');
+    });
+    out('}');
+  }
+
   void _generateReader(idlModel.ClassDeclaration cls) {
     String name = cls.name;
     String readerName = '_${name}Reader';
diff --git a/pkg/analyzer/tool/summary/idl.dart b/pkg/analyzer/tool/summary/idl.dart
index 39e7a4a..cb2ee1d 100644
--- a/pkg/analyzer/tool/summary/idl.dart
+++ b/pkg/analyzer/tool/summary/idl.dart
@@ -10,26 +10,30 @@
  * The code generation process introduces the following non-typical semantics:
  * - Fields of type List are never null, and have a default value of the empty
  *   list.
- * - Fields of type int are never null, and have a default value of zero.
+ * - Fields of type int are unsigned 32-bit integers, never null, and have a
+ *   default value of zero.
  * - Fields of type String are never null, and have a default value of ''.
  * - Fields of type bool are never null, and have a default value of false.
  * - Fields whose type is an enum are never null, and have a default value of
  *   the first value declared in the enum.
  *
  * Terminology used in this document:
- * - "Unlinked" refers to information that can be determined from reading the
- *   .dart file for the library itself (including all parts) and no other
- *   files.
- * - "Prelinked" refers to information that can be determined from reading the
- *   unlinked information for the library itself and the unlinked information
- *   for all direct imports (plus the transitive closure of exports reachable
- *   from those direct imports).
- * - "Linked" refers to information that can be determined only from reading
- *   the unlinked and prelinked information for the library itself and the
- *   transitive closure of its imports.
+ * - "Unlinked" refers to information that can be determined from reading a
+ *   single .dart file in isolation.
+ * - "Prelinked" refers to information that can be determined from the defining
+ *   compilation unit of a library, plus direct imports, plus the transitive
+ *   closure of exports reachable from those libraries, plus all part files
+ *   constituting those libraries.
+ * - "Linked" refers to all other information; in theory, this information may
+ *   depend on all files in the transitive import/export closure.  However, in
+ *   practice we expect that the number of additional dependencies will usually
+ *   be small, since the additional dependencies only need to be consulted for
+ *   type propagation, type inference, and constant evaluation, which typically
+ *   have short dependency chains.
  *
- * TODO(paulberry): currently the summary format only contains unlinked and
- * prelinked information.
+ * Since we expect "linked" and "prelinked" dependencies to be similar, we only
+ * rarely distinguish between them; most information is that is not "unlinked"
+ * is typically considered "linked" for simplicity.
  *
  * Except as otherwise noted, synthetic elements are not stored in the summary;
  * they are re-synthesized at the time the summary is read.
@@ -63,10 +67,59 @@
 const topLevel = null;
 
 /**
+ * Summary information about a reference to a an entity such as a type, top
+ * level executable, or executable within a class.
+ */
+class EntityRef {
+  /**
+   * If this [EntityRef] is contained within [LinkedUnit.types], slot id (which
+   * is unique within the compilation unit) identifying the target of type
+   * propagation or type inference with which this [EntityRef] is associated.
+   *
+   * Otherwise zero.
+   */
+  int slot;
+
+  /**
+   * Index into [UnlinkedUnit.references] for the entity being referred to, or
+   * zero if this is a reference to a type parameter.
+   */
+  int reference;
+
+  /**
+   * If this is a reference to a type parameter, one-based index into the list
+   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
+   * Bruijn index conventions; that is, innermost parameters come first, and
+   * if a class or method has multiple parameters, they are indexed from right
+   * to left.  So for instance, if the enclosing declaration is
+   *
+   *     class C<T,U> {
+   *       m<V,W> {
+   *         ...
+   *       }
+   *     }
+   *
+   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
+   * respectively.
+   *
+   * If the type being referred to is not a type parameter, [paramReference] is
+   * zero.
+   */
+  int paramReference;
+
+  /**
+   * If this is an instantiation of a generic type or generic executable, the
+   * type arguments used to instantiate it.  Trailing type arguments of type
+   * `dynamic` are omitted.
+   */
+  List<EntityRef> typeArguments;
+}
+
+/**
  * Information about a dependency that exists between one library and another
  * due to an "import" declaration.
  */
-class PrelinkedDependency {
+class LinkedDependency {
   /**
    * The relative URI of the dependent library.  This URI is relative to the
    * importing library, even if there are intervening `export` declarations.
@@ -84,58 +137,109 @@
 }
 
 /**
- * Pre-linked summary of a library.
+ * Information about a single name in the export namespace of the library that
+ * is not in the public namespace.
+ */
+class LinkedExportName {
+  /**
+   * Name of the exported entity.  TODO(paulberry): do we include the trailing
+   * '=' for a setter?
+   */
+  String name;
+
+  /**
+   * Index into [LinkedLibrary.dependencies] for the library in which the
+   * entity is defined.
+   */
+  int dependency;
+
+  /**
+   * Integer index indicating which unit in the exported library contains the
+   * definition of the entity.  As with indices into [LinkedLibrary.units],
+   * zero represents the defining compilation unit, and nonzero values
+   * represent parts in the order of the corresponding `part` declarations.
+   */
+  int unit;
+
+  /**
+   * The kind of the entity being referred to.
+   */
+  ReferenceKind kind;
+}
+
+/**
+ * Linked summary of a library.
  */
 @topLevel
-class PrelinkedLibrary {
+class LinkedLibrary {
   /**
-   * The pre-linked summary of all the compilation units constituting the
+   * The linked summary of all the compilation units constituting the
    * library.  The summary of the defining compilation unit is listed first,
    * followed by the summary of each part, in the order of the `part`
    * declarations in the defining compilation unit.
    */
-  List<PrelinkedUnit> units;
+  List<LinkedUnit> units;
 
   /**
    * The libraries that this library depends on (either via an explicit import
    * statement or via the implicit dependencies on `dart:core` and
    * `dart:async`).  The first element of this array is a pseudo-dependency
-   * representing the library itself (it is also used for "dynamic").
+   * representing the library itself (it is also used for `dynamic` and
+   * `void`).  This is followed by elements representing "prelinked"
+   * dependencies (direct imports and the transitive closure of exports).
+   * After the prelinked dependencies are elements representing "linked"
+   * dependencies.
    *
-   * TODO(paulberry): consider removing this entirely and just using
-   * [UnlinkedLibrary.imports].
+   * A library is only included as a "linked" dependency if it is a true
+   * dependency (e.g. a propagated or inferred type or constant value
+   * implicitly refers to an element declared in the library) or
+   * anti-dependency (e.g. the result of type propagation or type inference
+   * depends on the lack of a certain declaration in the library).
    */
-  List<PrelinkedDependency> dependencies;
+  List<LinkedDependency> dependencies;
 
   /**
    * For each import in [UnlinkedUnit.imports], an index into [dependencies]
    * of the library being imported.
-   *
-   * TODO(paulberry): if [dependencies] is removed, this can be removed as
-   * well, since there will effectively be a one-to-one mapping.
    */
   List<int> importDependencies;
+
+  /**
+   * Information about entities in the export namespace of the library that are
+   * not in the public namespace of the library (that is, entities that are
+   * brought into the namespace via `export` directives).
+   *
+   * Sorted by name.
+   */
+  List<LinkedExportName> exportNames;
+
+  /**
+   * The number of elements in [dependencies] which are not "linked"
+   * dependencies (that is, the number of libraries in the direct imports plus
+   * the transitive closure of exports, plus the library itself).
+   */
+  int numPrelinkedDependencies;
 }
 
 /**
  * Information about the resolution of an [UnlinkedReference].
  */
-class PrelinkedReference {
+class LinkedReference {
   /**
-   * Index into [PrelinkedLibrary.dependencies] indicating which imported library
+   * Index into [LinkedLibrary.dependencies] indicating which imported library
    * declares the entity being referred to.
    */
   int dependency;
 
   /**
-   * The kind of the entity being referred to.  For the pseudo-type `dynamic`,
-   * the kind is [PrelinkedReferenceKind.classOrEnum].
+   * The kind of the entity being referred to.  For the pseudo-types `dynamic`
+   * and `void`, the kind is [ReferenceKind.classOrEnum].
    */
-  PrelinkedReferenceKind kind;
+  ReferenceKind kind;
 
   /**
    * Integer index indicating which unit in the imported library contains the
-   * definition of the entity.  As with indices into [PrelinkedLibrary.units],
+   * definition of the entity.  As with indices into [LinkedLibrary.units],
    * zero represents the defining compilation unit, and nonzero values
    * represent parts in the order of the corresponding `part` declarations.
    */
@@ -146,27 +250,80 @@
    * it accepts.  Otherwise zero.
    */
   int numTypeParameters;
+
+  /**
+   * 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".
+   */
+  String name;
+}
+
+/**
+ * Linked summary of a compilation unit.
+ */
+class LinkedUnit {
+  /**
+   * Information about the resolution of references within the compilation
+   * unit.  Each element of [UnlinkedUnit.references] has a corresponding
+   * element in this list (at the same index).  If this list has additional
+   * elements beyond the number of elements in [UnlinkedUnit.references], those
+   * additional elements are references that are only referred to implicitly
+   * (e.g. elements involved in inferred or propagated types).
+   */
+  List<LinkedReference> references;
+
+  /**
+   * List associating slot ids found inside the unlinked summary for the
+   * compilation unit with propagated and inferred types.
+   */
+  List<EntityRef> types;
 }
 
 /**
  * Enum used to indicate the kind of entity referred to by a
- * [PrelinkedReference].
+ * [LinkedReference].
  */
-enum PrelinkedReferenceKind {
+enum ReferenceKind {
   /**
    * The entity is a class or enum.
    */
   classOrEnum,
 
   /**
+   * The entity is a constructor.
+   */
+  constructor,
+
+  /**
+   * The entity is a static const field.
+   */
+  constField,
+
+  /**
+   * The entity is a static method.
+   */
+  staticMethod,
+
+  /**
+   * The `length` property access.
+   */
+  length,
+
+  /**
    * The entity is a typedef.
    */
   typedef,
 
   /**
-   * The entity is a variable or executable.
+   * The entity is a top level function.
    */
-  other,
+  topLevelFunction,
+
+  /**
+   * The entity is a top level getter or setter.
+   */
+  topLevelPropertyAccessor,
 
   /**
    * The entity is a prefix.
@@ -180,30 +337,19 @@
 }
 
 /**
- * Pre-linked summary of a compilation unit.
- */
-class PrelinkedUnit {
-  /**
-   * For each reference in [UnlinkedUnit.references], information about how
-   * that reference is resolved.
-   */
-  List<PrelinkedReference> references;
-}
-
-/**
  * Information about SDK.
  */
 @topLevel
 class SdkBundle {
   /**
-   * The list of URIs of items in [prelinkedLibraries], e.g. `dart:core`.
+   * The list of URIs of items in [linkedLibraries], e.g. `dart:core`.
    */
-  List<String> prelinkedLibraryUris;
+  List<String> linkedLibraryUris;
 
   /**
-   * Pre-linked libraries.
+   * Linked libraries.
    */
-  List<PrelinkedLibrary> prelinkedLibraries;
+  List<LinkedLibrary> linkedLibraries;
 
   /**
    * The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
@@ -248,17 +394,17 @@
    * explicitly declare a supertype (and hence has supertype `Object`), or (b)
    * the class *is* `Object` (and hence has no supertype).
    */
-  UnlinkedTypeRef supertype;
+  EntityRef supertype;
 
   /**
    * Mixins appearing in a `with` clause, if any.
    */
-  List<UnlinkedTypeRef> mixins;
+  List<EntityRef> mixins;
 
   /**
    * Interfaces appearing in an `implements` clause, if any.
    */
-  List<UnlinkedTypeRef> interfaces;
+  List<EntityRef> interfaces;
 
   /**
    * Field declarations contained in the class.
@@ -304,6 +450,336 @@
 }
 
 /**
+ * Unlinked summary information about a compile-time constant expression, or a
+ * potentially constant expression.
+ *
+ * Constant expressions are represented using a simple stack-based language
+ * where [operations] is a sequence of operations to execute starting with an
+ * empty stack.  Once all operations have been executed, the stack should
+ * contain a single value which is the value of the constant.  Note that some
+ * operations consume additional data from the other fields of this class.
+ */
+class UnlinkedConst {
+  /**
+   * Sequence of operations to execute (starting with an empty stack) to form
+   * the constant value.
+   */
+  List<UnlinkedConstOperation> operations;
+
+  /**
+   * Sequence of unsigned 32-bit integers consumed by the operations
+   * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
+   * `makeList`, and `makeMap`.
+   */
+  List<int> ints;
+
+  /**
+   * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
+   */
+  List<double> doubles;
+
+  /**
+   * Sequence of strings consumed by the operations `pushString` and
+   * `invokeConstructor`.
+   */
+  List<String> strings;
+
+  /**
+   * Sequence of language constructs consumed by the operations
+   * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`.  Note
+   * that in the case of `pushReference` (and sometimes `invokeConstructor` the
+   * actual entity being referred to may be something other than a type.
+   */
+  List<EntityRef> references;
+}
+
+/**
+ * Enum representing the various kinds of operations which may be performed to
+ * produce a constant value.  These options are assumed to execute in the
+ * context of a stack which is initially empty.
+ */
+enum UnlinkedConstOperation {
+  /**
+   * Push the value of the n-th constructor argument (where n is obtained from
+   * [UnlinkedConst.ints]) onto the stack.
+   */
+  pushArgument,
+
+  /**
+   * Push the next value from [UnlinkedConst.ints] (a 32-bit unsigned integer)
+   * onto the stack.
+   *
+   * Note that Dart supports integers larger than 32 bits; these are
+   * represented by composing 32 bit values using the [shiftOr] operation.
+   */
+  pushInt,
+
+  /**
+   * Pop the top value off the stack, which should be an integer.  Multiply it
+   * by 2^32, "or" in the next value from [UnlinkedConst.ints] (which is
+   * interpreted as a 32-bit unsigned integer), and push the result back onto
+   * the stack.
+   */
+  shiftOr,
+
+  /**
+   * Push the next value from [UnlinkedConst.doubles] (a double precision
+   * floating point value) onto the stack.
+   */
+  pushDouble,
+
+  /**
+   * Push the constant `true` onto the stack.
+   */
+  pushTrue,
+
+  /**
+   * Push the constant `false` onto the stack.
+   */
+  pushFalse,
+
+  /**
+   * Push the next value from [UnlinkedConst.strings] onto the stack.
+   */
+  pushString,
+
+  /**
+   * Pop the top n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), convert them to strings (if they aren't already),
+   * concatenate them into a single string, and push it back onto the stack.
+   *
+   * This operation is used to represent constants whose value is a literal
+   * string containing string interpolations.
+   */
+  concatenate,
+
+  /**
+   * Pop the top value from the stack which should be string, convert it to
+   * a symbol, and push it back onto the stack.
+   */
+  makeSymbol,
+
+  /**
+   * Push the constant `null` onto the stack.
+   */
+  pushNull,
+
+  /**
+   * Evaluate a (potentially qualified) identifier expression and push the
+   * resulting value onto the stack.  The identifier to be evaluated is
+   * obtained from [UnlinkedConst.references].
+   *
+   * This operation is used to represent the following kinds of constants
+   * (which are indistinguishable from an unresolved AST alone):
+   *
+   * - A qualified reference to a static constant variable (e.g. `C.v`, where
+   *   C is a class and `v` is a constant static variable in `C`).
+   * - An identifier expression referring to a constant variable.
+   * - A simple or qualified identifier denoting a class or type alias.
+   * - A simple or qualified identifier denoting a top-level function or a
+   *   static method.
+   */
+  pushReference,
+
+  /**
+   * Pop the top `n` values from the stack (where `n` is obtained from
+   * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
+   * `n` values from [UnlinkedConst.strings] and use the lists of names and
+   * values to create named arguments.  Then pop the top `m` values from the
+   * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
+   * from the end) and use them as positional arguments.  Use the lists of
+   * positional and names arguments to invoke a constant constructor obtained
+   * from [UnlinkedConst.references], and push the resulting value back onto the
+   * stack.
+   *
+   * Note that for an invocation of the form `const a.b(...)` (where no type
+   * arguments are specified), it is impossible to tell from the unresolved AST
+   * alone whether `a` is a class name and `b` is a constructor name, or `a` is
+   * a prefix name and `b` is a class name.  For consistency between AST based
+   * and elements based summaries, references to default constructors are always
+   * recorded as references to corresponding classes.
+   */
+  invokeConstructor,
+
+  /**
+   * Pop the top n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), place them in a [List], and push the result back
+   * onto the stack.  The type parameter for the [List] is implicitly `dynamic`.
+   */
+  makeUntypedList,
+
+  /**
+   * Pop the top 2*n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
+   * [Map], and push the result back onto the stack.  The two type parameters
+   * for the [Map] are implicitly `dynamic`.
+   */
+  makeUntypedMap,
+
+  /**
+   * Pop the top n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), place them in a [List], and push the result back
+   * onto the stack.  The type parameter for the [List] is obtained from
+   * [UnlinkedConst.references].
+   */
+  makeTypedList,
+
+  /**
+   * Pop the top 2*n values from the stack (where n is obtained from
+   * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
+   * [Map], and push the result back onto the stack.  The two type parameters for
+   * the [Map] are obtained from [UnlinkedConst.references].
+   */
+  makeTypedMap,
+
+  /**
+   * Pop the top 2 values from the stack, pass them to the predefined Dart
+   * function `identical`, and push the result back onto the stack.
+   */
+  identical,
+
+  /**
+   * Pop the top 2 values from the stack, evaluate `v1 == v2`, and push the
+   * result back onto the stack.
+   *
+   * This is also used to represent `v1 != v2`, by composition with [not].
+   */
+  equal,
+
+  /**
+   * Pop the top value from the stack, compute its boolean negation, and push
+   * the result back onto the stack.
+   */
+  not,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 && v2`, and push the
+   * result back onto the stack.
+   */
+  and,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 || v2`, and push the
+   * result back onto the stack.
+   */
+  or,
+
+  /**
+   * Pop the top value from the stack, compute its integer complement, and push
+   * the result back onto the stack.
+   */
+  complement,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 ^ v2`, and push the
+   * result back onto the stack.
+   */
+  bitXor,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 & v2`, and push the
+   * result back onto the stack.
+   */
+  bitAnd,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 | v2`, and push the
+   * result back onto the stack.
+   */
+  bitOr,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 >> v2`, and push the
+   * result back onto the stack.
+   */
+  bitShiftRight,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 << v2`, and push the
+   * result back onto the stack.
+   */
+  bitShiftLeft,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 + v2`, and push the
+   * result back onto the stack.
+   */
+  add,
+
+  /**
+   * Pop the top value from the stack, compute its integer negation, and push
+   * the result back onto the stack.
+   */
+  negate,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 - v2`, and push the
+   * result back onto the stack.
+   */
+  subtract,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 * v2`, and push the
+   * result back onto the stack.
+   */
+  multiply,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 / v2`, and push the
+   * result back onto the stack.
+   */
+  divide,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 ~/ v2`, and push the
+   * result back onto the stack.
+   */
+  floorDivide,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 > v2`, and push the
+   * result back onto the stack.
+   */
+  greater,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 < v2`, and push the
+   * result back onto the stack.
+   */
+  less,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 >= v2`, and push the
+   * result back onto the stack.
+   */
+  greaterEqual,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 <= v2`, and push the
+   * result back onto the stack.
+   */
+  lessEqual,
+
+  /**
+   * Pop the top 2 values from the stack, compute `v1 % v2`, and push the
+   * result back onto the stack.
+   */
+  modulo,
+
+  /**
+   * Pop the top 3 values from the stack, compute `v1 ? v2 : v3`, and push the
+   * result back onto the stack.
+   */
+  conditional,
+
+  /**
+   * Pop the top value from the stack, evaluate `v.length`, and push the result
+   * back onto the stack.
+   */
+  length,
+}
+
+/**
  * Unlinked summary information about a documentation comment.
  */
 class UnlinkedDocumentationComment {
@@ -414,11 +890,10 @@
   List<UnlinkedTypeParam> typeParameters;
 
   /**
-   * Declared return type of the executable.  Absent if the return type is
-   * `void` or the executable is a constructor.  Note that when strong mode is
-   * enabled, the actual return type may be different due to type inference.
+   * Declared return type of the executable.  Absent if the executable is a
+   * constructor or the return type is implicit.
    */
-  UnlinkedTypeRef returnType;
+  EntityRef returnType;
 
   /**
    * Parameters of the executable, if any.  Note that getters have no
@@ -458,15 +933,18 @@
   bool isFactory;
 
   /**
-   * Indicates whether the executable lacks an explicit return type
-   * declaration.  False for constructors and setters.
-   */
-  bool hasImplicitReturnType;
-
-  /**
    * Indicates whether the executable is declared using the `external` keyword.
    */
   bool isExternal;
+
+  /**
+   * If this executable's return type is inferrable, nonzero slot id
+   * identifying which entry in [LinkedLibrary.types] contains the inferred
+   * return type.  If there is no matching entry in [LinkedLibrary.types], then
+   * no return type was inferred for this variable, so its static type is
+   * `dynamic`.
+   */
+  int inferredReturnTypeSlot;
 }
 
 /**
@@ -614,12 +1092,10 @@
 
   /**
    * If [isFunctionTyped] is `true`, the declared return type.  If
-   * [isFunctionTyped] is `false`, the declared type.  Absent if
-   * [isFunctionTyped] is `true` and the declared return type is `void`.  Note
-   * that when strong mode is enabled, the actual type may be different due to
-   * type inference.
+   * [isFunctionTyped] is `false`, the declared type.  Absent if the type is
+   * implicit.
    */
-  UnlinkedTypeRef type;
+  EntityRef type;
 
   /**
    * If [isFunctionTyped] is `true`, the parameters of the function type.
@@ -643,10 +1119,17 @@
   bool isInitializingFormal;
 
   /**
-   * Indicates whether this parameter lacks an explicit type declaration.
-   * Always false for a function-typed parameter.
+   * If this parameter's type is inferrable, 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
+   * this variable, so its static type is `dynamic`.
+   *
+   * Note that although strong mode considers initializing formals to be
+   * inferrable, they are not marked as such in the summary; if their type is
+   * not specified, they always inherit the static type of the corresponding
+   * field.
    */
-  bool hasImplicitType;
+  int inferredTypeSlot;
 }
 
 /**
@@ -692,12 +1175,6 @@
  * Unlinked summary information about a specific name contributed by a
  * compilation unit to a library's public namespace.
  *
- * TODO(paulberry): add a count of generic parameters, so that resynthesis
- * doesn't have to peek into the library to obtain this info.
- *
- * TODO(paulberry): for classes, add info about static members and
- * constructors, since this will be needed to prelink info about constants.
- *
  * TODO(paulberry): some of this information is redundant with information
  * elsewhere in the summary.  Consider reducing the redundancy to reduce
  * summary size.
@@ -711,13 +1188,20 @@
   /**
    * The kind of object referred to by the name.
    */
-  PrelinkedReferenceKind kind;
+  ReferenceKind kind;
 
   /**
    * If the entity being referred to is generic, the number of type parameters
    * it accepts.  Otherwise zero.
    */
   int numTypeParameters;
+
+  /**
+   * If this [UnlinkedPublicName] is a class, the list of members which can be
+   * referenced from constants - static constant fields, static methods, and
+   * constructors.  Otherwise empty.
+   */
+  List<UnlinkedPublicName> constMembers;
 }
 
 /**
@@ -752,8 +1236,8 @@
  */
 class UnlinkedReference {
   /**
-   * Name of the entity being referred to.  The empty string refers to the
-   * pseudo-type `dynamic`.
+   * 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".
    */
   String name;
 
@@ -796,9 +1280,9 @@
   List<UnlinkedTypeParam> typeParameters;
 
   /**
-   * Return type of the typedef.  Absent if the return type is `void`.
+   * Return type of the typedef.
    */
-  UnlinkedTypeRef returnType;
+  EntityRef returnType;
 
   /**
    * Parameters of the executable, if any.
@@ -825,51 +1309,7 @@
    * Bound of the type parameter, if a bound is explicitly declared.  Otherwise
    * null.
    */
-  UnlinkedTypeRef bound;
-}
-
-/**
- * Unlinked summary information about a reference to a type.
- */
-class UnlinkedTypeRef {
-  /**
-   * Index into [UnlinkedUnit.references] for the type being referred to, or
-   * zero if this is a reference to a type parameter.
-   *
-   * Note that since zero is also a valid index into
-   * [UnlinkedUnit.references], we cannot distinguish between references to
-   * type parameters and references to types by checking [reference] against
-   * zero.  To distinguish between references to type parameters and references
-   * to types, check whether [paramReference] is zero.
-   */
-  int reference;
-
-  /**
-   * If this is a reference to a type parameter, one-based index into the list
-   * of [UnlinkedTypeParam]s currently in effect.  Indexing is done using De
-   * Bruijn index conventions; that is, innermost parameters come first, and
-   * if a class or method has multiple parameters, they are indexed from right
-   * to left.  So for instance, if the enclosing declaration is
-   *
-   *     class C<T,U> {
-   *       m<V,W> {
-   *         ...
-   *       }
-   *     }
-   *
-   * Then [paramReference] values of 1, 2, 3, and 4 represent W, V, U, and T,
-   * respectively.
-   *
-   * If the type being referred to is not a type parameter, [paramReference] is
-   * zero.
-   */
-  int paramReference;
-
-  /**
-   * If this is an instantiation of a generic type, the type arguments used to
-   * instantiate it.  Trailing type arguments of type `dynamic` are omitted.
-   */
-  List<UnlinkedTypeRef> typeArguments;
+  EntityRef bound;
 }
 
 /**
@@ -910,8 +1350,10 @@
 
   /**
    * Top level and prefixed names referred to by this compilation unit.  The
-   * zeroth element of this array is always populated and always represents a
-   * reference to the pseudo-type "dynamic".
+   * zeroth element of this array is always populated and is used to represent
+   * the absence of a reference in places where a reference is optional (for
+   * example [UnlinkedReference.prefixReference or
+   * UnlinkedImport.prefixReference]).
    */
   List<UnlinkedReference> references;
 
@@ -981,10 +1423,15 @@
   UnlinkedDocumentationComment documentationComment;
 
   /**
-   * Declared type of the variable.  Note that when strong mode is enabled, the
-   * actual type of the variable may be different due to type inference.
+   * Declared type of the variable.  Absent if the type is implicit.
    */
-  UnlinkedTypeRef type;
+  EntityRef type;
+
+  /**
+   * If [isConst] is true, and the variable has an initializer, the constant
+   * expression in the initializer.
+   */
+  UnlinkedConst constExpr;
 
   /**
    * Indicates whether the variable is declared using the `static` keyword.
@@ -1006,7 +1453,20 @@
   bool isConst;
 
   /**
-   * Indicates whether this variable lacks an explicit type declaration.
+   * If this variable is propagable, nonzero slot id identifying which entry in
+   * [LinkedLibrary.types] contains the propagated type for this variable.  If
+   * there is no matching entry in [LinkedLibrary.types], then this variable's
+   * propagated type is the same as its declared type.
+   *
+   * Non-propagable variables have a [propagatedTypeSlot] of zero.
    */
-  bool hasImplicitType;
+  int propagatedTypeSlot;
+
+  /**
+   * If this variable is inferrable, nonzero slot id identifying which entry in
+   * [LinkedLibrary.types] contains the inferred type for this variable.  If
+   * there is no matching entry in [LinkedLibrary.types], then no type was
+   * inferred for this variable, so its static type is `dynamic`.
+   */
+  int inferredTypeSlot;
 }
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index 07be039..9317215 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -51,13 +51,21 @@
   /**
    * List of enumerated values.
    */
-  final List<String> values = <String>[];
+  final List<EnumValueDeclaration> values = <EnumValueDeclaration>[];
 
   EnumDeclaration(String documentation, String name)
       : super(documentation, name);
 }
 
 /**
+ * Information about a single enum value defined in the IDL.
+ */
+class EnumValueDeclaration extends Declaration {
+  EnumValueDeclaration(String documentation, String name)
+      : super(documentation, name);
+}
+
+/**
  * Information about a single class field defined in the IDL.
  */
 class FieldDeclaration extends Declaration {
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 0b6ae40..19b7af4 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
+import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/source/package_map_provider.dart';
 import 'package:analyzer/source/package_map_resolver.dart';
 import 'package:analyzer/source/pub_package_map_provider.dart';
@@ -302,7 +303,8 @@
   /// Decide on the appropriate method for resolving URIs based on the given
   /// [options] and [customUrlMappings] settings, and return a
   /// [SourceFactory] that has been configured accordingly.
-  SourceFactory _chooseUriResolutionPolicy(CommandLineOptions options) {
+  SourceFactory _chooseUriResolutionPolicy(
+      CommandLineOptions options, EmbedderYamlLocator yamlLocator) {
     Packages packages;
     Map<String, List<fileSystem.Folder>> packageMap;
     UriResolver packageUriResolver;
@@ -356,9 +358,24 @@
     }
 
     // Now, build our resolver list.
+    List<UriResolver> resolvers = [];
 
     // 'dart:' URIs come first.
-    List<UriResolver> resolvers = [new DartUriResolver(sdk)];
+
+    // Setup embedding.
+    yamlLocator.refresh(packageMap);
+
+    EmbedderUriResolver embedderUriResolver =
+        new EmbedderUriResolver(yamlLocator.embedderYamls);
+    if (embedderUriResolver.length == 0) {
+      // The embedder uri resolver has no mappings. Use the default Dart SDK
+      // uri resolver.
+      resolvers.add(new DartUriResolver(sdk));
+    } else {
+      // The embedder uri resolver has mappings, use it instead of the default
+      // Dart SDK uri resolver.
+      resolvers.add(embedderUriResolver);
+    }
 
     // Next SdkExts.
     if (packageMap != null) {
@@ -401,13 +418,16 @@
       return;
     }
     _previousOptions = options;
+
+    // Create a context.
+    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
+
     // Choose a package resolution policy and a diet parsing policy based on
     // the command-line options.
-    SourceFactory sourceFactory = _chooseUriResolutionPolicy(options);
+    SourceFactory sourceFactory = _chooseUriResolutionPolicy(
+        options, (context as InternalAnalysisContext).embedderYamlLocator);
     AnalyzeFunctionBodiesPredicate dietParsingPolicy =
         _chooseDietParsingPolicy(options);
-    // Create a context using these policies.
-    AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
 
     context.sourceFactory = sourceFactory;
 
diff --git a/pkg/analyzer_cli/test/data/embedder_client/_packages b/pkg/analyzer_cli/test/data/embedder_client/_packages
new file mode 100644
index 0000000..03ed0f7
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/embedder_client/_packages
@@ -0,0 +1 @@
+package_with_embedder_yaml:../package_with_embedder_yaml/lib/
diff --git a/pkg/analyzer_cli/test/data/embedder_client/embedder_yaml_user.dart b/pkg/analyzer_cli/test/data/embedder_client/embedder_yaml_user.dart
new file mode 100644
index 0000000..2d88a2a
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/embedder_client/embedder_yaml_user.dart
@@ -0,0 +1,9 @@
+// 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.
+
+import 'dart:bear'; // Defined in package_with_embedder_yaml/lib/_embedder.yaml
+
+main() {
+  print(new Bear()); // Defined in 'dart:bear'
+}
diff --git a/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/_embedder.yaml b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/_embedder.yaml
new file mode 100644
index 0000000..5253771
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/_embedder.yaml
@@ -0,0 +1,4 @@
+embedder_libs:
+  "dart:bear": "grizzly.dart"
+  "dart:core": "core.dart"
+  "dart:async": "async.dart"
diff --git a/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/async.dart b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/async.dart
new file mode 100644
index 0000000..3b69a2a
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/async.dart
@@ -0,0 +1,9 @@
+// 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 dart.async;
+
+abstract class Future<T> {}
+
+abstract class Stream<T> {}
diff --git a/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/core.dart b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/core.dart
new file mode 100644
index 0000000..a7fa657
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/core.dart
@@ -0,0 +1,106 @@
+// 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 dart.core;
+
+class Object {
+  bool operator ==(other) => identical(this, other);
+  String toString() => 'a string';
+  int get hashCode => 0;
+}
+
+class Function {}
+
+class StackTrace {}
+
+class Symbol {}
+
+class Type {}
+
+abstract class Comparable<T> {
+  int compareTo(T other);
+}
+
+abstract class String implements Comparable<String> {
+  external factory String.fromCharCodes(Iterable<int> charCodes,
+      [int start = 0, int end]);
+  bool get isEmpty => false;
+  bool get isNotEmpty => false;
+  int get length => 0;
+  String toUpperCase();
+  List<int> get codeUnits;
+}
+
+class bool extends Object {}
+
+abstract class num implements Comparable<num> {
+  bool operator <(num other);
+  bool operator <=(num other);
+  bool operator >(num other);
+  bool operator >=(num other);
+  num operator +(num other);
+  num operator -(num other);
+  num operator *(num other);
+  num operator %(num other);
+  num operator /(num other);
+  int toInt();
+  num abs();
+  int round();
+}
+
+abstract class int extends num {
+  bool get isEven => false;
+  int operator -();
+  external static int parse(String source,
+      {int radix, int onError(String source)});
+}
+
+class double extends num {}
+
+class DateTime extends Object {}
+
+class Null extends Object {}
+
+class Deprecated extends Object {
+  final String expires;
+  const Deprecated(this.expires);
+}
+
+const Object deprecated = const Deprecated("next release");
+
+class Iterator<E> {
+  bool moveNext();
+  E get current;
+}
+
+abstract class Iterable<E> {
+  Iterator<E> get iterator;
+  bool get isEmpty;
+}
+
+abstract class List<E> implements Iterable<E> {
+  void add(E value);
+  E operator [](int index);
+  void operator []=(int index, E value);
+  Iterator<E> get iterator => null;
+  void clear();
+}
+
+abstract class Map<K, V> extends Object {
+  bool containsKey(Object key);
+  Iterable<K> get keys;
+}
+
+external bool identical(Object a, Object b);
+
+void print(Object object) {}
+
+class Uri {
+  static List<int> parseIPv6Address(String host, [int start = 0, int end]) {
+    int parseHex(int start, int end) {
+      return 0;
+    }
+    return null;
+  }
+}
diff --git a/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/grizzly.dart b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/grizzly.dart
new file mode 100644
index 0000000..d575643
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_with_embedder_yaml/lib/grizzly.dart
@@ -0,0 +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 grizzly;
+
+class Bear {}
diff --git a/pkg/analyzer_cli/test/embedder_test.dart b/pkg/analyzer_cli/test/embedder_test.dart
new file mode 100644
index 0000000..ded83fd
--- /dev/null
+++ b/pkg/analyzer_cli/test/embedder_test.dart
@@ -0,0 +1,64 @@
+// 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.
+
+import 'dart:io';
+
+import 'package:analyzer_cli/src/driver.dart' show Driver, errorSink, outSink;
+import 'package:path/path.dart' as path;
+import 'package:unittest/unittest.dart';
+
+import 'utils.dart';
+
+main() {
+  initializeTestEnvironment();
+
+  group('_embedder.yaml', () {
+    StringSink savedOutSink, savedErrorSink;
+    int savedExitCode;
+
+    setUp(() {
+      savedOutSink = outSink;
+      savedErrorSink = errorSink;
+      savedExitCode = exitCode;
+      outSink = new StringBuffer();
+      errorSink = new StringBuffer();
+    });
+    tearDown(() {
+      outSink = savedOutSink;
+      errorSink = savedErrorSink;
+      exitCode = savedExitCode;
+    });
+
+    test('resolution', wrap(() {
+      var testDir = path.join(testDirectory, 'data', 'embedder_client');
+      new Driver().start([
+        '--packages',
+        path.join(testDir, '_packages'),
+        path.join(testDir, 'embedder_yaml_user.dart')
+      ]);
+
+      expect(exitCode, 0);
+      expect(outSink.toString(), contains('No issues found'));
+    }));
+  });
+}
+
+/// Wrap a function call to dump stdout and stderr in case of an exception.
+Function wrap(Function f) {
+  return () {
+    try {
+      f();
+    } catch (e) {
+      if (outSink.toString().isNotEmpty) {
+        print('stdout:');
+        print(outSink);
+      }
+      if (errorSink.toString().isNotEmpty) {
+        print('stderr:');
+        print(errorSink);
+      }
+      throw e;
+    }
+  };
+}
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 8f81d15..e84777f 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -33,6 +33,14 @@
 const bool forceIncrementalSupport =
     const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT');
 
+/// For every 'dart:' library, a corresponding environment variable is set
+/// to "true". The environment variable's name is the concatenation of
+/// this prefix and the name (without the 'dart:'.
+///
+/// For example 'dart:html' has the environment variable 'dart.library.html' set
+/// to "true".
+const String dartLibraryEnvironmentPrefix = 'dart.library.';
+
 /// Locations of the platform descriptor files relative to the library root.
 const String _clientPlatform = "lib/dart_client.platform";
 const String _serverPlatform = "lib/dart_server.platform";
@@ -580,7 +588,26 @@
     }
   }
 
-  fromEnvironment(String name) => environment[name];
+  fromEnvironment(String name) {
+    assert(invariant(NO_LOCATION_SPANNABLE,
+        sdkLibraries != null, message: "setupSdk() has not been run"));
+
+    var result = environment[name];
+    if (result != null || environment.containsKey(name)) return result;
+    if (!name.startsWith(dartLibraryEnvironmentPrefix)) return null;
+
+    String libraryName = name.substring(dartLibraryEnvironmentPrefix.length);
+    if (sdkLibraries.containsKey(libraryName)) {
+      // Dart2js always "supports" importing 'dart:mirrors' but will abort
+      // the compilation at a later point if the backend doesn't support
+      // mirrors. In this case 'mirrors' should not be in the environment.
+      if (name == dartLibraryEnvironmentPrefix + 'mirrors') {
+        return backend.supportsReflection ? "true" : null;
+      }
+      return "true";
+    }
+    return null;
+  }
 
   Uri lookupLibraryUri(String libraryName) {
     assert(invariant(NO_LOCATION_SPANNABLE,
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 53be699..4b37788 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1073,6 +1073,8 @@
       dumpInfoTask.dumpInfo();
     }
 
+    backend.sourceInformationStrategy.onComplete();
+
     checkQueues();
   }
 
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 945aaba..fde5cde 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -64,6 +64,8 @@
   bool get isMinusZero => false;
   bool get isZero => false;
   bool get isOne => false;
+  bool get isPositiveInfinity => false;
+  bool get isNegativeInfinity => false;
 
   // TODO(johnniwinther): Replace with a 'type' getter.
   DartType getType(CoreTypes types);
@@ -279,6 +281,10 @@
 
   bool get isOne => primitiveValue == 1.0;
 
+  bool get isPositiveInfinity => primitiveValue == double.INFINITY;
+
+  bool get isNegativeInfinity => primitiveValue == -double.INFINITY;
+
   DartType getType(CoreTypes types) => types.doubleType;
 
   bool operator ==(var other) {
diff --git a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
index 422aaa3..b55a433 100644
--- a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
+++ b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
@@ -77,7 +77,7 @@
       prim..replaceUsesWith(value)..destroy();
       let.remove();
     } else if (prim is GetLength || prim is GetField || prim is GetIndex) {
-      if (prim.hasNoEffectiveUses) {
+      if (prim.hasNoRefinedUses) {
         destroyRefinementsOfDeadPrimitive(prim);
         LetPrim let = prim.parent;
         prim..destroy();
diff --git a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
index 44cbbb0..798875f 100644
--- a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
+++ b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
@@ -614,6 +614,16 @@
 
   @override
   void visitInvokeMethod(InvokeMethod node) {
+    if (node.selector.isGetter && node.selector.name == 'length') {
+      // If the receiver type is not known to be indexable, the length call
+      // was not rewritten to GetLength.  But if we can prove that the call only
+      // succeeds for indexables, we can trust that it returns the length.
+      TypeMask successType =
+          types.receiverTypeFor(node.selector, node.dartReceiver.type);
+      if (types.isDefinitelyIndexable(successType)) {
+        valueOf[node] = getLength(node.dartReceiver, currentEffectNumber);
+      }
+    }
     // TODO(asgerf): What we really need is a "changes length" side effect flag.
     if (world
         .getSideEffectsOfSelector(node.selector, node.mask)
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 0a80f33..470a96d 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -21,7 +21,8 @@
 import '../js/js.dart' as js show
     js,
     LiteralStatement,
-    Template;
+    Template,
+    isIdentityTemplate;
 import '../native/native.dart' show
     NativeBehavior;
 import '../tree/tree.dart' as ast;
@@ -166,6 +167,11 @@
   JumpCollector.retrn(this._continuation)
       : _continuationEnvironment = null, target = null;
 
+  /// Construct a collector for collecting goto jumps.
+  ///
+  /// There is no continuation or environment at the destination.
+  JumpCollector.goto(this.target) : _continuationEnvironment = null;
+
   /// True if the collector has not recorded any jumps to its continuation.
   bool get isEmpty;
 
@@ -421,6 +427,31 @@
   }
 }
 
+/// Collect 'goto' jumps, continue to a labeled case from within a switch.
+///
+/// These jumps are unrestricted within the switch.  They can be forward or
+/// backward.  They are implemented by assigning to a state variable.
+class GotoJumpCollector extends JumpCollector {
+  bool isEmpty = true;
+  final ir.Continuation continuation = null;
+  final Environment environment = null;
+
+  int _stateVariableIndex;
+  int _stateValue;
+  JumpCollector _breakJoin;
+
+  GotoJumpCollector(JumpTarget target, this._stateVariableIndex,
+      this._stateValue, this._breakJoin) : super.goto(target);
+
+  void addJump(IrBuilder builder,
+      [ir.Primitive value, SourceInformation sourceInformation]) {
+    isEmpty = false;
+    ir.Primitive constant = builder.buildIntegerConstant(_stateValue);
+    builder.environment.index2value[_stateVariableIndex] = constant;
+    builder.jumpTo(_breakJoin);
+  }
+}
+
 /// Function for building a node in the context of the current builder.
 typedef ir.Node BuildFunction(node);
 
@@ -532,7 +563,7 @@
 ///
 /// The IR fragment is an expression with a hole in it. The hole represents
 /// the focus where new expressions can be added. The fragment is implemented
-/// by [_root] which is the root of the expression and [_current] which is the
+/// by [root] which is the root of the expression and [_current] which is the
 /// expression that immediately contains the hole. Not all expressions have a
 /// hole (e.g., invocations, which always occur in tail position, do not have a
 /// hole). Expressions with a hole have a plug method.
@@ -559,7 +590,7 @@
   /// side effects.
   Map<Local, ir.MutableVariable> mutableVariables;
 
-  ir.Expression _root = null;
+  ir.Expression root = null;
   ir.Expression _current = null;
 
   GlobalProgramInformation get program => state.program;
@@ -613,7 +644,7 @@
     return mutableVariables[local];
   }
 
-  bool get isOpen => _root == null || _current != null;
+  bool get isOpen => root == null || _current != null;
 
   List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
                                         {ClosureScope closureScope,
@@ -640,8 +671,8 @@
   /// new value of current.
   void add(ir.Expression expr) {
     assert(isOpen);
-    if (_root == null) {
-      _root = _current = expr;
+    if (root == null) {
+      root = _current = expr;
     } else {
       _current = _current.plug(expr);
     }
@@ -789,8 +820,8 @@
     //     if condition (then, else)
     ir.Continuation thenContinuation = new ir.Continuation([]);
     ir.Continuation elseContinuation = new ir.Continuation([]);
-    thenContinuation.body = thenBuilder._root;
-    elseContinuation.body = elseBuilder._root;
+    thenContinuation.body = thenBuilder.root;
+    elseContinuation.body = elseBuilder.root;
     add(new ir.LetCont(join.continuation,
             new ir.LetCont.two(thenContinuation, elseContinuation,
                 new ir.Branch.strict(condition,
@@ -812,7 +843,7 @@
     _current = null;
   }
 
-  /// Create a [ir.FunctionDefinition] using [_root] as the body.
+  /// Create a [ir.FunctionDefinition] using [root] as the body.
   ///
   /// The protocol for building a function is:
   /// 1. Call [buildFunctionHeader].
@@ -825,7 +856,7 @@
         state.thisParameter,
         state.functionParameters,
         state.returnContinuation,
-        _root);
+        root);
   }
 
   /// Create a invocation of the [method] on the super class where the call
@@ -1107,17 +1138,17 @@
     // case that one of them is null, it must be the only one that is open
     // and thus contains the new hole in the context.  This case is handled
     // after the branch is plugged into the current hole.
-    thenContinuation.body = thenBuilder._root;
-    elseContinuation.body = elseBuilder._root;
+    thenContinuation.body = thenBuilder.root;
+    elseContinuation.body = elseBuilder.root;
 
     add(result);
     if (join == null) {
       // At least one subexpression is closed.
       if (thenBuilder.isOpen) {
-        if (thenBuilder._root != null) _current = thenBuilder._current;
+        if (thenBuilder.root != null) _current = thenBuilder._current;
         environment = thenBuilder.environment;
       } else if (elseBuilder.isOpen) {
-        if (elseBuilder._root != null) _current = elseBuilder._current;
+        if (elseBuilder.root != null) _current = elseBuilder._current;
         environment = elseBuilder.environment;
       } else {
         _current = null;
@@ -1243,16 +1274,16 @@
     // it is guaranteed that the updateBuilder has a non-empty term.
     if (hasContinues) {
       outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation,
-          innerBodyBuilder._root));
-      continueCollector.continuation.body = updateBuilder._root;
+          innerBodyBuilder.root));
+      continueCollector.continuation.body = updateBuilder.root;
     } else {
-      outerBodyBuilder.add(innerBodyBuilder._root);
+      outerBodyBuilder.add(innerBodyBuilder.root);
     }
 
     // Create loop exit and body entry continuations and a branch to them.
     ir.Continuation exitContinuation = new ir.Continuation([]);
     ir.Continuation bodyContinuation = new ir.Continuation([]);
-    bodyContinuation.body = outerBodyBuilder._root;
+    bodyContinuation.body = outerBodyBuilder.root;
     // Note the order of continuations: the first one is the one that will
     // be filled by LetCont.plug.
     ir.LetCont branch =
@@ -1268,7 +1299,7 @@
     if (hasBreaks) {
       IrBuilder exitBuilder = makeDelimitedBuilder();
       exitBuilder.jumpTo(breakCollector);
-      exitContinuation.body = exitBuilder._root;
+      exitContinuation.body = exitBuilder.root;
       letBreak = new ir.LetCont(breakCollector.continuation, branch);
       add(letBreak);
       environment = breakCollector.environment;
@@ -1411,7 +1442,7 @@
     // in branch condition (body, exit)
     ir.Continuation exitContinuation = new ir.Continuation([]);
     ir.Continuation bodyContinuation = new ir.Continuation([]);
-    bodyContinuation.body = bodyBuilder._root;
+    bodyContinuation.body = bodyBuilder.root;
     // Note the order of continuations: the first one is the one that will
     // be filled by LetCont.plug.
     ir.LetCont branch =
@@ -1427,7 +1458,7 @@
     if (hasBreaks) {
       IrBuilder exitBuilder = makeDelimitedBuilder();
       exitBuilder.jumpTo(breakCollector);
-      exitContinuation.body = exitBuilder._root;
+      exitContinuation.body = exitBuilder.root;
       letBreak = new ir.LetCont(breakCollector.continuation, branch);
       add(letBreak);
       environment = breakCollector.environment;
@@ -1486,7 +1517,7 @@
     // Create body entry and loop exit continuations and a branch to them.
     ir.Continuation exitContinuation = new ir.Continuation([]);
     ir.Continuation bodyContinuation = new ir.Continuation([]);
-    bodyContinuation.body = bodyBuilder._root;
+    bodyContinuation.body = bodyBuilder.root;
     // Note the order of continuations: the first one is the one that will
     // be filled by LetCont.plug.
     ir.LetCont branch =
@@ -1502,7 +1533,7 @@
     if (hasBreaks) {
       IrBuilder exitBuilder = makeDelimitedBuilder();
       exitBuilder.jumpTo(breakCollector);
-      exitContinuation.body = exitBuilder._root;
+      exitContinuation.body = exitBuilder.root;
       letBreak = new ir.LetCont(breakCollector.continuation, branch);
       add(letBreak);
       environment = breakCollector.environment;
@@ -1569,18 +1600,18 @@
     ir.Continuation exitContinuation = new ir.Continuation([]);
     IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
     exitBuilder.jumpTo(breakCollector);
-    exitContinuation.body = exitBuilder._root;
+    exitContinuation.body = exitBuilder.root;
     ir.Continuation repeatContinuation = new ir.Continuation([]);
     IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder();
     repeatBuilder.jumpTo(loop);
-    repeatContinuation.body = repeatBuilder._root;
+    repeatContinuation.body = repeatBuilder.root;
 
     continueBuilder.add(
         new ir.LetCont.two(exitContinuation, repeatContinuation,
             new ir.Branch.strict(condition,
                                  repeatContinuation,
                                  exitContinuation)));
-    continueCollector.continuation.body = continueBuilder._root;
+    continueCollector.continuation.body = continueBuilder.root;
 
     // Construct the loop continuation (i.e., the body and condition).
     // <Loop> =
@@ -1589,56 +1620,25 @@
     // in [[body]]; continue(v, ...)
     loopBuilder.add(
         new ir.LetCont(continueCollector.continuation,
-            bodyBuilder._root));
+            bodyBuilder.root));
 
     // And tie it all together.
-    add(new ir.LetCont(breakCollector.continuation, loopBuilder._root));
+    add(new ir.LetCont(breakCollector.continuation, loopBuilder.root));
     environment = breakCollector.environment;
   }
 
-  void buildSimpleSwitch(JumpTarget target,
-                         ir.Primitive value,
+  void buildSimpleSwitch(JumpCollector join,
                          List<SwitchCaseInfo> cases,
-                         SwitchCaseInfo defaultCase,
-                         Element error,
-                         SourceInformation sourceInformation) {
-    assert(isOpen);
-    JumpCollector join = new ForwardJumpCollector(environment, target: target);
-
+                         SubbuildFunction buildDefaultBody) {
     IrBuilder casesBuilder = makeDelimitedBuilder();
-    casesBuilder.state.breakCollectors.add(join);
     for (SwitchCaseInfo caseInfo in cases) {
-      buildConditionsFrom(int index) => (IrBuilder builder) {
-        ir.Primitive comparison = builder.buildIdentical(
-            value, caseInfo.constants[index]);
-        return (index == caseInfo.constants.length - 1)
-            ? comparison
-            : builder.buildLogicalOperator(
-                comparison, buildConditionsFrom(index + 1), isLazyOr: true);
-      };
-
-      ir.Primitive condition = buildConditionsFrom(0)(casesBuilder);
+      ir.Primitive condition = caseInfo.buildCondition(casesBuilder);
       IrBuilder thenBuilder = makeDelimitedBuilder();
       caseInfo.buildBody(thenBuilder);
-      if (thenBuilder.isOpen) {
-        // It is a runtime error to reach the end of a switch case, unless
-        // it is the last case.
-        if (caseInfo == cases.last && defaultCase == null) {
-          thenBuilder.jumpTo(join);
-        } else {
-          ir.Primitive exception = thenBuilder.buildInvokeStatic(
-              error,
-              new Selector.fromElement(error),
-              <ir.Primitive>[],
-              sourceInformation);
-          thenBuilder.buildThrow(exception);
-        }
-      }
-
       ir.Continuation thenContinuation = new ir.Continuation([]);
-      thenContinuation.body = thenBuilder._root;
+      thenContinuation.body = thenBuilder.root;
       ir.Continuation elseContinuation = new ir.Continuation([]);
-      // A LetCont.many term has a hole as the body of the first listed
+      // A LetCont.two term has a hole as the body of the first listed
       // continuation, to be plugged by the translation.  Therefore put the
       // else continuation first.
       casesBuilder.add(
@@ -1648,18 +1648,17 @@
                                    elseContinuation)));
     }
 
-    if (defaultCase != null) {
-      defaultCase.buildBody(casesBuilder);
+    if (buildDefaultBody == null) {
+      casesBuilder.jumpTo(join);
+    } else {
+      buildDefaultBody(casesBuilder);
     }
-    if (casesBuilder.isOpen) casesBuilder.jumpTo(join);
-
-    casesBuilder.state.breakCollectors.removeLast();
 
     if (!join.isEmpty) {
-      add(new ir.LetCont(join.continuation, casesBuilder._root));
+      add(new ir.LetCont(join.continuation, casesBuilder.root));
       environment = join.environment;
-    } else if (casesBuilder._root != null) {
-      add(casesBuilder._root);
+    } else if (casesBuilder.root != null) {
+      add(casesBuilder.root);
       _current = casesBuilder._current;
       environment = casesBuilder.environment;
     } else {
@@ -1721,11 +1720,11 @@
 
     List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join);
     ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
-    catchContinuation.body = catchBuilder._root;
+    catchContinuation.body = catchBuilder.root;
     tryCatchBuilder.add(
-        new ir.LetHandler(catchContinuation, tryBuilder._root));
+        new ir.LetHandler(catchContinuation, tryBuilder.root));
 
-    leaveTryCatch(this, join, tryCatchBuilder._root);
+    leaveTryCatch(this, join, tryCatchBuilder.root);
   }
 
   /// Translates a try/catch.
@@ -1829,7 +1828,7 @@
         }
         clause.buildCatchBlock(clauseBuilder);
         if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
-        return clauseBuilder._root;
+        return clauseBuilder.root;
       }
 
       // Expand multiple catch clauses into an explicit if/then/else.  Iterate
@@ -1855,7 +1854,7 @@
             new ir.Branch.strict(typeMatches,
                                  thenContinuation,
                                  elseContinuation)));
-        catchBody = checkBuilder._root;
+        catchBody = checkBuilder.root;
       }
       builder.add(catchBody);
 
@@ -1960,7 +1959,7 @@
         IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
         buildFinallyBlock(builder);
         if (builder.isOpen) builder.jumpTo(originalCollector);
-        newCollector.continuation.body = builder._root;
+        newCollector.continuation.body = builder.root;
         exits.add(newCollector.continuation);
       }
       for (int i = 0; i < newBreaks.length; ++i) {
@@ -1974,7 +1973,7 @@
         ir.Primitive value = builder.environment.discard(1);
         buildFinallyBlock(builder);
         if (builder.isOpen) builder.buildReturn(value: value);
-        newReturn.continuation.body = builder._root;
+        newReturn.continuation.body = builder.root;
         exits.add(newReturn.continuation);
       }
       builder.add(new ir.LetCont.many(exits, body));
@@ -2062,7 +2061,8 @@
     ir.Primitive value = buildForeignCode(
         js.js.uncachedExpressionTemplate(code),
         arguments,
-        behavior);
+        behavior,
+        type: program.getTypeMaskForNativeFunction(function));
     buildReturn(value: value, sourceInformation: source);
   }
 
@@ -2100,10 +2100,10 @@
     bool hasBreaks = !join.isEmpty;
     if (hasBreaks) {
       if (innerBuilder.isOpen) innerBuilder.jumpTo(join);
-      add(new ir.LetCont(join.continuation, innerBuilder._root));
+      add(new ir.LetCont(join.continuation, innerBuilder.root));
       environment = join.environment;
-    } else if (innerBuilder._root != null) {
-      add(innerBuilder._root);
+    } else if (innerBuilder.root != null) {
+      add(innerBuilder.root);
       _current = innerBuilder._current;
       environment = innerBuilder.environment;
     } else {
@@ -2239,8 +2239,8 @@
     ir.Continuation leftFalseContinuation = new ir.Continuation([]);
     ir.Continuation rightTrueContinuation = new ir.Continuation([]);
     ir.Continuation rightFalseContinuation = new ir.Continuation([]);
-    rightTrueContinuation.body = rightTrueBuilder._root;
-    rightFalseContinuation.body = rightFalseBuilder._root;
+    rightTrueContinuation.body = rightTrueBuilder.root;
+    rightFalseContinuation.body = rightFalseBuilder.root;
     // The right subexpression has two continuations.
     rightBuilder.add(
         new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation,
@@ -2251,11 +2251,11 @@
     // either the right subexpression or an invocation of the join-point
     // continuation.
     if (isLazyOr) {
-      leftTrueContinuation.body = emptyBuilder._root;
-      leftFalseContinuation.body = rightBuilder._root;
+      leftTrueContinuation.body = emptyBuilder.root;
+      leftFalseContinuation.body = rightBuilder.root;
     } else {
-      leftTrueContinuation.body = rightBuilder._root;
-      leftFalseContinuation.body = emptyBuilder._root;
+      leftTrueContinuation.body = rightBuilder.root;
+      leftFalseContinuation.body = emptyBuilder.root;
     }
 
     add(new ir.LetCont(join.continuation,
@@ -2411,7 +2411,7 @@
       arguments.add(value);
     }
     return addPrimitive(new ir.CreateInstance(
-        classElement, arguments, const <ir.Primitive>[], sourceInformation));
+        classElement, arguments, null, sourceInformation));
   }
 
   /// Create a read access of [local] function, variable, or parameter.
@@ -2577,7 +2577,8 @@
         ir.Primitive value = buildTypeVariableAccess(variable);
         arguments.add(value);
       });
-      return addPrimitive(new ir.TypeExpression(type, arguments));
+      return addPrimitive(new ir.TypeExpression(ir.TypeExpressionKind.COMPLETE,
+                                                type, arguments));
     } else if (type.treatAsDynamic) {
       return buildNullConstant();
     } else {
@@ -2634,9 +2635,19 @@
   ir.Primitive buildForeignCode(js.Template codeTemplate,
                                 List<ir.Primitive> arguments,
                                 NativeBehavior behavior,
-                                {Element dependency}) {
+                                {Element dependency,
+                                 TypeMask type}) {
     assert(behavior != null);
-    TypeMask type = program.getTypeMaskForForeign(behavior);
+    if (type == null) {
+      type = program.getTypeMaskForForeign(behavior);
+    }
+    if (js.isIdentityTemplate(codeTemplate) && !program.isArrayType(type)) {
+      // JS expression is just a refinement.
+      // Do not do this for arrays - those are special because array types can
+      // change after creation.  The input and output must therefore be modeled
+      // as distinct values.
+      return addPrimitive(new ir.Refinement(arguments.single, type));
+    }
     ir.Primitive result = addPrimitive(new ir.ForeignCode(
         codeTemplate,
         type,
@@ -2834,10 +2845,8 @@
 }
 
 class SwitchCaseInfo {
-  final List<ir.Primitive> constants = <ir.Primitive>[];
+  final SubbuildFunction buildCondition;
   final SubbuildFunction buildBody;
 
-  SwitchCaseInfo(this.buildBody);
-
-  void addConstant(ir.Primitive constant) => constants.add(constant);
+  SwitchCaseInfo(this.buildCondition, this.buildBody);
 }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 5c55f63..f98c9dd 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -382,7 +382,7 @@
     IrBuilder builder = getBuilderFor(constructor);
 
     final bool requiresTypeInformation =
-    builder.program.requiresRuntimeTypesFor(classElement);
+        builder.program.requiresRuntimeTypesFor(classElement);
 
     return withBuilder(builder, () {
       // Setup parameters and create a box if anything is captured.
@@ -410,11 +410,15 @@
           closureScope: getClosureScopeForFunction(constructor));
 
       // Create a list of the values of all type argument parameters, if any.
-      List<ir.Primitive> typeInformation;
+      ir.Primitive typeInformation;
       if (requiresTypeInformation) {
-        typeInformation = irParameters.sublist(firstTypeArgumentParameterIndex);
+        typeInformation = new ir.TypeExpression(
+            ir.TypeExpressionKind.INSTANCE,
+            classElement.thisType,
+            irParameters.sublist(firstTypeArgumentParameterIndex));
+        irBuilder.add(new ir.LetPrim(typeInformation));
       } else {
-        typeInformation = const <ir.Primitive>[];
+        typeInformation = null;
       }
 
       // -- Load values for type variables declared on super classes --
@@ -753,7 +757,8 @@
     TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
     tryStatements = variables.tryStatements;
     IrBuilder builder = getBuilderFor(element);
-    return withBuilder(builder, () => _makeFunctionBody(element, node));
+    return withBuilder(builder,
+        () => _makeFunctionBody(builder, element, node));
   }
 
   ir.FunctionDefinition buildStaticFieldInitializer(FieldElement element) {
@@ -875,17 +880,24 @@
     }
   }
 
-  ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
-                                          ast.FunctionExpression node) {
+  ir.FunctionDefinition _makeFunctionBody(
+      IrBuilder builder,
+      FunctionElement element,
+      ast.FunctionExpression node) {
     FunctionSignature signature = element.functionSignature;
     List<Local> parameters = <Local>[];
     signature.orderedForEachParameter(
         (LocalParameterElement e) => parameters.add(e));
 
+    bool requiresRuntimeTypes = false;
     if (element.isFactoryConstructor) {
-      // Type arguments are passed in as extra parameters.
-      for (DartType typeVariable in element.enclosingClass.typeVariables) {
-        parameters.add(new closure.TypeVariableLocal(typeVariable, element));
+      requiresRuntimeTypes =
+          builder.program.requiresRuntimeTypesFor(element.enclosingElement);
+      if (requiresRuntimeTypes) {
+        // Type arguments are passed in as extra parameters.
+        for (DartType typeVariable in element.enclosingClass.typeVariables) {
+          parameters.add(new closure.TypeVariableLocal(typeVariable, element));
+        }
       }
     }
 
@@ -893,7 +905,45 @@
                                   closureScope: getClosureScopeForNode(node),
                                   env: getClosureEnvironment());
 
-    visit(node.body);
+    if (element == helpers.jsArrayTypedConstructor) {
+      // Generate a body for JSArray<E>.typed(allocation):
+      //
+      //    t1 = setRuntimeTypeInfo(allocation, TypeExpression($E));
+      //    return Refinement(t1, <JSArray>);
+      //
+      assert(parameters.length == 1 || parameters.length == 2);
+      ir.Primitive allocation = irBuilder.buildLocalGet(parameters[0]);
+      ClassElement classElement = element.enclosingElement;
+
+      // Only call setRuntimeTypeInfo if JSArray requires the type parameter.
+      if (requiresRuntimeTypes) {
+        assert(parameters.length == 2);
+        closure.TypeVariableLocal typeParameter = parameters[1];
+        ir.Primitive typeArgument =
+            irBuilder.buildTypeVariableAccess(typeParameter.typeVariable);
+
+        ir.Primitive typeInformation = irBuilder.addPrimitive(
+            new ir.TypeExpression(ir.TypeExpressionKind.INSTANCE,
+                                  element.enclosingClass.thisType,
+                                  <ir.Primitive>[typeArgument]));
+
+        MethodElement helper = helpers.setRuntimeTypeInfo;
+        CallStructure callStructure = CallStructure.TWO_ARGS;
+        Selector selector = new Selector.call(helper.memberName, callStructure);
+        allocation = irBuilder.buildInvokeStatic(
+            helper, selector, <ir.Primitive>[allocation, typeInformation],
+            sourceInformationBuilder.buildGeneric(node));
+      }
+
+      ir.Primitive refinement = irBuilder.addPrimitive(
+          new ir.Refinement(allocation, typeMaskSystem.arrayType));
+
+      irBuilder.buildReturn(value: refinement,
+          sourceInformation:
+              sourceInformationBuilder.buildImplicitReturn(element));
+    } else {
+      visit(node.body);
+    }
     return irBuilder.makeFunctionDefinition();
   }
 
@@ -1172,44 +1222,270 @@
   }
 
   visitSwitchStatement(ast.SwitchStatement node) {
+    // Dart switch cases can be labeled and be the target of continue from
+    // within the switch.  Such cases are 'recursive'.  If there are any
+    // recursive cases, we implement the switch using a pair of switches with
+    // the second one switching over a state variable in a loop.  The first
+    // switch contains the non-recursive cases, and the second switch contains
+    // the recursive ones.
+    //
+    // For example, for the Dart switch:
+    //
+    // switch (E) {
+    //   case 0:
+    //     BODY0;
+    //     break;
+    //   LABEL0: case 1:
+    //     BODY1;
+    //     break;
+    //   case 2:
+    //     BODY2;
+    //     continue LABEL1;
+    //   LABEL1: case 3:
+    //     BODY3;
+    //     continue LABEL0;
+    //   default:
+    //     BODY4;
+    // }
+    //
+    // We translate it as if it were the JavaScript:
+    //
+    // var state = -1;
+    // switch (E) {
+    //   case 0:
+    //     BODY0;
+    //     break;
+    //   case 1:
+    //     state = 0;  // Recursive, label ID = 0.
+    //     break;
+    //   case 2:
+    //     BODY2;
+    //     state = 1;  // Continue to label ID = 1.
+    //     break;
+    //   case 3:
+    //     state = 1;  // Recursive, label ID = 1.
+    //     break;
+    //   default:
+    //     BODY4;
+    // }
+    // L: while (state != -1) {
+    //   case 0:
+    //     BODY1;
+    //     break L;  // Break from switch becomes break from loop.
+    //   case 1:
+    //     BODY2;
+    //     state = 0;  // Continue to label ID = 0.
+    //     break;
+    // }
     assert(irBuilder.isOpen);
-    // We do not handle switch statements with continue to labeled cases.
-    for (ast.SwitchCase switchCase in node.cases) {
+    // Preprocess: compute a list of cases that are the target of continue.
+    // These are the so-called 'recursive' cases.
+    List<JumpTarget> continueTargets = <JumpTarget>[];
+    List<ast.Node> switchCases = node.cases.nodes.toList();
+    for (ast.SwitchCase switchCase in switchCases) {
       for (ast.Node labelOrCase in switchCase.labelsAndCases) {
         if (labelOrCase is ast.Label) {
           LabelDefinition definition = elements.getLabelDefinition(labelOrCase);
           if (definition != null && definition.isContinueTarget) {
-            return giveup(node, "continue to a labeled switch case");
+            continueTargets.add(definition.target);
           }
         }
       }
     }
 
-    // Each switch case contains a list of interleaved labels and expressions
-    // and a non-empty body.  We can ignore the labels because they are not
-    // jump targets.
-    List<SwitchCaseInfo> cases = <SwitchCaseInfo>[];
-    SwitchCaseInfo defaultCase;
-    for (ast.SwitchCase switchCase in node.cases) {
-      SwitchCaseInfo caseInfo =
-          new SwitchCaseInfo(subbuildSequence(switchCase.statements));
-      if (switchCase.isDefaultCase) {
-        defaultCase = caseInfo;
-      } else {
-        cases.add(caseInfo);
-        for (ast.Node labelOrCase in switchCase.labelsAndCases) {
-          if (labelOrCase is ast.CaseMatch) {
-            ir.Primitive constant = translateConstant(labelOrCase.expression);
-            caseInfo.addConstant(constant);
-          }
-        }
-      }
+    // If any cases are continue targets, use an anonymous local value to
+    // implement a state machine.  The initial value is -1.
+    ir.Primitive initial;
+    int stateIndex;
+    if (continueTargets.isNotEmpty) {
+      initial = irBuilder.buildIntegerConstant(-1);
+      stateIndex = irBuilder.environment.length;
+      irBuilder.environment.extend(null, initial);
     }
+
+    // Use a simple switch for the non-recursive cases.  A break will go to the
+    // join-point after the switch.  A continue to a labeled case will assign
+    // to the state variable and go to the join-point.
     ir.Primitive value = visit(node.expression);
-    JumpTarget target = elements.getTargetDefinition(node);
-    Element error = helpers.fallThroughError;
-    irBuilder.buildSimpleSwitch(target, value, cases, defaultCase, error,
-        sourceInformationBuilder.buildGeneric(node));
+    JumpCollector join = new ForwardJumpCollector(irBuilder.environment,
+        target: elements.getTargetDefinition(node));
+    irBuilder.state.breakCollectors.add(join);
+    for (int i = 0; i < continueTargets.length; ++i) {
+      // The state value is i, the case's position in the list of recursive
+      // cases.
+      irBuilder.state.continueCollectors.add(new GotoJumpCollector(
+          continueTargets[i], stateIndex, i, join));
+    }
+
+    // For each non-default case use a pair of functions, one to translate the
+    // condition and one to translate the body.  For the default case use a
+    // function to translate the body.  Use continueTargetIterator as a pointer
+    // to the next recursive case.
+    Iterator<JumpTarget> continueTargetIterator = continueTargets.iterator;
+    continueTargetIterator.moveNext();
+    List<SwitchCaseInfo> cases = <SwitchCaseInfo>[];
+    SubbuildFunction buildDefaultBody;
+    for (ast.SwitchCase switchCase in switchCases) {
+      JumpTarget nextContinueTarget = continueTargetIterator.current;
+      if (switchCase.isDefaultCase) {
+        if (nextContinueTarget != null &&
+            switchCase == nextContinueTarget.statement) {
+          // In this simple switch, recursive cases are as if they immediately
+          // continued to themselves.
+          buildDefaultBody = nested(() {
+            irBuilder.buildContinue(nextContinueTarget);
+          });
+          continueTargetIterator.moveNext();
+        } else {
+          // Non-recursive cases consist of the translation of the body.
+          // For the default case, there is implicitly a break if control
+          // flow reaches the end.
+          buildDefaultBody = nested(() {
+            irBuilder.buildSequence(switchCase.statements, visit);
+            if (irBuilder.isOpen) irBuilder.jumpTo(join);
+          });
+        }
+        continue;
+      }
+
+      ir.Primitive buildCondition(IrBuilder builder) {
+        // There can be multiple cases sharing the same body, because empty
+        // cases are allowed to fall through to the next one.  Each case is
+        // a comparison, build a short-circuited disjunction of all of them.
+        return withBuilder(builder, () {
+          ir.Primitive condition;
+          for (ast.Node labelOrCase in switchCase.labelsAndCases) {
+            if (labelOrCase is ast.CaseMatch) {
+              ir.Primitive buildComparison() {
+                ir.Primitive constant =
+                    translateConstant(labelOrCase.expression);
+                return irBuilder.buildIdentical(value, constant);
+              }
+
+              if (condition == null) {
+                condition = buildComparison();
+              } else {
+                condition = irBuilder.buildLogicalOperator(condition,
+                    nested(buildComparison), isLazyOr: true);
+              }
+            }
+          }
+          return condition;
+        });
+      }
+
+      SubbuildFunction buildBody;
+      if (nextContinueTarget != null &&
+          switchCase == nextContinueTarget.statement) {
+        // Recursive cases are as if they immediately continued to themselves.
+        buildBody = nested(() {
+          irBuilder.buildContinue(nextContinueTarget);
+        });
+        continueTargetIterator.moveNext();
+      } else {
+        // Non-recursive cases consist of the translation of the body.  It is a
+        // runtime error if control-flow reaches the end of the body of any but
+        // the last case.
+        buildBody = (IrBuilder builder) {
+          withBuilder(builder, () {
+            irBuilder.buildSequence(switchCase.statements, visit);
+            if (irBuilder.isOpen) {
+              if (switchCase == switchCases.last) {
+                irBuilder.jumpTo(join);
+              } else {
+                Element error = helpers.fallThroughError;
+                ir.Primitive exception = irBuilder.buildInvokeStatic(
+                    error,
+                    new Selector.fromElement(error),
+                    <ir.Primitive>[],
+                    sourceInformationBuilder.buildGeneric(node));
+                irBuilder.buildThrow(exception);
+              }
+            }
+          });
+          return null;
+        };
+      }
+
+      cases.add(new SwitchCaseInfo(buildCondition, buildBody));
+    }
+
+    irBuilder.buildSimpleSwitch(join, cases, buildDefaultBody);
+    irBuilder.state.breakCollectors.removeLast();
+    irBuilder.state.continueCollectors.length -= continueTargets.length;
+    if (continueTargets.isEmpty) return;
+
+    // If there were recursive cases build a while loop whose body is a
+    // switch containing (only) the recursive cases.  The condition is
+    // 'state != initialValue' so the loop is not taken when the state variable
+    // has not been assigned.
+    //
+    // 'loop' is the join-point of the exits from the inner switch which will
+    // perform another iteration of the loop.  'exit' is the join-point of the
+    // breaks from the switch, outside the loop.
+    JumpCollector loop = new ForwardJumpCollector(irBuilder.environment);
+    JumpCollector exit = new ForwardJumpCollector(irBuilder.environment,
+        target: elements.getTargetDefinition(node));
+    irBuilder.state.breakCollectors.add(exit);
+    for (int i = 0; i < continueTargets.length; ++i) {
+      irBuilder.state.continueCollectors.add(new GotoJumpCollector(
+          continueTargets[i], stateIndex, i, loop));
+    }
+    cases.clear();
+    for (int i = 0; i < continueTargets.length; ++i) {
+      // The conditions compare to the recursive case index.
+      ir.Primitive buildCondition(IrBuilder builder) {
+        ir.Primitive constant = builder.buildIntegerConstant(i);
+        return builder.buildIdentical(
+            builder.environment.index2value[stateIndex], constant);
+      }
+
+      ir.Primitive buildBody(IrBuilder builder) {
+        withBuilder(builder, () {
+          ast.SwitchCase switchCase = continueTargets[i].statement;
+          irBuilder.buildSequence(switchCase.statements, visit);
+          if (irBuilder.isOpen) {
+            if (switchCase == switchCases.last) {
+              irBuilder.jumpTo(exit);
+            } else {
+              Element error = helpers.fallThroughError;
+              ir.Primitive exception = irBuilder.buildInvokeStatic(
+                  error,
+                  new Selector.fromElement(error),
+                  <ir.Primitive>[],
+                  sourceInformationBuilder.buildGeneric(node));
+              irBuilder.buildThrow(exception);
+            }
+          }
+        });
+        return null;
+      }
+
+      cases.add(new SwitchCaseInfo(buildCondition, buildBody));
+    }
+
+    // A loop with a simple switch in the body.
+    IrBuilder whileBuilder = irBuilder.makeDelimitedBuilder();
+    whileBuilder.buildWhile(
+        buildCondition: (IrBuilder builder) {
+          ir.Primitive condition = builder.buildIdentical(
+              builder.environment.index2value[stateIndex], initial);
+          return builder.buildNegation(condition);
+        },
+        buildBody: (IrBuilder builder) {
+          builder.buildSimpleSwitch(loop, cases, null);
+        });
+    // Jump to the exit continuation.  This jump is the body of the loop exit
+    // continuation, so the loop exit continuation can be eta-reduced.  The
+    // jump is here for simplicity because `buildWhile` does not expose the
+    // loop's exit continuation directly and has already emitted all jumps
+    // to it anyway.
+    whileBuilder.jumpTo(exit);
+    irBuilder.add(new ir.LetCont(exit.continuation, whileBuilder.root));
+    irBuilder.environment = exit.environment;
+    irBuilder.environment.discard(1);  // Discard the state variable.
+    irBuilder.state.breakCollectors.removeLast();
+    irBuilder.state.continueCollectors.length -= continueTargets.length;
   }
 
   visitTryStatement(ast.TryStatement node) {
@@ -1325,8 +1601,25 @@
     }
     List<ir.Primitive> values = node.elements.nodes.mapToList(visit);
     InterfaceType type = elements.getType(node);
-    return irBuilder.buildListLiteral(type, values,
-        allocationSiteType: getAllocationSiteType(node));
+    TypeMask allocationSiteType = getAllocationSiteType(node);
+    // TODO(sra): In checked mode, the elements must be checked as though
+    // operator[]= is called.
+    ir.Primitive list = irBuilder.buildListLiteral(type, values,
+          allocationSiteType: allocationSiteType);
+    if (type.treatAsRaw) return list;
+    // Call JSArray<E>.typed(allocation) to install the reified type.
+    ConstructorElement constructor = helpers.jsArrayTypedConstructor;
+    ir.Primitive tagged = irBuilder.buildConstructorInvocation(
+        constructor.effectiveTarget,
+        CallStructure.ONE_ARG,
+        constructor.computeEffectiveTargetType(type),
+        <ir.Primitive>[list],
+        sourceInformationBuilder.buildNew(node));
+
+    if (allocationSiteType == null) return tagged;
+
+    return irBuilder.addPrimitive(
+        new ir.Refinement(tagged, allocationSiteType));
   }
 
   ir.Primitive visitLiteralMap(ast.LiteralMap node) {
@@ -1334,12 +1627,48 @@
     if (node.isConst) {
       return translateConstant(node);
     }
+
     InterfaceType type = elements.getType(node);
-    List<ir.LiteralMapEntry> entries =
-        node.entries.nodes.mapToList((ast.LiteralMapEntry e) {
-          return new ir.LiteralMapEntry(visit(e.key), visit(e.value));
-        });
-    return irBuilder.addPrimitive(new ir.LiteralMap(type, entries));
+
+    if (node.entries.nodes.isEmpty) {
+      if (type.treatAsRaw) {
+        return irBuilder.buildStaticFunctionInvocation(
+            helpers.mapLiteralUntypedEmptyMaker,
+            <ir.Primitive>[],
+            sourceInformation: sourceInformationBuilder.buildNew(node));
+      } else {
+        ConstructorElement constructor = helpers.mapLiteralConstructorEmpty;
+        return irBuilder.buildConstructorInvocation(
+            constructor.effectiveTarget,
+            CallStructure.NO_ARGS,
+            constructor.computeEffectiveTargetType(type),
+            <ir.Primitive>[],
+            sourceInformationBuilder.buildNew(node));
+      }
+    }
+
+    List<ir.Primitive> keysAndValues = <ir.Primitive>[];
+    for (ast.LiteralMapEntry entry in node.entries.nodes.toList()) {
+      keysAndValues.add(visit(entry.key));
+      keysAndValues.add(visit(entry.value));
+    }
+    ir.Primitive keysAndValuesList =
+        irBuilder.buildListLiteral(null, keysAndValues);
+
+    if (type.treatAsRaw) {
+      return irBuilder.buildStaticFunctionInvocation(
+          helpers.mapLiteralUntypedMaker,
+          <ir.Primitive>[keysAndValuesList],
+          sourceInformation: sourceInformationBuilder.buildNew(node));
+    } else {
+      ConstructorElement constructor = helpers.mapLiteralConstructor;
+      return irBuilder.buildConstructorInvocation(
+          constructor.effectiveTarget,
+          CallStructure.ONE_ARG,
+          constructor.computeEffectiveTargetType(type),
+          <ir.Primitive>[keysAndValuesList],
+          sourceInformationBuilder.buildNew(node));
+    }
   }
 
   ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) {
@@ -1869,7 +2198,10 @@
 
     List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
     // Use default values from the effective target, not the immediate target.
-    ConstructorElement target = constructor.effectiveTarget;
+    ConstructorElement target = constructor.implementation;
+    while (target.isRedirectingFactory && !target.isCyclicRedirection) {
+      target = target.effectiveTarget.implementation;
+    }
 
     callStructure = normalizeStaticArguments(callStructure, target, arguments);
     TypeMask allocationSiteType;
@@ -1880,10 +2212,11 @@
         Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) {
       allocationSiteType = getAllocationSiteType(send);
     }
+    ConstructorElement constructorImplementation = constructor.implementation;
     return irBuilder.buildConstructorInvocation(
         target,
         callStructure,
-        constructor.computeEffectiveTargetType(type),
+        constructorImplementation.computeEffectiveTargetType(type),
         arguments,
         sourceInformationBuilder.buildNew(node),
         allocationSiteType: allocationSiteType);
@@ -2900,7 +3233,7 @@
         return irBuilder.buildForeignCode(
             js.js.parseForeignJS(backend.namer.staticStateHolder),
             const <ir.Primitive>[],
-            NativeBehavior.PURE);
+            NativeBehavior.DEPENDS_OTHER);
 
       case 'JS_SET_STATIC_STATE':
         validateArgumentCount(exactly: 1);
@@ -2910,7 +3243,7 @@
         return irBuilder.buildForeignCode(
             js.js.parseForeignJS("$isolateName = #"),
             <ir.Primitive>[value],
-            NativeBehavior.PURE);
+            NativeBehavior.CHANGES_OTHER);
 
       case 'JS_CALL_IN_ISOLATE':
         validateArgumentCount(exactly: 2);
@@ -3544,6 +3877,14 @@
     return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
   }
 
+  bool isArrayType(TypeMask type) {
+    return type.satisfies(_backend.helpers.jsArrayClass, _compiler.world);
+  }
+
+  TypeMask getTypeMaskForNativeFunction(FunctionElement function) {
+    return  _compiler.typesTask.getGuaranteedReturnTypeOfElement(function);
+  }
+
   FieldElement locateSingleField(Selector selector, TypeMask type) {
     return _compiler.world.locateSingleField(selector, type);
   }
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 49c8a6b..e73dd84 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -5,6 +5,7 @@
 
 import 'dart:collection';
 import 'cps_fragment.dart' show CpsFragment;
+import 'cps_ir_nodes_sexpr.dart';
 import '../constants/values.dart' as values;
 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
 import '../elements/elements.dart';
@@ -39,6 +40,37 @@
   ///
   /// All constructors call this method to initialize parent pointers.
   void setParentPointers();
+
+  /// Returns the SExpression for the subtree rooted at this node.
+  ///
+  /// [annotations] maps strings to nodes and/or nodes to values that will be
+  /// converted to strings. Each binding causes the annotation to appear on the
+  /// given node.
+  ///
+  /// For example, the following could be used to diagnose a problem with nodes
+  /// not appearing in an environment map:
+  ///
+  ///     if (environment[node] == null)
+  ///       root.debugPrint({
+  ///         'currentNode': node,
+  ///         'caller': someContinuation
+  ///       });
+  ///       throw 'Node was not in environment';
+  ///     }
+  ///
+  /// If two strings map to the same node, it will be given both annotations.
+  ///
+  /// Avoid using nodes as keys if there is a chance that two keys are the
+  /// same node.
+  String debugString([Map annotations]) {
+    return new SExpressionStringifier()
+        .withAnnotations(annotations).visit(this);
+  }
+
+  /// Prints the result of [debugString].
+  void debugPrint([Map annotations]) {
+    print(debugString(annotations));
+  }
 }
 
 /// Expressions can be evaluated, and may diverge, throw, and/or have
@@ -195,9 +227,9 @@
   }
 }
 
-class EffectiveUseIterable extends IterableBase<Reference<Primitive>> {
+class RefinedUseIterable extends IterableBase<Reference<Primitive>> {
   Primitive primitive;
-  EffectiveUseIterable(this.primitive);
+  RefinedUseIterable(this.primitive);
   EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive);
 }
 
@@ -238,6 +270,9 @@
   // TODO(asgerf): Also do this for [TypeCast]?
   Primitive get effectiveDefinition => this;
 
+  /// Like [effectiveDefinition] but only unfolds [Refinement] nodes.
+  Primitive get unrefined => this;
+
   /// True if the two primitives are (refinements of) the same value.
   bool sameValue(Primitive other) {
     return effectiveDefinition == other.effectiveDefinition;
@@ -252,15 +287,15 @@
   /// - References to this primitive created during iteration will not be seen.
   /// - References to a refinement of this primitive may not be created during
   ///   iteration.
-  EffectiveUseIterable get effectiveUses => new EffectiveUseIterable(this);
+  RefinedUseIterable get refinedUses => new RefinedUseIterable(this);
 
-  bool get hasMultipleEffectiveUses {
-    Iterator it = effectiveUses.iterator;
+  bool get hasMultipleRefinedUses {
+    Iterator it = refinedUses.iterator;
     return it.moveNext() && it.moveNext();
   }
 
-  bool get hasNoEffectiveUses {
-    return effectiveUses.isEmpty;
+  bool get hasNoRefinedUses {
+    return refinedUses.isEmpty;
   }
 
   /// Unlinks all references contained in this node.
@@ -734,6 +769,8 @@
 
   Primitive get effectiveDefinition => value.definition.effectiveDefinition;
 
+  Primitive get unrefined => value.definition.unrefined;
+
   void setParentPointers() {
     value.parent = this;
   }
@@ -1446,15 +1483,17 @@
   /// May be `null` to indicate that no type information is needed because the
   /// compiler determined that the type information for instances of this class
   /// is not needed at runtime.
-  final List<Reference<Primitive>> typeInformation;
+  final Reference<Primitive> typeInformation;
 
   final SourceInformation sourceInformation;
 
   CreateInstance(this.classElement, List<Primitive> arguments,
-      List<Primitive> typeInformation,
+      Primitive typeInformation,
       this.sourceInformation)
       : this.arguments = _referenceList(arguments),
-        this.typeInformation = _referenceList(typeInformation);
+        this.typeInformation = typeInformation == null
+            ? null
+            : new Reference<Primitive>(typeInformation);
 
   accept(Visitor visitor) => visitor.visitCreateInstance(this);
 
@@ -1466,7 +1505,7 @@
 
   void setParentPointers() {
     _setParentsOnList(arguments, this);
-    if (typeInformation != null) _setParentsOnList(typeInformation, this);
+    if (typeInformation != null) typeInformation.parent = this;
   }
 }
 
@@ -1529,12 +1568,12 @@
 
 class ForeignCode extends UnsafePrimitive {
   final js.Template codeTemplate;
-  final TypeMask type;
+  final TypeMask storedType;
   final List<Reference<Primitive>> arguments;
   final native.NativeBehavior nativeBehavior;
   final FunctionElement dependency;
 
-  ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
+  ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments,
       this.nativeBehavior, {this.dependency})
       : this.arguments = _referenceList(arguments);
 
@@ -1596,35 +1635,6 @@
   }
 }
 
-class LiteralMapEntry {
-  final Reference<Primitive> key;
-  final Reference<Primitive> value;
-
-  LiteralMapEntry(Primitive key, Primitive value)
-      : this.key = new Reference<Primitive>(key),
-        this.value = new Reference<Primitive>(value);
-}
-
-class LiteralMap extends Primitive {
-  final InterfaceType dartType;
-  final List<LiteralMapEntry> entries;
-
-  LiteralMap(this.dartType, this.entries);
-
-  accept(Visitor visitor) => visitor.visitLiteralMap(this);
-
-  bool get hasValue => true;
-  bool get isSafeForElimination => true;
-  bool get isSafeForReordering => true;
-
-  void setParentPointers() {
-    for (LiteralMapEntry entry in entries) {
-      entry.key.parent = this;
-      entry.value.parent = this;
-    }
-  }
-}
-
 class Parameter extends Primitive {
   Parameter(Entity hint) {
     super.hint = hint;
@@ -1651,8 +1661,25 @@
   // A continuation is recursive if it has any recursive invocations.
   bool isRecursive;
 
+  /// True if this is the return continuation.  The return continuation is bound
+  /// by [FunctionDefinition].
   bool get isReturnContinuation => body == null;
 
+  /// True if this is a branch continuation.  Branch continuations are bound
+  /// by [LetCont] and can only have one use.
+  bool get isBranchContinuation => firstRef?.parent is Branch;
+
+  /// True if this is the exception handler bound by a [LetHandler].
+  bool get isHandlerContinuation => parent is LetHandler;
+
+  /// True if this is a non-return continuation that can be targeted by
+  /// [InvokeContinuation].
+  bool get isJoinContinuation {
+    return body != null &&
+           parent is! LetHandler &&
+           (firstRef == null || firstRef.parent is InvokeContinuation);
+  }
+
   Continuation(this.parameters, {this.isRecursive: false});
 
   Continuation.retrn()
@@ -1773,21 +1800,74 @@
   }
 }
 
-/// Representation of a closed type (that is, a type without type variables).
+enum TypeExpressionKind {
+  COMPLETE,
+  INSTANCE
+}
+
+/// Constructs a representation of a closed or ground-term type (that is, a type
+/// without type variables).
 ///
-/// The resulting value is constructed from [dartType] by replacing the type
+/// There are two forms:
+///
+/// - COMPLETE: A complete form that is self contained, used for the values of
+///   type parameters and non-raw is-checks.
+///
+/// - INSTANCE: A headless flat form for representing the sequence of values of
+///   the type parameters of an instance of a generic type.
+///
+/// The COMPLETE form value is constructed from [dartType] by replacing the type
 /// variables with consecutive values from [arguments], in the order generated
 /// by [DartType.forEachTypeVariable].  The type variables in [dartType] are
 /// treated as 'holes' in the term, which means that it must be ensured at
 /// construction, that duplicate occurences of a type variable in [dartType]
 /// are assigned the same value.
+///
+/// The INSTANCE form is constructed as a list of [arguments]. This is the same
+/// as the COMPLETE form for the 'thisType', except the root term's type is
+/// missing; this is implicit as the raw type of instance.  The [dartType] of
+/// the INSTANCE form must be the thisType of some class.
+///
+/// While we would like to remove the constrains on the INSTANCE form, we can
+/// get by with a tree of TypeExpressions.  Consider:
+///
+///     class Foo<T> {
+///       ... new Set<List<T>>()
+///     }
+///     class Set<E1> {
+///       factory Set() => new _LinkedHashSet<E1>();
+///     }
+///     class List<E2> { ... }
+///     class _LinkedHashSet<E3> { ... }
+///
+/// After inlining the factory constructor for `Set<E1>`, the CreateInstance
+/// should have type `_LinkedHashSet<List<T>>` and the TypeExpression should be
+/// a tree:
+///
+///    CreateInstance(dartType: _LinkedHashSet<List<T>>,
+///        [], // No arguments
+///        TypeExpression(INSTANCE,
+///            dartType: _LinkedHashSet<E3>, // _LinkedHashSet's thisType
+///            TypeExpression(COMPLETE,  // E3 = List<T>
+///                dartType: List<E2>,
+///                ReadTypeVariable(this, T)))) // E2 = T
+//
+// TODO(sra): The INSTANCE form requires the actual instance for full
+// interpretation. I want to move to a representation where the INSTANCE form is
+// also a complete form (possibly the same).
 class TypeExpression extends Primitive {
+  final TypeExpressionKind kind;
   final DartType dartType;
   final List<Reference<Primitive>> arguments;
 
-  TypeExpression(this.dartType,
-                 [List<Primitive> arguments = const <Primitive>[]])
-      : this.arguments = _referenceList(arguments);
+  TypeExpression(this.kind,
+                 this.dartType,
+                 List<Primitive> arguments)
+      : this.arguments = _referenceList(arguments) {
+    assert(kind == TypeExpressionKind.INSTANCE
+           ? dartType == (dartType.element as ClassElement).thisType
+           : true);
+  }
 
   @override
   accept(Visitor visitor) {
@@ -1801,6 +1881,13 @@
   void setParentPointers() {
     _setParentsOnList(arguments, this);
   }
+
+  String get kindAsString {
+    switch (kind) {
+      case TypeExpressionKind.COMPLETE: return 'COMPLETE';
+      case TypeExpressionKind.INSTANCE: return 'INSTANCE';
+    }
+  }
 }
 
 class Await extends UnsafePrimitive {
@@ -1965,7 +2052,6 @@
   T visitAwait(Await node);
   T visitYield(Yield node);
   T visitLiteralList(LiteralList node);
-  T visitLiteralMap(LiteralMap node);
   T visitConstant(Constant node);
   T visitGetMutable(GetMutable node);
   T visitParameter(Parameter node);
@@ -2016,7 +2102,6 @@
     processFunctionDefinition(node);
     if (node.thisParameter != null) visit(node.thisParameter);
     node.parameters.forEach(visit);
-    visit(node.returnContinuation);
     visit(node.body);
   }
 
@@ -2147,15 +2232,6 @@
     node.values.forEach(processReference);
   }
 
-  processLiteralMap(LiteralMap node) {}
-  visitLiteralMap(LiteralMap node) {
-    processLiteralMap(node);
-    for (LiteralMapEntry entry in node.entries) {
-      processReference(entry.key);
-      processReference(entry.value);
-    }
-  }
-
   processConstant(Constant node) {}
   visitConstant(Constant node)  {
     processConstant(node);
@@ -2187,7 +2263,7 @@
   visitCreateInstance(CreateInstance node) {
     processCreateInstance(node);
     node.arguments.forEach(processReference);
-    node.typeInformation.forEach(processReference);
+    if (node.typeInformation != null) processReference(node.typeInformation);
   }
 
   processSetField(SetField node) {}
@@ -2377,7 +2453,6 @@
     processFunctionDefinition(node);
     if (node.thisParameter != null) visit(node.thisParameter);
     node.parameters.forEach(visit);
-    visit(node.returnContinuation);
     visit(node.body);
   }
 
@@ -2574,13 +2649,6 @@
         ..allocationSiteType = node.allocationSiteType;
   }
 
-  Definition visitLiteralMap(LiteralMap node) {
-    List<LiteralMapEntry> entries = node.entries.map((LiteralMapEntry entry) {
-      return new LiteralMapEntry(getCopy(entry.key), getCopy(entry.value));
-    }).toList();
-    return new LiteralMap(node.dartType, entries);
-  }
-
   Definition visitConstant(Constant node) {
     return new Constant(node.value, sourceInformation: node.sourceInformation);
   }
@@ -2607,8 +2675,10 @@
   }
 
   Definition visitCreateInstance(CreateInstance node) {
-    return new CreateInstance(node.classElement, getList(node.arguments),
-        getList(node.typeInformation),
+    return new CreateInstance(
+        node.classElement,
+        getList(node.arguments),
+        node.typeInformation == null ? null : getCopy(node.typeInformation),
         node.sourceInformation);
   }
 
@@ -2630,7 +2700,8 @@
   }
 
   Definition visitTypeExpression(TypeExpression node) {
-    return new TypeExpression(node.dartType, getList(node.arguments));
+    return new TypeExpression(
+        node.kind, node.dartType, getList(node.arguments));
   }
 
   Definition visitCreateInvocationMirror(CreateInvocationMirror node) {
@@ -2695,7 +2766,7 @@
   }
 
   Definition visitForeignCode(ForeignCode node) {
-    return new ForeignCode(node.codeTemplate, node.type,
+    return new ForeignCode(node.codeTemplate, node.storedType,
         getList(node.arguments),
         node.nativeBehavior,
         dependency: node.dependency);
@@ -2723,6 +2794,7 @@
       assert(_current != null);
       InteriorExpression interior = _current;
       interior.body = body;
+      body.parent = interior;
     }
     _current = body;
   }
@@ -2740,7 +2812,9 @@
       Expression savedFirst = _first;
       _first = _current = null;
       _processBlock(cont.body);
-      _copies[cont].body = _first;
+      Continuation contCopy = _copies[cont];
+      contCopy.body = _first;
+      _first.parent = contCopy;
       _first = savedFirst;
       _current = null;
     });
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index bde9b0e..37836bf 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -29,7 +29,52 @@
     }
   }
 
+  /// Create a stringifier with an extra layer of decoration.
+  SExpressionStringifier withDecorator(Decorator subDecorator) {
+    return new SExpressionStringifier((node, String s) {
+      return subDecorator(node, decorator(node, s));
+    });
+  }
+
+  /// Create a stringifier that displays type information.
+  SExpressionStringifier withTypes() => withDecorator(typeDecorator);
+
+  /// Creates a stringifier that adds annotations from a map;
+  /// see [Node.debugString].
+  SExpressionStringifier withAnnotations(Map annotations) {
+    return withDecorator(decoratorFromMap(annotations));
+  }
+
+  static Decorator decoratorFromMap(Map annotations) {
+    Map<Node, String> nodeMap = {};
+    for (var key in annotations.keys) {
+      if (key is Node) {
+        nodeMap[key] = '${annotations[key]}';
+      } else {
+        String text = key;
+        Node node = annotations[key];
+        if (nodeMap.containsKey(node)) {
+          // In case two annotations belong to the same node,
+          // put both annotations on that node.
+          nodeMap[node] += ' $text';
+        } else {
+          nodeMap[node] = text;
+        }
+      }
+    }
+    return (node, string) {
+      String text = nodeMap[node];
+      if (text != null) return '***$string*** $text';
+      return string;
+    };
+  }
+
+  static String typeDecorator(node, String string) {
+    return node is Variable ? '$string:${node.type}' : string;
+  }
+
   String access(Reference<Definition> r) {
+    if (r == null) return '**** NULL ****';
     return decorator(r, namer.getName(r.definition));
   }
 
@@ -71,24 +116,42 @@
   String visitLetPrim(LetPrim node) {
     String name = newValueName(node.primitive);
     String value = visit(node.primitive);
+    String bindings = '($name $value)';
+    String skip = ' ' * '(LetPrim ('.length;
+    while (node.body is LetPrim) {
+      node = node.body;
+      name = newValueName(node.primitive);
+      value = visit(node.primitive);
+      String binding = decorator(node, '($name $value)');
+      bindings += '\n${indentation}$skip$binding';
+    }
     String body = indentBlock(() => visit(node.body));
-    return '$indentation(LetPrim ($name $value)\n$body)';
+    return '$indentation(LetPrim ($bindings)\n$body)';
+  }
+
+  bool isBranchTarget(Continuation cont) {
+    return cont.hasExactlyOneUse && cont.firstRef.parent is Branch;
   }
 
   String visitLetCont(LetCont node) {
     String conts;
     bool first = true;
+    String skip = ' ' * '(LetCont ('.length;
     for (Continuation continuation in node.continuations) {
+      // Branch continuations will be printed at their use site.
+      if (isBranchTarget(continuation)) continue;
       if (first) {
         first = false;
         conts = visit(continuation);
       } else {
         // Each subsequent line is indented additional spaces to align it
         // with the previous continuation.
-        String indent = '$indentation${' ' * '(LetCont ('.length}';
-        conts = '$conts\n$indent${visit(continuation)}';
+        conts += '\n${indentation}$skip${visit(continuation)}';
       }
     }
+    // If there were no continuations printed, just print the body.
+    if (first) return visit(node.body);
+
     String body = indentBlock(() => visit(node.body));
     return '$indentation(LetCont ($conts)\n$body)';
   }
@@ -175,7 +238,9 @@
   String visitInvokeContinuation(InvokeContinuation node) {
     String name = access(node.continuation);
     if (node.isRecursive) name = 'rec $name';
-    String args = node.arguments.map(access).join(' ');
+    String args = node.arguments == null
+        ? '**** NULL ****'
+	: node.arguments.map(access).join(' ');
     String escaping = node.isEscapingTry ? ' escape' : '';
     return '$indentation(InvokeContinuation $name ($args)$escaping)';
   }
@@ -191,10 +256,14 @@
 
   String visitBranch(Branch node) {
     String condition = access(node.condition);
-    String trueCont = access(node.trueContinuation);
-    String falseCont = access(node.falseContinuation);
+    assert(isBranchTarget(node.trueContinuation.definition));
+    assert(isBranchTarget(node.falseContinuation.definition));
+    String trueCont =
+        indentBlock(() => visit(node.trueContinuation.definition));
+    String falseCont =
+        indentBlock(() => visit(node.falseContinuation.definition));
     String strict = node.isStrictCheck ? 'Strict' : 'NonStrict';
-    return '$indentation(Branch $condition $trueCont $falseCont $strict)';
+    return '$indentation(Branch $strict $condition\n$trueCont\n$falseCont)';
   }
 
   String visitUnreachable(Unreachable node) {
@@ -207,11 +276,17 @@
   }
 
   String visitContinuation(Continuation node) {
+    if (isBranchTarget(node)) {
+      assert(node.parameters.isEmpty);
+      assert(!node.isRecursive);
+      return indentBlock(() => visit(node.body));
+    }
     String name = newContinuationName(node);
     if (node.isRecursive) name = 'rec $name';
-    // TODO(karlklose): this should be changed to `.map(visit).join(' ')`  and
-    // should recurse to [visit].  Currently we can't do that, because the
-    // unstringifier_test produces [LetConts] with dummy arguments on them.
+    // TODO(karlklose): this should be changed to `.map(visit).join(' ')`
+    // and should recurse to [visit].  Currently we can't do that, because
+    // the unstringifier_test produces [LetConts] with dummy arguments on
+    // them.
     String parameters = node.parameters
         .map((p) => '${decorator(p, newValueName(p))}')
         .join(' ');
@@ -250,12 +325,6 @@
     return '(LiteralList ($values))';
   }
 
-  String visitLiteralMap(LiteralMap node) {
-    String keys = node.entries.map((e) => access(e.key)).join(' ');
-    String values = node.entries.map((e) => access(e.value)).join(' ');
-    return '(LiteralMap ($keys) ($values))';
-  }
-
   String visitSetField(SetField node) {
     String object = access(node.object);
     String field = node.field.name;
@@ -292,7 +361,7 @@
   String visitCreateInstance(CreateInstance node) {
     String className = node.classElement.name;
     String arguments = node.arguments.map(access).join(' ');
-    String typeInformation = node.typeInformation.map(access).join(' ');
+    String typeInformation = optionalAccess(node.typeInformation);
     return '(CreateInstance $className ($arguments) ($typeInformation))';
   }
 
@@ -310,7 +379,7 @@
 
   String visitTypeExpression(TypeExpression node) {
     String args = node.arguments.map(access).join(' ');
-    return '(TypeExpression ${node.dartType} ($args))';
+    return '(TypeExpression ${node.kindAsString} ${node.dartType} ($args))';
   }
 
   String visitCreateInvocationMirror(CreateInvocationMirror node) {
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index e732f3d..db1592d 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -29,7 +29,7 @@
       builder.visit(node);
 
       for (Block block in builder.entries) {
-        printBlock(block, entryPointParameters: node.parameters);
+        printBlock(block, entryPoint: node);
       }
       for (Block block in builder.cont2block.values) {
         printBlock(block);
@@ -63,9 +63,8 @@
     return count;
   }
 
-  /// If [entryPointParameters] is given, this block is an entry point
-  /// and [entryPointParameters] is the list of function parameters.
-  printBlock(Block block, {List<cps_ir.Definition> entryPointParameters}) {
+  /// If [entryPoint] is given, this block is an entry point.
+  printBlock(Block block, {cps_ir.FunctionDefinition entryPoint}) {
     tag("block", () {
       printProperty("name", block.name);
       printProperty("from_bci", -1);
@@ -84,9 +83,12 @@
         String formatParameter(cps_ir.Parameter param) {
           return '${names.name(param)} ${param.type}';
         }
-        if (entryPointParameters != null) {
-          String params = entryPointParameters.map(formatParameter).join(', ');
-          printStmt('x0', 'Entry ($params)');
+        if (entryPoint != null) {
+          String thisParam = entryPoint.thisParameter != null
+              ? formatParameter(entryPoint.thisParameter)
+              : 'no receiver';
+          String params = entryPoint.parameters.map(formatParameter).join(', ');
+          printStmt('x0', 'Entry ($thisParam) ($params)');
         }
         String params = block.parameters.map(formatParameter).join(', ');
         printStmt('x0', 'Parameters ($params)');
@@ -192,16 +194,6 @@
     return "LiteralList ($values)";
   }
 
-  visitLiteralMap(cps_ir.LiteralMap node) {
-    List<String> entries = new List<String>();
-    for (cps_ir.LiteralMapEntry entry in node.entries) {
-      String key = formatReference(entry.key);
-      String value = formatReference(entry.value);
-      entries.add("$key: $value");
-    }
-    return "LiteralMap (${entries.join(', ')})";
-  }
-
   visitTypeCast(cps_ir.TypeCast node) {
     String value = formatReference(node.value);
     String args = node.typeArguments.map(formatReference).join(', ');
@@ -303,8 +295,7 @@
   visitCreateInstance(cps_ir.CreateInstance node) {
     String className = node.classElement.name;
     String arguments = node.arguments.map(formatReference).join(', ');
-    String typeInformation =
-        node.typeInformation.map(formatReference).join(', ');
+    String typeInformation = formatReference(node.typeInformation);
     return 'CreateInstance $className ($arguments) <$typeInformation>';
   }
 
@@ -328,7 +319,7 @@
   }
 
   visitTypeExpression(cps_ir.TypeExpression node) {
-    return "TypeExpression ${node.dartType} "
+    return "TypeExpression ${node.kindAsString} ${node.dartType}"
         "${node.arguments.map(formatReference).join(', ')}";
   }
 
@@ -578,10 +569,6 @@
     unexpectedNode(node);
   }
 
-  visitLiteralMap(cps_ir.LiteralMap node) {
-    unexpectedNode(node);
-  }
-
   visitConstant(cps_ir.Constant node) {
     unexpectedNode(node);
   }
diff --git a/pkg/compiler/lib/src/cps_ir/duplicate_branch.dart b/pkg/compiler/lib/src/cps_ir/duplicate_branch.dart
new file mode 100644
index 0000000..7b1d294
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/duplicate_branch.dart
@@ -0,0 +1,123 @@
+// 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;
+
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
+import 'cps_fragment.dart';
+
+/// Removes branches that branch on the same value as a previously seen branch.
+/// For example:
+///
+///     if (x == y) {
+///       if (x == y) TRUE else FALSE
+///     }
+///
+/// ==> ([GVN] pass merges identical expressions)
+///
+///     var b = (x == y)
+///     if (b) {
+///       if (b) TRUE else FALSE
+///     }
+///
+///  ==> (this pass removes the duplicate branch)
+///
+///     var b = (x == y)
+///     if (b) {
+///       TRUE
+///     }
+//
+// TODO(asgerf): A kind of redundant join can arise where a branching condition
+// is known to be true/false on all but one predecessor for a branch. We could
+// try to reduce those.
+//
+// TODO(asgerf): Could be more precise if GVN shared expressions that are not
+// in direct scope of one another, e.g. by using phis pass the shared value.
+//
+class DuplicateBranchEliminator extends TrampolineRecursiveVisitor
+                                implements Pass {
+  String get passName => 'Duplicate branch elimination';
+
+  static const int TRUE = 1 << 0;
+  static const int OTHER_TRUTHY = 1 << 1;
+  static const int FALSE = 1 << 2;
+  static const int OTHER_FALSY = 1 << 3;
+
+  static const int TRUTHY = TRUE | OTHER_TRUTHY;
+  static const int FALSY = FALSE | OTHER_FALSY;
+  static const int ANY = TRUTHY | FALSY;
+
+  /// The possible values of the given primitive (or ANY if absent) at the
+  /// current traversal position.
+  Map<Primitive, int> valueOf = <Primitive, int>{};
+
+  /// The possible values of each primitive at the entry to a continuation.
+  ///
+  /// Unreachable continuations are absent from the map.
+  final Map<Continuation, Map<Primitive, int>> valuesAt =
+      <Continuation, Map<Primitive, int>>{};
+
+  void rewrite(FunctionDefinition node) {
+    visit(node);
+  }
+
+  Map<Primitive, int> copy(Map<Primitive, int> map) {
+    return new Map<Primitive, int>.from(map);
+  }
+
+  Expression traverseLetHandler(LetHandler node) {
+    valuesAt[node.handler] = copy(valueOf);
+    push(node.handler);
+    return node.body;
+  }
+
+  Expression traverseContinuation(Continuation cont) {
+    valueOf = valuesAt[cont];
+    if (valueOf == null) {
+      // Do not go into unreachable code.
+      destroyAndReplace(cont.body, new Unreachable());
+    }
+    return cont.body;
+  }
+
+  void visitInvokeContinuation(InvokeContinuation node) {
+    Continuation cont = node.continuation.definition;
+    if (cont.isReturnContinuation) return;
+    if (node.isRecursive) return;
+    Map<Primitive, int> target = valuesAt[cont];
+    if (target == null) {
+      valuesAt[cont] = valueOf;
+    } else {
+      for (Primitive prim in target.keys) {
+        target[prim] |= valueOf[prim] ?? ANY;
+      }
+    }
+  }
+
+  visitBranch(Branch node) {
+    Primitive condition = node.condition.definition.effectiveDefinition;
+    Continuation trueCont = node.trueContinuation.definition;
+    Continuation falseCont = node.falseContinuation.definition;
+    if (condition.hasExactlyOneUse) {
+      // Handle common case specially. Do not add [condition] to the map if
+      // there are no other uses.
+      valuesAt[trueCont] = copy(valueOf);
+      valuesAt[falseCont] = valueOf;
+      return;
+    }
+    int values = valueOf[condition] ?? ANY;
+    int positiveValues = node.isStrictCheck ? TRUE : TRUTHY;
+    int negativeValues = (~positiveValues) & ANY;
+    if (values & positiveValues == 0) {
+      destroyAndReplace(node, new InvokeContinuation(falseCont, []));
+      valuesAt[falseCont] = valueOf;
+    } else if (values & negativeValues == 0) {
+      destroyAndReplace(node, new InvokeContinuation(trueCont, []));
+      valuesAt[trueCont] = valueOf;
+    } else {
+      valuesAt[trueCont] = copy(valueOf)..[condition] = values & positiveValues;
+      valuesAt[falseCont] = valueOf..[condition] = values & negativeValues;
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/finalize.dart b/pkg/compiler/lib/src/cps_ir/finalize.dart
index 1406a58..7e3b6e1 100644
--- a/pkg/compiler/lib/src/cps_ir/finalize.dart
+++ b/pkg/compiler/lib/src/cps_ir/finalize.dart
@@ -5,6 +5,7 @@
 import 'optimizers.dart' show Pass;
 import '../js_backend/js_backend.dart' show JavaScriptBackend;
 import '../js_backend/backend_helpers.dart';
+import '../js/js.dart' as js;
 
 /// A transformation pass that must run immediately before the tree IR builder.
 ///
@@ -78,4 +79,18 @@
       node..witness.unlink()..witness = null;
     }
   }
+
+  void visitForeignCode(ForeignCode node) {
+    if (js.isIdentityTemplate(node.codeTemplate)) {
+      // The CPS builder replaces identity templates with refinements, except
+      // when the refined type is an array type.  Some optimizations assume the
+      // type of an object is immutable, but the type of an array can change
+      // after allocation.  After the finalize pass, this assumption is no
+      // longer needed, so we can replace the remaining idenitity templates.
+      Refinement refinement = new Refinement(
+          node.arguments.single.definition,
+          node.type)..type = node.type;
+      node.replaceWith(refinement);
+    }
+  }
 }
diff --git a/pkg/compiler/lib/src/cps_ir/inline.dart b/pkg/compiler/lib/src/cps_ir/inline.dart
index cc046ee..554e93e 100644
--- a/pkg/compiler/lib/src/cps_ir/inline.dart
+++ b/pkg/compiler/lib/src/cps_ir/inline.dart
@@ -86,6 +86,9 @@
   static const int ABSENT = -1;
   static const int NO_INLINE = 0;
 
+  final Map<ExecutableElement, FunctionDefinition> unoptimized =
+      <ExecutableElement, FunctionDefinition>{};
+
   final Map<ExecutableElement, List<CacheEntry>> map =
       <ExecutableElement, List<CacheEntry>>{};
 
@@ -144,6 +147,29 @@
     }
     return ABSENT;
   }
+
+  /// Cache the unoptimized CPS term for a function.
+  ///
+  /// The unoptimized term should not have any inlining-context-specific
+  /// optimizations applied to it.  It will be used to compile the
+  /// non-specialized version of the function.
+  void putUnoptimized(ExecutableElement element, FunctionDefinition function) {
+    unoptimized.putIfAbsent(element, () => copier.copy(function));
+  }
+
+  /// Look up the unoptimized CPS term for a function.
+  ///
+  /// The unoptimized term will not have any inlining-context-specific
+  /// optimizations applied to it.  It can be used to compile the
+  /// non-specialized version of the function.
+  FunctionDefinition getUnoptimized(ExecutableElement element) {
+    FunctionDefinition function = unoptimized[element];
+    if (function != null) {
+      function = copier.copy(function);
+      ParentVisitor.setParents(function);
+    }
+    return function;
+  }
 }
 
 class Inliner implements Pass {
@@ -323,7 +349,7 @@
         outgoingNames.add(formal.name);
       });
       newCallStructure =
-      new CallStructure(signature.parameterCount, outgoingNames);
+          new CallStructure(signature.parameterCount, outgoingNames);
     } else {
       signature.forEachOptionalParameter((ParameterElement formal) {
         if (parameterIndex < parameters.length) {
@@ -372,6 +398,13 @@
       return null;
     }
 
+    // Don't inline methods that never return. They are usually helper functions
+    // that throw an exception.
+    if (invoke.type.isEmpty && !invoke.type.isNullable) {
+      // TODO(sra): It would be ok to inline if doing so was shrinking.
+      return null;
+    }
+
     Reference<Primitive> dartReceiver = invoke.dartReceiverReference;
     TypeMask abstractReceiver =
         dartReceiver == null ? null : abstractType(dartReceiver);
@@ -434,9 +467,14 @@
       // The argument count at the call site does not match the target's
       // formal parameter count.  Build the IR term for an adapter function
       // body.
-      function = buildAdapter(invoke, target);
+      if (backend.isNative(target)) {
+        // TODO(25548): Generate correct adaptor for native methods.
+        return doNotInline();
+      } else {
+        function = buildAdapter(invoke, target);
+      }
     } else {
-      function = _inliner.functionCompiler.compileToCpsIr(target);
+      function = compileToCpsIr(target);
       void setValue(Variable variable, Reference<Primitive> value) {
         variable.type = value.definition.type;
       }
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index 812b204..599476f 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -25,6 +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 DuplicateBranchEliminator;
 export 'parent_visitor.dart' show ParentVisitor;
 
 /// An optimization pass over the CPS IR.
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_join.dart b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
index 92f64ae..808c1c7 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_join.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
@@ -8,15 +8,15 @@
 import 'optimizers.dart';
 
 /// Eliminates redundant join points.
-/// 
+///
 /// A redundant join point is a continuation that immediately branches
 /// based on one of its parameters, and that parameter is a constant value
 /// at every invocation. Each invocation is redirected to jump directly
 /// to the branch target.
-/// 
+///
 /// Internally in this pass, parameters are treated as names with lexical
 /// scoping, and a given parameter "name" may be declared by more than
-/// one continuation. The reference chains for parameters are therefore 
+/// one continuation. The reference chains for parameters are therefore
 /// meaningless during this pass, until repaired by [AlphaRenamer] at
 /// the end.
 class RedundantJoinEliminator extends TrampolineRecursiveVisitor implements Pass {
@@ -113,11 +113,11 @@
       return;
     }
 
-    // Lift any continuations bound inside branchCont so they are in scope at 
+    // Lift any continuations bound inside branchCont so they are in scope at
     // the call sites. When lifting, the parameters of branchCont fall out of
     // scope, so they are added as parameters on each lifted continuation.
     // Schematically:
-    // 
+    //
     //   (LetCont (branchCont (x1, x2, x3) =
     //        (LetCont (innerCont (y) = ...) in
     //        [... innerCont(y') ...]))
@@ -127,8 +127,8 @@
     //   (LetCont (innerCont (y, x1, x2, x3) = ...) in
     //   (LetCont (branchCont (x1, x2, x3) =
     //        [... innerCont(y', x1, x2, x3) ...])
-    // 
-    // Parameter objects become shared between branchCont and the lifted 
+    //
+    // Parameter objects become shared between branchCont and the lifted
     // continuations. [AlphaRenamer] will clean up at the end of this pass.
     LetCont outerLetCont = branchCont.parent;
     while (branchCont.body is LetCont) {
@@ -202,13 +202,13 @@
 /// Ensures parameter objects are not shared between different continuations,
 /// akin to alpha-renaming variables so every variable is named uniquely.
 /// For example:
-/// 
+///
 ///   LetCont (k1 x = (return x)) in
 ///   LetCont (k2 x = (InvokeContinuation k3 x)) in ...
-///     => 
+///     =>
 ///   LetCont (k1 x = (return x)) in
 ///   LetCont (k2 x' = (InvokeContinuation k3 x')) in ...
-/// 
+///
 /// After lifting LetConts in the main pass above, parameter objects can have
 /// multiple bindings. Each reference implicitly refers to the binding that
 /// is currently in scope.
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_phi.dart b/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
index 7f16af9..f5d5423 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_phi.dart
@@ -61,10 +61,10 @@
     /// Returns the unique definition of parameter i if it exists and null
     /// otherwise. A definition is unique if it is the only value used to
     /// invoke the continuation, excluding feedback.
-    Definition uniqueDefinitionOf(int i) {
-      Definition value = null;
+    Primitive uniqueDefinitionOf(int i) {
+      Primitive value = null;
       for (InvokeContinuation invoke in invokes) {
-        Definition def = invoke.arguments[i].definition;
+        Primitive def = invoke.arguments[i].definition.effectiveDefinition;
 
         if (cont.parameters[i] == def) {
           // Invocation param == param in LetCont (i.e. a recursive call).
@@ -104,7 +104,7 @@
     int dst = 0;
     for (int src = 0; src < cont.parameters.length; src++) {
       // Is the current phi redundant?
-      Definition uniqueDefinition = uniqueDefinitionOf(src);
+      Primitive uniqueDefinition = uniqueDefinitionOf(src);
       if (uniqueDefinition == null || !safeForHandlers(uniqueDefinition)) {
         // Reorganize parameters and arguments in case of deletions.
         if (src != dst) {
@@ -117,7 +117,7 @@
         continue;
       }
 
-      Definition oldDefinition = cont.parameters[src];
+      Primitive oldDefinition = cont.parameters[src];
 
       // Add continuations of about-to-be modified invokes to worklist since
       // we might introduce new optimization opportunities.
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index 16a1d15..42ae6cd 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -6,7 +6,6 @@
 
 import 'cps_ir_nodes.dart';
 import 'optimizers.dart';
-import 'cps_fragment.dart';
 
 /**
  * [ShrinkingReducer] applies shrinking reductions to CPS terms as described
@@ -15,26 +14,68 @@
 class ShrinkingReducer extends Pass {
   String get passName => 'Shrinking reductions';
 
-  List<_ReductionTask> _worklist;
-
-  static final _DeletedNode _DELETED = new _DeletedNode();
+  final List<_ReductionTask> _worklist = new List<_ReductionTask>();
 
   /// Applies shrinking reductions to root, mutating root in the process.
   @override
   void rewrite(FunctionDefinition root) {
-    _worklist = new List<_ReductionTask>();
     _RedexVisitor redexVisitor = new _RedexVisitor(_worklist);
 
     // Sweep over the term, collecting redexes into the worklist.
     redexVisitor.visit(root);
 
-    // Process the worklist.
+    _iterateWorklist();
+  }
+
+  void _iterateWorklist() {
     while (_worklist.isNotEmpty) {
       _ReductionTask task = _worklist.removeLast();
       _processTask(task);
     }
   }
 
+  /// Call instead of [_iterateWorklist] to check at every step that no
+  /// redex was missed.
+  void _debugWorklist(FunctionDefinition root) {
+    while (_worklist.isNotEmpty) {
+      _ReductionTask task = _worklist.removeLast();
+      String irBefore = root.debugString({
+        task.node: '${task.kind} applied here'
+      });
+      _processTask(task);
+      Set seenRedexes = _worklist.where(isValidTask).toSet();
+      Set actualRedexes = (new _RedexVisitor([])..visit(root)).worklist.toSet();
+      if (!seenRedexes.containsAll(actualRedexes)) {
+        _ReductionTask missedTask =
+            actualRedexes.firstWhere((x) => !seenRedexes.contains(x));
+        print('\nBEFORE $task:\n');
+        print(irBefore);
+        print('\nAFTER $task:\n');
+        root.debugPrint({
+          missedTask.node: 'MISSED ${missedTask.kind}'
+        });
+        throw 'Missed $missedTask after processing $task';
+      }
+    }
+  }
+
+  bool isValidTask(_ReductionTask task) {
+    switch (task.kind) {
+      case _ReductionKind.DEAD_VAL:
+        return _isDeadVal(task.node);
+      case _ReductionKind.DEAD_CONT:
+        return _isDeadCont(task.node);
+      case _ReductionKind.BETA_CONT_LIN:
+        return _isBetaContLin(task.node);
+      case _ReductionKind.ETA_CONT:
+        return _isEtaCont(task.node);
+      case _ReductionKind.DEAD_PARAMETER:
+        return _isDeadParameter(task.node);
+      case _ReductionKind.BRANCH:
+        return _isBranchRedex(task.node);
+    }
+  }
+
   /// Removes the given node from the CPS graph, replacing it with its body
   /// and marking it as deleted. The node's parent must be a [[InteriorNode]].
   void _removeNode(InteriorNode node) {
@@ -44,7 +85,14 @@
 
     body.parent = parent;
     parent.body = body;
-    node.parent = _DELETED;
+    node.parent = null;
+
+    // The removed node could be the last node between a continuation and
+    // an InvokeContinuation in the body.
+    if (parent is Continuation) {
+      _checkEtaCont(parent);
+      _checkUselessBranchTarget(parent);
+    }
   }
 
   /// Remove a given continuation from the CPS graph.  The LetCont itself is
@@ -56,12 +104,12 @@
     } else {
       parent.continuations.remove(cont);
     }
-    cont.parent = _DELETED;
+    cont.parent = null;
   }
 
   void _processTask(_ReductionTask task) {
     // Skip tasks for deleted nodes.
-    if (task.node.parent == _DELETED) {
+    if (task.node.parent == null) {
       return;
     }
 
@@ -81,6 +129,9 @@
       case _ReductionKind.DEAD_PARAMETER:
         _reduceDeadParameter(task);
         break;
+      case _ReductionKind.BRANCH:
+        _reduceBranch(task);
+        break;
       default:
         assert(false);
     }
@@ -89,15 +140,31 @@
   /// Applies the dead-val reduction:
   ///   letprim x = V in E -> E (x not free in E).
   void _reduceDeadVal(_ReductionTask task) {
+    if (_isRemoved(task.node)) return;
     assert(_isDeadVal(task.node));
 
-    // Remove dead primitive.
-    LetPrim letPrim = task.node;
-    destroyRefinementsOfDeadPrimitive(letPrim.primitive);
-    _removeNode(letPrim);
+    LetPrim deadLet = task.node;
+    Primitive deadPrim = deadLet.primitive;
+    assert(deadPrim.hasNoRefinedUses);
+    // The node has no effective uses but can have refinement uses, which
+    // themselves can have more refinements uses (but only refinement uses).
+    // We must remove the entire refinement tree while looking for redexes
+    // whenever we remove one.
+    List<Primitive> deadlist = <Primitive>[deadPrim];
+    while (deadlist.isNotEmpty) {
+      Primitive node = deadlist.removeLast();
+      while (node.firstRef != null) {
+        Reference ref = node.firstRef;
+        Refinement use = ref.parent;
+        deadlist.add(use);
+        ref.unlink();
+      }
+      LetPrim binding = node.parent;
+      _removeNode(binding); // Remove the binding and check for eta redexes.
+    }
 
     // Perform bookkeeping on removed body and scan for new redexes.
-    new _RemovalVisitor(_worklist).visit(letPrim.primitive);
+    new _RemovalVisitor(_worklist).visit(deadPrim);
   }
 
   /// Applies the dead-cont reduction:
@@ -127,25 +194,36 @@
       return;
     }
 
-    // Remove the continuation.
     Continuation cont = task.node;
-    _removeContinuation(cont);
-
-    // Replace its invocation with the continuation body.
     InvokeContinuation invoke = cont.firstRef.parent;
     InteriorNode invokeParent = invoke.parent;
+    Expression body = cont.body;
 
-    cont.body.parent = invokeParent;
-    invokeParent.body = cont.body;
+    // Replace the invocation with the continuation body.
+    invokeParent.body = body;
+    body.parent = invokeParent;
+    cont.body = null;
 
     // Substitute the invocation argument for the continuation parameter.
     for (int i = 0; i < invoke.arguments.length; i++) {
-      cont.parameters[i].replaceUsesWith(invoke.arguments[i].definition);
-      invoke.arguments[i].definition.useElementAsHint(cont.parameters[i].hint);
+      Parameter param = cont.parameters[i];
+      Primitive argument = invoke.arguments[i].definition;
+      param.replaceUsesWith(argument);
+      argument.useElementAsHint(param.hint);
+      _checkConstantBranchCondition(argument);
     }
 
+    // Remove the continuation after inlining it so we can check for eta redexes
+    // which may arise after removing the LetCont.
+    _removeContinuation(cont);
+
     // Perform bookkeeping on substituted body and scan for new redexes.
     new _RemovalVisitor(_worklist).visit(invoke);
+
+    if (invokeParent is Continuation) {
+      _checkEtaCont(invokeParent);
+      _checkUselessBranchTarget(invokeParent);
+    }
   }
 
   /// Applies the eta-cont reduction:
@@ -184,13 +262,48 @@
       }
     }
 
-    // Replace all occurrences with the wrapped continuation.
-    cont.replaceUsesWith(wrappedCont);
+    // Replace all occurrences with the wrapped continuation and find redexes.
+    while (cont.firstRef != null) {
+      Reference ref = cont.firstRef;
+      ref.changeTo(wrappedCont);
+      Node use = ref.parent;
+      if (use is InvokeContinuation && use.parent is Continuation) {
+        _checkUselessBranchTarget(use.parent);
+      }
+    }
 
     // Perform bookkeeping on removed body and scan for new redexes.
     new _RemovalVisitor(_worklist).visit(cont);
   }
 
+  void _reduceBranch(_ReductionTask task) {
+    Branch branch = task.node;
+    // Replace Branch with InvokeContinuation of one of the targets. When the
+    // branch is deleted the other target becomes unreferenced and the chosen
+    // target becomes available for eta-cont and further reductions.
+    Continuation target;
+    Primitive condition = branch.condition.definition;
+    if (condition is Constant) {
+      target = isTruthyConstant(condition.value, strict: branch.isStrictCheck)
+          ? branch.trueContinuation.definition
+          : branch.falseContinuation.definition;
+    } else if (_isBranchTargetOfUselessIf(branch.trueContinuation.definition)) {
+      target = branch.trueContinuation.definition;
+    } else {
+      return;
+    }
+
+    InvokeContinuation invoke = new InvokeContinuation(
+        target, <Primitive>[]
+        // TODO(sra): Add sourceInformation.
+        /*, sourceInformation: branch.sourceInformation*/);
+    branch.parent.body = invoke;
+    invoke.parent = branch.parent;
+    branch.parent = null;
+
+    new _RemovalVisitor(_worklist).visit(branch);
+  }
+
   void _reduceDeadParameter(_ReductionTask task) {
     // Continuation eta-reduction can destroy a dead parameter redex.  For
     // example, in the term:
@@ -207,61 +320,105 @@
     // Where the dead parameter reduction is no longer valid because we do not
     // allow removing the paramter of call continuations.  We disallow such eta
     // reductions in [_isEtaCont].
-    assert(_isDeadParameter(task.node));
-
     Parameter parameter = task.node;
+    if (_isParameterRemoved(parameter)) return;
+    assert(_isDeadParameter(parameter));
+
     Continuation continuation = parameter.parent;
     int index = continuation.parameters.indexOf(parameter);
     assert(index != -1);
+    continuation.parameters.removeAt(index);
+    parameter.parent = null; // Mark as removed.
 
     // Remove the index'th argument from each invocation.
-    Reference<Continuation> current = continuation.firstRef;
-    while (current != null) {
-      InvokeContinuation invoke = current.parent;
+    for (Reference ref = continuation.firstRef; ref != null; ref = ref.next) {
+      InvokeContinuation invoke = ref.parent;
       Reference<Primitive> argument = invoke.arguments[index];
       argument.unlink();
-      // Removing an argument can create a dead parameter or dead value redex.
-      if (argument.definition is Parameter) {
-        if (_isDeadParameter(argument.definition)) {
-          _worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER,
-                                           argument.definition));
-        }
-      } else {
-        Node parent = argument.definition.parent;
-        if (parent is LetPrim) {
-          if (_isDeadVal(parent)) {
-            _worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent));
-          }
-        }
-      }
       invoke.arguments.removeAt(index);
-      current = current.next;
+      // Removing an argument can create a dead primitive or an eta-redex
+      // in case the parent is a continuation that now has matching parameters.
+      _checkDeadPrimitive(argument.definition);
+      if (invoke.parent is Continuation) {
+        _checkEtaCont(invoke.parent);
+        _checkUselessBranchTarget(invoke.parent);
+      }
     }
-    continuation.parameters.removeAt(index);
 
-    // Removing an unused parameter can create an eta-redex.
+    // Removing an unused parameter can create an eta-redex, in case the
+    // body is an InvokeContinuation that now has matching arguments.
+    _checkEtaCont(continuation);
+  }
+
+  void _checkEtaCont(Continuation continuation) {
     if (_isEtaCont(continuation)) {
       _worklist.add(new _ReductionTask(_ReductionKind.ETA_CONT, continuation));
     }
   }
+
+  void _checkUselessBranchTarget(Continuation continuation) {
+    if (_isBranchTargetOfUselessIf(continuation)) {
+      _worklist.add(new _ReductionTask(_ReductionKind.BRANCH,
+          continuation.firstRef.parent));
+    }
+  }
+
+  void _checkConstantBranchCondition(Primitive primitive) {
+    if (primitive is! Constant) return;
+    for (Reference ref = primitive.firstRef; ref != null; ref = ref.next) {
+      Node use = ref.parent;
+      if (use is Branch) {
+        _worklist.add(new _ReductionTask(_ReductionKind.BRANCH, use));
+      }
+    }
+  }
+
+  void _checkDeadPrimitive(Primitive primitive) {
+    primitive = primitive.unrefined;
+    if (primitive is Parameter) {
+      if (_isDeadParameter(primitive)) {
+        _worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER,
+                                         primitive));
+      }
+    } else if (primitive.parent is LetPrim) {
+      LetPrim letPrim = primitive.parent;
+      if (_isDeadVal(letPrim)) {
+        _worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, letPrim));
+      }
+    }
+  }
+}
+
+bool _isRemoved(InteriorNode node) {
+  return node.parent == null;
+}
+
+bool _isParameterRemoved(Parameter parameter) {
+  // A parameter can be removed directly or because its continuation is removed.
+  return parameter.parent == null || _isRemoved(parameter.parent);
 }
 
 /// Returns true iff the bound primitive is unused, and has no effects
 /// preventing it from being eliminated.
 bool _isDeadVal(LetPrim node) {
-  return node.primitive.hasNoEffectiveUses &&
+  return !_isRemoved(node) &&
+         node.primitive.hasNoRefinedUses &&
          node.primitive.isSafeForElimination;
 }
 
 /// Returns true iff the continuation is unused.
 bool _isDeadCont(Continuation cont) {
-  return !cont.isReturnContinuation && !cont.hasAtLeastOneUse;
+  return !_isRemoved(cont) &&
+         !cont.isReturnContinuation &&
+         !cont.hasAtLeastOneUse;
 }
 
 /// Returns true iff the continuation has a body (i.e., it is not the return
 /// continuation), it is used exactly once, and that use is as the continuation
 /// of a continuation invocation.
 bool _isBetaContLin(Continuation cont) {
+  if (_isRemoved(cont)) return false;
+
   // There is a restriction on continuation eta-redexes that the body is not an
   // invocation of the return continuation, because that leads to worse code
   // when translating back to direct style (it duplicates returns).  There is no
@@ -275,26 +432,21 @@
   if (cont.firstRef.parent is! InvokeContinuation) return false;
 
   InvokeContinuation invoke = cont.firstRef.parent;
-  if (cont != invoke.continuation.definition) return false;
 
   // Beta-reduction will move the continuation's body to its unique invocation
   // site.  This is not safe if the body is moved into an exception handler
-  // binding.  Search from the invocation to the continuation binding to
-  // make sure that there is no binding for a handler.
-  Node current = invoke.parent;
-  while (current != cont.parent) {
-    // There is no need to reduce a beta-redex inside a deleted subterm.
-    if (current == ShrinkingReducer._DELETED) return false;
-    if (current is LetHandler) return false;
-    current = current.parent;
-  }
+  // binding.
+  if (invoke.isEscapingTry) return false;
+
   return true;
 }
 
 /// Returns true iff the continuation consists of a continuation
 /// invocation, passing on all parameters. Special cases exist (see below).
 bool _isEtaCont(Continuation cont) {
-  if (cont.isReturnContinuation || cont.body is! InvokeContinuation) {
+  if (_isRemoved(cont)) return false;
+
+  if (!cont.isJoinContinuation || cont.body is! InvokeContinuation) {
     return false;
   }
 
@@ -307,25 +459,6 @@
     return false;
   }
 
-  // Do not perform reductions replace a function call continuation with a
-  // non-call continuation.  The invoked continuation is definitely not a call
-  // continuation, because it has a direct invocation in this continuation's
-  // body.
-  bool isCallContinuation(Continuation continuation) {
-    Reference<Continuation> current = cont.firstRef;
-    while (current != null) {
-      if (current.parent is InvokeContinuation) {
-        InvokeContinuation invoke = current.parent;
-        if (invoke.continuation.definition == continuation) return false;
-      }
-      current = current.next;
-    }
-    return true;
-  }
-  if (isCallContinuation(cont)) {
-    return false;
-  }
-
   // Translation to direct style generates different statements for recursive
   // and non-recursive invokes. It should still be possible to apply eta-cont if
   // this is not a self-invocation.
@@ -371,15 +504,61 @@
   return true;
 }
 
-bool _isDeadParameter(Parameter parameter) {
-  // We cannot remove function parameters as an intraprocedural optimization.
-  if (parameter.parent is! Continuation || parameter.hasAtLeastOneUse) {
+Expression _unfoldDeadRefinements(Expression node) {
+  while (node is LetPrim) {
+    LetPrim let = node;
+    Primitive prim = let.primitive;
+    if (prim.hasAtLeastOneUse || prim is! Refinement) return node;
+    node = node.next;
+  }
+  return node;
+}
+
+bool _isBranchRedex(Branch branch) {
+  return _isUselessIf(branch) || branch.condition.definition is Constant;
+}
+
+bool _isBranchTargetOfUselessIf(Continuation cont) {
+  // A useless-if has an empty then and else branch, e.g. `if (cond);`.
+  //
+  // Detect T or F in
+  //
+  //     let cont Join() = ...
+  //       in let cont T() = Join()
+  //                   F() = Join()
+  //         in branch condition T F
+  //
+  if (!cont.hasExactlyOneUse) return false;
+  Node use = cont.firstRef.parent;
+  if (use is! Branch) return false;
+  return _isUselessIf(use);
+}
+
+bool _isUselessIf(Branch branch) {
+  Continuation trueCont = branch.trueContinuation.definition;
+  Expression trueBody = _unfoldDeadRefinements(trueCont.body);
+  if (trueBody is! InvokeContinuation) return false;
+  Continuation falseCont = branch.falseContinuation.definition;
+  Expression falseBody = _unfoldDeadRefinements(falseCont.body);
+  if (falseBody is! InvokeContinuation) return false;
+  InvokeContinuation trueInvoke = trueBody;
+  InvokeContinuation falseInvoke = falseBody;
+  if (trueInvoke.continuation.definition !=
+      falseInvoke.continuation.definition) {
     return false;
   }
+  assert(trueInvoke.arguments.length == falseInvoke.arguments.length);
+  // Matching zero arguments should be adequate, since isomorphic true and false
+  // invocations should result in redundant phis which are removed elsewhere.
+  if (trueInvoke.arguments.isNotEmpty) return false;
+  return true;
+}
 
-  // We cannot remove exception handler parameters, they have a fixed arity
-  // of two.
-  if (parameter.parent.parent is LetHandler) {
+bool _isDeadParameter(Parameter parameter) {
+  if (_isParameterRemoved(parameter)) return false;
+
+  // We cannot remove function parameters as an intraprocedural optimization.
+  if (parameter.parent is! Continuation || parameter.hasAtLeastOneUse) {
     return false;
   }
 
@@ -388,14 +567,8 @@
   // exactly one argument).  The return continuation is a call continuation, so
   // we cannot remove its dummy parameter.
   Continuation continuation = parameter.parent;
-  if (continuation.isReturnContinuation) return false;
-  Reference<Continuation> current = continuation.firstRef;
-  while (current != null) {
-    if (current.parent is! InvokeContinuation) return false;
-    InvokeContinuation invoke = current.parent;
-    if (invoke.continuation.definition != continuation) return false;
-    current = current.next;
-  }
+  if (!continuation.isJoinContinuation) return false;
+
   return true;
 }
 
@@ -411,6 +584,12 @@
     }
   }
 
+  void processBranch(Branch node) {
+    if (_isBranchRedex(node)) {
+      worklist.add(new _ReductionTask(_ReductionKind.BRANCH, node));
+    }
+  }
+
   void processContinuation(Continuation node) {
     // While it would be nice to remove exception handlers that are provably
     // unnecessary (e.g., the body cannot throw), that takes more sophisticated
@@ -452,23 +631,26 @@
   _RemovalVisitor(this.worklist);
 
   void processLetPrim(LetPrim node) {
-    node.parent = ShrinkingReducer._DELETED;
+    node.parent = null;
   }
 
   void processContinuation(Continuation node) {
-    node.parent = ShrinkingReducer._DELETED;
+    node.parent = null;
   }
 
   void processReference(Reference reference) {
     reference.unlink();
 
     if (reference.definition is Primitive) {
-      Primitive primitive = reference.definition;
+      Primitive primitive = reference.definition.unrefined;
       Node parent = primitive.parent;
       // The parent might be the deleted sentinel, or it might be a
       // Continuation or FunctionDefinition if the primitive is an argument.
       if (parent is LetPrim && _isDeadVal(parent)) {
         worklist.add(new _ReductionTask(_ReductionKind.DEAD_VAL, parent));
+      } else if (primitive is Parameter && _isDeadParameter(primitive)) {
+        worklist.add(new _ReductionTask(_ReductionKind.DEAD_PARAMETER,
+            primitive));
       }
     } else if (reference.definition is Continuation) {
       Continuation cont = reference.definition;
@@ -486,29 +668,22 @@
           worklist.add(new _ReductionTask(_ReductionKind.DEAD_CONT, cont));
         } else if (_isBetaContLin(cont)) {
           worklist.add(new _ReductionTask(_ReductionKind.BETA_CONT_LIN, cont));
+        } else if (_isBranchTargetOfUselessIf(cont)) {
+          worklist.add(
+              new _ReductionTask(_ReductionKind.BRANCH, cont.firstRef.parent));
         }
       }
     }
   }
 }
 
-
-
-class _ReductionKind {
-  final String name;
-  final int hashCode;
-
-  const _ReductionKind(this.name, this.hashCode);
-
-  static const _ReductionKind DEAD_VAL = const _ReductionKind('dead-val', 0);
-  static const _ReductionKind DEAD_CONT = const _ReductionKind('dead-cont', 1);
-  static const _ReductionKind BETA_CONT_LIN =
-      const _ReductionKind('beta-cont-lin', 2);
-  static const _ReductionKind ETA_CONT = const _ReductionKind('eta-cont', 3);
-  static const _ReductionKind DEAD_PARAMETER =
-      const _ReductionKind('dead-parameter', 4);
-
-  String toString() => name;
+enum _ReductionKind {
+  DEAD_VAL,
+  DEAD_CONT,
+  BETA_CONT_LIN,
+  ETA_CONT,
+  DEAD_PARAMETER,
+  BRANCH
 }
 
 /// Represents a reduction task on the worklist. Implements both hashCode and
@@ -518,12 +693,12 @@
   final Node node;
 
   int get hashCode {
-    assert(kind.hashCode < (1 << 3));
-    return (node.hashCode << 3) | kind.hashCode;
+    return (node.hashCode << 3) | kind.index;
   }
 
   _ReductionTask(this.kind, this.node) {
-    assert(node is Continuation || node is LetPrim || node is Parameter);
+    assert(node is Continuation || node is LetPrim || node is Parameter ||
+           node is Branch);
   }
 
   bool operator==(_ReductionTask that) {
@@ -532,10 +707,3 @@
 
   String toString() => "$kind: $node";
 }
-
-/// A dummy class used solely to mark nodes as deleted once they are removed
-/// from a term.
-class _DeletedNode extends Node {
-  accept(_) {}
-  setParentPointers() {}
-}
diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
index 25fb1c9..0a21c3f 100644
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
@@ -448,10 +448,8 @@
   }
 
   @override
-  bool areDisjoint(TypeMask leftType, TypeMask rightType) {
-    TypeMask intersected = intersection(leftType, rightType);
-    return intersected.isEmpty && !intersected.isNullable;
-  }
+  bool areDisjoint(TypeMask leftType, TypeMask rightType) =>
+      leftType.isDisjoint(rightType, classWorld);
 
   @override
   bool isMorePreciseOrEqual(TypeMask t1, TypeMask t2) {
@@ -468,8 +466,8 @@
     }
     if (type is types.InterfaceType) {
       TypeMask typeAsMask = allowNull
-      ? new TypeMask.subtype(type.element, classWorld)
-      : new TypeMask.nonNullSubtype(type.element, classWorld);
+          ? new TypeMask.subtype(type.element, classWorld)
+          : new TypeMask.nonNullSubtype(type.element, classWorld);
       if (areDisjoint(value, typeAsMask)) {
         // Disprove the subtype relation based on the class alone.
         return AbstractBool.False;
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index aa26e31..6277667 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -714,8 +714,10 @@
   final CpsFunctionCompiler _functionCompiler;
   final Map<Variable, ConstantValue> _values= <Variable, ConstantValue>{};
   final ConstantPropagationLattice _lattice;
+  final bool recomputeAll;
 
-  TypePropagator(CpsFunctionCompiler functionCompiler)
+  TypePropagator(CpsFunctionCompiler functionCompiler,
+      {this.recomputeAll: false})
       : _functionCompiler = functionCompiler,
         _lattice = new ConstantPropagationLattice(functionCompiler);
 
@@ -731,7 +733,7 @@
         _values,
         _internalError);
 
-    analyzer.analyze(root);
+    analyzer.analyze(root, recomputeAll);
 
     // Transform. Uses the data acquired in the previous analysis phase to
     // replace branches with fixed targets and side-effect-free expressions
@@ -1047,6 +1049,16 @@
       push(invoke);
       return;
     }
+
+    // Shortcut negation to help simplify control flow. The tree IR will insert
+    // a negation again if that's useful.
+    if (condition is ApplyBuiltinOperator &&
+        condition.operator == BuiltinOperator.IsFalsy) {
+      node.condition.changeTo(condition.arguments.single.definition);
+      node.trueContinuation.changeTo(falseCont);
+      node.falseContinuation.changeTo(trueCont);
+      return;
+    }
   }
 
   void visitInvokeContinuation(InvokeContinuation node) {
@@ -1142,7 +1154,7 @@
       return cps;
     }
 
-    if (node.selector.isOperator && node.arguments.length == 2) {
+    if (node.selector.isOperator && node.dartArgumentsLength == 1) {
       Primitive leftArg = node.dartReceiver;
       Primitive rightArg = node.dartArgument(0);
       AbstractConstantValue left = getValue(leftArg);
@@ -1223,7 +1235,7 @@
         }
       }
     }
-    if (node.selector.isOperator && node.arguments.length == 1) {
+    if (node.selector.isOperator && node.dartArgumentsLength == 0) {
       Primitive argument = node.dartReceiver;
       AbstractConstantValue value = getValue(argument);
 
@@ -1244,7 +1256,7 @@
       Primitive receiver = node.dartReceiver;
       AbstractConstantValue receiverValue = getValue(receiver);
       if (name == 'remainder') {
-        if (node.arguments.length == 2) {
+        if (node.dartArgumentsLength == 1) {
           Primitive arg = node.dartArgument(0);
           AbstractConstantValue argValue = getValue(arg);
           if (lattice.isDefinitelyInt(receiverValue, allowNull: true) &&
@@ -1255,7 +1267,7 @@
           }
         }
       } else if (name == 'codeUnitAt') {
-        if (node.arguments.length == 2) {
+        if (node.dartArgumentsLength == 1) {
           Primitive index = node.dartArgument(0);
           if (lattice.isDefinitelyString(receiverValue) &&
               lattice.isDefinitelyInt(getValue(index))) {
@@ -1534,7 +1546,7 @@
         // Check that all uses of the iterator are 'moveNext' and 'current'.
         assert(!isInterceptedSelector(Selectors.moveNext));
         assert(!isInterceptedSelector(Selectors.current));
-        for (Reference ref in iterator.effectiveUses) {
+        for (Reference ref in iterator.refinedUses) {
           if (ref.parent is! InvokeMethod) return null;
           InvokeMethod use = ref.parent;
           if (ref != use.receiver) return null;
@@ -1551,7 +1563,7 @@
         MutableVariable current = new MutableVariable(new LoopItemEntity());
 
         // Rewrite all uses of the iterator.
-        for (Reference ref in iterator.effectiveUses) {
+        for (Reference ref in iterator.refinedUses) {
           InvokeMethod use = ref.parent;
           if (use.selector == Selectors.current) {
             // Rewrite iterator.current to a use of the 'current' variable.
@@ -1760,7 +1772,7 @@
 
       // If there are multiple uses, we cannot eliminate the getter call and
       // therefore risk duplicating its side effects.
-      if (!isPure && tearOff.hasMultipleEffectiveUses) return null;
+      if (!isPure && tearOff.hasMultipleRefinedUses) return null;
 
       // If the getter call is impure, we risk reordering side effects,
       // unless it is immediately prior to the closure call.
@@ -1776,7 +1788,7 @@
         sourceInformation: node.sourceInformation);
       node.receiver.changeTo(new Parameter(null)); // Remove the tear off use.
 
-      if (tearOff.hasNoEffectiveUses) {
+      if (tearOff.hasNoRefinedUses) {
         // Eliminate the getter call if it has no more uses.
         // This cannot be delegated to other optimizations because we need to
         // avoid duplication of side effects.
@@ -1991,7 +2003,7 @@
   //     Nothing happens. The primitive remains as it is.
   //
 
-  void visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
+  visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
     ast.DartString getString(AbstractConstantValue value) {
       StringConstantValue constant = value.constant;
       return constant.primitiveValue;
@@ -2051,42 +2063,70 @@
         Primitive rightArg = node.arguments[1].definition;
         AbstractConstantValue left = getValue(leftArg);
         AbstractConstantValue right = getValue(rightArg);
-        if (lattice.isDefinitelyBool(left) &&
-            right.isConstant &&
-            right.constant.isTrue) {
-          // Replace identical(x, true) by x when x is known to be a boolean.
-          // Note that this is not safe if x is null, because the value might
-          // not be used as a condition.
-          node.replaceUsesWith(leftArg);
-        } else if (lattice.isDefinitelyBool(right) &&
-            left.isConstant &&
-            left.constant.isTrue) {
-          node.replaceUsesWith(rightArg);
-        } else if (left.isNullConstant || right.isNullConstant) {
+        BuiltinOperator newOperator;
+        if (left.isNullConstant || right.isNullConstant) {
           // Use `==` for comparing against null, so JS undefined and JS null
           // are considered equal.
-          node.operator = BuiltinOperator.LooseEq;
+          newOperator = BuiltinOperator.LooseEq;
         } else if (!left.isNullable || !right.isNullable) {
           // If at most one operand can be Dart null, we can use `===`.
           // This is not safe when we might compare JS null and JS undefined.
-          node.operator = BuiltinOperator.StrictEq;
+          newOperator = BuiltinOperator.StrictEq;
         } else if (lattice.isDefinitelyNum(left, allowNull: true) &&
                    lattice.isDefinitelyNum(right, allowNull: true)) {
           // If both operands can be null, but otherwise are of the same type,
           // we can use `==` for comparison.
           // This is not safe e.g. for comparing strings against numbers.
-          node.operator = BuiltinOperator.LooseEq;
+          newOperator = BuiltinOperator.LooseEq;
         } else if (lattice.isDefinitelyString(left, allowNull: true) &&
                    lattice.isDefinitelyString(right, allowNull: true)) {
-          node.operator = BuiltinOperator.LooseEq;
+          newOperator = BuiltinOperator.LooseEq;
         } else if (lattice.isDefinitelyBool(left, allowNull: true) &&
                    lattice.isDefinitelyBool(right, allowNull: true)) {
-          node.operator = BuiltinOperator.LooseEq;
+          newOperator = BuiltinOperator.LooseEq;
+        }
+        if (newOperator != null) {
+          return new ApplyBuiltinOperator(newOperator,
+              node.arguments.map((ref) => ref.definition).toList(),
+              node.sourceInformation);
+        }
+        break;
+
+      case BuiltinOperator.StrictEq:
+      case BuiltinOperator.LooseEq:
+      case BuiltinOperator.StrictNeq:
+      case BuiltinOperator.LooseNeq:
+        bool negated =
+            node.operator == BuiltinOperator.StrictNeq ||
+            node.operator == BuiltinOperator.LooseNeq;
+        for (int firstIndex in [0, 1]) {
+          int secondIndex = 1 - firstIndex;
+          Primitive firstArg = node.arguments[firstIndex].definition;
+          Primitive secondArg = node.arguments[secondIndex].definition;
+          AbstractConstantValue first = getValue(firstArg);
+          if (!lattice.isDefinitelyBool(first)) continue;
+          AbstractConstantValue second = getValue(secondArg);
+          if (!second.isConstant || !second.constant.isBool) continue;
+          bool isTrueConstant = second.constant.isTrue;
+          if (isTrueConstant == !negated) {
+            // (x === true) ==> x
+            // (x !== false) ==> x
+            node.replaceUsesWith(firstArg);
+            return null;
+          } else {
+            // (x === false) ==> !x
+            // (x !== true) ==> !x
+            return new ApplyBuiltinOperator(
+                BuiltinOperator.IsFalsy,
+                [firstArg],
+                node.sourceInformation);
+          }
         }
         break;
 
       default:
     }
+    return null;
   }
 
   void visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
@@ -2288,8 +2328,11 @@
                          this.values,
                          this.internalError);
 
-  void analyze(FunctionDefinition root) {
+  void analyze(FunctionDefinition root, bool recomputeAll) {
     reachableContinuations.clear();
+    if (recomputeAll) {
+      new ResetAnalysisInfo(reachableContinuations, values).visit(root);
+    }
 
     // Initially, only the root node is reachable.
     push(root);
@@ -2532,7 +2575,7 @@
 
     // Calculate the resulting constant if possible.
     String opname = node.selector.name;
-    if (node.arguments.length == 1) {
+    if (node.dartArgumentsLength == 0) {
       // Unary operator.
       if (opname == "unary-") {
         opname = "-";
@@ -2540,7 +2583,7 @@
       UnaryOperator operator = UnaryOperator.parse(opname);
       AbstractConstantValue result = lattice.unaryOp(operator, receiver);
       return finish(result, canReplace: !receiver.isNullable);
-    } else if (node.arguments.length == 2) {
+    } else if (node.dartArgumentsLength == 1) {
       // Binary operator.
       AbstractConstantValue right = getValue(node.dartArgument(0));
       BinaryOperator operator = BinaryOperator.parse(opname);
@@ -2619,37 +2662,34 @@
 
       case BuiltinOperator.Identical:
       case BuiltinOperator.StrictEq:
+      case BuiltinOperator.StrictNeq:
       case BuiltinOperator.LooseEq:
-        AbstractConstantValue leftConst =
-            getValue(node.arguments[0].definition);
-        AbstractConstantValue rightConst =
-            getValue(node.arguments[1].definition);
-        ConstantValue leftValue = leftConst.constant;
-        ConstantValue rightValue = rightConst.constant;
-        if (leftConst.isNothing || rightConst.isNothing) {
+      case BuiltinOperator.LooseNeq:
+        bool negated =
+            node.operator == BuiltinOperator.StrictNeq ||
+            node.operator == BuiltinOperator.LooseNeq;
+        AbstractConstantValue left = getValue(node.arguments[0].definition);
+        AbstractConstantValue right = getValue(node.arguments[1].definition);
+        if (left.isNothing || right.isNothing) {
           setValue(node, lattice.nothing);
-          return; // And come back later.
-        } else if (!leftConst.isConstant || !rightConst.isConstant) {
-          TypeMask leftType = leftConst.type;
-          TypeMask rightType = rightConst.type;
-          if (typeSystem.areDisjoint(leftType, rightType)) {
-            setValue(node,
-                constantValue(new FalseConstantValue(), typeSystem.boolType));
-          } else {
-            setValue(node, nonConstant(typeSystem.boolType));
-          }
           return;
-        } else if (leftValue.isPrimitive && rightValue.isPrimitive) {
-          assert(leftConst.isConstant && rightConst.isConstant);
-          PrimitiveConstantValue left = leftValue;
-          PrimitiveConstantValue right = rightValue;
-          // Should this be constantSystem.identity.fold(left, right)?
-          ConstantValue result =
-            new BoolConstantValue(left.primitiveValue == right.primitiveValue);
-          setValue(node, constantValue(result, typeSystem.boolType));
-        } else {
-          setValue(node, nonConstant(typeSystem.boolType));
         }
+        if (left.isConstant && right.isConstant) {
+          ConstantValue equal = lattice.constantSystem.identity.fold(
+              left.constant, right.constant);
+          if (equal != null && equal.isBool) {
+            ConstantValue result =
+                new BoolConstantValue(equal.isTrue == !negated);
+            setValue(node, constantValue(result, typeSystem.boolType));
+            return;
+          }
+        }
+        if (typeSystem.areDisjoint(left.type, right.type)) {
+          ConstantValue result = new BoolConstantValue(negated);
+          setValue(node, constantValue(result, typeSystem.boolType));
+          return;
+        }
+        setValue(node, nonConstant(typeSystem.boolType));
         break;
 
       case BuiltinOperator.NumAdd:
@@ -2862,12 +2902,6 @@
     }
   }
 
-  void visitLiteralMap(LiteralMap node) {
-    // Constant maps are translated into (Constant MapConstant(...)) IR nodes,
-    // and thus LiteralMap nodes are NonConst.
-    setValue(node, nonConstant(typeSystem.mapType));
-  }
-
   void visitConstant(Constant node) {
     ConstantValue value = node.value;
     if (value.isDummy || !value.isConstant) {
@@ -2980,7 +3014,21 @@
 
   @override
   void visitForeignCode(ForeignCode node) {
-    setValue(node, nonConstant(node.type));
+    bool firstArgumentIsNullable = false;
+    if (node.arguments.length > 0) {
+      AbstractConstantValue first = getValue(node.arguments.first.definition);
+      if (first.isNothing) {
+        setValue(node, nothing);
+        return;
+      }
+      firstArgumentIsNullable = first.isNullable;
+    }
+    setValue(node, nonConstant(node.storedType));
+    node.isSafeForElimination =
+        !node.nativeBehavior.sideEffects.hasSideEffects() &&
+        (!node.nativeBehavior.throwBehavior.canThrow ||
+         (!firstArgumentIsNullable &&
+          node.nativeBehavior.throwBehavior.isOnlyNullNSMGuard));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/cps_ir/update_refinements.dart b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
index d93e747..48e3242 100644
--- a/pkg/compiler/lib/src/cps_ir/update_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
@@ -20,7 +20,7 @@
 
   final TypeMaskSystem typeSystem;
 
-  Map<Primitive, Refinement> refinementFor = <Primitive, Refinement>{};
+  Map<Primitive, Primitive> refinementFor = <Primitive, Primitive>{};
 
   UpdateRefinements(this.typeSystem);
 
@@ -29,11 +29,33 @@
   }
 
   Expression traverseLetPrim(LetPrim node) {
+    Expression next = node.body;
     visit(node.primitive);
-    return node.body;
+    return next;
   }
 
-  @override
+  visitNullCheck(NullCheck node) {
+    if (refine(node.value)) {
+      Primitive value = node.value.definition;
+      if (value.type.isNullable) {
+        // Update the type if the input has changed.
+        node.type = value.type.nonNullable();
+      } else {
+        node..replaceUsesWith(value)..destroy();
+        LetPrim letPrim = node.parent;
+        letPrim.remove();
+        return;
+      }
+    }
+    // Use the NullCheck as a refinement.
+    Primitive value = node.effectiveDefinition;
+    Primitive old = refinementFor[value];
+    refinementFor[value] = node;
+    pushAction(() {
+      refinementFor[value] = old;
+    });
+  }
+
   visitRefinement(Refinement node) {
     if (refine(node.value)) {
       // Update the type if the input has changed.
@@ -41,14 +63,13 @@
           node.refineType);
     }
     Primitive value = node.effectiveDefinition;
-    Refinement old = refinementFor[value];
+    Primitive old = refinementFor[value];
     refinementFor[value] = node;
     pushAction(() {
       refinementFor[value] = old;
     });
   }
 
-  @override
   processReference(Reference ref) {
     refine(ref);
   }
@@ -56,7 +77,7 @@
   bool refine(Reference ref) {
     Definition def = ref.definition;
     if (def is Primitive) {
-      Refinement refinement = refinementFor[def.effectiveDefinition];
+      Primitive refinement = refinementFor[def.effectiveDefinition];
       if (refinement != null && refinement != ref.definition) {
         ref.changeTo(refinement);
         return true;
diff --git a/pkg/compiler/lib/src/diagnostics/dart2js_messages.dart b/pkg/compiler/lib/src/diagnostics/dart2js_messages.dart
deleted file mode 100644
index 90d4ecf..0000000
--- a/pkg/compiler/lib/src/diagnostics/dart2js_messages.dart
+++ /dev/null
@@ -1,3732 +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.
-
-// The messages in this file should meet the following guide lines:
-//
-// 1. The message should be a complete sentence starting with an uppercase
-// letter, and ending with a period.
-//
-// 2. Reserved words and embedded identifiers should be in single quotes, so
-// prefer double quotes for the complete message. For example, "The
-// class '#{className}' can't use 'super'." Notice that the word 'class' in the
-// preceding message is not quoted as it refers to the concept 'class', not the
-// reserved word. On the other hand, 'super' refers to the reserved word. Do
-// not quote 'null' and numeric literals.
-//
-// 3. Do not try to compose messages, as it can make translating them hard.
-//
-// 4. Try to keep the error messages short, but informative.
-//
-// 5. Use simple words and terminology, assume the reader of the message
-// doesn't have an advanced degree in math, and that English is not the
-// reader's native language. Do not assume any formal computer science
-// training. For example, do not use Latin abbreviations (prefer "that is" over
-// "i.e.", and "for example" over "e.g."). Also avoid phrases such as "if and
-// only if" and "iff", that level of precision is unnecessary.
-//
-// 6. Prefer contractions when they are in common use, for example, prefer
-// "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
-// off-putting to people new to programming.
-//
-// 7. Use common terminology, preferably from the Dart Language
-// Specification. This increases the user's chance of finding a good
-// explanation on the web.
-//
-// 8. Do not try to be cute or funny. It is extremely frustrating to work on a
-// product that crashes with a "tongue-in-cheek" message, especially if you did
-// not want to use this product to begin with.
-//
-// 9. Do not lie, that is, do not write error messages containing phrases like
-// "can't happen".  If the user ever saw this message, it would be a
-// lie. Prefer messages like: "Internal error: This function should not be
-// called when 'x' is null.".
-//
-// 10. Prefer to not use imperative tone. That is, the message should not sound
-// accusing or like it is ordering the user around. The computer should
-// describe the problem, not criticize for violating the specification.
-//
-// Other things to keep in mind:
-//
-// An INFO message should always be preceded by a non-INFO message, and the
-// INFO messages are additional details about the preceding non-INFO
-// message. For example, consider duplicated elements. First report a WARNING
-// or ERROR about the duplicated element, and then report an INFO about the
-// location of the existing element.
-//
-// Generally, we want to provide messages that consists of three sentences:
-// 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we
-// combine the first two in [template] and the last in [howToFix].
-
-/// Padding used before and between import chains in the message for
-/// [MessageKind.IMPORT_EXPERIMENTAL_MIRRORS].
-const String IMPORT_EXPERIMENTAL_MIRRORS_PADDING = '\n*   ';
-
-/// Padding used before and between import chains in the message for
-/// [MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND].
-const String MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING = '\n   ';
-
-/// Padding used before and between import chains in the message for
-/// [MessageKind.DISALLOWED_LIBRARY_IMPORT].
-const String DISALLOWED_LIBRARY_IMPORT_PADDING = '\n  ';
-
-const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
-
-final Map<String, Map> MESSAGES = {
-  /// Do not use this. It is here for legacy and debugging. It violates item
-  /// 4 of the guide lines for error messages in the beginning of the file.
-  'GENERIC': {'id': 'SOWPSL', 'template': "#{text}",},
-
-  'NOT_ASSIGNABLE': {
-    'id': 'VYNMAP',
-    'template': "'#{fromType}' is not assignable to '#{toType}'.",
-  },
-
-  'FORIN_NOT_ASSIGNABLE': {
-    'id': 'XQSRXO',
-    'template': "The element type '#{currentType}' of '#{expressionType}' "
-        "is not assignable to '#{elementType}'.",
-  },
-
-  'VOID_EXPRESSION': {
-    'id': 'QHEVSC',
-    'template': "Expression does not yield a value.",
-  },
-
-  'VOID_VARIABLE': {
-    'id': 'RFEURK',
-    'template': "Variable cannot be of type void.",
-  },
-
-  'RETURN_VALUE_IN_VOID': {
-    'id': 'FUNYDS',
-    'template': "Cannot return value from void function.",
-  },
-
-  'RETURN_NOTHING': {
-    'id': 'HPPODJ',
-    'template': "Value of type '#{returnType}' expected.",
-  },
-
-  'MISSING_ARGUMENT': {
-    'id': 'LHMCIK',
-    'template': "Missing argument of type '#{argumentType}'.",
-  },
-
-  'ADDITIONAL_ARGUMENT': {'id': 'GMITMA', 'template': "Additional argument.",},
-
-  'NAMED_ARGUMENT_NOT_FOUND': {
-    'id': 'UCEARQ',
-    'template': "No named argument '#{argumentName}' found on method.",
-  },
-
-  'MEMBER_NOT_FOUND': {
-    'id': 'MMQODC',
-    'template': "No member named '#{memberName}' in class '#{className}'.",
-  },
-
-  'AWAIT_MEMBER_NOT_FOUND': {
-    'id': 'XIDLIP',
-    'template': "No member named 'await' in class '#{className}'.",
-    'howToFix': "Did you mean to add the 'async' marker "
-        "to '#{functionName}'?",
-    'examples': [
-      """
-class A {
-m() => await -3;
-}
-main() => new A().m();
-"""
-    ],
-  },
-
-  'AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE': {
-    'id': 'HBIYGN',
-    'template': "No member named 'await' in class '#{className}'.",
-    'howToFix': "Did you mean to add the 'async' marker "
-        "to the enclosing function?",
-    'examples': [
-      """
-class A {
-m() => () => await -3;
-}
-main() => new A().m();
-"""
-    ],
-  },
-
-  'METHOD_NOT_FOUND': {
-    'id': 'QYYHBU',
-    'template': "No method named '#{memberName}' in class '#{className}'.",
-  },
-
-  'OPERATOR_NOT_FOUND': {
-    'id': 'SXGOYS',
-    'template': "No operator '#{memberName}' in class '#{className}'.",
-  },
-
-  'SETTER_NOT_FOUND': {
-    'id': 'ADFRVF',
-    'template': "No setter named '#{memberName}' in class '#{className}'.",
-  },
-
-  'SETTER_NOT_FOUND_IN_SUPER': {
-    'id': 'OCVRNJ',
-    'template': "No setter named '#{name}' in superclass of '#{className}'.",
-  },
-
-  'GETTER_NOT_FOUND': {
-    'id': 'PBNXAC',
-    'template': "No getter named '#{memberName}' in class '#{className}'.",
-  },
-
-  'NOT_CALLABLE': {
-    'id': 'SEMKJO',
-    'template': "'#{elementName}' is not callable.",
-  },
-
-  'MEMBER_NOT_STATIC': {
-    'id': 'QIOISX',
-    'template': "'#{className}.#{memberName}' is not static.",
-  },
-
-  'NO_INSTANCE_AVAILABLE': {
-    'id': 'FQPYLR',
-    'template': "'#{name}' is only available in instance methods.",
-  },
-
-  'NO_THIS_AVAILABLE': {
-    'id': 'LXPXKG',
-    'template': "'this' is only available in instance methods.",
-  },
-
-  'PRIVATE_ACCESS': {
-    'id': 'DIMHCR',
-    'template': "'#{name}' is declared private within library "
-        "'#{libraryName}'.",
-  },
-
-  'THIS_IS_THE_DECLARATION': {
-    'id': 'YIJWTO',
-    'template': "This is the declaration of '#{name}'.",
-  },
-
-  'THIS_IS_THE_METHOD': {
-    'id': 'PYXWLF',
-    'template': "This is the method declaration.",
-  },
-
-  'CANNOT_RESOLVE': {'id': 'SPVJYO', 'template': "Cannot resolve '#{name}'.",},
-
-  'CANNOT_RESOLVE_AWAIT': {
-    'id': 'YQYLRS',
-    'template': "Cannot resolve '#{name}'.",
-    'howToFix': "Did you mean to add the 'async' marker "
-        "to '#{functionName}'?",
-    'examples': ["main() => await -3;", "foo() => await -3; main() => foo();"],
-  },
-
-  'CANNOT_RESOLVE_AWAIT_IN_CLOSURE': {
-    'id': 'SIXRAA',
-    'template': "Cannot resolve '#{name}'.",
-    'howToFix': "Did you mean to add the 'async' marker "
-        "to the enclosing function?",
-    'examples': ["main() { (() => await -3)(); }",],
-  },
-
-  'CANNOT_RESOLVE_IN_INITIALIZER': {
-    'id': 'VVEQFD',
-    'template':
-        "Cannot resolve '#{name}'. It would be implicitly looked up on this "
-        "instance, but instances are not available in initializers.",
-    'howToFix': "Try correcting the unresolved reference or move the "
-        "initialization to a constructor body.",
-    'examples': [
-      """
-class A {
-var test = unresolvedName;
-}
-main() => new A();
-"""
-    ],
-  },
-
-  'CANNOT_RESOLVE_CONSTRUCTOR': {
-    'id': 'QRPATN',
-    'template': "Cannot resolve constructor '#{constructorName}'.",
-  },
-
-  'CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT': {
-    'id': 'IFKCHF',
-    'template': "cannot resolve constructor '#{constructorName}' "
-        "for implicit super call.",
-    'howToFix': "Try explicitly invoking a constructor of the super class",
-    'examples': [
-      """
-class A {
-A.foo() {}
-}
-class B extends A {
-B();
-}
-main() => new B();
-"""
-    ],
-  },
-
-  'INVALID_UNNAMED_CONSTRUCTOR_NAME': {
-    'id': 'VPJLVI',
-    'template': "Unnamed constructor name must be '#{name}'.",
-  },
-
-  'INVALID_CONSTRUCTOR_NAME': {
-    'id': 'LMDCAS',
-    'template': "Constructor name must start with '#{name}'.",
-  },
-
-  'CANNOT_RESOLVE_TYPE': {
-    'id': 'PQIAPG',
-    'template': "Cannot resolve type '#{typeName}'.",
-  },
-
-  'DUPLICATE_DEFINITION': {
-    'id': 'LVTYNW',
-    'template': "Duplicate definition of '#{name}'.",
-    'howToFix': "Try to rename or remove this definition.",
-    'examples': [
-      """
-class C {
-void f() {}
-int get f => 1;
-}
-
-main() {
-new C();
-}
-
-"""
-    ],
-  },
-
-  'EXISTING_DEFINITION': {
-    'id': 'DAUYKK',
-    'template': "Existing definition of '#{name}'.",
-  },
-
-  'DUPLICATE_IMPORT': {
-    'id': 'KYJFJN',
-    'template': "Duplicate import of '#{name}'.",
-  },
-
-  'HIDDEN_IMPORT': {
-    'id': 'ACRDPR',
-    'template': "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
-        "from library '#{hidingUri}'.",
-    'howToFix': "Try adding 'hide #{name}' to the import of '#{hiddenUri}'.",
-    'examples': [
-      {
-        'main.dart': """
-import 'dart:async'; // This imports a class Future.
-import 'future.dart';
-
-void main() => new Future();""",
-        'future.dart': """
-library future;
-
-class Future {}"""
-      },
-      {
-        'main.dart': """
-import 'future.dart';
-import 'dart:async'; // This imports a class Future.
-
-void main() => new Future();""",
-        'future.dart': """
-library future;
-
-class Future {}"""
-      },
-      {
-        'main.dart': """
-import 'export.dart';
-import 'dart:async'; // This imports a class Future.
-
-void main() => new Future();""",
-        'future.dart': """
-library future;
-
-class Future {}""",
-        'export.dart': """
-library export;
-
-export 'future.dart';"""
-      },
-      {
-        'main.dart': """
-import 'future.dart' as prefix;
-import 'dart:async' as prefix; // This imports a class Future.
-
-void main() => new prefix.Future();""",
-        'future.dart': """
-library future;
-
-class Future {}"""
-      }
-    ],
-  },
-
-  'HIDDEN_IMPLICIT_IMPORT': {
-    'id': 'WDNFSI',
-    'template': "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
-        "from library '#{hidingUri}'.",
-    'howToFix': "Try adding an explicit "
-        "'import \"#{hiddenUri}\" hide #{name}'.",
-    'examples': [
-      {
-        'main.dart': """
-// This hides the implicit import of class Type from dart:core.
-import 'type.dart';
-
-void main() => new Type();""",
-        'type.dart': """
-library type;
-
-class Type {}"""
-      },
-      {
-        'conflictsWithDart.dart': """
-library conflictsWithDart;
-
-class Duration {
-static var x = 100;
-}
-""",
-        'conflictsWithDartAsWell.dart': """
-library conflictsWithDartAsWell;
-
-class Duration {
-static var x = 100;
-}
-""",
-        'main.dart': r"""
-library testDartConflicts;
-
-import 'conflictsWithDart.dart';
-import 'conflictsWithDartAsWell.dart';
-
-main() {
-print("Hail Caesar ${Duration.x}");
-}
-"""
-      }
-    ],
-  },
-
-  'DUPLICATE_EXPORT': {
-    'id': 'XGNOCL',
-    'template': "Duplicate export of '#{name}'.",
-    'howToFix': "Try adding 'hide #{name}' to one of the exports.",
-    'examples': [
-      {
-        'main.dart': """
-export 'decl1.dart';
-export 'decl2.dart';
-
-main() {}""",
-        'decl1.dart': "class Class {}",
-        'decl2.dart': "class Class {}"
-      }
-    ],
-  },
-
-  'DUPLICATE_EXPORT_CONT': {
-    'id': 'BDROED',
-    'template': "This is another export of '#{name}'.",
-  },
-
-  'DUPLICATE_EXPORT_DECL': {
-    'id': 'GFFLMA',
-    'template':
-        "The exported '#{name}' from export #{uriString} is defined here.",
-  },
-
-  'EMPTY_HIDE': {
-    'id': 'ODFAOC',
-    'template': "Library '#{uri}' doesn't export a '#{name}' declaration.",
-    'howToFix': "Try removing '#{name}' the 'hide' clause.",
-    'examples': [
-      {
-        'main.dart': """
-import 'dart:core' hide Foo;
-
-main() {}"""
-      },
-      {
-        'main.dart': """
-export 'dart:core' hide Foo;
-
-main() {}"""
-      },
-    ],
-  },
-
-  'EMPTY_SHOW': {
-    'id': 'EXONIK',
-    'template': "Library '#{uri}' doesn't export a '#{name}' declaration.",
-    'howToFix': "Try removing '#{name}' from the 'show' clause.",
-    'examples': [
-      {
-        'main.dart': """
-import 'dart:core' show Foo;
-
-main() {}"""
-      },
-      {
-        'main.dart': """
-export 'dart:core' show Foo;
-
-main() {}"""
-      },
-    ],
-  },
-
-  'NOT_A_TYPE': {'id': 'CTTAXD', 'template': "'#{node}' is not a type.",},
-
-  'NOT_A_PREFIX': {'id': 'LKEUMI', 'template': "'#{node}' is not a prefix.",},
-
-  'PREFIX_AS_EXPRESSION': {
-    'id': 'CYIMBJ',
-    'template': "Library prefix '#{prefix}' is not a valid expression.",
-  },
-
-  'CANNOT_FIND_CONSTRUCTOR': {
-    'id': 'DROVNH',
-    'template': "Cannot find constructor '#{constructorName}' in class "
-        "'#{className}'.",
-  },
-
-  'CANNOT_FIND_UNNAMED_CONSTRUCTOR': {
-    'id': 'GDCTGB',
-    'template': "Cannot find unnamed constructor in class "
-        "'#{className}'.",
-  },
-
-  'CYCLIC_CLASS_HIERARCHY': {
-    'id': 'HKFYOA',
-    'template': "'#{className}' creates a cycle in the class hierarchy.",
-  },
-
-  'CYCLIC_REDIRECTING_FACTORY': {
-    'id': 'QGETJC',
-    'template': "Redirecting factory leads to a cyclic redirection.",
-  },
-
-  'INVALID_RECEIVER_IN_INITIALIZER': {
-    'id': 'SYUTHA',
-    'template': "Field initializer expected.",
-  },
-
-  'NO_SUPER_IN_STATIC': {
-    'id': 'HSCESG',
-    'template': "'super' is only available in instance methods.",
-  },
-
-  'DUPLICATE_INITIALIZER': {
-    'id': 'GKVFEP',
-    'template': "Field '#{fieldName}' is initialized more than once.",
-  },
-
-  'ALREADY_INITIALIZED': {
-    'id': 'NCRMVD',
-    'template': "'#{fieldName}' was already initialized here.",
-  },
-
-  'INIT_STATIC_FIELD': {
-    'id': 'DBSRHA',
-    'template': "Cannot initialize static field '#{fieldName}'.",
-  },
-
-  'NOT_A_FIELD': {
-    'id': 'FYEPLC',
-    'template': "'#{fieldName}' is not a field.",
-  },
-
-  'CONSTRUCTOR_CALL_EXPECTED': {
-    'id': 'GEJCDX',
-    'template': "only call to 'this' or 'super' constructor allowed.",
-  },
-
-  'INVALID_FOR_IN': {
-    'id': 'AUQJBG',
-    'template': "Invalid for-in variable declaration.",
-  },
-
-  'INVALID_INITIALIZER': {'id': 'JKUKSA', 'template': "Invalid initializer.",},
-
-  'FUNCTION_WITH_INITIALIZER': {
-    'id': 'BNRDDK',
-    'template': "Only constructors can have initializers.",
-  },
-
-  'REDIRECTING_CONSTRUCTOR_CYCLE': {
-    'id': 'CQTMEP',
-    'template': "Cyclic constructor redirection.",
-  },
-
-  'REDIRECTING_CONSTRUCTOR_HAS_BODY': {
-    'id': 'WXJQNE',
-    'template': "Redirecting constructor can't have a body.",
-  },
-
-  'CONST_CONSTRUCTOR_HAS_BODY': {
-    'id': 'GNEFQG',
-    'template': "Const constructor or factory can't have a body.",
-    'howToFix': "Remove the 'const' keyword or the body",
-    'examples': [
-      """
-class C {
-const C() {}
-}
-
-main() => new C();"""
-    ],
-  },
-
-  'REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER': {
-    'id': 'NUIDSF',
-    'template': "Redirecting constructor cannot have other initializers.",
-  },
-
-  'SUPER_INITIALIZER_IN_OBJECT': {
-    'id': 'DXYGND',
-    'template': "'Object' cannot have a super initializer.",
-  },
-
-  'DUPLICATE_SUPER_INITIALIZER': {
-    'id': 'FFKOWP',
-    'template': "Cannot have more than one super initializer.",
-  },
-
-  'SUPER_CALL_TO_FACTORY': {
-    'id': 'YTOWGV',
-    'template': "The target of the superinitializer must be a generative "
-        "constructor.",
-    'howToFix': "Try calling another constructor on the superclass.",
-    'examples': [
-      """
-class Super {
-factory Super() => null;
-}
-class Class extends Super {}
-main() => new Class();
-""",
-      """
-class Super {
-factory Super() => null;
-}
-class Class extends Super {
-Class();
-}
-main() => new Class();
-""",
-      """
-class Super {
-factory Super() => null;
-}
-class Class extends Super {
-Class() : super();
-}
-main() => new Class();
-""",
-      """
-class Super {
-factory Super.foo() => null;
-}
-class Class extends Super {
-Class() : super.foo();
-}
-main() => new Class();
-"""
-    ],
-  },
-
-  'THIS_CALL_TO_FACTORY': {
-    'id': 'JLATDB',
-    'template': "The target of the redirection clause must be a generative "
-        "constructor",
-    'howToFix': "Try redirecting to another constructor.",
-    'examples': [
-      """
-class Class {
-factory Class() => null;
-Class.foo() : this();
-}
-main() => new Class.foo();
-""",
-      """
-class Class {
-factory Class.foo() => null;
-Class() : this.foo();
-}
-main() => new Class();
-"""
-    ],
-  },
-
-  'INVALID_CONSTRUCTOR_ARGUMENTS': {
-    'id': 'WVPLKL',
-    'template': "Arguments do not match the expected parameters of constructor "
-        "'#{constructorName}'.",
-  },
-
-  'NO_MATCHING_CONSTRUCTOR': {
-    'id': 'OJQQLE',
-    'template':
-        "'super' call arguments and constructor parameters do not match.",
-  },
-
-  'NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT': {
-    'id': 'WHCVID',
-    'template': "Implicit 'super' call arguments and constructor parameters "
-        "do not match.",
-  },
-
-  'CONST_CALLS_NON_CONST': {
-    'id': 'CQFHXC',
-    'template': "'const' constructor cannot call a non-const constructor.",
-  },
-
-  'CONST_CALLS_NON_CONST_FOR_IMPLICIT': {
-    'id': 'SFCEXS',
-    'template': "'const' constructor cannot call a non-const constructor. "
-        "This constructor has an implicit call to a "
-        "super non-const constructor.",
-    'howToFix': "Try making the super constructor const.",
-    'examples': [
-      """
-class C {
-C(); // missing const
-}
-class D extends C {
-final d;
-const D(this.d);
-}
-main() => new D(0);"""
-    ],
-  },
-
-  'CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS': {
-    'id': 'XBHUDL',
-    'template': "Can't declare constructor 'const' on class #{className} "
-        "because the class contains non-final instance fields.",
-    'howToFix': "Try making all fields final.",
-    'examples': [
-      """
-class C {
-// 'a' must be declared final to allow for the const constructor.
-var a;
-const C(this.a);
-}
-
-main() => new C(0);"""
-    ],
-  },
-
-  'CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD': {
-    'id': 'YYAHVD',
-    'template': "This non-final field prevents using const constructors.",
-  },
-
-  'CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR': {
-    'id': 'FROWJB',
-    'template': "This const constructor is not allowed due to "
-        "non-final fields.",
-  },
-
-  'INITIALIZING_FORMAL_NOT_ALLOWED': {
-    'id': 'YIPXYP',
-    'template': "Initializing formal parameter only allowed in generative "
-        "constructor.",
-  },
-
-  'INVALID_PARAMETER': {
-    'id': 'OWWLIX',
-    'template': "Cannot resolve parameter.",
-  },
-
-  'NOT_INSTANCE_FIELD': {
-    'id': 'VSPKMU',
-    'template': "'#{fieldName}' is not an instance field.",
-  },
-
-  'THIS_PROPERTY': {'id': 'MWFIGH', 'template': "Expected an identifier.",},
-
-  'NO_CATCH_NOR_FINALLY': {
-    'id': 'OPJXPP',
-    'template': "Expected 'catch' or 'finally'.",
-  },
-
-  'EMPTY_CATCH_DECLARATION': {
-    'id': 'UNHCPY',
-    'template': "Expected an identifier in catch declaration.",
-  },
-
-  'EXTRA_CATCH_DECLARATION': {
-    'id': 'YGGRAK',
-    'template': "Extra parameter in catch declaration.",
-  },
-
-  'PARAMETER_WITH_TYPE_IN_CATCH': {
-    'id': 'EXQVDU',
-    'template': "Cannot use type annotations in catch.",
-  },
-
-  'PARAMETER_WITH_MODIFIER_IN_CATCH': {
-    'id': 'BQLKRF',
-    'template': "Cannot use modifiers in catch.",
-  },
-
-  'OPTIONAL_PARAMETER_IN_CATCH': {
-    'id': 'DAICPP',
-    'template': "Cannot use optional parameters in catch.",
-  },
-
-  'THROW_WITHOUT_EXPRESSION': {
-    'id': 'YHACYV',
-    'template': "Cannot use re-throw outside of catch block "
-        "(expression expected after 'throw').",
-  },
-
-  'UNBOUND_LABEL': {
-    'id': 'GLDXHY',
-    'template': "Cannot resolve label '#{labelName}'.",
-  },
-
-  'NO_BREAK_TARGET': {
-    'id': 'VBXXBE',
-    'template': "'break' statement not inside switch or loop.",
-  },
-
-  'NO_CONTINUE_TARGET': {
-    'id': 'JTTHHM',
-    'template': "'continue' statement not inside loop.",
-  },
-
-  'EXISTING_LABEL': {
-    'id': 'AHCSXF',
-    'template': "Original declaration of duplicate label '#{labelName}'.",
-  },
-
-  'DUPLICATE_LABEL': {
-    'id': 'HPULLI',
-    'template': "Duplicate declaration of label '#{labelName}'.",
-  },
-
-  'UNUSED_LABEL': {'id': 'KFREJO', 'template': "Unused label '#{labelName}'.",},
-
-  'INVALID_CONTINUE': {
-    'id': 'DSKTPX',
-    'template': "Target of continue is not a loop or switch case.",
-  },
-
-  'INVALID_BREAK': {
-    'id': 'MFCCWX',
-    'template': "Target of break is not a statement.",
-  },
-
-  'DUPLICATE_TYPE_VARIABLE_NAME': {
-    'id': 'BAYCCM',
-    'template': "Type variable '#{typeVariableName}' already declared.",
-  },
-
-  'TYPE_VARIABLE_WITHIN_STATIC_MEMBER': {
-    'id': 'XQLXRL',
-    'template': "Cannot refer to type variable '#{typeVariableName}' "
-        "within a static member.",
-  },
-
-  'TYPE_VARIABLE_IN_CONSTANT': {
-    'id': 'ANDEVG',
-    'template': "Constant expressions can't refer to type variables.",
-    'howToFix': "Try removing the type variable or replacing it with a "
-        "concrete type.",
-    'examples': [
-      """
-class C<T> {
-const C();
-
-m(T t) => const C<T>();
-}
-
-void main() => new C().m(null);
-"""
-    ],
-  },
-
-  'INVALID_TYPE_VARIABLE_BOUND': {
-    'id': 'WQAEDK',
-    'template': "'#{typeArgument}' is not a subtype of bound '#{bound}' for "
-        "type variable '#{typeVariable}' of type '#{thisType}'.",
-    'howToFix': "Try to change or remove the type argument.",
-    'examples': [
-      """
-class C<T extends num> {}
-
-// 'String' is not a valid instantiation of T with bound num.'.
-main() => new C<String>();
-"""
-    ],
-  },
-
-  'INVALID_USE_OF_SUPER': {
-    'id': 'JKYYSN',
-    'template': "'super' not allowed here.",
-  },
-
-  'INVALID_CASE_DEFAULT': {
-    'id': 'ABSPBM',
-    'template': "'default' only allowed on last case of a switch.",
-  },
-
-  'SWITCH_CASE_TYPES_NOT_EQUAL': {
-    'id': 'UFQPBC',
-    'template': "'case' expressions do not all have type '#{type}'.",
-  },
-
-  'SWITCH_CASE_TYPES_NOT_EQUAL_CASE': {
-    'id': 'RDMVAC',
-    'template': "'case' expression of type '#{type}'.",
-  },
-
-  'SWITCH_CASE_FORBIDDEN': {
-    'id': 'UHSCSU',
-    'template': "'case' expression may not be of type '#{type}'.",
-  },
-
-  'SWITCH_CASE_VALUE_OVERRIDES_EQUALS': {
-    'id': 'NRTWXL',
-    'template': "'case' expression type '#{type}' overrides 'operator =='.",
-  },
-
-  'INVALID_ARGUMENT_AFTER_NAMED': {
-    'id': 'WAJURC',
-    'template': "Unnamed argument after named argument.",
-  },
-
-  'NOT_A_COMPILE_TIME_CONSTANT': {
-    'id': 'SBCHWL',
-    'template': "Not a compile-time constant.",
-  },
-
-  'DEFERRED_COMPILE_TIME_CONSTANT': {
-    'id': 'FHXTCK',
-    'template': "A deferred value cannot be used as a compile-time constant.",
-  },
-
-  'DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION': {
-    'id': 'TSBXLG',
-    'template': "A deferred class cannot be used to create a "
-        "compile-time constant.",
-  },
-
-  'CYCLIC_COMPILE_TIME_CONSTANTS': {
-    'id': 'JJWJYE',
-    'template': "Cycle in the compile-time constant computation.",
-  },
-
-  'CONSTRUCTOR_IS_NOT_CONST': {
-    'id': 'DOJCUX',
-    'template': "Constructor is not a 'const' constructor.",
-  },
-
-  'CONST_MAP_KEY_OVERRIDES_EQUALS': {
-    'id': 'VJNWEL',
-    'template': "Const-map key type '#{type}' overrides 'operator =='.",
-  },
-
-  'NO_SUCH_LIBRARY_MEMBER': {
-    'id': 'IOXVBA',
-    'template': "'#{libraryName}' has no member named '#{memberName}'.",
-  },
-
-  'CANNOT_INSTANTIATE_TYPEDEF': {
-    'id': 'KOYNMU',
-    'template': "Cannot instantiate typedef '#{typedefName}'.",
-  },
-
-  'REQUIRED_PARAMETER_WITH_DEFAULT': {
-    'id': 'CJWECI',
-    'template': "Non-optional parameters can't have a default value.",
-    'howToFix':
-        "Try removing the default value or making the parameter optional.",
-    'examples': [
-      """
-main() {
-foo(a: 1) => print(a);
-foo(2);
-}""",
-      """
-main() {
-foo(a = 1) => print(a);
-foo(2);
-}"""
-    ],
-  },
-
-  'NAMED_PARAMETER_WITH_EQUALS': {
-    'id': 'RPJDXD',
-    'template': "Named optional parameters can't use '=' to specify a default "
-        "value.",
-    'howToFix': "Try replacing '=' with ':'.",
-    'examples': [
-      """
-main() {
-foo({a = 1}) => print(a);
-foo(a: 2);
-}"""
-    ],
-  },
-
-  'POSITIONAL_PARAMETER_WITH_EQUALS': {
-    'id': 'JMSSDX',
-    'template': "Positional optional parameters can't use ':' to specify a "
-        "default value.",
-    'howToFix': "Try replacing ':' with '='.",
-    'examples': [
-      """
-main() {
-foo([a: 1]) => print(a);
-foo(2);
-}"""
-    ],
-  },
-
-  'TYPEDEF_FORMAL_WITH_DEFAULT': {
-    'id': 'NABHHS',
-    'template': "A parameter of a typedef can't specify a default value.",
-    'howToFix': "Try removing the default value.",
-    'examples': [
-      """
-typedef void F([int arg = 0]);
-
-main() {
-F f;
-}""",
-      """
-typedef void F({int arg: 0});
-
-main() {
-F f;
-}"""
-    ],
-  },
-
-  'FUNCTION_TYPE_FORMAL_WITH_DEFAULT': {
-    'id': 'APKYLU',
-    'template': "A function type parameter can't specify a default value.",
-    'howToFix': "Try removing the default value.",
-    'examples': [
-      """
-foo(f(int i, [a = 1])) {}
-
-main() {
-foo(1, 2);
-}""",
-      """
-foo(f(int i, {a: 1})) {}
-
-main() {
-foo(1, a: 2);
-}"""
-    ],
-  },
-
-  'REDIRECTING_FACTORY_WITH_DEFAULT': {
-    'id': 'AWSSEY',
-    'template':
-        "A parameter of a redirecting factory constructor can't specify a "
-        "default value.",
-    'howToFix': "Try removing the default value.",
-    'examples': [
-      """
-class A {
-A([a]);
-factory A.foo([a = 1]) = A;
-}
-
-main() {
-new A.foo(1);
-}""",
-      """
-class A {
-A({a});
-factory A.foo({a: 1}) = A;
-}
-
-main() {
-new A.foo(a: 1);
-}"""
-    ],
-  },
-
-  'FORMAL_DECLARED_CONST': {
-    'id': 'AVPRDK',
-    'template': "A formal parameter can't be declared const.",
-    'howToFix': "Try removing 'const'.",
-    'examples': [
-      """
-foo(const x) {}
-main() => foo(42);
-""",
-      """
-foo({const x}) {}
-main() => foo(42);
-""",
-      """
-foo([const x]) {}
-main() => foo(42);
-"""
-    ],
-  },
-
-  'FORMAL_DECLARED_STATIC': {
-    'id': 'PJKDMX',
-    'template': "A formal parameter can't be declared static.",
-    'howToFix': "Try removing 'static'.",
-    'examples': [
-      """
-foo(static x) {}
-main() => foo(42);
-""",
-      """
-foo({static x}) {}
-main() => foo(42);
-""",
-      """
-foo([static x]) {}
-main() => foo(42);
-"""
-    ],
-  },
-
-  'FINAL_FUNCTION_TYPE_PARAMETER': {
-    'id': 'JIOPIQ',
-    'template': "A function type parameter can't be declared final.",
-    'howToFix': "Try removing 'final'.",
-    'examples': [
-      """
-foo(final int x(int a)) {}
-main() => foo((y) => 42);
-""",
-      """
-foo({final int x(int a)}) {}
-main() => foo((y) => 42);
-""",
-      """
-foo([final int x(int a)]) {}
-main() => foo((y) => 42);
-"""
-    ],
-  },
-
-  'VAR_FUNCTION_TYPE_PARAMETER': {
-    'id': 'FOQOHK',
-    'template': "A function type parameter can't be declared with 'var'.",
-    'howToFix': "Try removing 'var'.",
-    'examples': [
-      """
-foo(var int x(int a)) {}
-main() => foo((y) => 42);
-""",
-      """
-foo({var int x(int a)}) {}
-main() => foo((y) => 42);
-""",
-      """
-foo([var int x(int a)]) {}
-main() => foo((y) => 42);
-"""
-    ],
-  },
-
-  'CANNOT_INSTANTIATE_TYPE_VARIABLE': {
-    'id': 'JAYHCH',
-    'template': "Cannot instantiate type variable '#{typeVariableName}'.",
-  },
-
-  'CYCLIC_TYPE_VARIABLE': {
-    'id': 'RQMPSO',
-    'template': "Type variable '#{typeVariableName}' is a supertype of itself.",
-  },
-
-  'CYCLIC_TYPEDEF': {
-    'id': 'VFERCQ',
-    'template': "A typedef can't refer to itself.",
-    'howToFix': "Try removing all references to '#{typedefName}' "
-        "in the definition of '#{typedefName}'.",
-    'examples': [
-      """
-typedef F F(); // The return type 'F' is a self-reference.
-main() { F f = null; }"""
-    ],
-  },
-
-  'CYCLIC_TYPEDEF_ONE': {
-    'id': 'ASWLWR',
-    'template': "A typedef can't refer to itself through another typedef.",
-    'howToFix': "Try removing all references to "
-        "'#{otherTypedefName}' in the definition of '#{typedefName}'.",
-    'examples': [
-      """
-typedef G F(); // The return type 'G' is a self-reference through typedef 'G'.
-typedef F G(); // The return type 'F' is a self-reference through typedef 'F'.
-main() { F f = null; }""",
-      """
-typedef G F(); // The return type 'G' creates a self-reference.
-typedef H G(); // The return type 'H' creates a self-reference.
-typedef H(F f); // The argument type 'F' creates a self-reference.
-main() { F f = null; }"""
-    ],
-  },
-
-  'CLASS_NAME_EXPECTED': {'id': 'DPKNHY', 'template': "Class name expected.",},
-
-  'CANNOT_EXTEND': {
-    'id': 'GCIQXD',
-    'template': "'#{type}' cannot be extended.",
-  },
-
-  'CANNOT_IMPLEMENT': {
-    'id': 'IBOQKV',
-    'template': "'#{type}' cannot be implemented.",
-  },
-
-  // TODO(johnnwinther): Split messages into reasons for malformedness.
-  'CANNOT_EXTEND_MALFORMED': {
-    'id': 'YPFJBD',
-    'template': "Class '#{className}' can't extend the type '#{malformedType}' "
-        "because it is malformed.",
-    'howToFix': "Try correcting the malformed type annotation or removing the "
-        "'extends' clause.",
-    'examples': [
-      """
-class A extends Malformed {}
-main() => new A();"""
-    ],
-  },
-
-  'CANNOT_IMPLEMENT_MALFORMED': {
-    'id': 'XJUIAQ',
-    'template':
-        "Class '#{className}' can't implement the type '#{malformedType}' "
-        "because it is malformed.",
-    'howToFix': "Try correcting the malformed type annotation or removing the "
-        "type from the 'implements' clause.",
-    'examples': [
-      """
-class A implements Malformed {}
-main() => new A();"""
-    ],
-  },
-
-  'CANNOT_MIXIN_MALFORMED': {
-    'id': 'SSMNXN',
-    'template': "Class '#{className}' can't mixin the type '#{malformedType}' "
-        "because it is malformed.",
-    'howToFix': "Try correcting the malformed type annotation or removing the "
-        "type from the 'with' clause.",
-    'examples': [
-      """
-class A extends Object with Malformed {}
-main() => new A();"""
-    ],
-  },
-
-  'CANNOT_MIXIN': {
-    'id': 'KLSXDQ',
-    'template': "The type '#{type}' can't be mixed in.",
-    'howToFix': "Try removing '#{type}' from the 'with' clause.",
-    'examples': [
-      """
-class C extends Object with String {}
-
-main() => new C();
-""",
-      """
-typedef C = Object with String;
-
-main() => new C();
-"""
-    ],
-  },
-
-  'CANNOT_EXTEND_ENUM': {
-    'id': 'JEPRST',
-    'template':
-        "Class '#{className}' can't extend the type '#{enumType}' because "
-        "it is declared by an enum.",
-    'howToFix': "Try making '#{enumType}' a normal class or removing the "
-        "'extends' clause.",
-    'examples': [
-      """
-enum Enum { A }
-class B extends Enum {}
-main() => new B();"""
-    ],
-  },
-
-  'CANNOT_IMPLEMENT_ENUM': {
-    'id': 'JMJMSH',
-    'template': "Class '#{className}' can't implement the type '#{enumType}' "
-        "because it is declared by an enum.",
-    'howToFix': "Try making '#{enumType}' a normal class or removing the "
-        "type from the 'implements' clause.",
-    'examples': [
-      """
-enum Enum { A }
-class B implements Enum {}
-main() => new B();"""
-    ],
-  },
-
-  'CANNOT_MIXIN_ENUM': {
-    'id': 'YSYDIM',
-    'template':
-        "Class '#{className}' can't mixin the type '#{enumType}' because it "
-        "is declared by an enum.",
-    'howToFix': "Try making '#{enumType}' a normal class or removing the "
-        "type from the 'with' clause.",
-    'examples': [
-      """
-enum Enum { A }
-class B extends Object with Enum {}
-main() => new B();"""
-    ],
-  },
-
-  'CANNOT_INSTANTIATE_ENUM': {
-    'id': 'CQYIFU',
-    'template': "Enum type '#{enumName}' cannot be instantiated.",
-    'howToFix': "Try making '#{enumType}' a normal class or use an enum "
-        "constant.",
-    'examples': [
-      """
-enum Enum { A }
-main() => new Enum(0);""",
-      """
-enum Enum { A }
-main() => const Enum(0);"""
-    ],
-  },
-
-  'EMPTY_ENUM_DECLARATION': {
-    'id': 'JFPDOH',
-    'template': "Enum '#{enumName}' must contain at least one value.",
-    'howToFix': "Try adding an enum constant or making #{enumName} a "
-        "normal class.",
-    'examples': [
-      """
-enum Enum {}
-main() { Enum e; }"""
-    ],
-  },
-
-  'MISSING_ENUM_CASES': {
-    'id': 'HHEOIW',
-    'template': "Missing enum constants in switch statement: #{enumValues}.",
-    'howToFix': "Try adding the missing constants or a default case.",
-    'examples': [
-      """
-enum Enum { A, B }
-main() {
-switch (Enum.A) {
-case Enum.B: break;
-}
-}""",
-      """
-enum Enum { A, B, C }
-main() {
-switch (Enum.A) {
-case Enum.B: break;
-}
-}"""
-    ],
-  },
-
-  'DUPLICATE_EXTENDS_IMPLEMENTS': {
-    'id': 'BKRKEO',
-    'template': "'#{type}' can not be both extended and implemented.",
-  },
-
-  'DUPLICATE_IMPLEMENTS': {
-    'id': 'IWJFTU',
-    'template': "'#{type}' must not occur more than once "
-        "in the implements clause.",
-  },
-
-  'MULTI_INHERITANCE': {
-    'id': 'NWXGOI',
-    'template':
-        "Dart2js does not currently support inheritance of the same class "
-        "with different type arguments: Both #{firstType} and #{secondType} "
-        "are supertypes of #{thisType}.",
-  },
-
-  'ILLEGAL_SUPER_SEND': {
-    'id': 'LDRGIU',
-    'template': "'#{name}' cannot be called on super.",
-  },
-
-  'NO_SUCH_SUPER_MEMBER': {
-    'id': 'HIJJVG',
-    'template':
-        "Cannot resolve '#{memberName}' in a superclass of '#{className}'.",
-  },
-
-  'ADDITIONAL_TYPE_ARGUMENT': {
-    'id': 'HWYHWH',
-    'template': "Additional type argument.",
-  },
-
-  'MISSING_TYPE_ARGUMENT': {
-    'id': 'KYTQWA',
-    'template': "Missing type argument.",
-  },
-
-  // TODO(johnniwinther): Use ADDITIONAL_TYPE_ARGUMENT or
-  // MISSING_TYPE_ARGUMENT instead.
-  'TYPE_ARGUMENT_COUNT_MISMATCH': {
-    'id': 'ECXGRM',
-    'template': "Incorrect number of type arguments on '#{type}'.",
-  },
-
-  'GETTER_MISMATCH': {
-    'id': 'MNODFW',
-    'template': "Setter disagrees on: '#{modifiers}'.",
-  },
-
-  'SETTER_MISMATCH': {
-    'id': 'FMNHPL',
-    'template': "Getter disagrees on: '#{modifiers}'.",
-  },
-
-  'ILLEGAL_SETTER_FORMALS': {
-    'id': 'COTPVN',
-    'template': "A setter must have exactly one argument.",
-  },
-
-  'NO_STATIC_OVERRIDE': {
-    'id': 'EHINXB',
-    'template':
-        "Static member cannot override instance member '#{memberName}' of "
-        "'#{className}'.",
-  },
-
-  'NO_STATIC_OVERRIDE_CONT': {
-    'id': 'TEVJMA',
-    'template': "This is the instance member that cannot be overridden "
-        "by a static member.",
-  },
-
-  'INSTANCE_STATIC_SAME_NAME': {
-    'id': 'LTBFBO',
-    'template': "Instance member '#{memberName}' and static member of "
-        "superclass '#{className}' have the same name.",
-  },
-
-  'INSTANCE_STATIC_SAME_NAME_CONT': {
-    'id': 'CHSUCQ',
-    'template': "This is the static member with the same name.",
-  },
-
-  'INVALID_OVERRIDE_METHOD': {
-    'id': 'NINKPI',
-    'template': "The type '#{declaredType}' of method '#{name}' declared in "
-        "'#{class}' is not a subtype of the overridden method type "
-        "'#{inheritedType}' inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDDEN_METHOD': {
-    'id': 'BQHUPY',
-    'template': "This is the overridden method '#{name}' declared in class "
-        "'#{class}'.",
-  },
-
-  'INVALID_OVERRIDE_GETTER': {
-    'id': 'KLMPWO',
-    'template': "The type '#{declaredType}' of getter '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden getter inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDDEN_GETTER': {
-    'id': 'ASSKCT',
-    'template': "This is the overridden getter '#{name}' declared in class "
-        "'#{class}'.",
-  },
-
-  'INVALID_OVERRIDE_GETTER_WITH_FIELD': {
-    'id': 'TCCGXU',
-    'template': "The type '#{declaredType}' of field '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden getter inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDE_FIELD_WITH_GETTER': {
-    'id': 'UMMEXO',
-    'template': "The type '#{declaredType}' of getter '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden field inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDE_SETTER': {
-    'id': 'BWRGEC',
-    'template': "The type '#{declaredType}' of setter '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden setter inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDDEN_SETTER': {
-    'id': 'XQUOLL',
-    'template': "This is the overridden setter '#{name}' declared in class "
-        "'#{class}'.",
-  },
-
-  'INVALID_OVERRIDE_SETTER_WITH_FIELD': {
-    'id': 'GKGOFA',
-    'template': "The type '#{declaredType}' of field '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden setter inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDE_FIELD_WITH_SETTER': {
-    'id': 'OOXKHQ',
-    'template': "The type '#{declaredType}' of setter '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden field inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDE_FIELD': {
-    'id': 'LDPKOL',
-    'template': "The type '#{declaredType}' of field '#{name}' declared in "
-        "'#{class}' is not assignable to the type '#{inheritedType}' of the "
-        "overridden field inherited from '#{inheritedClass}'.",
-  },
-
-  'INVALID_OVERRIDDEN_FIELD': {
-    'id': 'UNQFWX',
-    'template': "This is the overridden field '#{name}' declared in class "
-        "'#{class}'.",
-  },
-
-  'CANNOT_OVERRIDE_FIELD_WITH_METHOD': {
-    'id': 'SYKCSK',
-    'template': "Method '#{name}' in '#{class}' can't override field from "
-        "'#{inheritedClass}'.",
-  },
-
-  'CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT': {
-    'id': 'HYHQSO',
-    'template': "This is the field that cannot be overridden by a method.",
-  },
-
-  'CANNOT_OVERRIDE_METHOD_WITH_FIELD': {
-    'id': 'UROMAS',
-    'template': "Field '#{name}' in '#{class}' can't override method from "
-        "'#{inheritedClass}'.",
-  },
-
-  'CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT': {
-    'id': 'NSORYS',
-    'template': "This is the method that cannot be overridden by a field.",
-  },
-
-  'CANNOT_OVERRIDE_GETTER_WITH_METHOD': {
-    'id': 'MMFIOH',
-    'template': "Method '#{name}' in '#{class}' can't override getter from "
-        "'#{inheritedClass}'.",
-  },
-
-  'CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT': {
-    'id': 'YGWPDH',
-    'template': "This is the getter that cannot be overridden by a method.",
-  },
-
-  'CANNOT_OVERRIDE_METHOD_WITH_GETTER': {
-    'id': 'BNKNXO',
-    'template': "Getter '#{name}' in '#{class}' can't override method from "
-        "'#{inheritedClass}'.",
-  },
-
-  'CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT': {
-    'id': 'KFBCYX',
-    'template': "This is the method that cannot be overridden by a getter.",
-  },
-
-  'MISSING_FORMALS': {
-    'id': 'BOERAF',
-    'template': "Formal parameters are missing.",
-  },
-
-  'EXTRA_FORMALS': {
-    'id': 'UTWRIU',
-    'template': "Formal parameters are not allowed here.",
-  },
-
-  'UNARY_OPERATOR_BAD_ARITY': {
-    'id': 'TNHLAL',
-    'template': "Operator '#{operatorName}' must have no parameters.",
-  },
-
-  'MINUS_OPERATOR_BAD_ARITY': {
-    'id': 'SXDRRU',
-    'template': "Operator '-' must have 0 or 1 parameters.",
-  },
-
-  'BINARY_OPERATOR_BAD_ARITY': {
-    'id': 'QKWAUM',
-    'template': "Operator '#{operatorName}' must have exactly 1 parameter.",
-  },
-
-  'TERNARY_OPERATOR_BAD_ARITY': {
-    'id': 'LSMQGF',
-    'template': "Operator '#{operatorName}' must have exactly 2 parameters.",
-  },
-
-  'OPERATOR_OPTIONAL_PARAMETERS': {
-    'id': 'HSGRBV',
-    'template': "Operator '#{operatorName}' cannot have optional parameters.",
-  },
-
-  'OPERATOR_NAMED_PARAMETERS': {
-    'id': 'EACWGS',
-    'template': "Operator '#{operatorName}' cannot have named parameters.",
-  },
-
-  'CONSTRUCTOR_WITH_RETURN_TYPE': {
-    'id': 'OPMBHF',
-    'template': "Cannot have return type for constructor.",
-  },
-
-  'CANNOT_RETURN_FROM_CONSTRUCTOR': {
-    'id': 'NFUGNH',
-    'template': "Constructors can't return values.",
-    'howToFix': "Remove the return statement or use a factory constructor.",
-    'examples': [
-      """
-class C {
-C() {
-  return 1;
-}
-}
-
-main() => new C();"""
-    ],
-  },
-
-  'ILLEGAL_FINAL_METHOD_MODIFIER': {
-    'id': 'YUKCVU',
-    'template': "Cannot have final modifier on method.",
-  },
-
-  'ILLEGAL_CONST_FIELD_MODIFIER': {
-    'id': 'JGFAGV',
-    'template': "Cannot have const modifier on non-static field.",
-    'howToFix': "Try adding a static modifier, or removing the const modifier.",
-    'examples': [
-      """
-class C {
-const int a = 1;
-}
-
-main() => new C();"""
-    ],
-  },
-
-  'ILLEGAL_CONSTRUCTOR_MODIFIERS': {
-    'id': 'WODRHN',
-    'template': "Illegal constructor modifiers: '#{modifiers}'.",
-  },
-
-  'ILLEGAL_MIXIN_APPLICATION_MODIFIERS': {
-    'id': 'OFLFHN',
-    'template': "Illegal mixin application modifiers: '#{modifiers}'.",
-  },
-
-  'ILLEGAL_MIXIN_SUPERCLASS': {
-    'id': 'TPVVYN',
-    'template': "Class used as mixin must have Object as superclass.",
-  },
-
-  'ILLEGAL_MIXIN_OBJECT': {
-    'id': 'CMVTLF',
-    'template': "Cannot use Object as mixin.",
-  },
-
-  'ILLEGAL_MIXIN_CONSTRUCTOR': {
-    'id': 'HXBUIB',
-    'template': "Class used as mixin cannot have non-factory constructor.",
-  },
-
-  'ILLEGAL_MIXIN_CYCLE': {
-    'id': 'ANXAMU',
-    'template': "Class used as mixin introduces mixin cycle: "
-        "'#{mixinName1}' <-> '#{mixinName2}'.",
-  },
-
-  'ILLEGAL_MIXIN_WITH_SUPER': {
-    'id': 'KIEUGK',
-    'template': "Cannot use class '#{className}' as a mixin because it uses "
-        "'super'.",
-  },
-
-  'ILLEGAL_MIXIN_SUPER_USE': {
-    'id': 'QKUPLH',
-    'template': "Use of 'super' in class used as mixin.",
-  },
-
-  'PARAMETER_NAME_EXPECTED': {
-    'id': 'JOUOBT',
-    'template': "parameter name expected.",
-  },
-
-  'CANNOT_RESOLVE_GETTER': {
-    'id': 'TDHKSW',
-    'template': "Cannot resolve getter.",
-  },
-
-  'CANNOT_RESOLVE_SETTER': {
-    'id': 'QQFANP',
-    'template': "Cannot resolve setter.",
-  },
-
-  'ASSIGNING_FINAL_FIELD_IN_SUPER': {
-    'id': 'LXUPCC',
-    'template': "Cannot assign a value to final field '#{name}' "
-        "in superclass '#{superclassName}'.",
-  },
-
-  'ASSIGNING_METHOD': {
-    'id': 'JUVMYC',
-    'template': "Cannot assign a value to a method.",
-  },
-
-  'ASSIGNING_METHOD_IN_SUPER': {
-    'id': 'AGMAXN',
-    'template': "Cannot assign a value to method '#{name}' "
-        "in superclass '#{superclassName}'.",
-  },
-
-  'ASSIGNING_TYPE': {
-    'id': 'VXTPWE',
-    'template': "Cannot assign a value to a type.",
-  },
-
-  'IF_NULL_ASSIGNING_TYPE': {
-    'id': 'XBRHGK',
-    'template':
-        "Cannot assign a value to a type. Note that types are never null, "
-        "so this ??= assignment has no effect.",
-    'howToFix': "Try removing the '??=' assignment.",
-    'examples': ["class A {} main() { print(A ??= 3);}",],
-  },
-
-  'VOID_NOT_ALLOWED': {
-    'id': 'DMMDXT',
-    'template':
-        "Type 'void' can't be used here because it isn't a return type.",
-    'howToFix':
-        "Try removing 'void' keyword or replace it with 'var', 'final', "
-        "or a type.",
-    'examples': ["void x; main() {}", "foo(void x) {} main() { foo(null); }",],
-  },
-
-  'NULL_NOT_ALLOWED': {
-    'id': 'STYNSK',
-    'template': "`null` can't be used here.",
-  },
-
-  'BEFORE_TOP_LEVEL': {
-    'id': 'GRCXQF',
-    'template': "Part header must come before top-level definitions.",
-  },
-
-  'IMPORT_PART_OF': {
-    'id': 'VANCWE',
-    'template': "The imported library must not have a 'part-of' directive.",
-    'howToFix': "Try removing the 'part-of' directive or replacing the "
-        "import of the library with a 'part' directive.",
-    'examples': [
-      {
-        'main.dart': """
-library library;
-
-import 'part.dart';
-
-main() {}
-""",
-        'part.dart': """
-part of library;
-"""
-      }
-    ],
-  },
-
-  'IMPORT_PART_OF_HERE': {
-    'id': 'TRSZOJ',
-    'template': 'The library is imported here.',
-  },
-
-  'MAIN_HAS_PART_OF': {
-    'id': 'MFMRRL',
-    'template': "The main application file must not have a 'part-of' "
-                "directive.",
-    'howToFix': "Try removing the 'part-of' directive or starting compilation "
-                "from another file.",
-    'examples': [
-      {
-        'main.dart': """
-part of library;
-
-main() {}
-"""
-      }
-    ],
-  },
-
-  'LIBRARY_NAME_MISMATCH': {
-    'id': 'AXGYPQ',
-    'template': "Expected part of library name '#{libraryName}'.",
-    'howToFix': "Try changing the directive to 'part of #{libraryName};'.",
-    'examples': [
-      {
-        'main.dart': """
-library lib.foo;
-
-part 'part.dart';
-
-main() {}
-""",
-        'part.dart': """
-part of lib.bar;
-"""
-      }
-    ],
-  },
-
-  'MISSING_LIBRARY_NAME': {
-    'id': 'NYQNCA',
-    'template': "Library has no name. Part directive expected library name "
-        "to be '#{libraryName}'.",
-    'howToFix': "Try adding 'library #{libraryName};' to the library.",
-    'examples': [
-      {
-        'main.dart': """
-part 'part.dart';
-
-main() {}
-""",
-        'part.dart': """
-part of lib.foo;
-"""
-      }
-    ],
-  },
-
-  'THIS_IS_THE_PART_OF_TAG': {
-    'id': 'RPSJRS',
-    'template': "This is the part of directive.",
-  },
-
-  'MISSING_PART_OF_TAG': {
-    'id': 'QNYCMV',
-    'template': "This file has no part-of tag, but it is being used as a part.",
-  },
-
-  'DUPLICATED_PART_OF': {
-    'id': 'UJDYHF',
-    'template': "Duplicated part-of directive.",
-  },
-
-  'DUPLICATED_LIBRARY_NAME': {
-    'id': 'OSEHXI',
-    'template': "Duplicated library name '#{libraryName}'.",
-  },
-
-  'DUPLICATED_RESOURCE': {
-    'id': 'UFWKBY',
-    'template': "The resource '#{resourceUri}' is loaded through both "
-        "'#{canonicalUri1}' and '#{canonicalUri2}'.",
-  },
-
-  'DUPLICATED_LIBRARY_RESOURCE': {
-    'id': 'KYGYTT',
-    'template':
-        "The library '#{libraryName}' in '#{resourceUri}' is loaded through "
-        "both '#{canonicalUri1}' and '#{canonicalUri2}'.",
-  },
-
-  // This is used as an exception.
-  'INVALID_SOURCE_FILE_LOCATION': {
-    'id': 'WIGJFG',
-    'template': """
-Invalid offset (#{offset}) in source map.
-File: #{fileName}
-Length: #{length}""",
-  },
-
-  'TOP_LEVEL_VARIABLE_DECLARED_STATIC': {
-    'id': 'IVNDML',
-    'template': "Top-level variable cannot be declared static.",
-  },
-
-  'REFERENCE_IN_INITIALIZATION': {
-    'id': 'OVWTEU',
-    'template': "Variable '#{variableName}' is referenced during its "
-        "initialization.",
-    'howToFix': "If you are trying to reference a shadowed variable, rename "
-        "one of the variables.",
-    'examples': [
-      """
-foo(t) {
-var t = t;
-return t;
-}
-
-main() => foo(1);
-"""
-    ],
-  },
-
-  'CONST_WITHOUT_INITIALIZER': {
-    'id': 'UDWCNH',
-    'template': "A constant variable must be initialized.",
-    'howToFix': "Try adding an initializer or "
-        "removing the 'const' modifier.",
-    'examples': [
-      """
-void main() {
-const c; // This constant variable must be initialized.
-}"""
-    ],
-  },
-
-  'FINAL_WITHOUT_INITIALIZER': {
-    'id': 'YMESFI',
-    'template': "A final variable must be initialized.",
-    'howToFix': "Try adding an initializer or "
-        "removing the 'final' modifier.",
-    'examples': ["class C { static final field; } main() => C.field;"],
-  },
-
-  'CONST_LOOP_VARIABLE': {
-    'id': 'WUSKMG',
-    'template': "A loop variable cannot be constant.",
-    'howToFix': "Try remove the 'const' modifier or "
-        "replacing it with a 'final' modifier.",
-    'examples': [
-      """
-void main() {
-  for (const c in []) {}
-}"""
-    ],
-  },
-
-  'MEMBER_USES_CLASS_NAME': {
-    'id': 'TVFYRK',
-    'template': "Member variable can't have the same name as the class it is "
-        "declared in.",
-    'howToFix': "Try renaming the variable.",
-    'examples': [
-      """
-class A { var A; }
-main() {
-var a = new A();
-a.A = 1;
-}
-""",
-      """
-class A { static var A; }
-main() => A.A = 1;
-"""
-    ],
-  },
-
-  'WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT': {
-    'id': 'IXYNUF',
-    'template': "Wrong number of arguments to assert. Should be 1, but given "
-        "#{argumentCount}.",
-  },
-
-  'ASSERT_IS_GIVEN_NAMED_ARGUMENTS': {
-    'id': 'EJFDTO',
-    'template':
-        "'assert' takes no named arguments, but given #{argumentCount}.",
-  },
-
-  'FACTORY_REDIRECTION_IN_NON_FACTORY': {
-    'id': 'DTBWEX',
-    'template': "Factory redirection only allowed in factories.",
-  },
-
-  'MISSING_FACTORY_KEYWORD': {
-    'id': 'HOQYYA',
-    'template': "Did you forget a factory keyword here?",
-  },
-
-  'NO_SUCH_METHOD_IN_NATIVE': {
-    'id': 'MSDDBX',
-    'template':
-        "'NoSuchMethod' is not supported for classes that extend native "
-        "classes.",
-  },
-
-  'DEFERRED_LIBRARY_DART_2_DART': {
-    'id': 'RIRQAH',
-    'template': "Deferred loading is not supported by the dart backend yet. "
-        "The output will not be split.",
-  },
-
-  'DEFERRED_LIBRARY_WITHOUT_PREFIX': {
-    'id': 'CARRII',
-    'template': "This import is deferred but there is no prefix keyword.",
-    'howToFix': "Try adding a prefix to the import."
-  },
-
-  'DEFERRED_OLD_SYNTAX': {
-    'id': 'QCBRAE',
-    'template': "The DeferredLibrary annotation is obsolete.",
-    'howToFix':
-        "Use the \"import 'lib.dart' deferred as prefix\" syntax instead.",
-  },
-
-  'DEFERRED_LIBRARY_DUPLICATE_PREFIX': {
-    'id': 'BBMJTD',
-    'template': "The prefix of this deferred import is not unique.",
-    'howToFix': "Try changing the import prefix."
-  },
-
-  'DEFERRED_TYPE_ANNOTATION': {
-    'id': 'JOUEFD',
-    'template': "The type #{node} is deferred. "
-        "Deferred types are not valid as type annotations.",
-    'howToFix': "Try using a non-deferred abstract class as an interface.",
-  },
-
-  'ILLEGAL_STATIC': {
-    'id': 'HFBHVE',
-    'template': "Modifier static is only allowed on functions declared in "
-        "a class.",
-  },
-
-  'STATIC_FUNCTION_BLOAT': {
-    'id': 'SJHTKF',
-    'template': "Using '#{class}.#{name}' may lead to unnecessarily large "
-        "generated code.",
-    'howToFix': "Try adding '@MirrorsUsed(...)' as described at "
-        "https://goo.gl/Akrrog.",
-  },
-
-  'NON_CONST_BLOAT': {
-    'id': 'RDRSHO',
-    'template': "Using 'new #{name}' may lead to unnecessarily large generated "
-        "code.",
-    'howToFix': "Try using 'const #{name}' or adding '@MirrorsUsed(...)' as "
-        "described at https://goo.gl/Akrrog.",
-  },
-
-  'STRING_EXPECTED': {
-    'id': 'OEJOOI',
-    'template': "Expected a 'String', but got an instance of '#{type}'.",
-  },
-
-  'PRIVATE_IDENTIFIER': {
-    'id': 'XAHVWI',
-    'template': "'#{value}' is not a valid Symbol name because it starts with "
-        "'_'.",
-  },
-
-  'PRIVATE_NAMED_PARAMETER': {
-    'id': 'VFGCLK',
-    'template': "Named optional parameter can't have a library private name.",
-    'howToFix': "Try removing the '_' or making the parameter positional or "
-        "required.",
-    'examples': ["""foo({int _p}) {} main() => foo();"""],
-  },
-
-  'UNSUPPORTED_LITERAL_SYMBOL': {
-    'id': 'OYCDII',
-    'template':
-        "Symbol literal '##{value}' is currently unsupported by dart2js.",
-  },
-
-  'INVALID_SYMBOL': {
-    'id': 'RUXMBL',
-    'template': '''
-'#{value}' is not a valid Symbol name because is not:
-* an empty String,
-* a user defined operator,
-* a qualified non-private identifier optionally followed by '=', or
-* a qualified non-private identifier followed by '.' and a user-defined '''
-        "operator.",
-  },
-
-  'AMBIGUOUS_REEXPORT': {
-    'id': 'YNTOND',
-    'template': "'#{name}' is (re)exported by multiple libraries.",
-  },
-
-  'AMBIGUOUS_LOCATION': {
-    'id': 'SKLTYA',
-    'template': "'#{name}' is defined here.",
-  },
-
-  'IMPORTED_HERE': {'id': 'IMUXAE', 'template': "'#{name}' is imported here.",},
-
-  'OVERRIDE_EQUALS_NOT_HASH_CODE': {
-    'id': 'MUHYXI',
-    'template': "The class '#{class}' overrides 'operator==', "
-        "but not 'get hashCode'.",
-  },
-
-  'INTERNAL_LIBRARY_FROM': {
-    'id': 'RXOCLX',
-    'template': "Internal library '#{resolvedUri}' is not accessible from "
-        "'#{importingUri}'.",
-  },
-
-  'INTERNAL_LIBRARY': {
-    'id': 'SYLJAV',
-    'template': "Internal library '#{resolvedUri}' is not accessible.",
-  },
-
-  'JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS': {
-    'id': 'LSHKJK',
-    'template':
-        "Js-interop class '#{cls}' cannot extend from the non js-interop "
-        "class '#{superclass}'.",
-    'howToFix': "Annotate the superclass with @JS.",
-    'examples': [
-      """
-            import 'package:js/js.dart';
-
-            class Foo { }
-
-            @JS()
-            class Bar extends Foo { }
-
-            main() {
-              new Bar();
-            }
-            """
-    ],
-  },
-
-  'JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER': {
-    'id': 'QLLLEE',
-    'template':
-        "Member '#{member}' in js-interop class '#{cls}' is not external.",
-    'howToFix': "Mark all interop methods external",
-    'examples': [
-      """
-            import 'package:js/js.dart';
-
-            @JS()
-            class Foo {
-              bar() {}
-            }
-
-            main() {
-              new Foo().bar();
-            }
-            """
-    ],
-  },
-
-  'JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS': {
-    'id': 'TDQHRY',
-    'template': "Js-interop method '#{method}' has named arguments but is not "
-        "a factory constructor of an @anonymous @JS class.",
-    'howToFix': "Remove all named arguments from js-interop method or "
-        "in the case of a factory constructor annotate the class "
-        "as @anonymous.",
-    'examples': [
-      """
-            import 'package:js/js.dart';
-
-            @JS()
-            class Foo {
-              external bar(foo, {baz});
-            }
-
-            main() {
-              new Foo().bar(4, baz: 5);
-            }
-            """
-    ],
-  },
-
-  'JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS': {
-    'id': 'EHEKUY',
-    'template':
-        "Parameter '#{parameter}' in anonymous js-interop class '#{cls}' "
-        "object literal constructor is positional instead of named."
-        ".",
-    'howToFix': "Make all arguments in external factory object literal "
-        "constructors named.",
-    'examples': [
-      """
-            import 'package:js/js.dart';
-
-            @anonymous
-            @JS()
-            class Foo {
-              external factory Foo(foo, {baz});
-            }
-
-            main() {
-              new Foo(5, baz: 5);
-            }
-            """
-    ],
-  },
-
-  'LIBRARY_NOT_FOUND': {
-    'id': 'BARPSL',
-    'template': "Library not found '#{resolvedUri}'.",
-  },
-
-  'LIBRARY_NOT_SUPPORTED': {
-    'id': 'GDXUNS',
-    'template': "Library not supported '#{resolvedUri}'.",
-    'howToFix': "Try removing the dependency or enabling support using "
-        "the '--categories' option.",
-    'examples': [
-//            """
-//            import 'dart:io';
-//            main() {}
-//            """
-    ],
-    // TODO(johnniwinther): Enable example when message_kind_test.dart
-    // supports library loader callbacks.
-  },
-
-  'UNSUPPORTED_EQ_EQ_EQ': {
-    'id': 'GPOVNO',
-    'template': "'===' is not an operator. "
-        "Did you mean '#{lhs} == #{rhs}' or 'identical(#{lhs}, #{rhs})'?",
-  },
-
-  'UNSUPPORTED_BANG_EQ_EQ': {
-    'id': 'HDYKMV',
-    'template': "'!==' is not an operator. "
-        "Did you mean '#{lhs} != #{rhs}' or '!identical(#{lhs}, #{rhs})'?",
-  },
-
-  'UNSUPPORTED_PREFIX_PLUS': {
-    'id': 'LSQTHP',
-    'template': "'+' is not a prefix operator. ",
-    'howToFix': "Try removing '+'.",
-    'examples': ["main() => +2;  // No longer a valid way to write '2'"],
-  },
-
-  'UNSUPPORTED_THROW_WITHOUT_EXP': {
-    'id': 'QOAKGE',
-    'template': "No expression after 'throw'. "
-        "Did you mean 'rethrow'?",
-  },
-
-  'DEPRECATED_TYPEDEF_MIXIN_SYNTAX': {
-    'id': 'BBGGFE',
-    'template': "'typedef' not allowed here. ",
-    'howToFix': "Try replacing 'typedef' with 'class'.",
-    'examples': [
-      """
-class B { }
-class M1 {  }
-typedef C = B with M1;  // Need to replace 'typedef' with 'class'.
-main() { new C(); }
-"""
-    ],
-  },
-
-  'MIRRORS_EXPECTED_STRING': {
-    'id': 'XSKTIB',
-    'template':
-        "Can't use '#{name}' here because it's an instance of '#{type}' "
-        "and a 'String' value is expected.",
-    'howToFix': "Did you forget to add quotes?",
-    'examples': [
-      """
-// 'Foo' is a type literal, not a string.
-@MirrorsUsed(symbols: const [Foo])
-import 'dart:mirrors';
-
-class Foo {}
-
-main() {}
-"""
-    ],
-  },
-
-  'MIRRORS_EXPECTED_STRING_OR_TYPE': {
-    'id': 'JQDJPL',
-    'template':
-        "Can't use '#{name}' here because it's an instance of '#{type}' "
-        "and a 'String' or 'Type' value is expected.",
-    'howToFix': "Did you forget to add quotes?",
-    'examples': [
-      """
-// 'main' is a method, not a class.
-@MirrorsUsed(targets: const [main])
-import 'dart:mirrors';
-
-main() {}
-"""
-    ],
-  },
-
-  'MIRRORS_EXPECTED_STRING_OR_LIST': {
-    'id': 'UVYCOE',
-    'template':
-        "Can't use '#{name}' here because it's an instance of '#{type}' "
-        "and a 'String' or 'List' value is expected.",
-    'howToFix': "Did you forget to add quotes?",
-    'examples': [
-      """
-// 'Foo' is not a string.
-@MirrorsUsed(symbols: Foo)
-import 'dart:mirrors';
-
-class Foo {}
-
-main() {}
-"""
-    ],
-  },
-
-  'MIRRORS_EXPECTED_STRING_TYPE_OR_LIST': {
-    'id': 'WSYDFL',
-    'template':
-        "Can't use '#{name}' here because it's an instance of '#{type}' "
-        "but a 'String', 'Type', or 'List' value is expected.",
-    'howToFix': "Did you forget to add quotes?",
-    'examples': [
-      """
-// '1' is not a string.
-@MirrorsUsed(targets: 1)
-import 'dart:mirrors';
-
-main() {}
-"""
-    ],
-  },
-
-  'MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY': {
-    'id': 'VDBBNE',
-    'template': "Can't find '#{name}' in the current library.",
-    // TODO(ahe): The closest identifiers in edit distance would be nice.
-    'howToFix': "Did you forget to add an import?",
-    'examples': [
-      """
-// 'window' is not in scope because dart:html isn't imported.
-@MirrorsUsed(targets: 'window')
-import 'dart:mirrors';
-
-main() {}
-"""
-    ],
-  },
-
-  'MIRRORS_CANNOT_RESOLVE_IN_LIBRARY': {
-    'id': 'RUEKXE',
-    'template': "Can't find '#{name}' in the library '#{library}'.",
-    // TODO(ahe): The closest identifiers in edit distance would be nice.
-    'howToFix': "Is '#{name}' spelled right?",
-    'examples': [
-      """
-// 'List' is misspelled.
-@MirrorsUsed(targets: 'dart.core.Lsit')
-import 'dart:mirrors';
-
-main() {}
-"""
-    ],
-  },
-
-  'MIRRORS_CANNOT_FIND_IN_ELEMENT': {
-    'id': 'ACPDCS',
-    'template': "Can't find '#{name}' in '#{element}'.",
-    // TODO(ahe): The closest identifiers in edit distance would be nice.
-    'howToFix': "Is '#{name}' spelled right?",
-    'examples': [
-      """
-// 'addAll' is misspelled.
-@MirrorsUsed(targets: 'dart.core.List.addAl')
-import 'dart:mirrors';
-
-main() {}
-"""
-    ],
-  },
-
-  'INVALID_URI': {
-    'id': 'QQEQMK',
-    'template': "'#{uri}' is not a valid URI.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      """
-// can't have a '[' in a URI
-import '../../Udyn[mic ils/expect.dart';
-
-main() {}
-"""
-    ],
-  },
-
-  'INVALID_PACKAGE_CONFIG': {
-    'id': 'XKFAJO',
-    'template': """Package config file '#{uri}' is invalid.
-#{exception}""",
-    'howToFix': DONT_KNOW_HOW_TO_FIX
-  },
-
-  'INVALID_PACKAGE_URI': {
-    'id': 'MFVNNJ',
-    'template': "'#{uri}' is not a valid package URI (#{exception}).",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      """
-// can't have a 'top level' package URI
-import 'package:foo.dart';
-
-main() {}
-""",
-      """
-// can't have 2 slashes
-import 'package://foo/foo.dart';
-
-main() {}
-""",
-      """
-// package name must be valid
-import 'package:not\valid/foo.dart';
-
-main() {}
-"""
-    ],
-  },
-
-  'READ_SCRIPT_ERROR': {
-    'id': 'JDDYLH',
-    'template': "Can't read '#{uri}' (#{exception}).",
-    // Don't know how to fix since the underlying error is unknown.
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      """
-// 'foo.dart' does not exist.
-import 'foo.dart';
-
-main() {}
-"""
-    ],
-  },
-
-  'READ_SELF_ERROR': {
-    'id': 'CRJUAV',
-    'template': "#{exception}",
-    // Don't know how to fix since the underlying error is unknown.
-    'howToFix': DONT_KNOW_HOW_TO_FIX
-  },
-
-  'EXTRANEOUS_MODIFIER': {
-    'id': 'DPLVJG',
-    'template': "Can't have modifier '#{modifier}' here.",
-    'howToFix': "Try removing '#{modifier}'.",
-    'examples': [
-      "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': {
-    'id': 'SSXDLN',
-    'template': "Can't have modifier '#{modifier}' here.",
-    'howToFix': "Try replacing modifier '#{modifier}' with 'var', 'final', "
-        "or a type.",
-    'examples': [
-      // "get foo; main(){}",
-      "set foo; main(){}",
-      "abstract foo; main(){}",
-      "static foo; main(){}",
-      "external foo; main(){}"
-    ],
-  },
-
-  'ABSTRACT_CLASS_INSTANTIATION': {
-    'id': 'KOBCRO',
-    'template': "Can't instantiate abstract class.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': ["abstract class A {} main() { new A(); }"],
-  },
-
-  'BODY_EXPECTED': {
-    'id': 'YXCAHO',
-    'template': "Expected a function body or '=>'.",
-    // TODO(ahe): In some scenarios, we can suggest removing the 'static'
-    // keyword.
-    'howToFix': "Try adding {}.",
-    'examples': ["main();"],
-  },
-
-  'MIRROR_BLOAT': {
-    'id': 'BSEAIT',
-    'template':
-        "#{count} methods retained for use by dart:mirrors out of #{total}"
-        " total methods (#{percentage}%).",
-  },
-
-  'MIRROR_IMPORT': {'id': 'BDAETE', 'template': "Import of 'dart:mirrors'.",},
-
-  'MIRROR_IMPORT_NO_USAGE': {
-    'id': 'OJOHTR',
-    'template':
-        "This import is not annotated with @MirrorsUsed, which may lead to "
-        "unnecessarily large generated code.",
-    'howToFix': "Try adding '@MirrorsUsed(...)' as described at "
-        "https://goo.gl/Akrrog.",
-  },
-
-  'JS_PLACEHOLDER_CAPTURE': {
-    'id': 'EJXEGQ',
-    'template': "JS code must not use '#' placeholders inside functions.",
-    'howToFix': "Use an immediately called JavaScript function to capture the"
-        " the placeholder values as JavaScript function parameters.",
-  },
-
-  'WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT': {
-    'id': 'JHRISO',
-    'template':
-        "Argument for 'JS_INTERCEPTOR_CONSTANT' must be a type constant.",
-  },
-
-  'EXPECTED_IDENTIFIER_NOT_RESERVED_WORD': {
-    'id': 'FEJXJF',
-    'template': "'#{keyword}' is a reserved word and can't be used here.",
-    'howToFix': "Try using a different name.",
-    'examples': ["do() {} main() {}"],
-  },
-
-  'NAMED_FUNCTION_EXPRESSION': {
-    'id': 'CTHFPI',
-    'template': "Function expression '#{name}' cannot be named.",
-    'howToFix': "Try removing the name.",
-    'examples': ["main() { var f = func() {}; }"],
-  },
-
-  'UNUSED_METHOD': {
-    'id': 'PKLRQL',
-    'template': "The method '#{name}' is never called.",
-    'howToFix': "Consider deleting it.",
-    'examples': ["deadCode() {} main() {}"],
-  },
-
-  'UNUSED_CLASS': {
-    'id': 'TBIECC',
-    'template': "The class '#{name}' is never used.",
-    'howToFix': "Consider deleting it.",
-    'examples': ["class DeadCode {} main() {}"],
-  },
-
-  'UNUSED_TYPEDEF': {
-    'id': 'JBIPCN',
-    'template': "The typedef '#{name}' is never used.",
-    'howToFix': "Consider deleting it.",
-    'examples': ["typedef DeadCode(); main() {}"],
-  },
-
-  'ABSTRACT_METHOD': {
-    'id': 'HOKOBG',
-    'template': "The method '#{name}' has no implementation in "
-        "class '#{class}'.",
-    'howToFix': "Try adding a body to '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-class Class {
-method();
-}
-main() => new Class().method();
-"""
-    ],
-  },
-
-  'ABSTRACT_GETTER': {
-    'id': 'VKTRNK',
-    'template': "The getter '#{name}' has no implementation in "
-        "class '#{class}'.",
-    'howToFix': "Try adding a body to '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-class Class {
-get getter;
-}
-main() => new Class();
-"""
-    ],
-  },
-
-  'ABSTRACT_SETTER': {
-    'id': 'XGDGKK',
-    'template': "The setter '#{name}' has no implementation in "
-        "class '#{class}'.",
-    'howToFix': "Try adding a body to '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-class Class {
-set setter(_);
-}
-main() => new Class();
-"""
-    ],
-  },
-
-  'INHERIT_GETTER_AND_METHOD': {
-    'id': 'UMEUEG',
-    'template': "The class '#{class}' can't inherit both getters and methods "
-        "by the named '#{name}'.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      """
-class A {
-get member => null;
-}
-class B {
-member() {}
-}
-class Class implements A, B {
-}
-main() => new Class();
-"""
-    ],
-  },
-
-  'INHERITED_METHOD': {
-    'id': 'GMSVBM',
-    'template': "The inherited method '#{name}' is declared here in class "
-        "'#{class}'.",
-  },
-
-  'INHERITED_EXPLICIT_GETTER': {
-    'id': 'KKAVRS',
-    'template': "The inherited getter '#{name}' is declared here in class "
-        "'#{class}'.",
-  },
-
-  'INHERITED_IMPLICIT_GETTER': {
-    'id': 'JBAMEJ',
-    'template': "The inherited getter '#{name}' is implicitly declared by this "
-        "field in class '#{class}'.",
-  },
-
-  'UNIMPLEMENTED_METHOD_ONE': {
-    'id': 'CMCLWO',
-    'template': "'#{class}' doesn't implement '#{method}' "
-        "declared in '#{declarer}'.",
-    'howToFix': "Try adding an implementation of '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-abstract class I {
-m();
-}
-class C implements I {}
-main() => new C();
-""",
-      """
-abstract class I {
-m();
-}
-class C extends I {}
-main() => new C();
-"""
-    ],
-  },
-
-  'UNIMPLEMENTED_METHOD': {
-    'id': 'IJSNQB',
-    'template': "'#{class}' doesn't implement '#{method}'.",
-    'howToFix': "Try adding an implementation of '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-abstract class I {
-m();
-}
-
-abstract class J {
-m();
-}
-
-class C implements I, J {}
-
-main() {
-new C();
-}
-""",
-      """
-abstract class I {
-m();
-}
-
-abstract class J {
-m();
-}
-
-class C extends I implements J {}
-
-main() {
-new C();
-}
-"""
-    ],
-  },
-
-  'UNIMPLEMENTED_METHOD_CONT': {
-    'id': 'KFBKPO',
-    'template': "The method '#{name}' is declared here in class '#{class}'.",
-  },
-
-  'UNIMPLEMENTED_SETTER_ONE': {
-    'id': 'QGKTEA',
-    'template': "'#{class}' doesn't implement the setter '#{name}' "
-        "declared in '#{declarer}'.",
-    'howToFix': "Try adding an implementation of '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-abstract class I {
-set m(_);
-}
-class C implements I {}
-class D implements I {
-set m(_) {}
-}
-main() {
-new D().m = 0;
-new C();
-}
-"""
-    ],
-  },
-
-  'UNIMPLEMENTED_SETTER': {
-    'id': 'VEEGJQ',
-    'template': "'#{class}' doesn't implement the setter '#{name}'.",
-    'howToFix': "Try adding an implementation of '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-abstract class I {
-set m(_);
-}
-abstract class J {
-set m(_);
-}
-class C implements I, J {}
-main() => new C();
-""",
-      """
-abstract class I {
-set m(_);
-}
-abstract class J {
-set m(_);
-}
-class C extends I implements J {}
-main() => new C();
-"""
-    ],
-  },
-
-  'UNIMPLEMENTED_EXPLICIT_SETTER': {
-    'id': 'SABABA',
-    'template': "The setter '#{name}' is declared here in class '#{class}'.",
-  },
-
-  'UNIMPLEMENTED_IMPLICIT_SETTER': {
-    'id': 'SWESAQ',
-    'template': "The setter '#{name}' is implicitly declared by this field "
-        "in class '#{class}'.",
-  },
-
-  'UNIMPLEMENTED_GETTER_ONE': {
-    'id': 'ODEPFW',
-    'template': "'#{class}' doesn't implement the getter '#{name}' "
-        "declared in '#{declarer}'.",
-    'howToFix': "Try adding an implementation of '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-abstract class I {
-get m;
-}
-class C implements I {}
-main() => new C();
-""",
-      """
-abstract class I {
-get m;
-}
-class C extends I {}
-main() => new C();
-"""
-    ],
-  },
-
-  'UNIMPLEMENTED_GETTER': {
-    'id': 'VHSECG',
-    'template': "'#{class}' doesn't implement the getter '#{name}'.",
-    'howToFix': "Try adding an implementation of '#{name}' or declaring "
-        "'#{class}' to be 'abstract'.",
-    'examples': [
-      """
-abstract class I {
-get m;
-}
-abstract class J {
-get m;
-}
-class C implements I, J {}
-main() => new C();
-""",
-      """
-abstract class I {
-get m;
-}
-abstract class J {
-get m;
-}
-class C extends I implements J {}
-main() => new C();
-"""
-    ],
-  },
-
-  'UNIMPLEMENTED_EXPLICIT_GETTER': {
-    'id': 'HFDJPP',
-    'template': "The getter '#{name}' is declared here in class '#{class}'.",
-  },
-
-  'UNIMPLEMENTED_IMPLICIT_GETTER': {
-    'id': 'BSCQNO',
-    'template': "The getter '#{name}' is implicitly declared by this field "
-        "in class '#{class}'.",
-  },
-
-  'INVALID_METADATA': {
-    'id': 'RKJGDE',
-    'template':
-        "A metadata annotation must be either a reference to a compile-time "
-        "constant variable or a call to a constant constructor.",
-    'howToFix':
-        "Try using a different constant value or referencing it through a "
-        "constant variable.",
-    'examples': [
-'@Object main() {}',
-'@print main() {}']
-  },
-
-  'INVALID_METADATA_GENERIC': {
-    'id': 'WEEDQD',
-    'template':
-        "A metadata annotation using a constant constructor cannot use type "
-        "arguments.",
-    'howToFix':
-        "Try removing the type arguments or referencing the constant "
-        "through a constant variable.",
-    'examples': [
-      '''
-class C<T> {
-  const C();
-}
-@C<int>() main() {}
-'''],
-  },
-
-  'EQUAL_MAP_ENTRY_KEY': {
-    'id': 'KIDLPM',
-    'template': "An entry with the same key already exists in the map.",
-    'howToFix': "Try removing the previous entry or changing the key in one "
-        "of the entries.",
-    'examples': [
-      """
-main() {
-var m = const {'foo': 1, 'foo': 2};
-}"""
-    ],
-  },
-
-  'BAD_INPUT_CHARACTER': {
-    'id': 'SHQWJY',
-    'template': "Character U+#{characterHex} isn't allowed here.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      """
-main() {
-String x = ç;
-}
-"""
-    ],
-  },
-
-  'UNTERMINATED_STRING': {
-    'id': 'TRLTHK',
-    'template': "String must end with #{quote}.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      """
-main() {
-return '
-;
-}
-""",
-      """
-main() {
-return \"
-;
-}
-""",
-      """
-main() {
-return r'
-;
-}
-""",
-      """
-main() {
-return r\"
-;
-}
-""",
-      """
-main() => '''
-""",
-      """
-main() => \"\"\"
-""",
-      """
-main() => r'''
-""",
-      """
-main() => r\"\"\"
-"""
-    ],
-  },
-
-  'UNMATCHED_TOKEN': {
-    'id': 'AGJKMQ',
-    'template': "Can't find '#{end}' to match '#{begin}'.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': ["main(", "main(){", "main(){]}",],
-  },
-
-  'UNTERMINATED_TOKEN': {
-    'id': 'VIIXHQ',
-    'template':
-        // This is a fall-back message that shouldn't happen.
-        "Incomplete token.",
-  },
-
-  'EXPONENT_MISSING': {
-    'id': 'CXPLCR',
-    'template':
-        "Numbers in exponential notation should always contain an exponent"
-        " (an integer number with an optional sign).",
-    'howToFix': "Make sure there is an exponent, and remove any whitespace "
-        "before it.",
-    'examples': [
-      """
-main() {
-var i = 1e;
-}
-"""
-    ],
-  },
-
-  'HEX_DIGIT_EXPECTED': {
-    'id': 'GKCAGV',
-    'template': "A hex digit (0-9 or A-F) must follow '0x'.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX, // Seems obvious from the error message.
-    'examples': [
-      """
-main() {
-var i = 0x;
-}
-"""
-    ],
-  },
-
-  'MALFORMED_STRING_LITERAL': {
-    'id': 'DULNSD',
-    'template':
-        r"A '$' has special meaning inside a string, and must be followed by "
-        "an identifier or an expression in curly braces ({}).",
-    'howToFix': r"Try adding a backslash (\) to escape the '$'.",
-    'examples': [
-      r"""
-main() {
-return '$';
-}
-""",
-      r'''
-main() {
-return "$";
-}
-''',
-      r"""
-main() {
-return '''$''';
-}
-""",
-      r'''
-main() {
-return """$""";
-}
-'''
-    ],
-  },
-
-  'UNTERMINATED_COMMENT': {
-    'id': 'NECJNM',
-    'template': "Comment starting with '/*' must end with '*/'.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      r"""
-main() {
-}
-/*"""
-    ],
-  },
-
-  'MISSING_TOKEN_BEFORE_THIS': {
-    'id': 'AFKXGU',
-    'template': "Expected '#{token}' before this.",
-    // Consider the second example below: the parser expects a ')' before
-    // 'y', but a ',' would also have worked. We don't have enough
-    // information to give a good suggestion.
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': ["main() => true ? 1;", "main() => foo(x: 1 y: 2);",],
-  },
-
-  'MISSING_TOKEN_AFTER_THIS': {
-    'id': 'FMUFJL',
-    'template': "Expected '#{token}' after this.",
-    // See [MISSING_TOKEN_BEFORE_THIS], we don't have enough information
-    // to give a good suggestion.
-    'howToFix': DONT_KNOW_HOW_TO_FIX,
-    'examples': [
-      "main(x) {x}",
-      """
-class S1 {}
-class S2 {}
-class S3 {}
-class A = S1 with S2, S3
-main() => new A();
-"""
-    ],
-  },
-
-  'CONSIDER_ANALYZE_ALL': {
-    'id': 'HHILSH',
-    'template': "Could not find '#{main}'.  Nothing will be analyzed.",
-    'howToFix': "Try using '--analyze-all' to analyze everything.",
-    'examples': [''],
-  },
-
-  'MISSING_MAIN': {
-    'id': 'HNAOPV',
-    'template': "Could not find '#{main}'.",
-    // No example, test uses '--analyze-only' which will produce the above
-    // message [CONSIDER_ANALYZE_ALL].  An example for a human operator
-    // would be an empty file.
-    'howToFix': "Try adding a method named '#{main}' to your program."
-  },
-
-  'MAIN_NOT_A_FUNCTION': {
-    'id': 'PIURPA',
-    'template': "'#{main}' is not a function.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX, // Don't state the obvious.
-    'examples': ['var main;'],
-  },
-
-  'MAIN_WITH_EXTRA_PARAMETER': {
-    'id': 'ONOGQB',
-    'template': "'#{main}' cannot have more than two parameters.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX, // Don't state the obvious.
-    'examples': ['main(a, b, c) {}'],
-  },
-
-  'COMPILER_CRASHED': {
-    'id': 'MHDWAV',
-    'template': "The compiler crashed when compiling this element.",
-  },
-
-  'PLEASE_REPORT_THE_CRASH': {
-    'id': 'UUTHXX',
-    'template': '''
-The compiler is broken.
-
-When compiling the above element, the compiler crashed. It is not
-possible to tell if this is caused by a problem in your program or
-not. Regardless, the compiler should not crash.
-
-The Dart team would greatly appreciate if you would take a moment to
-report this problem at http://dartbug.com/new.
-
-Please include the following information:
-
-* the name and version of your operating system,
-
-* the Dart SDK build number (#{buildId}), and
-
-* the entire message you see here (including the full stack trace
-below as well as the source location above).
-''',
-  },
-
-  'POTENTIAL_MUTATION': {
-    'id': 'YGNLLB',
-    'template': "Variable '#{variableName}' is not known to be of type "
-        "'#{shownType}' because it is potentially mutated in the scope for "
-        "promotion.",
-  },
-
-  'POTENTIAL_MUTATION_HERE': {
-    'id': 'ATMSVX',
-    'template': "Variable '#{variableName}' is potentially mutated here.",
-  },
-
-  'POTENTIAL_MUTATION_IN_CLOSURE': {
-    'id': 'XUAHTW',
-    'template': "Variable '#{variableName}' is not known to be of type "
-        "'#{shownType}' because it is potentially mutated within a closure.",
-  },
-
-  'POTENTIAL_MUTATION_IN_CLOSURE_HERE': {
-    'id': 'UHFXLG',
-    'template': "Variable '#{variableName}' is potentially mutated in a "
-        "closure here.",
-  },
-
-  'ACCESSED_IN_CLOSURE': {
-    'id': 'JJHKSF',
-    'template': "Variable '#{variableName}' is not known to be of type "
-        "'#{shownType}' because it is accessed by a closure in the scope for "
-        "promotion and potentially mutated in the scope of "
-        "'#{variableName}'.",
-  },
-
-  'ACCESSED_IN_CLOSURE_HERE': {
-    'id': 'KMJVEA',
-    'template': "Variable '#{variableName}' is accessed in a closure here.",
-  },
-
-  'NOT_MORE_SPECIFIC': {
-    'id': 'EJHQAG',
-    'template': "Variable '#{variableName}' is not shown to have type "
-        "'#{shownType}' because '#{shownType}' is not more specific than the "
-        "known type '#{knownType}' of '#{variableName}'.",
-  },
-
-  'NOT_MORE_SPECIFIC_SUBTYPE': {
-    'id': 'APICDL',
-    'template': "Variable '#{variableName}' is not shown to have type "
-        "'#{shownType}' because '#{shownType}' is not a subtype of the "
-        "known type '#{knownType}' of '#{variableName}'.",
-  },
-
-  'NOT_MORE_SPECIFIC_SUGGESTION': {
-    'id': 'FFNCJX',
-    'template': "Variable '#{variableName}' is not shown to have type "
-        "'#{shownType}' because '#{shownType}' is not more specific than the "
-        "known type '#{knownType}' of '#{variableName}'.",
-    'howToFix': "Try replacing '#{shownType}' with '#{shownTypeSuggestion}'.",
-  },
-
-  'NO_COMMON_SUBTYPES': {
-    'id': 'XKJOEC',
-    'template': "Types '#{left}' and '#{right}' have no common subtypes.",
-  },
-
-  'HIDDEN_WARNINGS_HINTS': {
-    'id': 'JBAWEK',
-    'template':
-        "#{warnings} warning(s) and #{hints} hint(s) suppressed in #{uri}.",
-  },
-
-  'HIDDEN_WARNINGS': {
-    'id': 'JIYWDC',
-    'template': "#{warnings} warning(s) suppressed in #{uri}.",
-  },
-
-  'HIDDEN_HINTS': {
-    'id': 'RHNXQT',
-    'template': "#{hints} hint(s) suppressed in #{uri}.",
-  },
-
-  'PREAMBLE': {
-    'id': 'GXGWIF',
-    'template': "When run on the command-line, the compiled output might"
-        " require a preamble file located in:\n"
-        "  <sdk>/lib/_internal/js_runtime/lib/preambles.",
-  },
-
-  'INVALID_SYNC_MODIFIER': {
-    'id': 'FNYUYU',
-    'template': "Invalid modifier 'sync'.",
-    'howToFix': "Try replacing 'sync' with 'sync*'.",
-    'examples': ["main() sync {}"],
-  },
-
-  'INVALID_AWAIT_FOR': {
-    'id': 'IEYGCY',
-    'template': "'await' is only supported on for-in loops.",
-    'howToFix': "Try rewriting the loop as a for-in loop or removing the "
-        "'await' keyword.",
-    'examples': [
-      """
-main() async* {
-await for (int i = 0; i < 10; i++) {}
-}
-"""
-    ],
-  },
-
-  'INVALID_AWAIT_FOR_IN': {
-    'id': 'FIEYGC',
-    'template': "'await' is only supported in methods with an 'async' or "
-                "'async*' body modifier.",
-    'howToFix': "Try adding 'async' or 'async*' to the method body or "
-                "removing the 'await' keyword.",
-    'examples': [
-      """
-main(o) sync* {
-  await for (var e in o) {}
-}
-"""
-    ],
-  },
-
-  'INVALID_AWAIT': {
-    'id': 'IEYHYD',
-    'template': "'await' is only supported in methods with an 'async' or "
-                "'async*' body modifier.",
-    'howToFix': "Try adding 'async' or 'async*' to the method body.",
-    'examples': [
-      """
-main() sync* {
-  await null;
-}
-"""
-    ],
-  },
-
-  'INVALID_YIELD': {
-    'id': 'IPGGCY',
-    'template': "'yield' is only supported in methods with a 'sync*' or "
-                "'async*' body modifier.",
-    'howToFix': "Try adding 'sync*' or 'async*' to the method body.",
-    'examples': [
-      """
-main() async {
-  yield 0;
-}
-"""
-    ],
-  },
-
-  'ASYNC_MODIFIER_ON_ABSTRACT_METHOD': {
-    'id': 'VRISLY',
-    'template':
-        "The modifier '#{modifier}' is not allowed on an abstract method.",
-    'options': ['--enable-async'],
-    'howToFix': "Try removing the '#{modifier}' modifier or adding a "
-        "body to the method.",
-    'examples': [
-      """
-abstract class A {
-method() async;
-}
-class B extends A {
-method() {}
-}
-main() {
-A a = new B();
-a.method();
-}
-"""
-    ],
-  },
-
-  'ASYNC_MODIFIER_ON_CONSTRUCTOR': {
-    'id': 'DHCFON',
-    'template': "The modifier '#{modifier}' is not allowed on constructors.",
-    'options': ['--enable-async'],
-    'howToFix': "Try removing the '#{modifier}' modifier.",
-    'examples': [
-      """
-class A {
-A() async;
-}
-main() => new A();""",
-      """
-class A {
-A();
-factory A.a() async* {}
-}
-main() => new A.a();"""
-    ],
-  },
-
-  'ASYNC_MODIFIER_ON_SETTER': {
-    'id': 'NMJLJE',
-    'template': "The modifier '#{modifier}' is not allowed on setters.",
-    'options': ['--enable-async'],
-    'howToFix': "Try removing the '#{modifier}' modifier.",
-    'examples': [
-      """
-class A {
-set foo(v) async {}
-}
-main() => new A().foo = 0;"""
-    ],
-  },
-
-  'YIELDING_MODIFIER_ON_ARROW_BODY': {
-    'id': 'UOGLUX',
-    'template':
-        "The modifier '#{modifier}' is not allowed on methods implemented "
-        "using '=>'.",
-    'options': ['--enable-async'],
-    'howToFix': "Try removing the '#{modifier}' modifier or implementing "
-        "the method body using a block: '{ ... }'.",
-    'examples': ["main() sync* => null;", "main() async* => null;"],
-  },
-
-  // TODO(johnniwinther): Check for 'async' as identifier.
-  'ASYNC_KEYWORD_AS_IDENTIFIER': {
-    'id': 'VTWSMA',
-    'template':
-        "'#{keyword}' cannot be used as an identifier in a function body "
-        "marked with '#{modifier}'.",
-    'options': ['--enable-async'],
-    'howToFix': "Try removing the '#{modifier}' modifier or renaming the "
-        "identifier.",
-    'examples': [
-      """
-main() async {
-var await;
-}""",
-      """
-main() async* {
-var yield;
-}""",
-      """
-main() sync* {
-var yield;
-}"""
-    ],
-  },
-
-  'RETURN_IN_GENERATOR': {
-    'id': 'AWGUVF',
-    'template':
-        "'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': [
-      """
-foo() async* { return 0; }
-main() => foo();
-""",
-      """
-foo() sync* { return 0; }
-main() => foo();
-"""
-    ],
-  },
-
-  'NATIVE_NOT_SUPPORTED': {
-    'id': 'QMMLUT',
-    'template': "'native' modifier is not supported.",
-    'howToFix': "Try removing the 'native' implementation or analyzing the "
-        "code with the --allow-native-extensions option.",
-    'examples': [
-      """
-main() native "Main";
-"""
-    ],
-  },
-
-  'DART_EXT_NOT_SUPPORTED': {
-    'id': 'JLPQFJ',
-    'template': "The 'dart-ext' scheme is not supported.",
-    'howToFix': "Try analyzing the code with the --allow-native-extensions "
-        "option.",
-    'examples': [
-      """
-import 'dart-ext:main';
-
-main() {}
-"""
-    ],
-  },
-
-  'LIBRARY_TAG_MUST_BE_FIRST': {
-    'id': 'JFUSRX',
-    'template':
-        "The library declaration should come before other declarations.",
-    'howToFix': "Try moving the declaration to the top of the file.",
-    'examples': [
-      """
-import 'dart:core';
-library foo;
-main() {}
-""",
-    ],
-  },
-
-  'ONLY_ONE_LIBRARY_TAG': {
-    'id': 'CCXFMY',
-    'template': "There can only be one library declaration.",
-    'howToFix': "Try removing all other library declarations.",
-    'examples': [
-      """
-library foo;
-library bar;
-main() {}
-""",
-      """
-library foo;
-import 'dart:core';
-library bar;
-main() {}
-""",
-    ],
-  },
-
-  'IMPORT_BEFORE_PARTS': {
-    'id': 'NSMOQI',
-    'template': "Import declarations should come before parts.",
-    'howToFix': "Try moving this import further up in the file.",
-    'examples': [
-      {
-        'main.dart': """
-library test.main;
-part 'part.dart';
-import 'dart:core';
-main() {}
-""",
-        'part.dart': """
-part of test.main;
-""",
-      }
-    ],
-  },
-
-  'EXPORT_BEFORE_PARTS': {
-    'id': 'KYJTTC',
-    'template': "Export declarations should come before parts.",
-    'howToFix': "Try moving this export further up in the file.",
-    'examples': [
-      {
-        'main.dart': """
-library test.main;
-part 'part.dart';
-export 'dart:core';
-main() {}
-""",
-        'part.dart': """
-part of test.main;
-""",
-      }
-    ],
-
-//////////////////////////////////////////////////////////////////////////////
-// Patch errors start.
-//////////////////////////////////////////////////////////////////////////////
-  },
-
-  'PATCH_RETURN_TYPE_MISMATCH': {
-    'id': 'DTOQDU',
-    'template': "Patch return type '#{patchReturnType}' does not match "
-        "'#{originReturnType}' on origin method '#{methodName}'.",
-  },
-
-  'PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH': {
-    'id': 'KJUUYC',
-    'template': "Required parameter count of patch method "
-        "(#{patchParameterCount}) does not match parameter count on origin "
-        "method '#{methodName}' (#{originParameterCount}).",
-  },
-
-  'PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH': {
-    'id': 'GUTGTE',
-    'template': "Optional parameter count of patch method "
-        "(#{patchParameterCount}) does not match parameter count on origin "
-        "method '#{methodName}' (#{originParameterCount}).",
-  },
-
-  'PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH': {
-    'id': 'MCHEIC',
-    'template': "Optional parameters of origin and patch method "
-        "'#{methodName}' must both be either named or positional.",
-  },
-
-  'PATCH_PARAMETER_MISMATCH': {
-    'id': 'XISHPB',
-    'template': "Patch method parameter '#{patchParameter}' does not match "
-        "'#{originParameter}' on origin method '#{methodName}'.",
-  },
-
-  'PATCH_PARAMETER_TYPE_MISMATCH': {
-    'id': 'UGRBYD',
-    'template': "Patch method parameter '#{parameterName}' type "
-        "'#{patchParameterType}' does not match '#{originParameterType}' on "
-        "origin method '#{methodName}'.",
-  },
-
-  'PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION': {
-    'id': 'WSNMKD',
-    'template': "External method without an implementation.",
-  },
-
-  'PATCH_POINT_TO_FUNCTION': {
-    'id': 'CAVBPN',
-    'template': "This is the function patch '#{functionName}'.",
-  },
-
-  'PATCH_POINT_TO_CLASS': {
-    'id': 'TWDLDX',
-    'template': "This is the class patch '#{className}'.",
-  },
-
-  'PATCH_POINT_TO_GETTER': {
-    'id': 'TRBBNY',
-    'template': "This is the getter patch '#{getterName}'.",
-  },
-
-  'PATCH_POINT_TO_SETTER': {
-    'id': 'DAXDLW',
-    'template': "This is the setter patch '#{setterName}'.",
-  },
-
-  'PATCH_POINT_TO_CONSTRUCTOR': {
-    'id': 'VYQISY',
-    'template': "This is the constructor patch '#{constructorName}'.",
-  },
-
-  'PATCH_POINT_TO_PARAMETER': {
-    'id': 'TFPAGO',
-    'template': "This is the patch parameter '#{parameterName}'.",
-  },
-
-  'PATCH_NON_EXISTING': {
-    'id': 'AWOACF',
-    'template': "Origin does not exist for patch '#{name}'.",
-  },
-
-  // TODO(ahe): Eventually, this error should be removed as it will be
-  // handled by the regular parser.
-  'PATCH_NONPATCHABLE': {
-    'id': 'WQEPJI',
-    'template': "Only classes and functions can be patched.",
-  },
-
-  'PATCH_NON_EXTERNAL': {
-    'id': 'MHLXNK',
-    'template': "Only external functions can be patched.",
-  },
-
-  'PATCH_NON_CLASS': {
-    'id': 'UIALAB',
-    'template': "Patching non-class with class patch '#{className}'.",
-  },
-
-  'PATCH_NON_GETTER': {
-    'id': 'VTNQCJ',
-    'template': "Cannot patch non-getter '#{name}' with getter patch.",
-  },
-
-  'PATCH_NO_GETTER': {
-    'id': 'XOPDHD',
-    'template': "No getter found for getter patch '#{getterName}'.",
-  },
-
-  'PATCH_NON_SETTER': {
-    'id': 'XBOMMN',
-    'template': "Cannot patch non-setter '#{name}' with setter patch.",
-  },
-
-  'PATCH_NO_SETTER': {
-    'id': 'YITARQ',
-    'template': "No setter found for setter patch '#{setterName}'.",
-  },
-
-  'PATCH_NON_CONSTRUCTOR': {
-    'id': 'TWAEQV',
-    'template': "Cannot patch non-constructor with constructor patch "
-        "'#{constructorName}'.",
-  },
-
-  'PATCH_NON_FUNCTION': {
-    'id': 'EDXBPI',
-    'template': "Cannot patch non-function with function patch "
-        "'#{functionName}'.",
-  },
-
-  'INJECTED_PUBLIC_MEMBER': {
-    'id': 'JGMXMI',
-    'template': "Non-patch members in patch libraries must be private.",
-  },
-
-  'EXTERNAL_WITH_BODY': {
-    'id': 'GAVMSQ',
-    'template':
-        "External function '#{functionName}' cannot have a function body.",
-    'options': ["--output-type=dart"],
-    'howToFix': "Try removing the 'external' modifier or the function body.",
-    'examples': [
-      """
-external foo() => 0;
-main() => foo();
-""",
-      """
-external foo() {}
-main() => foo();
-"""
-    ],
-
-//////////////////////////////////////////////////////////////////////////////
-// Patch errors end.
-//////////////////////////////////////////////////////////////////////////////
-  },
-
-  'EXPERIMENTAL_ASSERT_MESSAGE': {
-    'id': 'NENGIS',
-    'template': "Experimental language feature 'assertion with message'"
-        " is not supported.",
-    'howToFix':
-        "Use option '--assert-message' to use assertions with messages.",
-    'examples': [
-      r'''
-main() {
-int n = -7;
-assert(n > 0, 'must be positive: $n');
-}
-'''
-    ],
-  },
-
-  'IMPORT_EXPERIMENTAL_MIRRORS': {
-    'id': 'SCJYPH',
-    'template': '''
-
-****************************************************************
-* WARNING: dart:mirrors support in dart2js is experimental,
-*          and not recommended.
-*          This implementation of mirrors is incomplete,
-*          and often greatly increases the size of the generated
-*          JavaScript code.
-*
-* Your app imports dart:mirrors via:'''
-        '''
-$IMPORT_EXPERIMENTAL_MIRRORS_PADDING#{importChain}
-*
-* You can disable this message by using the --enable-experimental-mirrors
-* command-line flag.
-*
-* To learn what to do next, please visit:
-*    http://dartlang.org/dart2js-reflection
-****************************************************************
-''',
-  },
-
-  'DISALLOWED_LIBRARY_IMPORT': {
-    'id': 'OCSFJU',
-    'template': '''
-Your app imports the unsupported library '#{uri}' via:
-'''
-        '''
-$DISALLOWED_LIBRARY_IMPORT_PADDING#{importChain}
-
-Use the --categories option to support import of '#{uri}'.
-''',
-  },
-
-  'MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND': {
-    'id': 'JBTRRM',
-    'template': """
-dart:mirrors library is not supported when using this backend.
-
-Your app imports dart:mirrors via:"""
-        """
-$MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING#{importChain}""",
-  },
-
-  'CALL_NOT_SUPPORTED_ON_NATIVE_CLASS': {
-    'id': 'HAULDW',
-    'template': "Non-supported 'call' member on a native class, or a "
-        "subclass of a native class.",
-  },
-
-  'DIRECTLY_THROWING_NSM': {
-    'id': 'XLTPCS',
-    'template': "This 'noSuchMethod' implementation is guaranteed to throw an "
-        "exception. The generated code will be smaller if it is "
-        "rewritten.",
-    'howToFix': "Rewrite to "
-        "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'.",
-  },
-
-  'COMPLEX_THROWING_NSM': {
-    'id': 'PLCXVX',
-    'template': "This 'noSuchMethod' implementation is guaranteed to throw an "
-        "exception. The generated code will be smaller and the compiler "
-        "will be able to perform more optimizations if it is rewritten.",
-    'howToFix': "Rewrite to "
-        "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'.",
-  },
-
-  'COMPLEX_RETURNING_NSM': {
-    'id': 'HUTCTQ',
-    'template': "Overriding 'noSuchMethod' causes the compiler to generate "
-        "more code and prevents the compiler from doing some optimizations.",
-    'howToFix': "Consider removing this 'noSuchMethod' implementation."
-  },
-
-  'UNRECOGNIZED_VERSION_OF_LOOKUP_MAP': {
-    'id': 'OVAFEW',
-    'template': "Unsupported version of package:lookup_map.",
-    'howToFix': DONT_KNOW_HOW_TO_FIX
-  },
-};
diff --git a/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart b/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
new file mode 100644
index 0000000..c8617cc
--- /dev/null
+++ b/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
@@ -0,0 +1,37 @@
+// 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.
+/*
+DON'T EDIT. GENERATED. DON'T EDIT.
+This file has been generated by 'publish.dart' in the dart_messages package.
+
+Messages are maintained in `lib/shared_messages.dart` of that same package.
+After any change to that file, run `bin/publish.dart` to generate a new version
+of the json, dart2js and analyzer representations.
+*/
+import '../messages.dart' show MessageTemplate;
+
+enum SharedMessageKind {
+  exampleMessage
+}
+
+const Map<SharedMessageKind, MessageTemplate> TEMPLATES = const <SharedMessageKind, MessageTemplate>{ 
+  SharedMessageKind.exampleMessage: const MessageTemplate(
+    SharedMessageKind.exampleMessage,
+    "#use #named #arguments",
+    howToFix: "an explanation on how to fix things",
+    examples: const [
+      r'''
+      Some multiline example;
+      That generates the bug.''',
+      const {
+      'fileA.dart': r'''
+        or a map from file to content.
+        again multiline''',
+      'fileB.dart': r'''
+        with possibly multiple files.
+        muliline too''',
+      },
+    ]
+  ),  // Generated. Don't edit.
+};
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index b529e1c..f394bdf 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -2,16 +2,81 @@
 // 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.
 
+
+/**
+ * The messages in this file should meet the following guide lines:
+ *
+ * 1. The message should be a complete sentence starting with an uppercase
+ * letter, and ending with a period.
+ *
+ * 2. Reserved words and embedded identifiers should be in single quotes, so
+ * prefer double quotes for the complete message. For example, "The
+ * class '#{className}' can't use 'super'." Notice that the word 'class' in the
+ * preceding message is not quoted as it refers to the concept 'class', not the
+ * reserved word. On the other hand, 'super' refers to the reserved word. Do
+ * not quote 'null' and numeric literals.
+ *
+ * 3. Do not try to compose messages, as it can make translating them hard.
+ *
+ * 4. Try to keep the error messages short, but informative.
+ *
+ * 5. Use simple words and terminology, assume the reader of the message
+ * doesn't have an advanced degree in math, and that English is not the
+ * reader's native language. Do not assume any formal computer science
+ * training. For example, do not use Latin abbreviations (prefer "that is" over
+ * "i.e.", and "for example" over "e.g."). Also avoid phrases such as "if and
+ * only if" and "iff", that level of precision is unnecessary.
+ *
+ * 6. Prefer contractions when they are in common use, for example, prefer
+ * "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is
+ * off-putting to people new to programming.
+ *
+ * 7. Use common terminology, preferably from the Dart Language
+ * Specification. This increases the user's chance of finding a good
+ * explanation on the web.
+ *
+ * 8. Do not try to be cute or funny. It is extremely frustrating to work on a
+ * product that crashes with a "tongue-in-cheek" message, especially if you did
+ * not want to use this product to begin with.
+ *
+ * 9. Do not lie, that is, do not write error messages containing phrases like
+ * "can't happen".  If the user ever saw this message, it would be a
+ * lie. Prefer messages like: "Internal error: This function should not be
+ * called when 'x' is null.".
+ *
+ * 10. Prefer to not use imperative tone. That is, the message should not sound
+ * accusing or like it is ordering the user around. The computer should
+ * describe the problem, not criticize for violating the specification.
+ *
+ * Other things to keep in mind:
+ *
+ * An INFO message should always be preceded by a non-INFO message, and the
+ * INFO messages are additional details about the preceding non-INFO
+ * message. For example, consider duplicated elements. First report a WARNING
+ * or ERROR about the duplicated element, and then report an INFO about the
+ * location of the existing element.
+ *
+ * Generally, we want to provide messages that consists of three sentences:
+ * 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we
+ * combine the first two in [template] and the last in [howToFix].
+ */
+
 library dart2js.messages;
 
-import 'package:dart_messages/shared_messages.dart' as shared_messages;
+import '../tokens/token.dart' show
+    ErrorToken,
+    Token;
 
-import '../tokens/token.dart' show ErrorToken, Token;
+import 'invariant.dart' show
+    invariant;
+import 'spannable.dart' show
+    CURRENT_ELEMENT_SPANNABLE;
 
-import 'invariant.dart' show invariant;
-import 'spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
+import 'generated/shared_messages.dart' as shared_messages;
 
-import 'dart2js_messages.dart' as dart2js_messages;
+export 'generated/shared_messages.dart' show SharedMessageKind;
+
+const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
 
 /// Keys for the [MessageTemplate]s.
 enum MessageKind {
@@ -406,472 +471,13 @@
   YIELDING_MODIFIER_ON_ARROW_BODY,
 }
 
-const _KIND_TO_STRING_MAP = const <MessageKind, String>{
-  MessageKind.ABSTRACT_CLASS_INSTANTIATION: "ABSTRACT_CLASS_INSTANTIATION",
-  MessageKind.ABSTRACT_GETTER: "ABSTRACT_GETTER",
-  MessageKind.ABSTRACT_METHOD: "ABSTRACT_METHOD",
-  MessageKind.ABSTRACT_SETTER: "ABSTRACT_SETTER",
-  MessageKind.ACCESSED_IN_CLOSURE: "ACCESSED_IN_CLOSURE",
-  MessageKind.ACCESSED_IN_CLOSURE_HERE: "ACCESSED_IN_CLOSURE_HERE",
-  MessageKind.ADDITIONAL_ARGUMENT: "ADDITIONAL_ARGUMENT",
-  MessageKind.ADDITIONAL_TYPE_ARGUMENT: "ADDITIONAL_TYPE_ARGUMENT",
-  MessageKind.ALREADY_INITIALIZED: "ALREADY_INITIALIZED",
-  MessageKind.AMBIGUOUS_LOCATION: "AMBIGUOUS_LOCATION",
-  MessageKind.AMBIGUOUS_REEXPORT: "AMBIGUOUS_REEXPORT",
-  MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS:
-      "ASSERT_IS_GIVEN_NAMED_ARGUMENTS",
-  MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER: "ASSIGNING_FINAL_FIELD_IN_SUPER",
-  MessageKind.ASSIGNING_METHOD: "ASSIGNING_METHOD",
-  MessageKind.ASSIGNING_METHOD_IN_SUPER: "ASSIGNING_METHOD_IN_SUPER",
-  MessageKind.ASSIGNING_TYPE: "ASSIGNING_TYPE",
-  MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER: "ASYNC_KEYWORD_AS_IDENTIFIER",
-  MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD:
-      "ASYNC_MODIFIER_ON_ABSTRACT_METHOD",
-  MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR: "ASYNC_MODIFIER_ON_CONSTRUCTOR",
-  MessageKind.ASYNC_MODIFIER_ON_SETTER: "ASYNC_MODIFIER_ON_SETTER",
-  MessageKind.AWAIT_MEMBER_NOT_FOUND: "AWAIT_MEMBER_NOT_FOUND",
-  MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE:
-      "AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE",
-  MessageKind.BAD_INPUT_CHARACTER: "BAD_INPUT_CHARACTER",
-  MessageKind.BEFORE_TOP_LEVEL: "BEFORE_TOP_LEVEL",
-  MessageKind.BINARY_OPERATOR_BAD_ARITY: "BINARY_OPERATOR_BAD_ARITY",
-  MessageKind.BODY_EXPECTED: "BODY_EXPECTED",
-  MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS:
-      "CALL_NOT_SUPPORTED_ON_NATIVE_CLASS",
-  MessageKind.CANNOT_EXTEND: "CANNOT_EXTEND",
-  MessageKind.CANNOT_EXTEND_ENUM: "CANNOT_EXTEND_ENUM",
-  MessageKind.CANNOT_EXTEND_MALFORMED: "CANNOT_EXTEND_MALFORMED",
-  MessageKind.CANNOT_FIND_CONSTRUCTOR: "CANNOT_FIND_CONSTRUCTOR",
-  MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR:
-      "CANNOT_FIND_UNNAMED_CONSTRUCTOR",
-  MessageKind.CANNOT_IMPLEMENT: "CANNOT_IMPLEMENT",
-  MessageKind.CANNOT_IMPLEMENT_ENUM: "CANNOT_IMPLEMENT_ENUM",
-  MessageKind.CANNOT_IMPLEMENT_MALFORMED: "CANNOT_IMPLEMENT_MALFORMED",
-  MessageKind.CANNOT_INSTANTIATE_ENUM: "CANNOT_INSTANTIATE_ENUM",
-  MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE:
-      "CANNOT_INSTANTIATE_TYPE_VARIABLE",
-  MessageKind.CANNOT_INSTANTIATE_TYPEDEF: "CANNOT_INSTANTIATE_TYPEDEF",
-  MessageKind.CANNOT_MIXIN: "CANNOT_MIXIN",
-  MessageKind.CANNOT_MIXIN_ENUM: "CANNOT_MIXIN_ENUM",
-  MessageKind.CANNOT_MIXIN_MALFORMED: "CANNOT_MIXIN_MALFORMED",
-  MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD:
-      "CANNOT_OVERRIDE_FIELD_WITH_METHOD",
-  MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT:
-      "CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT",
-  MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD:
-      "CANNOT_OVERRIDE_GETTER_WITH_METHOD",
-  MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT:
-      "CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT",
-  MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD:
-      "CANNOT_OVERRIDE_METHOD_WITH_FIELD",
-  MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT:
-      "CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT",
-  MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER:
-      "CANNOT_OVERRIDE_METHOD_WITH_GETTER",
-  MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT:
-      "CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT",
-  MessageKind.CANNOT_RESOLVE: "CANNOT_RESOLVE",
-  MessageKind.CANNOT_RESOLVE_AWAIT: "CANNOT_RESOLVE_AWAIT",
-  MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE:
-      "CANNOT_RESOLVE_AWAIT_IN_CLOSURE",
-  MessageKind.CANNOT_RESOLVE_CONSTRUCTOR: "CANNOT_RESOLVE_CONSTRUCTOR",
-  MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT:
-      "CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT",
-  MessageKind.CANNOT_RESOLVE_GETTER: "CANNOT_RESOLVE_GETTER",
-  MessageKind.CANNOT_RESOLVE_IN_INITIALIZER: "CANNOT_RESOLVE_IN_INITIALIZER",
-  MessageKind.CANNOT_RESOLVE_SETTER: "CANNOT_RESOLVE_SETTER",
-  MessageKind.CANNOT_RESOLVE_TYPE: "CANNOT_RESOLVE_TYPE",
-  MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR: "CANNOT_RETURN_FROM_CONSTRUCTOR",
-  MessageKind.CLASS_NAME_EXPECTED: "CLASS_NAME_EXPECTED",
-  MessageKind.COMPILER_CRASHED: "COMPILER_CRASHED",
-  MessageKind.COMPLEX_RETURNING_NSM: "COMPLEX_RETURNING_NSM",
-  MessageKind.COMPLEX_THROWING_NSM: "COMPLEX_THROWING_NSM",
-  MessageKind.CONSIDER_ANALYZE_ALL: "CONSIDER_ANALYZE_ALL",
-  MessageKind.CONST_CALLS_NON_CONST: "CONST_CALLS_NON_CONST",
-  MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT:
-      "CONST_CALLS_NON_CONST_FOR_IMPLICIT",
-  MessageKind.CONST_CONSTRUCTOR_HAS_BODY: "CONST_CONSTRUCTOR_HAS_BODY",
-  MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS:
-      "CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS",
-  MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR:
-      "CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR",
-  MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD:
-      "CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD",
-  MessageKind.CONST_LOOP_VARIABLE: "CONST_LOOP_VARIABLE",
-  MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS: "CONST_MAP_KEY_OVERRIDES_EQUALS",
-  MessageKind.CONST_WITHOUT_INITIALIZER: "CONST_WITHOUT_INITIALIZER",
-  MessageKind.CONSTRUCTOR_CALL_EXPECTED: "CONSTRUCTOR_CALL_EXPECTED",
-  MessageKind.CONSTRUCTOR_IS_NOT_CONST: "CONSTRUCTOR_IS_NOT_CONST",
-  MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE: "CONSTRUCTOR_WITH_RETURN_TYPE",
-  MessageKind.CYCLIC_CLASS_HIERARCHY: "CYCLIC_CLASS_HIERARCHY",
-  MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS: "CYCLIC_COMPILE_TIME_CONSTANTS",
-  MessageKind.CYCLIC_REDIRECTING_FACTORY: "CYCLIC_REDIRECTING_FACTORY",
-  MessageKind.CYCLIC_TYPE_VARIABLE: "CYCLIC_TYPE_VARIABLE",
-  MessageKind.CYCLIC_TYPEDEF: "CYCLIC_TYPEDEF",
-  MessageKind.CYCLIC_TYPEDEF_ONE: "CYCLIC_TYPEDEF_ONE",
-  MessageKind.DART_EXT_NOT_SUPPORTED: "DART_EXT_NOT_SUPPORTED",
-  MessageKind.DEFERRED_COMPILE_TIME_CONSTANT: "DEFERRED_COMPILE_TIME_CONSTANT",
-  MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION:
-      "DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION",
-  MessageKind.DEFERRED_LIBRARY_DART_2_DART: "DEFERRED_LIBRARY_DART_2_DART",
-  MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX:
-      "DEFERRED_LIBRARY_DUPLICATE_PREFIX",
-  MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX:
-      "DEFERRED_LIBRARY_WITHOUT_PREFIX",
-  MessageKind.DEFERRED_OLD_SYNTAX: "DEFERRED_OLD_SYNTAX",
-  MessageKind.DEFERRED_TYPE_ANNOTATION: "DEFERRED_TYPE_ANNOTATION",
-  MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX:
-      "DEPRECATED_TYPEDEF_MIXIN_SYNTAX",
-  MessageKind.DIRECTLY_THROWING_NSM: "DIRECTLY_THROWING_NSM",
-  MessageKind.DISALLOWED_LIBRARY_IMPORT: "DISALLOWED_LIBRARY_IMPORT",
-  MessageKind.DUPLICATE_DEFINITION: "DUPLICATE_DEFINITION",
-  MessageKind.DUPLICATE_EXPORT: "DUPLICATE_EXPORT",
-  MessageKind.DUPLICATE_EXPORT_CONT: "DUPLICATE_EXPORT_CONT",
-  MessageKind.DUPLICATE_EXPORT_DECL: "DUPLICATE_EXPORT_DECL",
-  MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS: "DUPLICATE_EXTENDS_IMPLEMENTS",
-  MessageKind.DUPLICATE_IMPLEMENTS: "DUPLICATE_IMPLEMENTS",
-  MessageKind.DUPLICATE_IMPORT: "DUPLICATE_IMPORT",
-  MessageKind.DUPLICATE_INITIALIZER: "DUPLICATE_INITIALIZER",
-  MessageKind.DUPLICATE_LABEL: "DUPLICATE_LABEL",
-  MessageKind.DUPLICATE_SUPER_INITIALIZER: "DUPLICATE_SUPER_INITIALIZER",
-  MessageKind.DUPLICATE_TYPE_VARIABLE_NAME: "DUPLICATE_TYPE_VARIABLE_NAME",
-  MessageKind.DUPLICATED_LIBRARY_NAME: "DUPLICATED_LIBRARY_NAME",
-  MessageKind.DUPLICATED_LIBRARY_RESOURCE: "DUPLICATED_LIBRARY_RESOURCE",
-  MessageKind.DUPLICATED_PART_OF: "DUPLICATED_PART_OF",
-  MessageKind.DUPLICATED_RESOURCE: "DUPLICATED_RESOURCE",
-  MessageKind.EMPTY_CATCH_DECLARATION: "EMPTY_CATCH_DECLARATION",
-  MessageKind.EMPTY_ENUM_DECLARATION: "EMPTY_ENUM_DECLARATION",
-  MessageKind.EMPTY_HIDE: "EMPTY_HIDE",
-  MessageKind.EQUAL_MAP_ENTRY_KEY: "EQUAL_MAP_ENTRY_KEY",
-  MessageKind.EMPTY_SHOW: "EMPTY_SHOW",
-  MessageKind.EXISTING_DEFINITION: "EXISTING_DEFINITION",
-  MessageKind.EXISTING_LABEL: "EXISTING_LABEL",
-  MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD:
-      "EXPECTED_IDENTIFIER_NOT_RESERVED_WORD",
-  MessageKind.EXPERIMENTAL_ASSERT_MESSAGE: "EXPERIMENTAL_ASSERT_MESSAGE",
-  MessageKind.EXPONENT_MISSING: "EXPONENT_MISSING",
-  MessageKind.EXPORT_BEFORE_PARTS: "EXPORT_BEFORE_PARTS",
-  MessageKind.EXTERNAL_WITH_BODY: "EXTERNAL_WITH_BODY",
-  MessageKind.EXTRA_CATCH_DECLARATION: "EXTRA_CATCH_DECLARATION",
-  MessageKind.EXTRA_FORMALS: "EXTRA_FORMALS",
-  MessageKind.EXTRANEOUS_MODIFIER: "EXTRANEOUS_MODIFIER",
-  MessageKind.EXTRANEOUS_MODIFIER_REPLACE: "EXTRANEOUS_MODIFIER_REPLACE",
-  MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY:
-      "FACTORY_REDIRECTION_IN_NON_FACTORY",
-  MessageKind.FINAL_FUNCTION_TYPE_PARAMETER: "FINAL_FUNCTION_TYPE_PARAMETER",
-  MessageKind.FINAL_WITHOUT_INITIALIZER: "FINAL_WITHOUT_INITIALIZER",
-  MessageKind.FORIN_NOT_ASSIGNABLE: "FORIN_NOT_ASSIGNABLE",
-  MessageKind.FORMAL_DECLARED_CONST: "FORMAL_DECLARED_CONST",
-  MessageKind.FORMAL_DECLARED_STATIC: "FORMAL_DECLARED_STATIC",
-  MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT:
-      "FUNCTION_TYPE_FORMAL_WITH_DEFAULT",
-  MessageKind.FUNCTION_WITH_INITIALIZER: "FUNCTION_WITH_INITIALIZER",
-  MessageKind.GENERIC: "GENERIC",
-  MessageKind.GETTER_MISMATCH: "GETTER_MISMATCH",
-  MessageKind.GETTER_NOT_FOUND: "GETTER_NOT_FOUND",
-  MessageKind.HEX_DIGIT_EXPECTED: "HEX_DIGIT_EXPECTED",
-  MessageKind.HIDDEN_HINTS: "HIDDEN_HINTS",
-  MessageKind.HIDDEN_IMPLICIT_IMPORT: "HIDDEN_IMPLICIT_IMPORT",
-  MessageKind.HIDDEN_IMPORT: "HIDDEN_IMPORT",
-  MessageKind.HIDDEN_WARNINGS: "HIDDEN_WARNINGS",
-  MessageKind.HIDDEN_WARNINGS_HINTS: "HIDDEN_WARNINGS_HINTS",
-  MessageKind.IF_NULL_ASSIGNING_TYPE: "IF_NULL_ASSIGNING_TYPE",
-  MessageKind.ILLEGAL_CONST_FIELD_MODIFIER: "ILLEGAL_CONST_FIELD_MODIFIER",
-  MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS: "ILLEGAL_CONSTRUCTOR_MODIFIERS",
-  MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER: "ILLEGAL_FINAL_METHOD_MODIFIER",
-  MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS:
-      "ILLEGAL_MIXIN_APPLICATION_MODIFIERS",
-  MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR: "ILLEGAL_MIXIN_CONSTRUCTOR",
-  MessageKind.ILLEGAL_MIXIN_CYCLE: "ILLEGAL_MIXIN_CYCLE",
-  MessageKind.ILLEGAL_MIXIN_OBJECT: "ILLEGAL_MIXIN_OBJECT",
-  MessageKind.ILLEGAL_MIXIN_SUPER_USE: "ILLEGAL_MIXIN_SUPER_USE",
-  MessageKind.ILLEGAL_MIXIN_SUPERCLASS: "ILLEGAL_MIXIN_SUPERCLASS",
-  MessageKind.ILLEGAL_MIXIN_WITH_SUPER: "ILLEGAL_MIXIN_WITH_SUPER",
-  MessageKind.ILLEGAL_SETTER_FORMALS: "ILLEGAL_SETTER_FORMALS",
-  MessageKind.ILLEGAL_STATIC: "ILLEGAL_STATIC",
-  MessageKind.ILLEGAL_SUPER_SEND: "ILLEGAL_SUPER_SEND",
-  MessageKind.IMPORT_BEFORE_PARTS: "IMPORT_BEFORE_PARTS",
-  MessageKind.IMPORT_EXPERIMENTAL_MIRRORS: "IMPORT_EXPERIMENTAL_MIRRORS",
-  MessageKind.IMPORT_PART_OF: "IMPORT_PART_OF",
-  MessageKind.IMPORT_PART_OF_HERE: "IMPORT_PART_OF_HERE",
-  MessageKind.IMPORTED_HERE: "IMPORTED_HERE",
-  MessageKind.INHERIT_GETTER_AND_METHOD: "INHERIT_GETTER_AND_METHOD",
-  MessageKind.INHERITED_EXPLICIT_GETTER: "INHERITED_EXPLICIT_GETTER",
-  MessageKind.INHERITED_IMPLICIT_GETTER: "INHERITED_IMPLICIT_GETTER",
-  MessageKind.INHERITED_METHOD: "INHERITED_METHOD",
-  MessageKind.INJECTED_PUBLIC_MEMBER: "INJECTED_PUBLIC_MEMBER",
-  MessageKind.INIT_STATIC_FIELD: "INIT_STATIC_FIELD",
-  MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED:
-      "INITIALIZING_FORMAL_NOT_ALLOWED",
-  MessageKind.INSTANCE_STATIC_SAME_NAME: "INSTANCE_STATIC_SAME_NAME",
-  MessageKind.INSTANCE_STATIC_SAME_NAME_CONT: "INSTANCE_STATIC_SAME_NAME_CONT",
-  MessageKind.INTERNAL_LIBRARY: "INTERNAL_LIBRARY",
-  MessageKind.INTERNAL_LIBRARY_FROM: "INTERNAL_LIBRARY_FROM",
-  MessageKind.INVALID_ARGUMENT_AFTER_NAMED: "INVALID_ARGUMENT_AFTER_NAMED",
-  MessageKind.INVALID_AWAIT: "INVALID_AWAIT",
-  MessageKind.INVALID_AWAIT_FOR: "INVALID_AWAIT_FOR",
-  MessageKind.INVALID_AWAIT_FOR_IN: "INVALID_AWAIT_FOR_IN",
-  MessageKind.INVALID_BREAK: "INVALID_BREAK",
-  MessageKind.INVALID_CASE_DEFAULT: "INVALID_CASE_DEFAULT",
-  MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS: "INVALID_CONSTRUCTOR_ARGUMENTS",
-  MessageKind.INVALID_CONSTRUCTOR_NAME: "INVALID_CONSTRUCTOR_NAME",
-  MessageKind.INVALID_CONTINUE: "INVALID_CONTINUE",
-  MessageKind.INVALID_FOR_IN: "INVALID_FOR_IN",
-  MessageKind.INVALID_INITIALIZER: "INVALID_INITIALIZER",
-  MessageKind.INVALID_METADATA: "INVALID_METADATA",
-  MessageKind.INVALID_METADATA_GENERIC: "INVALID_METADATA_GENERIC",
-  MessageKind.INVALID_OVERRIDDEN_FIELD: "INVALID_OVERRIDDEN_FIELD",
-  MessageKind.INVALID_OVERRIDDEN_GETTER: "INVALID_OVERRIDDEN_GETTER",
-  MessageKind.INVALID_OVERRIDDEN_METHOD: "INVALID_OVERRIDDEN_METHOD",
-  MessageKind.INVALID_OVERRIDDEN_SETTER: "INVALID_OVERRIDDEN_SETTER",
-  MessageKind.INVALID_OVERRIDE_FIELD: "INVALID_OVERRIDE_FIELD",
-  MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER:
-      "INVALID_OVERRIDE_FIELD_WITH_GETTER",
-  MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER:
-      "INVALID_OVERRIDE_FIELD_WITH_SETTER",
-  MessageKind.INVALID_OVERRIDE_GETTER: "INVALID_OVERRIDE_GETTER",
-  MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD:
-      "INVALID_OVERRIDE_GETTER_WITH_FIELD",
-  MessageKind.INVALID_OVERRIDE_METHOD: "INVALID_OVERRIDE_METHOD",
-  MessageKind.INVALID_OVERRIDE_SETTER: "INVALID_OVERRIDE_SETTER",
-  MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD:
-      "INVALID_OVERRIDE_SETTER_WITH_FIELD",
-  MessageKind.INVALID_PACKAGE_CONFIG: "INVALID_PACKAGE_CONFIG",
-  MessageKind.INVALID_PACKAGE_URI: "INVALID_PACKAGE_URI",
-  MessageKind.INVALID_PARAMETER: "INVALID_PARAMETER",
-  MessageKind.INVALID_RECEIVER_IN_INITIALIZER:
-      "INVALID_RECEIVER_IN_INITIALIZER",
-  MessageKind.INVALID_SOURCE_FILE_LOCATION: "INVALID_SOURCE_FILE_LOCATION",
-  MessageKind.INVALID_SYMBOL: "INVALID_SYMBOL",
-  MessageKind.INVALID_SYNC_MODIFIER: "INVALID_SYNC_MODIFIER",
-  MessageKind.INVALID_TYPE_VARIABLE_BOUND: "INVALID_TYPE_VARIABLE_BOUND",
-  MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME:
-      "INVALID_UNNAMED_CONSTRUCTOR_NAME",
-  MessageKind.INVALID_URI: "INVALID_URI",
-  MessageKind.INVALID_USE_OF_SUPER: "INVALID_USE_OF_SUPER",
-  MessageKind.INVALID_YIELD: "INVALID_YIELD",
-  MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS:
-      "JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS",
-  MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER:
-      "JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER",
-  MessageKind.JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS:
-      "JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS",
-  MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS:
-      "JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS",
-  MessageKind.JS_PLACEHOLDER_CAPTURE: "JS_PLACEHOLDER_CAPTURE",
-  MessageKind.LIBRARY_NAME_MISMATCH: "LIBRARY_NAME_MISMATCH",
-  MessageKind.LIBRARY_NOT_FOUND: "LIBRARY_NOT_FOUND",
-  MessageKind.LIBRARY_NOT_SUPPORTED: "LIBRARY_NOT_SUPPORTED",
-  MessageKind.LIBRARY_TAG_MUST_BE_FIRST: "LIBRARY_TAG_MUST_BE_FIRST",
-  MessageKind.MAIN_HAS_PART_OF: "MAIN_HAS_PART_OF",
-  MessageKind.MAIN_NOT_A_FUNCTION: "MAIN_NOT_A_FUNCTION",
-  MessageKind.MAIN_WITH_EXTRA_PARAMETER: "MAIN_WITH_EXTRA_PARAMETER",
-  MessageKind.MALFORMED_STRING_LITERAL: "MALFORMED_STRING_LITERAL",
-  MessageKind.MEMBER_NOT_FOUND: "MEMBER_NOT_FOUND",
-  MessageKind.MEMBER_NOT_STATIC: "MEMBER_NOT_STATIC",
-  MessageKind.MEMBER_USES_CLASS_NAME: "MEMBER_USES_CLASS_NAME",
-  MessageKind.METHOD_NOT_FOUND: "METHOD_NOT_FOUND",
-  MessageKind.MINUS_OPERATOR_BAD_ARITY: "MINUS_OPERATOR_BAD_ARITY",
-  MessageKind.MIRROR_BLOAT: "MIRROR_BLOAT",
-  MessageKind.MIRROR_IMPORT: "MIRROR_IMPORT",
-  MessageKind.MIRROR_IMPORT_NO_USAGE: "MIRROR_IMPORT_NO_USAGE",
-  MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT: "MIRRORS_CANNOT_FIND_IN_ELEMENT",
-  MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY:
-      "MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY",
-  MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY:
-      "MIRRORS_CANNOT_RESOLVE_IN_LIBRARY",
-  MessageKind.MIRRORS_EXPECTED_STRING: "MIRRORS_EXPECTED_STRING",
-  MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST:
-      "MIRRORS_EXPECTED_STRING_OR_LIST",
-  MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE:
-      "MIRRORS_EXPECTED_STRING_OR_TYPE",
-  MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST:
-      "MIRRORS_EXPECTED_STRING_TYPE_OR_LIST",
-  MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND:
-      "MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND",
-  MessageKind.MISSING_ARGUMENT: "MISSING_ARGUMENT",
-  MessageKind.MISSING_ENUM_CASES: "MISSING_ENUM_CASES",
-  MessageKind.MISSING_FACTORY_KEYWORD: "MISSING_FACTORY_KEYWORD",
-  MessageKind.MISSING_FORMALS: "MISSING_FORMALS",
-  MessageKind.MISSING_LIBRARY_NAME: "MISSING_LIBRARY_NAME",
-  MessageKind.MISSING_MAIN: "MISSING_MAIN",
-  MessageKind.MISSING_PART_OF_TAG: "MISSING_PART_OF_TAG",
-  MessageKind.MISSING_TOKEN_AFTER_THIS: "MISSING_TOKEN_AFTER_THIS",
-  MessageKind.MISSING_TOKEN_BEFORE_THIS: "MISSING_TOKEN_BEFORE_THIS",
-  MessageKind.MISSING_TYPE_ARGUMENT: "MISSING_TYPE_ARGUMENT",
-  MessageKind.MULTI_INHERITANCE: "MULTI_INHERITANCE",
-  MessageKind.NAMED_ARGUMENT_NOT_FOUND: "NAMED_ARGUMENT_NOT_FOUND",
-  MessageKind.NAMED_FUNCTION_EXPRESSION: "NAMED_FUNCTION_EXPRESSION",
-  MessageKind.NAMED_PARAMETER_WITH_EQUALS: "NAMED_PARAMETER_WITH_EQUALS",
-  MessageKind.NATIVE_NOT_SUPPORTED: "NATIVE_NOT_SUPPORTED",
-  MessageKind.NO_BREAK_TARGET: "NO_BREAK_TARGET",
-  MessageKind.NO_CATCH_NOR_FINALLY: "NO_CATCH_NOR_FINALLY",
-  MessageKind.NO_COMMON_SUBTYPES: "NO_COMMON_SUBTYPES",
-  MessageKind.NO_CONTINUE_TARGET: "NO_CONTINUE_TARGET",
-  MessageKind.NO_INSTANCE_AVAILABLE: "NO_INSTANCE_AVAILABLE",
-  MessageKind.NO_MATCHING_CONSTRUCTOR: "NO_MATCHING_CONSTRUCTOR",
-  MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT:
-      "NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT",
-  MessageKind.NO_STATIC_OVERRIDE: "NO_STATIC_OVERRIDE",
-  MessageKind.NO_STATIC_OVERRIDE_CONT: "NO_STATIC_OVERRIDE_CONT",
-  MessageKind.NO_SUCH_LIBRARY_MEMBER: "NO_SUCH_LIBRARY_MEMBER",
-  MessageKind.NO_SUCH_METHOD_IN_NATIVE: "NO_SUCH_METHOD_IN_NATIVE",
-  MessageKind.NO_SUCH_SUPER_MEMBER: "NO_SUCH_SUPER_MEMBER",
-  MessageKind.NO_SUPER_IN_STATIC: "NO_SUPER_IN_STATIC",
-  MessageKind.NO_THIS_AVAILABLE: "NO_THIS_AVAILABLE",
-  MessageKind.NON_CONST_BLOAT: "NON_CONST_BLOAT",
-  MessageKind.NOT_A_COMPILE_TIME_CONSTANT: "NOT_A_COMPILE_TIME_CONSTANT",
-  MessageKind.NOT_A_FIELD: "NOT_A_FIELD",
-  MessageKind.NOT_A_PREFIX: "NOT_A_PREFIX",
-  MessageKind.NOT_A_TYPE: "NOT_A_TYPE",
-  MessageKind.NOT_ASSIGNABLE: "NOT_ASSIGNABLE",
-  MessageKind.NOT_CALLABLE: "NOT_CALLABLE",
-  MessageKind.NOT_INSTANCE_FIELD: "NOT_INSTANCE_FIELD",
-  MessageKind.NOT_MORE_SPECIFIC: "NOT_MORE_SPECIFIC",
-  MessageKind.NOT_MORE_SPECIFIC_SUBTYPE: "NOT_MORE_SPECIFIC_SUBTYPE",
-  MessageKind.NOT_MORE_SPECIFIC_SUGGESTION: "NOT_MORE_SPECIFIC_SUGGESTION",
-  MessageKind.NULL_NOT_ALLOWED: "NULL_NOT_ALLOWED",
-  MessageKind.ONLY_ONE_LIBRARY_TAG: "ONLY_ONE_LIBRARY_TAG",
-  MessageKind.OPERATOR_NAMED_PARAMETERS: "OPERATOR_NAMED_PARAMETERS",
-  MessageKind.OPERATOR_NOT_FOUND: "OPERATOR_NOT_FOUND",
-  MessageKind.OPERATOR_OPTIONAL_PARAMETERS: "OPERATOR_OPTIONAL_PARAMETERS",
-  MessageKind.OPTIONAL_PARAMETER_IN_CATCH: "OPTIONAL_PARAMETER_IN_CATCH",
-  MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE: "OVERRIDE_EQUALS_NOT_HASH_CODE",
-  MessageKind.PARAMETER_NAME_EXPECTED: "PARAMETER_NAME_EXPECTED",
-  MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH:
-      "PARAMETER_WITH_MODIFIER_IN_CATCH",
-  MessageKind.PARAMETER_WITH_TYPE_IN_CATCH: "PARAMETER_WITH_TYPE_IN_CATCH",
-  MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION:
-      "PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION",
-  MessageKind.PATCH_NO_GETTER: "PATCH_NO_GETTER",
-  MessageKind.PATCH_NO_SETTER: "PATCH_NO_SETTER",
-  MessageKind.PATCH_NON_CLASS: "PATCH_NON_CLASS",
-  MessageKind.PATCH_NON_CONSTRUCTOR: "PATCH_NON_CONSTRUCTOR",
-  MessageKind.PATCH_NON_EXISTING: "PATCH_NON_EXISTING",
-  MessageKind.PATCH_NON_EXTERNAL: "PATCH_NON_EXTERNAL",
-  MessageKind.PATCH_NON_FUNCTION: "PATCH_NON_FUNCTION",
-  MessageKind.PATCH_NON_GETTER: "PATCH_NON_GETTER",
-  MessageKind.PATCH_NON_SETTER: "PATCH_NON_SETTER",
-  MessageKind.PATCH_NONPATCHABLE: "PATCH_NONPATCHABLE",
-  MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH:
-      "PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH",
-  MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH:
-      "PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH",
-  MessageKind.PATCH_PARAMETER_MISMATCH: "PATCH_PARAMETER_MISMATCH",
-  MessageKind.PATCH_PARAMETER_TYPE_MISMATCH: "PATCH_PARAMETER_TYPE_MISMATCH",
-  MessageKind.PATCH_POINT_TO_CLASS: "PATCH_POINT_TO_CLASS",
-  MessageKind.PATCH_POINT_TO_CONSTRUCTOR: "PATCH_POINT_TO_CONSTRUCTOR",
-  MessageKind.PATCH_POINT_TO_FUNCTION: "PATCH_POINT_TO_FUNCTION",
-  MessageKind.PATCH_POINT_TO_GETTER: "PATCH_POINT_TO_GETTER",
-  MessageKind.PATCH_POINT_TO_PARAMETER: "PATCH_POINT_TO_PARAMETER",
-  MessageKind.PATCH_POINT_TO_SETTER: "PATCH_POINT_TO_SETTER",
-  MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH:
-      "PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH",
-  MessageKind.PATCH_RETURN_TYPE_MISMATCH: "PATCH_RETURN_TYPE_MISMATCH",
-  MessageKind.PLEASE_REPORT_THE_CRASH: "PLEASE_REPORT_THE_CRASH",
-  MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS:
-      "POSITIONAL_PARAMETER_WITH_EQUALS",
-  MessageKind.POTENTIAL_MUTATION: "POTENTIAL_MUTATION",
-  MessageKind.POTENTIAL_MUTATION_HERE: "POTENTIAL_MUTATION_HERE",
-  MessageKind.POTENTIAL_MUTATION_IN_CLOSURE: "POTENTIAL_MUTATION_IN_CLOSURE",
-  MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE:
-      "POTENTIAL_MUTATION_IN_CLOSURE_HERE",
-  MessageKind.PREAMBLE: "PREAMBLE",
-  MessageKind.PREFIX_AS_EXPRESSION: "PREFIX_AS_EXPRESSION",
-  MessageKind.PRIVATE_ACCESS: "PRIVATE_ACCESS",
-  MessageKind.PRIVATE_IDENTIFIER: "PRIVATE_IDENTIFIER",
-  MessageKind.PRIVATE_NAMED_PARAMETER: "PRIVATE_NAMED_PARAMETER",
-  MessageKind.READ_SCRIPT_ERROR: "READ_SCRIPT_ERROR",
-  MessageKind.READ_SELF_ERROR: "READ_SELF_ERROR",
-  MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE: "REDIRECTING_CONSTRUCTOR_CYCLE",
-  MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY:
-      "REDIRECTING_CONSTRUCTOR_HAS_BODY",
-  MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER:
-      "REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER",
-  MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT:
-      "REDIRECTING_FACTORY_WITH_DEFAULT",
-  MessageKind.REFERENCE_IN_INITIALIZATION: "REFERENCE_IN_INITIALIZATION",
-  MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT:
-      "REQUIRED_PARAMETER_WITH_DEFAULT",
-  MessageKind.RETURN_IN_GENERATOR: "RETURN_IN_GENERATOR",
-  MessageKind.RETURN_NOTHING: "RETURN_NOTHING",
-  MessageKind.RETURN_VALUE_IN_VOID: "RETURN_VALUE_IN_VOID",
-  MessageKind.SETTER_MISMATCH: "SETTER_MISMATCH",
-  MessageKind.SETTER_NOT_FOUND: "SETTER_NOT_FOUND",
-  MessageKind.SETTER_NOT_FOUND_IN_SUPER: "SETTER_NOT_FOUND_IN_SUPER",
-  MessageKind.STATIC_FUNCTION_BLOAT: "STATIC_FUNCTION_BLOAT",
-  MessageKind.STRING_EXPECTED: "STRING_EXPECTED",
-  MessageKind.SUPER_CALL_TO_FACTORY: "SUPER_CALL_TO_FACTORY",
-  MessageKind.SUPER_INITIALIZER_IN_OBJECT: "SUPER_INITIALIZER_IN_OBJECT",
-  MessageKind.SWITCH_CASE_FORBIDDEN: "SWITCH_CASE_FORBIDDEN",
-  MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL: "SWITCH_CASE_TYPES_NOT_EQUAL",
-  MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE:
-      "SWITCH_CASE_TYPES_NOT_EQUAL_CASE",
-  MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS:
-      "SWITCH_CASE_VALUE_OVERRIDES_EQUALS",
-  MessageKind.TERNARY_OPERATOR_BAD_ARITY: "TERNARY_OPERATOR_BAD_ARITY",
-  MessageKind.THIS_CALL_TO_FACTORY: "THIS_CALL_TO_FACTORY",
-  MessageKind.THIS_IS_THE_DECLARATION: "THIS_IS_THE_DECLARATION",
-  MessageKind.THIS_IS_THE_METHOD: "THIS_IS_THE_METHOD",
-  MessageKind.THIS_IS_THE_PART_OF_TAG: "THIS_IS_THE_PART_OF_TAG",
-  MessageKind.THIS_PROPERTY: "THIS_PROPERTY",
-  MessageKind.THROW_WITHOUT_EXPRESSION: "THROW_WITHOUT_EXPRESSION",
-  MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC:
-      "TOP_LEVEL_VARIABLE_DECLARED_STATIC",
-  MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH: "TYPE_ARGUMENT_COUNT_MISMATCH",
-  MessageKind.TYPE_VARIABLE_IN_CONSTANT: "TYPE_VARIABLE_IN_CONSTANT",
-  MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER:
-      "TYPE_VARIABLE_WITHIN_STATIC_MEMBER",
-  MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT: "TYPEDEF_FORMAL_WITH_DEFAULT",
-  MessageKind.UNARY_OPERATOR_BAD_ARITY: "UNARY_OPERATOR_BAD_ARITY",
-  MessageKind.UNBOUND_LABEL: "UNBOUND_LABEL",
-  MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER: "UNIMPLEMENTED_EXPLICIT_GETTER",
-  MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER: "UNIMPLEMENTED_EXPLICIT_SETTER",
-  MessageKind.UNIMPLEMENTED_GETTER: "UNIMPLEMENTED_GETTER",
-  MessageKind.UNIMPLEMENTED_GETTER_ONE: "UNIMPLEMENTED_GETTER_ONE",
-  MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER: "UNIMPLEMENTED_IMPLICIT_GETTER",
-  MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER: "UNIMPLEMENTED_IMPLICIT_SETTER",
-  MessageKind.UNIMPLEMENTED_METHOD: "UNIMPLEMENTED_METHOD",
-  MessageKind.UNIMPLEMENTED_METHOD_CONT: "UNIMPLEMENTED_METHOD_CONT",
-  MessageKind.UNIMPLEMENTED_METHOD_ONE: "UNIMPLEMENTED_METHOD_ONE",
-  MessageKind.UNIMPLEMENTED_SETTER: "UNIMPLEMENTED_SETTER",
-  MessageKind.UNIMPLEMENTED_SETTER_ONE: "UNIMPLEMENTED_SETTER_ONE",
-  MessageKind.UNMATCHED_TOKEN: "UNMATCHED_TOKEN",
-  MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP:
-      "UNRECOGNIZED_VERSION_OF_LOOKUP_MAP",
-  MessageKind.UNSUPPORTED_BANG_EQ_EQ: "UNSUPPORTED_BANG_EQ_EQ",
-  MessageKind.UNSUPPORTED_EQ_EQ_EQ: "UNSUPPORTED_EQ_EQ_EQ",
-  MessageKind.UNSUPPORTED_LITERAL_SYMBOL: "UNSUPPORTED_LITERAL_SYMBOL",
-  MessageKind.UNSUPPORTED_PREFIX_PLUS: "UNSUPPORTED_PREFIX_PLUS",
-  MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP: "UNSUPPORTED_THROW_WITHOUT_EXP",
-  MessageKind.UNTERMINATED_COMMENT: "UNTERMINATED_COMMENT",
-  MessageKind.UNTERMINATED_STRING: "UNTERMINATED_STRING",
-  MessageKind.UNTERMINATED_TOKEN: "UNTERMINATED_TOKEN",
-  MessageKind.UNUSED_CLASS: "UNUSED_CLASS",
-  MessageKind.UNUSED_LABEL: "UNUSED_LABEL",
-  MessageKind.UNUSED_METHOD: "UNUSED_METHOD",
-  MessageKind.UNUSED_TYPEDEF: "UNUSED_TYPEDEF",
-  MessageKind.VAR_FUNCTION_TYPE_PARAMETER: "VAR_FUNCTION_TYPE_PARAMETER",
-  MessageKind.VOID_EXPRESSION: "VOID_EXPRESSION",
-  MessageKind.VOID_NOT_ALLOWED: "VOID_NOT_ALLOWED",
-  MessageKind.VOID_VARIABLE: "VOID_VARIABLE",
-  MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT:
-      "WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT",
-  MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT:
-      "WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT",
-  MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY:
-      "YIELDING_MODIFIER_ON_ARROW_BODY",
-};
-
 /// A message template for an error, warning, hint or info message generated
 /// by the compiler. Each template is associated with a [MessageKind] that
 /// uniquely identifies the message template.
 // TODO(johnnniwinther): For Infos, consider adding a reference to the
 // error/warning/hint that they belong to.
 class MessageTemplate {
-  final MessageKind kind;
-
-  final String id;
+  final dynamic/*MessageKind | SharedMessageKind*/ kind;
 
   /// Should describe what is wrong and why.
   final String template;
@@ -892,8 +498,3176 @@
   /// Additional options needed for the examples to work.
   final List<String> options;
 
-  const MessageTemplate(this.kind, this.id, this.template, this.howToFix,
-      this.examples, this.options);
+  const MessageTemplate(
+      this.kind,
+      this.template,
+      {this.howToFix,
+       this.examples,
+       this.options: const <String>[]});
+
+  /// All templates used by the compiler.
+  ///
+  /// The map is complete mapping from [MessageKind] to their corresponding
+  /// [MessageTemplate].
+  // The key type is a union of MessageKind and SharedMessageKind.
+  static final Map<dynamic, MessageTemplate> TEMPLATES =
+      <dynamic, MessageTemplate>{}
+    ..addAll(shared_messages.TEMPLATES)
+    ..addAll(const<MessageKind, MessageTemplate>{
+      /// Do not use this. It is here for legacy and debugging. It violates item
+      /// 4 of the guide lines for error messages in the beginning of the file.
+      MessageKind.GENERIC:
+        const MessageTemplate(MessageKind.GENERIC, '#{text}'),
+
+      MessageKind.NOT_ASSIGNABLE:
+        const MessageTemplate(MessageKind.NOT_ASSIGNABLE,
+          "'#{fromType}' is not assignable to '#{toType}'."),
+
+      MessageKind.FORIN_NOT_ASSIGNABLE:
+        const MessageTemplate(MessageKind.FORIN_NOT_ASSIGNABLE,
+          "The element type '#{currentType}' of '#{expressionType}' "
+          "is not assignable to '#{elementType}'."),
+
+      MessageKind.VOID_EXPRESSION:
+        const MessageTemplate(MessageKind.VOID_EXPRESSION,
+          "Expression does not yield a value."),
+
+      MessageKind.VOID_VARIABLE:
+        const MessageTemplate(MessageKind.VOID_VARIABLE,
+          "Variable cannot be of type void."),
+
+      MessageKind.RETURN_VALUE_IN_VOID:
+        const MessageTemplate(MessageKind.RETURN_VALUE_IN_VOID,
+          "Cannot return value from void function."),
+
+      MessageKind.RETURN_NOTHING:
+        const MessageTemplate(MessageKind.RETURN_NOTHING,
+          "Value of type '#{returnType}' expected."),
+
+      MessageKind.MISSING_ARGUMENT:
+        const MessageTemplate(MessageKind.MISSING_ARGUMENT,
+          "Missing argument of type '#{argumentType}'."),
+
+      MessageKind.ADDITIONAL_ARGUMENT:
+        const MessageTemplate(MessageKind.ADDITIONAL_ARGUMENT,
+          "Additional argument."),
+
+      MessageKind.NAMED_ARGUMENT_NOT_FOUND:
+        const MessageTemplate(MessageKind.NAMED_ARGUMENT_NOT_FOUND,
+          "No named argument '#{argumentName}' found on method."),
+
+      MessageKind.MEMBER_NOT_FOUND:
+        const MessageTemplate(MessageKind.MEMBER_NOT_FOUND,
+          "No member named '#{memberName}' in class '#{className}'."),
+
+      MessageKind.AWAIT_MEMBER_NOT_FOUND:
+        const MessageTemplate(MessageKind.AWAIT_MEMBER_NOT_FOUND,
+          "No member named 'await' in class '#{className}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to '#{functionName}'?",
+          examples: const ["""
+class A {
+  m() => await -3;
+}
+main() => new A().m();
+"""]),
+
+      MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE:
+        const MessageTemplate(MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE,
+          "No member named 'await' in class '#{className}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to the enclosing function?",
+          examples: const ["""
+class A {
+  m() => () => await -3;
+}
+main() => new A().m();
+"""]),
+
+      MessageKind.METHOD_NOT_FOUND:
+        const MessageTemplate(MessageKind.METHOD_NOT_FOUND,
+          "No method named '#{memberName}' in class '#{className}'."),
+
+      MessageKind.OPERATOR_NOT_FOUND:
+        const MessageTemplate(MessageKind.OPERATOR_NOT_FOUND,
+          "No operator '#{memberName}' in class '#{className}'."),
+
+      MessageKind.SETTER_NOT_FOUND:
+        const MessageTemplate(MessageKind.SETTER_NOT_FOUND,
+          "No setter named '#{memberName}' in class '#{className}'."),
+
+      MessageKind.SETTER_NOT_FOUND_IN_SUPER:
+        const MessageTemplate(MessageKind.SETTER_NOT_FOUND_IN_SUPER,
+          "No setter named '#{name}' in superclass of '#{className}'."),
+
+      MessageKind.GETTER_NOT_FOUND:
+        const MessageTemplate(MessageKind.GETTER_NOT_FOUND,
+          "No getter named '#{memberName}' in class '#{className}'."),
+
+      MessageKind.NOT_CALLABLE:
+        const MessageTemplate(MessageKind.NOT_CALLABLE,
+          "'#{elementName}' is not callable."),
+
+      MessageKind.MEMBER_NOT_STATIC:
+        const MessageTemplate(MessageKind.MEMBER_NOT_STATIC,
+          "'#{className}.#{memberName}' is not static."),
+
+      MessageKind.NO_INSTANCE_AVAILABLE:
+        const MessageTemplate(MessageKind.NO_INSTANCE_AVAILABLE,
+          "'#{name}' is only available in instance methods."),
+
+      MessageKind.NO_THIS_AVAILABLE:
+        const MessageTemplate(MessageKind.NO_THIS_AVAILABLE,
+          "'this' is only available in instance methods."),
+
+      MessageKind.PRIVATE_ACCESS:
+        const MessageTemplate(MessageKind.PRIVATE_ACCESS,
+          "'#{name}' is declared private within library "
+          "'#{libraryName}'."),
+
+      MessageKind.THIS_IS_THE_DECLARATION:
+        const MessageTemplate(MessageKind.THIS_IS_THE_DECLARATION,
+          "This is the declaration of '#{name}'."),
+
+      MessageKind.THIS_IS_THE_METHOD:
+        const MessageTemplate(MessageKind.THIS_IS_THE_METHOD,
+          "This is the method declaration."),
+
+      MessageKind.CANNOT_RESOLVE:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE,
+          "Cannot resolve '#{name}'."),
+
+      MessageKind.CANNOT_RESOLVE_AWAIT:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_AWAIT,
+          "Cannot resolve '#{name}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to '#{functionName}'?",
+          examples: const [
+              "main() => await -3;",
+              "foo() => await -3; main() => foo();"
+          ]),
+
+      MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE,
+          "Cannot resolve '#{name}'.",
+          howToFix: "Did you mean to add the 'async' marker "
+                    "to the enclosing function?",
+          examples: const [
+              "main() { (() => await -3)(); }",
+          ]),
+
+      MessageKind.CANNOT_RESOLVE_IN_INITIALIZER:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_IN_INITIALIZER,
+          "Cannot resolve '#{name}'. It would be implicitly looked up on this "
+          "instance, but instances are not available in initializers.",
+          howToFix: "Try correcting the unresolved reference or move the "
+              "initialization to a constructor body.",
+          examples: const ["""
+class A {
+  var test = unresolvedName;
+}
+main() => new A();
+"""]),
+
+      MessageKind.CANNOT_RESOLVE_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_CONSTRUCTOR,
+          "Cannot resolve constructor '#{constructorName}'."),
+
+      MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT:
+        const MessageTemplate(
+          MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT,
+          "cannot resolve constructor '#{constructorName}' "
+          "for implicit super call.",
+          howToFix: "Try explicitly invoking a constructor of the super class",
+          examples: const ["""
+class A {
+  A.foo() {}
+}
+class B extends A {
+  B();
+}
+main() => new B();
+"""]),
+
+      MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME:
+        const MessageTemplate(MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
+          "Unnamed constructor name must be '#{name}'."),
+
+      MessageKind.INVALID_CONSTRUCTOR_NAME:
+        const MessageTemplate(MessageKind.INVALID_CONSTRUCTOR_NAME,
+          "Constructor name must start with '#{name}'."),
+
+      MessageKind.CANNOT_RESOLVE_TYPE:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_TYPE,
+          "Cannot resolve type '#{typeName}'."),
+
+      MessageKind.DUPLICATE_DEFINITION:
+        const MessageTemplate(MessageKind.DUPLICATE_DEFINITION,
+          "Duplicate definition of '#{name}'.",
+          howToFix: "Try to rename or remove this definition.",
+          examples: const ["""
+class C {
+  void f() {}
+  int get f => 1;
+}
+
+main() {
+  new C();
+}
+
+"""]),
+
+      MessageKind.EXISTING_DEFINITION:
+        const MessageTemplate(MessageKind.EXISTING_DEFINITION,
+          "Existing definition of '#{name}'."),
+
+      MessageKind.DUPLICATE_IMPORT:
+        const MessageTemplate(MessageKind.DUPLICATE_IMPORT,
+          "Duplicate import of '#{name}'."),
+
+      MessageKind.HIDDEN_IMPORT:
+        const MessageTemplate(MessageKind.HIDDEN_IMPORT,
+          "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
+          "from library '#{hidingUri}'.",
+          howToFix:
+            "Try adding 'hide #{name}' to the import of '#{hiddenUri}'.",
+          examples: const [
+              const {
+'main.dart':
+"""
+import 'dart:async'; // This imports a class Future.
+import 'future.dart';
+
+void main() => new Future();""",
+
+'future.dart':
+"""
+library future;
+
+class Future {}"""},
+
+          const {
+'main.dart':
+"""
+import 'future.dart';
+import 'dart:async'; // This imports a class Future.
+
+void main() => new Future();""",
+
+'future.dart':
+"""
+library future;
+
+class Future {}"""},
+
+          const {
+'main.dart':
+"""
+import 'export.dart';
+import 'dart:async'; // This imports a class Future.
+
+void main() => new Future();""",
+
+'future.dart':
+"""
+library future;
+
+class Future {}""",
+
+'export.dart':
+"""
+library export;
+
+export 'future.dart';"""},
+
+         const {
+'main.dart':
+"""
+import 'future.dart' as prefix;
+import 'dart:async' as prefix; // This imports a class Future.
+
+void main() => new prefix.Future();""",
+
+'future.dart':
+"""
+library future;
+
+class Future {}"""}]),
+
+
+      MessageKind.HIDDEN_IMPLICIT_IMPORT:
+        const MessageTemplate(MessageKind.HIDDEN_IMPLICIT_IMPORT,
+          "'#{name}' from library '#{hiddenUri}' is hidden by '#{name}' "
+          "from library '#{hidingUri}'.",
+          howToFix: "Try adding an explicit "
+                    "'import \"#{hiddenUri}\" hide #{name}'.",
+          examples: const [
+              const {
+'main.dart':
+"""
+// This hides the implicit import of class Type from dart:core.
+import 'type.dart';
+
+void main() => new Type();""",
+
+'type.dart':
+"""
+library type;
+
+class Type {}"""},
+          const {
+'conflictsWithDart.dart':
+"""
+library conflictsWithDart;
+
+class Duration {
+  static var x = 100;
+}
+""",
+
+'conflictsWithDartAsWell.dart':
+"""
+library conflictsWithDartAsWell;
+
+class Duration {
+  static var x = 100;
+}
+""",
+
+'main.dart':
+r"""
+library testDartConflicts;
+
+import 'conflictsWithDart.dart';
+import 'conflictsWithDartAsWell.dart';
+
+main() {
+  print("Hail Caesar ${Duration.x}");
+}
+"""}]),
+
+      MessageKind.DUPLICATE_EXPORT:
+        const MessageTemplate(MessageKind.DUPLICATE_EXPORT,
+          "Duplicate export of '#{name}'.",
+          howToFix: "Try adding 'hide #{name}' to one of the exports.",
+          examples: const [const {
+'main.dart': """
+export 'decl1.dart';
+export 'decl2.dart';
+
+main() {}""",
+'decl1.dart': "class Class {}",
+'decl2.dart': "class Class {}"}]),
+
+      MessageKind.DUPLICATE_EXPORT_CONT:
+        const MessageTemplate(MessageKind.DUPLICATE_EXPORT_CONT,
+          "This is another export of '#{name}'."),
+
+      MessageKind.DUPLICATE_EXPORT_DECL:
+        const MessageTemplate(MessageKind.DUPLICATE_EXPORT_DECL,
+          "The exported '#{name}' from export #{uriString} is defined here."),
+
+      MessageKind.EMPTY_HIDE:
+        const MessageTemplate(MessageKind.EMPTY_HIDE,
+            "Library '#{uri}' doesn't export a '#{name}' declaration.",
+      howToFix: "Try removing '#{name}' the 'hide' clause.",
+      examples: const [
+        const {
+            'main.dart': """
+import 'dart:core' hide Foo;
+
+main() {}"""},
+        const {
+'main.dart': """
+export 'dart:core' hide Foo;
+
+main() {}"""},
+]),
+
+      MessageKind.EMPTY_SHOW:
+        const MessageTemplate(MessageKind.EMPTY_SHOW,
+            "Library '#{uri}' doesn't export a '#{name}' declaration.",
+      howToFix: "Try removing '#{name}' from the 'show' clause.",
+      examples: const [
+        const {
+            'main.dart': """
+import 'dart:core' show Foo;
+
+main() {}"""},
+        const {
+'main.dart': """
+export 'dart:core' show Foo;
+
+main() {}"""},
+]),
+
+      MessageKind.NOT_A_TYPE:
+        const MessageTemplate(MessageKind.NOT_A_TYPE,
+          "'#{node}' is not a type."),
+
+      MessageKind.NOT_A_PREFIX:
+        const MessageTemplate(MessageKind.NOT_A_PREFIX,
+          "'#{node}' is not a prefix."),
+
+      MessageKind.PREFIX_AS_EXPRESSION:
+        const MessageTemplate(MessageKind.PREFIX_AS_EXPRESSION,
+          "Library prefix '#{prefix}' is not a valid expression."),
+
+      MessageKind.CANNOT_FIND_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.CANNOT_FIND_CONSTRUCTOR,
+          "Cannot find constructor '#{constructorName}' in class "
+          "'#{className}'."),
+
+      MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR,
+          "Cannot find unnamed constructor in class "
+          "'#{className}'."),
+
+      MessageKind.CYCLIC_CLASS_HIERARCHY:
+        const MessageTemplate(MessageKind.CYCLIC_CLASS_HIERARCHY,
+          "'#{className}' creates a cycle in the class hierarchy."),
+
+      MessageKind.CYCLIC_REDIRECTING_FACTORY:
+        const MessageTemplate(MessageKind.CYCLIC_REDIRECTING_FACTORY,
+          'Redirecting factory leads to a cyclic redirection.'),
+
+      MessageKind.INVALID_RECEIVER_IN_INITIALIZER:
+        const MessageTemplate(MessageKind.INVALID_RECEIVER_IN_INITIALIZER,
+          "Field initializer expected."),
+
+      MessageKind.NO_SUPER_IN_STATIC:
+        const MessageTemplate(MessageKind.NO_SUPER_IN_STATIC,
+          "'super' is only available in instance methods."),
+
+      MessageKind.DUPLICATE_INITIALIZER:
+        const MessageTemplate(MessageKind.DUPLICATE_INITIALIZER,
+          "Field '#{fieldName}' is initialized more than once."),
+
+      MessageKind.ALREADY_INITIALIZED:
+        const MessageTemplate(MessageKind.ALREADY_INITIALIZED,
+          "'#{fieldName}' was already initialized here."),
+
+      MessageKind.INIT_STATIC_FIELD:
+        const MessageTemplate(MessageKind.INIT_STATIC_FIELD,
+          "Cannot initialize static field '#{fieldName}'."),
+
+      MessageKind.NOT_A_FIELD:
+        const MessageTemplate(MessageKind.NOT_A_FIELD,
+          "'#{fieldName}' is not a field."),
+
+      MessageKind.CONSTRUCTOR_CALL_EXPECTED:
+        const MessageTemplate(MessageKind.CONSTRUCTOR_CALL_EXPECTED,
+          "only call to 'this' or 'super' constructor allowed."),
+
+      MessageKind.INVALID_FOR_IN:
+        const MessageTemplate(MessageKind.INVALID_FOR_IN,
+          "Invalid for-in variable declaration."),
+
+      MessageKind.INVALID_INITIALIZER:
+        const MessageTemplate(MessageKind.INVALID_INITIALIZER,
+          "Invalid initializer."),
+
+      MessageKind.FUNCTION_WITH_INITIALIZER:
+        const MessageTemplate(MessageKind.FUNCTION_WITH_INITIALIZER,
+          "Only constructors can have initializers."),
+
+      MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE:
+        const MessageTemplate(MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE,
+          "Cyclic constructor redirection."),
+
+      MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY:
+        const MessageTemplate(MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY,
+          "Redirecting constructor can't have a body."),
+
+      MessageKind.CONST_CONSTRUCTOR_HAS_BODY:
+        const MessageTemplate(MessageKind.CONST_CONSTRUCTOR_HAS_BODY,
+          "Const constructor or factory can't have a body.",
+          howToFix: "Remove the 'const' keyword or the body",
+          examples: const ["""
+class C {
+  const C() {}
+}
+
+main() => new C();"""]),
+
+      MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER:
+        const MessageTemplate(
+          MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER,
+          "Redirecting constructor cannot have other initializers."),
+
+      MessageKind.SUPER_INITIALIZER_IN_OBJECT:
+        const MessageTemplate(MessageKind.SUPER_INITIALIZER_IN_OBJECT,
+          "'Object' cannot have a super initializer."),
+
+      MessageKind.DUPLICATE_SUPER_INITIALIZER:
+        const MessageTemplate(MessageKind.DUPLICATE_SUPER_INITIALIZER,
+          "Cannot have more than one super initializer."),
+
+      MessageKind.SUPER_CALL_TO_FACTORY:
+        const MessageTemplate(MessageKind.SUPER_CALL_TO_FACTORY,
+          "The target of the superinitializer must be a generative "
+          "constructor.",
+          howToFix: "Try calling another constructor on the superclass.",
+          examples: const ["""
+class Super {
+  factory Super() => null;
+}
+class Class extends Super {}
+main() => new Class();
+""", """
+class Super {
+  factory Super() => null;
+}
+class Class extends Super {
+  Class();
+}
+main() => new Class();
+""", """
+class Super {
+  factory Super() => null;
+}
+class Class extends Super {
+  Class() : super();
+}
+main() => new Class();
+""", """
+class Super {
+  factory Super.foo() => null;
+}
+class Class extends Super {
+  Class() : super.foo();
+}
+main() => new Class();
+"""]),
+
+      MessageKind.THIS_CALL_TO_FACTORY:
+        const MessageTemplate(MessageKind.THIS_CALL_TO_FACTORY,
+          "The target of the redirection clause must be a generative "
+          "constructor",
+        howToFix: "Try redirecting to another constructor.",
+        examples: const ["""
+class Class {
+  factory Class() => null;
+  Class.foo() : this();
+}
+main() => new Class.foo();
+""", """
+class Class {
+  factory Class.foo() => null;
+  Class() : this.foo();
+}
+main() => new Class();
+"""]),
+
+      MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS:
+        const MessageTemplate(MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS,
+          "Arguments do not match the expected parameters of constructor "
+          "'#{constructorName}'."),
+
+      MessageKind.NO_MATCHING_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.NO_MATCHING_CONSTRUCTOR,
+          "'super' call arguments and constructor parameters do not match."),
+
+      MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT:
+        const MessageTemplate(MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT,
+              "Implicit 'super' call arguments and constructor parameters "
+              "do not match."),
+
+      MessageKind.CONST_CALLS_NON_CONST:
+        const MessageTemplate(MessageKind.CONST_CALLS_NON_CONST,
+          "'const' constructor cannot call a non-const constructor."),
+
+      MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT:
+        const MessageTemplate(MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT,
+              "'const' constructor cannot call a non-const constructor. "
+              "This constructor has an implicit call to a "
+              "super non-const constructor.",
+              howToFix: "Try making the super constructor const.",
+              examples: const ["""
+class C {
+  C(); // missing const
+}
+class D extends C {
+  final d;
+  const D(this.d);
+}
+main() => new D(0);"""]),
+
+      MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS:
+        const MessageTemplate(
+          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
+          "Can't declare constructor 'const' on class #{className} "
+          "because the class contains non-final instance fields.",
+          howToFix: "Try making all fields final.",
+          examples: const ["""
+class C {
+  // 'a' must be declared final to allow for the const constructor.
+  var a;
+  const C(this.a);
+}
+
+main() => new C(0);"""]),
+
+      MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD:
+        const MessageTemplate(
+          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD,
+          "This non-final field prevents using const constructors."),
+
+      MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR:
+        const MessageTemplate(
+          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR,
+          "This const constructor is not allowed due to "
+          "non-final fields."),
+
+
+      MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED:
+        const MessageTemplate(MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED,
+          "Initializing formal parameter only allowed in generative "
+          "constructor."),
+
+      MessageKind.INVALID_PARAMETER:
+        const MessageTemplate(MessageKind.INVALID_PARAMETER,
+          "Cannot resolve parameter."),
+
+      MessageKind.NOT_INSTANCE_FIELD:
+        const MessageTemplate(MessageKind.NOT_INSTANCE_FIELD,
+          "'#{fieldName}' is not an instance field."),
+
+      MessageKind.THIS_PROPERTY:
+        const MessageTemplate(MessageKind.THIS_PROPERTY,
+          "Expected an identifier."),
+
+      MessageKind.NO_CATCH_NOR_FINALLY:
+        const MessageTemplate(MessageKind.NO_CATCH_NOR_FINALLY,
+          "Expected 'catch' or 'finally'."),
+
+      MessageKind.EMPTY_CATCH_DECLARATION:
+        const MessageTemplate(MessageKind.EMPTY_CATCH_DECLARATION,
+          "Expected an identifier in catch declaration."),
+
+      MessageKind.EXTRA_CATCH_DECLARATION:
+        const MessageTemplate(MessageKind.EXTRA_CATCH_DECLARATION,
+          "Extra parameter in catch declaration."),
+
+      MessageKind.PARAMETER_WITH_TYPE_IN_CATCH:
+        const MessageTemplate(MessageKind.PARAMETER_WITH_TYPE_IN_CATCH,
+          "Cannot use type annotations in catch."),
+
+      MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH:
+        const MessageTemplate(MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH,
+          "Cannot use modifiers in catch."),
+
+      MessageKind.OPTIONAL_PARAMETER_IN_CATCH:
+        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}'."),
+
+      MessageKind.NO_BREAK_TARGET:
+        const MessageTemplate(MessageKind.NO_BREAK_TARGET,
+          "'break' statement not inside switch or loop."),
+
+      MessageKind.NO_CONTINUE_TARGET:
+        const MessageTemplate(MessageKind.NO_CONTINUE_TARGET,
+          "'continue' statement not inside loop."),
+
+      MessageKind.EXISTING_LABEL:
+        const MessageTemplate(MessageKind.EXISTING_LABEL,
+          "Original declaration of duplicate label '#{labelName}'."),
+
+      MessageKind.DUPLICATE_LABEL:
+        const MessageTemplate(MessageKind.DUPLICATE_LABEL,
+          "Duplicate declaration of label '#{labelName}'."),
+
+      MessageKind.UNUSED_LABEL:
+        const MessageTemplate(MessageKind.UNUSED_LABEL,
+          "Unused label '#{labelName}'."),
+
+      MessageKind.INVALID_CONTINUE:
+        const MessageTemplate(MessageKind.INVALID_CONTINUE,
+          "Target of continue is not a loop or switch case."),
+
+      MessageKind.INVALID_BREAK:
+        const MessageTemplate(MessageKind.INVALID_BREAK,
+          "Target of break is not a statement."),
+
+      MessageKind.DUPLICATE_TYPE_VARIABLE_NAME:
+        const MessageTemplate(MessageKind.DUPLICATE_TYPE_VARIABLE_NAME,
+          "Type variable '#{typeVariableName}' already declared."),
+
+      MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER:
+        const MessageTemplate(MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
+              "Cannot refer to type variable '#{typeVariableName}' "
+              "within a static member."),
+
+      MessageKind.TYPE_VARIABLE_IN_CONSTANT:
+        const MessageTemplate(MessageKind.TYPE_VARIABLE_IN_CONSTANT,
+          "Constant expressions can't refer to type variables.",
+          howToFix: "Try removing the type variable or replacing it with a "
+                    "concrete type.",
+          examples: const ["""
+class C<T> {
+  const C();
+
+  m(T t) => const C<T>();
+}
+
+void main() => new C().m(null);
+"""
+]),
+
+      MessageKind.INVALID_TYPE_VARIABLE_BOUND:
+        const MessageTemplate(MessageKind.INVALID_TYPE_VARIABLE_BOUND,
+          "'#{typeArgument}' is not a subtype of bound '#{bound}' for "
+          "type variable '#{typeVariable}' of type '#{thisType}'.",
+          howToFix: "Try to change or remove the type argument.",
+          examples: const ["""
+class C<T extends num> {}
+
+// 'String' is not a valid instantiation of T with bound num.'.
+main() => new C<String>();
+"""]),
+
+      MessageKind.INVALID_USE_OF_SUPER:
+        const MessageTemplate(MessageKind.INVALID_USE_OF_SUPER,
+          "'super' not allowed here."),
+
+      MessageKind.INVALID_CASE_DEFAULT:
+        const MessageTemplate(MessageKind.INVALID_CASE_DEFAULT,
+          "'default' only allowed on last case of a switch."),
+
+      MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL:
+        const MessageTemplate(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL,
+          "'case' expressions do not all have type '#{type}'."),
+
+      MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE:
+        const MessageTemplate(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
+          "'case' expression of type '#{type}'."),
+
+      MessageKind.SWITCH_CASE_FORBIDDEN:
+        const MessageTemplate(MessageKind.SWITCH_CASE_FORBIDDEN,
+          "'case' expression may not be of type '#{type}'."),
+
+      MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS:
+        const MessageTemplate(MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
+              "'case' expression type '#{type}' overrides 'operator =='."),
+
+      MessageKind.INVALID_ARGUMENT_AFTER_NAMED:
+        const MessageTemplate(MessageKind.INVALID_ARGUMENT_AFTER_NAMED,
+          "Unnamed argument after named argument."),
+
+      MessageKind.INVALID_AWAIT_FOR_IN:
+        const MessageTemplate(MessageKind.INVALID_AWAIT_FOR_IN,
+          "'await' is only supported in methods with an 'async' or "
+              "'async*' body modifier.",
+          howToFix: "Try adding 'async' or 'async*' to the method body or "
+              "removing the 'await' keyword.",
+          examples: const [
+            """
+main(o) sync* {
+  await for (var e in o) {}
+}"""]),
+
+      MessageKind.INVALID_AWAIT:
+        const MessageTemplate(MessageKind.INVALID_AWAIT,
+          "'await' is only supported in methods with an 'async' or "
+              "'async*' body modifier.",
+          howToFix: "Try adding 'async' or 'async*' to the method body.",
+          examples: const [
+          """
+main(o) sync* {
+  await null;
+}"""]),
+
+      MessageKind.INVALID_YIELD:
+        const MessageTemplate(MessageKind.INVALID_YIELD,
+          "'yield' is only supported in methods with a 'sync*' or "
+              "'async*' body modifier.",
+          howToFix: "Try adding 'sync*' or 'async*' to the method body.",
+          examples: const [
+            """
+main(o) async {
+  yield 0;
+}"""]),
+
+      MessageKind.NOT_A_COMPILE_TIME_CONSTANT:
+        const MessageTemplate(MessageKind.NOT_A_COMPILE_TIME_CONSTANT,
+          "Not a compile-time constant."),
+
+      MessageKind.DEFERRED_COMPILE_TIME_CONSTANT:
+        const MessageTemplate(MessageKind.DEFERRED_COMPILE_TIME_CONSTANT,
+          "A deferred value cannot be used as a compile-time constant."),
+
+      MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION:
+        const MessageTemplate(
+          MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION,
+          "A deferred class cannot be used to create a "
+          "compile-time constant."),
+
+      MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS:
+        const MessageTemplate(MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS,
+          "Cycle in the compile-time constant computation."),
+
+      MessageKind.CONSTRUCTOR_IS_NOT_CONST:
+        const MessageTemplate(MessageKind.CONSTRUCTOR_IS_NOT_CONST,
+          "Constructor is not a 'const' constructor."),
+
+      MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS:
+        const MessageTemplate(MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS,
+              "Const-map key type '#{type}' overrides 'operator =='."),
+
+      MessageKind.NO_SUCH_LIBRARY_MEMBER:
+        const MessageTemplate(MessageKind.NO_SUCH_LIBRARY_MEMBER,
+          "'#{libraryName}' has no member named '#{memberName}'."),
+
+      MessageKind.CANNOT_INSTANTIATE_TYPEDEF:
+        const MessageTemplate(MessageKind.CANNOT_INSTANTIATE_TYPEDEF,
+          "Cannot instantiate typedef '#{typedefName}'."),
+
+      MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT,
+          "Non-optional parameters can't have a default value.",
+          howToFix:
+            "Try removing the default value or making the parameter optional.",
+          examples: const ["""
+main() {
+  foo(a: 1) => print(a);
+  foo(2);
+}""", """
+main() {
+  foo(a = 1) => print(a);
+  foo(2);
+}"""]),
+
+      MessageKind.NAMED_PARAMETER_WITH_EQUALS:
+        const MessageTemplate(MessageKind.NAMED_PARAMETER_WITH_EQUALS,
+          "Named optional parameters can't use '=' to specify a default "
+          "value.",
+          howToFix: "Try replacing '=' with ':'.",
+          examples: const ["""
+main() {
+  foo({a = 1}) => print(a);
+  foo(a: 2);
+}"""]),
+
+      MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS:
+        const MessageTemplate(MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS,
+          "Positional optional parameters can't use ':' to specify a "
+          "default value.",
+          howToFix: "Try replacing ':' with '='.",
+          examples: const ["""
+main() {
+  foo([a: 1]) => print(a);
+  foo(2);
+}"""]),
+
+      MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT,
+          "A parameter of a typedef can't specify a default value.",
+          howToFix:
+            "Try removing the default value.",
+          examples: const ["""
+typedef void F([int arg = 0]);
+
+main() {
+  F f;
+}""", """
+typedef void F({int arg: 0});
+
+main() {
+  F f;
+}"""]),
+
+      MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT,
+          "A function type parameter can't specify a default value.",
+          howToFix:
+            "Try removing the default value.",
+          examples: const ["""
+foo(f(int i, [a = 1])) {}
+
+main() {
+  foo(1, 2);
+}""", """
+foo(f(int i, {a: 1})) {}
+
+main() {
+  foo(1, a: 2);
+}"""]),
+
+      MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT:
+        const MessageTemplate(MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT,
+          "A parameter of a redirecting factory constructor can't specify a "
+          "default value.",
+          howToFix:
+            "Try removing the default value.",
+          examples: const ["""
+class A {
+  A([a]);
+  factory A.foo([a = 1]) = A;
+}
+
+main() {
+  new A.foo(1);
+}""", """
+class A {
+  A({a});
+  factory A.foo({a: 1}) = A;
+}
+
+main() {
+  new A.foo(a: 1);
+}"""]),
+
+      MessageKind.FORMAL_DECLARED_CONST:
+        const MessageTemplate(MessageKind.FORMAL_DECLARED_CONST,
+          "A formal parameter can't be declared const.",
+          howToFix: "Try removing 'const'.",
+          examples: const ["""
+foo(const x) {}
+main() => foo(42);
+""", """
+foo({const x}) {}
+main() => foo(42);
+""", """
+foo([const x]) {}
+main() => foo(42);
+"""]),
+
+      MessageKind.FORMAL_DECLARED_STATIC:
+        const MessageTemplate(MessageKind.FORMAL_DECLARED_STATIC,
+          "A formal parameter can't be declared static.",
+          howToFix: "Try removing 'static'.",
+          examples: const ["""
+foo(static x) {}
+main() => foo(42);
+""", """
+foo({static x}) {}
+main() => foo(42);
+""", """
+foo([static x]) {}
+main() => foo(42);
+"""]),
+
+      MessageKind.FINAL_FUNCTION_TYPE_PARAMETER:
+        const MessageTemplate(MessageKind.FINAL_FUNCTION_TYPE_PARAMETER,
+          "A function type parameter can't be declared final.",
+          howToFix: "Try removing 'final'.",
+          examples: const ["""
+foo(final int x(int a)) {}
+main() => foo((y) => 42);
+""", """
+foo({final int x(int a)}) {}
+main() => foo((y) => 42);
+""", """
+foo([final int x(int a)]) {}
+main() => foo((y) => 42);
+"""]),
+
+      MessageKind.VAR_FUNCTION_TYPE_PARAMETER:
+        const MessageTemplate(MessageKind.VAR_FUNCTION_TYPE_PARAMETER,
+          "A function type parameter can't be declared with 'var'.",
+          howToFix: "Try removing 'var'.",
+          examples: const ["""
+foo(var int x(int a)) {}
+main() => foo((y) => 42);
+""", """
+foo({var int x(int a)}) {}
+main() => foo((y) => 42);
+""", """
+foo([var int x(int a)]) {}
+main() => foo((y) => 42);
+"""]),
+
+      MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE:
+        const MessageTemplate(MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
+          "Cannot instantiate type variable '#{typeVariableName}'."),
+
+      MessageKind.CYCLIC_TYPE_VARIABLE:
+        const MessageTemplate(MessageKind.CYCLIC_TYPE_VARIABLE,
+          "Type variable '#{typeVariableName}' is a supertype of itself."),
+
+      MessageKind.CYCLIC_TYPEDEF:
+        const MessageTemplate(MessageKind.CYCLIC_TYPEDEF,
+          "A typedef can't refer to itself.",
+          howToFix: "Try removing all references to '#{typedefName}' "
+                    "in the definition of '#{typedefName}'.",
+          examples: const ["""
+typedef F F(); // The return type 'F' is a self-reference.
+main() { F f = null; }"""]),
+
+      MessageKind.CYCLIC_TYPEDEF_ONE:
+        const MessageTemplate(MessageKind.CYCLIC_TYPEDEF_ONE,
+          "A typedef can't refer to itself through another typedef.",
+          howToFix:
+            "Try removing all references to "
+            "'#{otherTypedefName}' in the definition of '#{typedefName}'.",
+          examples: const ["""
+typedef G F(); // The return type 'G' is a self-reference through typedef 'G'.
+typedef F G(); // The return type 'F' is a self-reference through typedef 'F'.
+main() { F f = null; }""",
+"""
+typedef G F(); // The return type 'G' creates a self-reference.
+typedef H G(); // The return type 'H' creates a self-reference.
+typedef H(F f); // The argument type 'F' creates a self-reference.
+main() { F f = null; }"""]),
+
+      MessageKind.CLASS_NAME_EXPECTED:
+        const MessageTemplate(MessageKind.CLASS_NAME_EXPECTED,
+          "Class name expected."),
+
+      MessageKind.CANNOT_EXTEND:
+        const MessageTemplate(MessageKind.CANNOT_EXTEND,
+          "'#{type}' cannot be extended."),
+
+      MessageKind.CANNOT_IMPLEMENT:
+        const MessageTemplate(MessageKind.CANNOT_IMPLEMENT,
+          "'#{type}' cannot be implemented."),
+
+      // TODO(johnnwinther): Split messages into reasons for malformedness.
+      MessageKind.CANNOT_EXTEND_MALFORMED:
+        const MessageTemplate(MessageKind.CANNOT_EXTEND_MALFORMED,
+          "Class '#{className}' can't extend the type '#{malformedType}' "
+          "because it is malformed.",
+          howToFix:
+            "Try correcting the malformed type annotation or removing the "
+            "'extends' clause.",
+          examples: const ["""
+class A extends Malformed {}
+main() => new A();"""]),
+
+      MessageKind.CANNOT_IMPLEMENT_MALFORMED:
+        const MessageTemplate(MessageKind.CANNOT_IMPLEMENT_MALFORMED,
+          "Class '#{className}' can't implement the type '#{malformedType}' "
+          "because it is malformed.",
+          howToFix:
+            "Try correcting the malformed type annotation or removing the "
+            "type from the 'implements' clause.",
+          examples: const ["""
+class A implements Malformed {}
+main() => new A();"""]),
+
+      MessageKind.CANNOT_MIXIN_MALFORMED:
+        const MessageTemplate(MessageKind.CANNOT_MIXIN_MALFORMED,
+          "Class '#{className}' can't mixin the type '#{malformedType}' "
+          "because it is malformed.",
+          howToFix:
+            "Try correcting the malformed type annotation or removing the "
+            "type from the 'with' clause.",
+          examples: const ["""
+class A extends Object with Malformed {}
+main() => new A();"""]),
+
+      MessageKind.CANNOT_MIXIN:
+        const MessageTemplate(MessageKind.CANNOT_MIXIN,
+          "The type '#{type}' can't be mixed in.",
+          howToFix: "Try removing '#{type}' from the 'with' clause.",
+          examples: const ["""
+class C extends Object with String {}
+
+main() => new C();
+""", """
+typedef C = Object with String;
+
+main() => new C();
+"""]),
+
+      MessageKind.CANNOT_EXTEND_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_EXTEND_ENUM,
+          "Class '#{className}' can't extend the type '#{enumType}' because "
+          "it is declared by an enum.",
+          howToFix: "Try making '#{enumType}' a normal class or removing the "
+            "'extends' clause.",
+          examples: const ["""
+enum Enum { A }
+class B extends Enum {}
+main() => new B();"""]),
+
+      MessageKind.CANNOT_IMPLEMENT_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_IMPLEMENT_ENUM,
+          "Class '#{className}' can't implement the type '#{enumType}' "
+          "because it is declared by an enum.",
+          howToFix: "Try making '#{enumType}' a normal class or removing the "
+            "type from the 'implements' clause.",
+          examples: const ["""
+enum Enum { A }
+class B implements Enum {}
+main() => new B();"""]),
+
+      MessageKind.CANNOT_MIXIN_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_MIXIN_ENUM,
+          "Class '#{className}' can't mixin the type '#{enumType}' because it "
+          "is declared by an enum.",
+          howToFix: "Try making '#{enumType}' a normal class or removing the "
+            "type from the 'with' clause.",
+          examples: const ["""
+enum Enum { A }
+class B extends Object with Enum {}
+main() => new B();"""]),
+
+      MessageKind.CANNOT_INSTANTIATE_ENUM:
+        const MessageTemplate(MessageKind.CANNOT_INSTANTIATE_ENUM,
+          "Enum type '#{enumName}' cannot be instantiated.",
+          howToFix: "Try making '#{enumType}' a normal class or use an enum "
+                    "constant.",
+          examples: const ["""
+enum Enum { A }
+main() => new Enum(0);""", """
+enum Enum { A }
+main() => const Enum(0);"""]),
+
+      MessageKind.EMPTY_ENUM_DECLARATION:
+        const MessageTemplate(MessageKind.EMPTY_ENUM_DECLARATION,
+          "Enum '#{enumName}' must contain at least one value.",
+          howToFix: "Try adding an enum constant or making #{enumName} a "
+                    "normal class.",
+          examples: const ["""
+enum Enum {}
+main() { Enum e; }"""]),
+
+      MessageKind.MISSING_ENUM_CASES:
+        const MessageTemplate(MessageKind.MISSING_ENUM_CASES,
+          "Missing enum constants in switch statement: #{enumValues}.",
+          howToFix: "Try adding the missing constants or a default case.",
+          examples: const ["""
+enum Enum { A, B }
+main() {
+  switch (Enum.A) {
+  case Enum.B: break;
+  }
+}""", """
+enum Enum { A, B, C }
+main() {
+  switch (Enum.A) {
+  case Enum.B: break;
+  }
+}"""]),
+
+      MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS:
+        const MessageTemplate(MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
+          "'#{type}' can not be both extended and implemented."),
+
+      MessageKind.DUPLICATE_IMPLEMENTS:
+        const MessageTemplate(MessageKind.DUPLICATE_IMPLEMENTS,
+          "'#{type}' must not occur more than once "
+          "in the implements clause."),
+
+      MessageKind.MULTI_INHERITANCE:
+        const MessageTemplate(MessageKind.MULTI_INHERITANCE,
+          "Dart2js does not currently support inheritance of the same class "
+          "with different type arguments: Both #{firstType} and #{secondType} "
+          "are supertypes of #{thisType}."),
+
+      MessageKind.ILLEGAL_SUPER_SEND:
+        const MessageTemplate(MessageKind.ILLEGAL_SUPER_SEND,
+          "'#{name}' cannot be called on super."),
+
+      MessageKind.NO_SUCH_SUPER_MEMBER:
+        const MessageTemplate(MessageKind.NO_SUCH_SUPER_MEMBER,
+          "Cannot resolve '#{memberName}' in a superclass of '#{className}'."),
+
+      MessageKind.ADDITIONAL_TYPE_ARGUMENT:
+        const MessageTemplate(MessageKind.ADDITIONAL_TYPE_ARGUMENT,
+          "Additional type argument."),
+
+      MessageKind.MISSING_TYPE_ARGUMENT:
+        const MessageTemplate(MessageKind.MISSING_TYPE_ARGUMENT,
+          "Missing type argument."),
+
+      // TODO(johnniwinther): Use ADDITIONAL_TYPE_ARGUMENT or
+      // MISSING_TYPE_ARGUMENT instead.
+      MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH:
+        const MessageTemplate(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
+          "Incorrect number of type arguments on '#{type}'."),
+
+      MessageKind.GETTER_MISMATCH:
+        const MessageTemplate(MessageKind.GETTER_MISMATCH,
+          "Setter disagrees on: '#{modifiers}'."),
+
+      MessageKind.SETTER_MISMATCH:
+        const MessageTemplate(MessageKind.SETTER_MISMATCH,
+          "Getter disagrees on: '#{modifiers}'."),
+
+      MessageKind.ILLEGAL_SETTER_FORMALS:
+        const MessageTemplate(MessageKind.ILLEGAL_SETTER_FORMALS,
+          "A setter must have exactly one argument."),
+
+      MessageKind.NO_STATIC_OVERRIDE:
+        const MessageTemplate(MessageKind.NO_STATIC_OVERRIDE,
+          "Static member cannot override instance member '#{memberName}' of "
+          "'#{className}'."),
+
+      MessageKind.NO_STATIC_OVERRIDE_CONT:
+        const MessageTemplate(MessageKind.NO_STATIC_OVERRIDE_CONT,
+          "This is the instance member that cannot be overridden "
+          "by a static member."),
+
+      MessageKind.INSTANCE_STATIC_SAME_NAME:
+        const MessageTemplate(MessageKind.INSTANCE_STATIC_SAME_NAME,
+          "Instance member '#{memberName}' and static member of "
+          "superclass '#{className}' have the same name."),
+
+      MessageKind.INSTANCE_STATIC_SAME_NAME_CONT:
+        const MessageTemplate(MessageKind.INSTANCE_STATIC_SAME_NAME_CONT,
+          "This is the static member with the same name."),
+
+      MessageKind.INVALID_OVERRIDE_METHOD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_METHOD,
+          "The type '#{declaredType}' of method '#{name}' declared in "
+          "'#{class}' is not a subtype of the overridden method type "
+          "'#{inheritedType}' inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDDEN_METHOD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_METHOD,
+          "This is the overridden method '#{name}' declared in class "
+          "'#{class}'."),
+
+      MessageKind.INVALID_OVERRIDE_GETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_GETTER,
+          "The type '#{declaredType}' of getter '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden getter inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDDEN_GETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_GETTER,
+          "This is the overridden getter '#{name}' declared in class "
+          "'#{class}'."),
+
+      MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD,
+          "The type '#{declaredType}' of field '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden getter inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER,
+          "The type '#{declaredType}' of getter '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden field inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDE_SETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_SETTER,
+          "The type '#{declaredType}' of setter '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden setter inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDDEN_SETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_SETTER,
+          "This is the overridden setter '#{name}' declared in class "
+          "'#{class}'."),
+
+      MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD,
+          "The type '#{declaredType}' of field '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden setter inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER,
+          "The type '#{declaredType}' of setter '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden field inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDE_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDE_FIELD,
+          "The type '#{declaredType}' of field '#{name}' declared in "
+          "'#{class}' is not assignable to the type '#{inheritedType}' of the "
+          "overridden field inherited from '#{inheritedClass}'."),
+
+      MessageKind.INVALID_OVERRIDDEN_FIELD:
+        const MessageTemplate(MessageKind.INVALID_OVERRIDDEN_FIELD,
+          "This is the overridden field '#{name}' declared in class "
+          "'#{class}'."),
+
+      MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD:
+        const MessageTemplate(MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD,
+          "Method '#{name}' in '#{class}' can't override field from "
+          "'#{inheritedClass}'."),
+
+      MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT,
+          "This is the field that cannot be overridden by a method."),
+
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD,
+          "Field '#{name}' in '#{class}' can't override method from "
+          "'#{inheritedClass}'."),
+
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT,
+          "This is the method that cannot be overridden by a field."),
+
+      MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD:
+        const MessageTemplate(MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD,
+              "Method '#{name}' in '#{class}' can't override getter from "
+              "'#{inheritedClass}'."),
+
+      MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT,
+          "This is the getter that cannot be overridden by a method."),
+
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER:
+        const MessageTemplate(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER,
+          "Getter '#{name}' in '#{class}' can't override method from "
+          "'#{inheritedClass}'."),
+
+      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT:
+        const MessageTemplate(
+          MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT,
+          "This is the method that cannot be overridden by a getter."),
+
+      MessageKind.MISSING_FORMALS:
+        const MessageTemplate(MessageKind.MISSING_FORMALS,
+          "Formal parameters are missing."),
+
+      MessageKind.EXTRA_FORMALS:
+        const MessageTemplate(MessageKind.EXTRA_FORMALS,
+          "Formal parameters are not allowed here."),
+
+      MessageKind.UNARY_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.UNARY_OPERATOR_BAD_ARITY,
+          "Operator '#{operatorName}' must have no parameters."),
+
+      MessageKind.MINUS_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.MINUS_OPERATOR_BAD_ARITY,
+          "Operator '-' must have 0 or 1 parameters."),
+
+      MessageKind.BINARY_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.BINARY_OPERATOR_BAD_ARITY,
+          "Operator '#{operatorName}' must have exactly 1 parameter."),
+
+      MessageKind.TERNARY_OPERATOR_BAD_ARITY:
+        const MessageTemplate(MessageKind.TERNARY_OPERATOR_BAD_ARITY,
+          "Operator '#{operatorName}' must have exactly 2 parameters."),
+
+      MessageKind.OPERATOR_OPTIONAL_PARAMETERS:
+        const MessageTemplate(MessageKind.OPERATOR_OPTIONAL_PARAMETERS,
+          "Operator '#{operatorName}' cannot have optional parameters."),
+
+      MessageKind.OPERATOR_NAMED_PARAMETERS:
+        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."),
+
+      MessageKind.ILLEGAL_CONST_FIELD_MODIFIER:
+        const MessageTemplate(MessageKind.ILLEGAL_CONST_FIELD_MODIFIER,
+          "Cannot have const modifier on non-static field.",
+          howToFix:
+            "Try adding a static modifier, or removing the const modifier.",
+          examples: const ["""
+class C {
+  const int a = 1;
+}
+
+main() => new C();"""]),
+
+      MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS:
+        const MessageTemplate(MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS,
+          "Illegal constructor modifiers: '#{modifiers}'."),
+
+      MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS,
+              "Illegal mixin application modifiers: '#{modifiers}'."),
+
+      MessageKind.ILLEGAL_MIXIN_SUPERCLASS:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_SUPERCLASS,
+          "Class used as mixin must have Object as superclass."),
+
+      MessageKind.ILLEGAL_MIXIN_OBJECT:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_OBJECT,
+          "Cannot use Object as mixin."),
+
+      MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR,
+          "Class used as mixin cannot have non-factory constructor."),
+
+      MessageKind.ILLEGAL_MIXIN_CYCLE:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_CYCLE,
+          "Class used as mixin introduces mixin cycle: "
+          "'#{mixinName1}' <-> '#{mixinName2}'."),
+
+      MessageKind.ILLEGAL_MIXIN_WITH_SUPER:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_WITH_SUPER,
+          "Cannot use class '#{className}' as a mixin because it uses "
+          "'super'."),
+
+      MessageKind.ILLEGAL_MIXIN_SUPER_USE:
+        const MessageTemplate(MessageKind.ILLEGAL_MIXIN_SUPER_USE,
+          "Use of 'super' in class used as mixin."),
+
+      MessageKind.PARAMETER_NAME_EXPECTED:
+        const MessageTemplate(MessageKind.PARAMETER_NAME_EXPECTED,
+          "parameter name expected."),
+
+      MessageKind.CANNOT_RESOLVE_GETTER:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_GETTER,
+          "Cannot resolve getter."),
+
+      MessageKind.CANNOT_RESOLVE_SETTER:
+        const MessageTemplate(MessageKind.CANNOT_RESOLVE_SETTER,
+          "Cannot resolve setter."),
+
+      MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER:
+        const MessageTemplate(MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER,
+          "Cannot assign a value to final field '#{name}' "
+          "in superclass '#{superclassName}'."),
+
+      MessageKind.ASSIGNING_METHOD:
+        const MessageTemplate(MessageKind.ASSIGNING_METHOD,
+          "Cannot assign a value to a method."),
+
+      MessageKind.ASSIGNING_METHOD_IN_SUPER:
+        const MessageTemplate(MessageKind.ASSIGNING_METHOD_IN_SUPER,
+          "Cannot assign a value to method '#{name}' "
+          "in superclass '#{superclassName}'."),
+
+      MessageKind.ASSIGNING_TYPE:
+        const MessageTemplate(MessageKind.ASSIGNING_TYPE,
+          "Cannot assign a value to a type."),
+
+      MessageKind.IF_NULL_ASSIGNING_TYPE:
+        const MessageTemplate(MessageKind.IF_NULL_ASSIGNING_TYPE,
+          "Cannot assign a value to a type. Note that types are never null, "
+          "so this ??= assignment has no effect.",
+          howToFix: "Try removing the '??=' assignment.",
+          examples: const [
+              "class A {} main() { print(A ??= 3);}",
+          ]),
+
+      MessageKind.VOID_NOT_ALLOWED:
+        const MessageTemplate(MessageKind.VOID_NOT_ALLOWED,
+          "Type 'void' can't be used here because it isn't a return type.",
+          howToFix:
+            "Try removing 'void' keyword or replace it with 'var', 'final', "
+            "or a type.",
+          examples: const [
+              "void x; main() {}",
+              "foo(void x) {} main() { foo(null); }",
+          ]),
+
+      MessageKind.NULL_NOT_ALLOWED:
+        const MessageTemplate(MessageKind.NULL_NOT_ALLOWED,
+          "`null` can't be used here."),
+
+      MessageKind.BEFORE_TOP_LEVEL:
+        const MessageTemplate(MessageKind.BEFORE_TOP_LEVEL,
+          "Part header must come before top-level definitions."),
+
+      MessageKind.IMPORT_PART_OF:
+        const MessageTemplate(MessageKind.IMPORT_PART_OF,
+          "The imported library must not have a 'part-of' directive.",
+          howToFix: "Try removing the 'part-of' directive or replacing the "
+                    "import of the library with a 'part' directive.",
+          examples: const [const {
+'main.dart': """
+library library;
+
+import 'part.dart';
+
+main() {}
+""",
+
+'part.dart': """
+part of library;
+"""}]),
+
+      MessageKind.IMPORT_PART_OF_HERE:
+        const MessageTemplate(MessageKind.IMPORT_PART_OF_HERE,
+          "The library is imported here."),
+
+      MessageKind.MAIN_HAS_PART_OF:
+        const MessageTemplate(MessageKind.MAIN_HAS_PART_OF,
+          "The main application file must not have a 'part-of' directive.",
+          howToFix:  "Try removing the 'part-of' directive or starting "
+              "compilation from another file.",
+          examples: const [const {
+'main.dart': """
+part of library;
+
+main() {}
+"""}]),
+
+      MessageKind.LIBRARY_NAME_MISMATCH:
+        const MessageTemplate(MessageKind.LIBRARY_NAME_MISMATCH,
+          "Expected part of library name '#{libraryName}'.",
+          howToFix: "Try changing the directive to 'part of #{libraryName};'.",
+          examples: const [const {
+'main.dart': """
+library lib.foo;
+
+part 'part.dart';
+
+main() {}
+""",
+
+'part.dart': """
+part of lib.bar;
+"""}]),
+
+      MessageKind.MISSING_LIBRARY_NAME:
+        const MessageTemplate(MessageKind.MISSING_LIBRARY_NAME,
+          "Library has no name. Part directive expected library name "
+          "to be '#{libraryName}'.",
+          howToFix: "Try adding 'library #{libraryName};' to the library.",
+          examples: const [const {
+'main.dart': """
+part 'part.dart';
+
+main() {}
+""",
+
+'part.dart': """
+part of lib.foo;
+"""}]),
+
+      MessageKind.THIS_IS_THE_PART_OF_TAG:
+        const MessageTemplate(MessageKind.THIS_IS_THE_PART_OF_TAG,
+          "This is the part of directive."),
+
+      MessageKind.MISSING_PART_OF_TAG:
+        const MessageTemplate(MessageKind.MISSING_PART_OF_TAG,
+          "This file has no part-of tag, but it is being used as a part."),
+
+      MessageKind.DUPLICATED_PART_OF:
+        const MessageTemplate(MessageKind.DUPLICATED_PART_OF,
+          "Duplicated part-of directive."),
+
+      MessageKind.DUPLICATED_LIBRARY_NAME:
+        const MessageTemplate(MessageKind.DUPLICATED_LIBRARY_NAME,
+          "Duplicated library name '#{libraryName}'."),
+
+      MessageKind.DUPLICATED_RESOURCE:
+        const MessageTemplate(MessageKind.DUPLICATED_RESOURCE,
+          "The resource '#{resourceUri}' is loaded through both "
+          "'#{canonicalUri1}' and '#{canonicalUri2}'."),
+
+      MessageKind.DUPLICATED_LIBRARY_RESOURCE:
+        const MessageTemplate(MessageKind.DUPLICATED_LIBRARY_RESOURCE,
+          "The library '#{libraryName}' in '#{resourceUri}' is loaded through "
+          "both '#{canonicalUri1}' and '#{canonicalUri2}'."),
+
+      // This is used as an exception.
+      MessageKind.INVALID_SOURCE_FILE_LOCATION:
+        const MessageTemplate(MessageKind.INVALID_SOURCE_FILE_LOCATION, '''
+Invalid offset (#{offset}) in source map.
+File: #{fileName}
+Length: #{length}'''),
+
+      MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC:
+        const MessageTemplate(MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC,
+              "Top-level variable cannot be declared static."),
+
+      MessageKind.REFERENCE_IN_INITIALIZATION:
+        const MessageTemplate(MessageKind.REFERENCE_IN_INITIALIZATION,
+           "Variable '#{variableName}' is referenced during its "
+           "initialization.",
+           howToFix:
+             "If you are trying to reference a shadowed variable, rename "
+             "one of the variables.",
+           examples: const ["""
+foo(t) {
+  var t = t;
+  return t;
+}
+
+main() => foo(1);
+"""]),
+
+      MessageKind.CONST_WITHOUT_INITIALIZER:
+        const MessageTemplate(MessageKind.CONST_WITHOUT_INITIALIZER,
+          "A constant variable must be initialized.",
+          howToFix: "Try adding an initializer or "
+                    "removing the 'const' modifier.",
+          examples: const ["""
+void main() {
+  const c; // This constant variable must be initialized.
+}"""]),
+
+      MessageKind.FINAL_WITHOUT_INITIALIZER:
+        const MessageTemplate(MessageKind.FINAL_WITHOUT_INITIALIZER,
+          "A final variable must be initialized.",
+          howToFix: "Try adding an initializer or "
+                    "removing the 'final' modifier.",
+          examples: const [
+              "class C { static final field; } main() => C.field;"]),
+
+      MessageKind.CONST_LOOP_VARIABLE:
+        const MessageTemplate(MessageKind.CONST_LOOP_VARIABLE,
+          "A loop variable cannot be constant.",
+          howToFix: "Try remove the 'const' modifier or "
+                    "replacing it with a 'final' modifier.",
+          examples: const ["""
+void main() {
+  for (const c in []) {}
+}"""]),
+
+      MessageKind.MEMBER_USES_CLASS_NAME:
+        const MessageTemplate(MessageKind.MEMBER_USES_CLASS_NAME,
+          "Member variable can't have the same name as the class it is "
+          "declared in.",
+          howToFix: "Try renaming the variable.",
+          examples: const ["""
+class A { var A; }
+main() {
+  var a = new A();
+  a.A = 1;
+}
+""", """
+class A { static var A; }
+main() => A.A = 1;
+"""]),
+
+      MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT:
+        const MessageTemplate(
+          MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT,
+          "Wrong number of arguments to assert. Should be 1, but given "
+          "#{argumentCount}."),
+
+      MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS:
+        const MessageTemplate(MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS,
+          "'assert' takes no named arguments, but given #{argumentCount}."),
+
+      MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY:
+        const MessageTemplate(MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY,
+          "Factory redirection only allowed in factories."),
+
+      MessageKind.MISSING_FACTORY_KEYWORD:
+        const MessageTemplate(MessageKind.MISSING_FACTORY_KEYWORD,
+          "Did you forget a factory keyword here?"),
+
+      MessageKind.NO_SUCH_METHOD_IN_NATIVE:
+        const MessageTemplate(MessageKind.NO_SUCH_METHOD_IN_NATIVE,
+          "'NoSuchMethod' is not supported for classes that extend native "
+          "classes."),
+
+      MessageKind.DEFERRED_LIBRARY_DART_2_DART:
+        const MessageTemplate(MessageKind.DEFERRED_LIBRARY_DART_2_DART,
+          "Deferred loading is not supported by the dart backend yet. "
+          "The output will not be split."),
+
+      MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX:
+        const MessageTemplate(MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX,
+          "This import is deferred but there is no prefix keyword.",
+          howToFix: "Try adding a prefix to the import."),
+
+      MessageKind.DEFERRED_OLD_SYNTAX:
+        const MessageTemplate(MessageKind.DEFERRED_OLD_SYNTAX,
+          "The DeferredLibrary annotation is obsolete.",
+          howToFix:
+            "Use the \"import 'lib.dart' deferred as prefix\" syntax instead."),
+
+      MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX:
+        const MessageTemplate(MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX,
+          "The prefix of this deferred import is not unique.",
+          howToFix: "Try changing the import prefix."),
+
+      MessageKind.DEFERRED_TYPE_ANNOTATION:
+        const MessageTemplate(MessageKind.DEFERRED_TYPE_ANNOTATION,
+          "The type #{node} is deferred. "
+          "Deferred types are not valid as type annotations.",
+          howToFix:
+            "Try using a non-deferred abstract class as an interface."),
+
+      MessageKind.ILLEGAL_STATIC:
+        const MessageTemplate(MessageKind.ILLEGAL_STATIC,
+          "Modifier static is only allowed on functions declared in "
+          "a class."),
+
+      MessageKind.STATIC_FUNCTION_BLOAT:
+        const MessageTemplate(MessageKind.STATIC_FUNCTION_BLOAT,
+          "Using '#{class}.#{name}' may lead to unnecessarily large "
+          "generated code.",
+          howToFix:
+              "Try adding '@MirrorsUsed(...)' as described at "
+              "https://goo.gl/Akrrog."),
+
+      MessageKind.NON_CONST_BLOAT:
+        const MessageTemplate(MessageKind.NON_CONST_BLOAT,
+          "Using 'new #{name}' may lead to unnecessarily large generated "
+          "code.",
+          howToFix:
+              "Try using 'const #{name}' or adding '@MirrorsUsed(...)' as "
+              "described at https://goo.gl/Akrrog."),
+
+      MessageKind.STRING_EXPECTED:
+        const MessageTemplate(MessageKind.STRING_EXPECTED,
+          "Expected a 'String', but got an instance of '#{type}'."),
+
+      MessageKind.PRIVATE_IDENTIFIER:
+        const MessageTemplate(MessageKind.PRIVATE_IDENTIFIER,
+          "'#{value}' is not a valid Symbol name because it starts with "
+          "'_'."),
+
+      MessageKind.PRIVATE_NAMED_PARAMETER:
+        const MessageTemplate(MessageKind.PRIVATE_NAMED_PARAMETER,
+          "Named optional parameter can't have a library private name.",
+          howToFix:
+            "Try removing the '_' or making the parameter positional or "
+            "required.",
+          examples: const ["""foo({int _p}) {} main() => foo();"""]),
+
+      MessageKind.UNSUPPORTED_LITERAL_SYMBOL:
+        const MessageTemplate(MessageKind.UNSUPPORTED_LITERAL_SYMBOL,
+          "Symbol literal '##{value}' is currently unsupported by dart2js."),
+
+      MessageKind.INVALID_SYMBOL:
+        const MessageTemplate(MessageKind.INVALID_SYMBOL, '''
+'#{value}' is not a valid Symbol name because is not:
+ * an empty String,
+ * a user defined operator,
+ * a qualified non-private identifier optionally followed by '=', or
+ * a qualified non-private identifier followed by '.' and a user-defined '''
+"operator."),
+
+      MessageKind.AMBIGUOUS_REEXPORT:
+        const MessageTemplate(MessageKind.AMBIGUOUS_REEXPORT,
+          "'#{name}' is (re)exported by multiple libraries."),
+
+      MessageKind.AMBIGUOUS_LOCATION:
+        const MessageTemplate(MessageKind.AMBIGUOUS_LOCATION,
+          "'#{name}' is defined here."),
+
+      MessageKind.IMPORTED_HERE:
+        const MessageTemplate(MessageKind.IMPORTED_HERE,
+          "'#{name}' is imported here."),
+
+      MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE:
+        const MessageTemplate(MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
+          "The class '#{class}' overrides 'operator==', "
+          "but not 'get hashCode'."),
+
+      MessageKind.INTERNAL_LIBRARY_FROM:
+        const MessageTemplate(MessageKind.INTERNAL_LIBRARY_FROM,
+          "Internal library '#{resolvedUri}' is not accessible from "
+          "'#{importingUri}'."),
+
+      MessageKind.INTERNAL_LIBRARY:
+        const MessageTemplate(MessageKind.INTERNAL_LIBRARY,
+          "Internal library '#{resolvedUri}' is not accessible."),
+
+      MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS:
+        const MessageTemplate(
+          MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS,
+          "Js-interop class '#{cls}' cannot extend from the non js-interop "
+          "class '#{superclass}'.",
+          howToFix: "Annotate the superclass with @JS.",
+          examples: const [
+              """
+              import 'package:js/js.dart';
+
+              class Foo { }
+
+              @JS()
+              class Bar extends Foo { }
+
+              main() {
+                new Bar();
+              }
+              """]),
+
+      MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER:
+        const MessageTemplate(
+          MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
+          "Member '#{member}' in js-interop class '#{cls}' is not external.",
+          howToFix: "Mark all interop methods external",
+          examples: const [
+              """
+              import 'package:js/js.dart';
+
+              @JS()
+              class Foo {
+                bar() {}
+              }
+
+              main() {
+                new Foo().bar();
+              }
+              """]),
+
+      MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS:
+        const MessageTemplate(
+          MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
+          "Js-interop method '#{method}' has named arguments but is not "
+          "a factory constructor of an @anonymous @JS class.",
+          howToFix: "Remove all named arguments from js-interop method or "
+                    "in the case of a factory constructor annotate the class "
+                    "as @anonymous.",
+          examples: const [
+              """
+              import 'package:js/js.dart';
+
+              @JS()
+              class Foo {
+                external bar(foo, {baz});
+              }
+
+              main() {
+                new Foo().bar(4, baz: 5);
+              }
+              """]),
+
+      MessageKind.JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS:
+        const MessageTemplate(
+          MessageKind.JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS,
+          "Parameter '#{parameter}' in anonymous js-interop class '#{cls}' "
+          "object literal constructor is positional instead of named."
+          ".",
+          howToFix: "Make all arguments in external factory object literal "
+                    "constructors named.",
+          examples: const [
+              """
+              import 'package:js/js.dart';
+
+              @anonymous
+              @JS()
+              class Foo {
+                external factory Foo(foo, {baz});
+              }
+
+              main() {
+                new Foo(5, baz: 5);
+              }
+              """]),
+
+      MessageKind.LIBRARY_NOT_FOUND:
+        const MessageTemplate(MessageKind.LIBRARY_NOT_FOUND,
+          "Library not found '#{resolvedUri}'."),
+
+      MessageKind.LIBRARY_NOT_SUPPORTED:
+        const MessageTemplate(MessageKind.LIBRARY_NOT_SUPPORTED,
+          "Library not supported '#{resolvedUri}'.",
+          howToFix: "Try removing the dependency or enabling support using "
+                    "the '--categories' option.",
+          examples: const [/*
+              """
+              import 'dart:io';
+              main() {}
+              """
+          */]),
+          // TODO(johnniwinther): Enable example when message_kind_test.dart
+          // supports library loader callbacks.
+
+      MessageKind.UNSUPPORTED_EQ_EQ_EQ:
+        const MessageTemplate(MessageKind.UNSUPPORTED_EQ_EQ_EQ,
+          "'===' is not an operator. "
+          "Did you mean '#{lhs} == #{rhs}' or 'identical(#{lhs}, #{rhs})'?"),
+
+      MessageKind.UNSUPPORTED_BANG_EQ_EQ:
+        const MessageTemplate(MessageKind.UNSUPPORTED_BANG_EQ_EQ,
+          "'!==' is not an operator. "
+          "Did you mean '#{lhs} != #{rhs}' or '!identical(#{lhs}, #{rhs})'?"),
+
+      MessageKind.UNSUPPORTED_PREFIX_PLUS:
+        const MessageTemplate(MessageKind.UNSUPPORTED_PREFIX_PLUS,
+          "'+' is not a prefix operator. ",
+          howToFix: "Try removing '+'.",
+          examples: const [
+              "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. ",
+          howToFix: "Try replacing 'typedef' with 'class'.",
+          examples: const [
+              """
+class B { }
+class M1 {  }
+typedef C = B with M1;  // Need to replace 'typedef' with 'class'.
+main() { new C(); }
+"""]),
+
+      MessageKind.MIRRORS_EXPECTED_STRING:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "and a 'String' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
+// 'Foo' is a type literal, not a string.
+@MirrorsUsed(symbols: const [Foo])
+import 'dart:mirrors';
+
+class Foo {}
+
+main() {}
+"""]),
+
+      MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING_OR_TYPE,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "and a 'String' or 'Type' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
+// 'main' is a method, not a class.
+@MirrorsUsed(targets: const [main])
+import 'dart:mirrors';
+
+main() {}
+"""]),
+
+      MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING_OR_LIST,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "and a 'String' or 'List' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
+// 'Foo' is not a string.
+@MirrorsUsed(symbols: Foo)
+import 'dart:mirrors';
+
+class Foo {}
+
+main() {}
+"""]),
+
+      MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST:
+        const MessageTemplate(MessageKind.MIRRORS_EXPECTED_STRING_TYPE_OR_LIST,
+          "Can't use '#{name}' here because it's an instance of '#{type}' "
+          "but a 'String', 'Type', or 'List' value is expected.",
+          howToFix: "Did you forget to add quotes?",
+          examples: const [
+              """
+// '1' is not a string.
+@MirrorsUsed(targets: 1)
+import 'dart:mirrors';
+
+main() {}
+"""]),
+
+      MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY:
+        const MessageTemplate(
+          MessageKind.MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY,
+          "Can't find '#{name}' in the current library.",
+          // TODO(ahe): The closest identifiers in edit distance would be nice.
+          howToFix: "Did you forget to add an import?",
+          examples: const [
+              """
+// 'window' is not in scope because dart:html isn't imported.
+@MirrorsUsed(targets: 'window')
+import 'dart:mirrors';
+
+main() {}
+"""]),
+
+      MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY:
+        const MessageTemplate(MessageKind.MIRRORS_CANNOT_RESOLVE_IN_LIBRARY,
+          "Can't find '#{name}' in the library '#{library}'.",
+          // TODO(ahe): The closest identifiers in edit distance would be nice.
+          howToFix: "Is '#{name}' spelled right?",
+          examples: const [
+              """
+// 'List' is misspelled.
+@MirrorsUsed(targets: 'dart.core.Lsit')
+import 'dart:mirrors';
+
+main() {}
+"""]),
+
+      MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT:
+        const MessageTemplate(MessageKind.MIRRORS_CANNOT_FIND_IN_ELEMENT,
+          "Can't find '#{name}' in '#{element}'.",
+          // TODO(ahe): The closest identifiers in edit distance would be nice.
+          howToFix: "Is '#{name}' spelled right?",
+          examples: const [
+              """
+// 'addAll' is misspelled.
+@MirrorsUsed(targets: 'dart.core.List.addAl')
+import 'dart:mirrors';
+
+main() {}
+"""]),
+
+      MessageKind.INVALID_URI:
+        const MessageTemplate(MessageKind.INVALID_URI,
+          "'#{uri}' is not a valid URI.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+            """
+// can't have a '[' in a URI
+import '../../Udyn[mic ils/expect.dart';
+
+main() {}
+"""]),
+
+      MessageKind.INVALID_PACKAGE_CONFIG:
+          const MessageTemplate(MessageKind.INVALID_PACKAGE_CONFIG,
+            """Package config file '#{uri}' is invalid.
+#{exception}""",
+            howToFix: DONT_KNOW_HOW_TO_FIX
+      ),
+
+      MessageKind.INVALID_PACKAGE_URI:
+        const MessageTemplate(MessageKind.INVALID_PACKAGE_URI,
+          "'#{uri}' is not a valid package URI (#{exception}).",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+            """
+// can't have a 'top level' package URI
+import 'package:foo.dart';
+
+main() {}
+""", """
+// can't have 2 slashes
+import 'package://foo/foo.dart';
+
+main() {}
+""", """
+// package name must be valid
+import 'package:not\valid/foo.dart';
+
+main() {}
+"""]),
+
+      MessageKind.READ_SCRIPT_ERROR:
+        const MessageTemplate(MessageKind.READ_SCRIPT_ERROR,
+          "Can't read '#{uri}' (#{exception}).",
+          // Don't know how to fix since the underlying error is unknown.
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+              """
+// 'foo.dart' does not exist.
+import 'foo.dart';
+
+main() {}
+"""]),
+
+      MessageKind.READ_SELF_ERROR:
+        const MessageTemplate(MessageKind.READ_SELF_ERROR,
+          "#{exception}",
+          // 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.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["abstract class A {} main() { new A(); }"]),
+
+      MessageKind.BODY_EXPECTED:
+        const MessageTemplate(MessageKind.BODY_EXPECTED,
+          "Expected a function body or '=>'.",
+          // TODO(ahe): In some scenarios, we can suggest removing the 'static'
+          // keyword.
+          howToFix: "Try adding {}.",
+          examples: const [
+              "main();"]),
+
+      MessageKind.MIRROR_BLOAT:
+        const MessageTemplate(MessageKind.MIRROR_BLOAT,
+          "#{count} methods retained for use by dart:mirrors out of #{total}"
+          " total methods (#{percentage}%)."),
+
+      MessageKind.MIRROR_IMPORT:
+        const MessageTemplate(MessageKind.MIRROR_IMPORT,
+          "Import of 'dart:mirrors'."),
+
+      MessageKind.MIRROR_IMPORT_NO_USAGE:
+        const MessageTemplate(MessageKind.MIRROR_IMPORT_NO_USAGE,
+          "This import is not annotated with @MirrorsUsed, which may lead to "
+          "unnecessarily large generated code.",
+          howToFix:
+              "Try adding '@MirrorsUsed(...)' as described at "
+              "https://goo.gl/Akrrog."),
+
+      MessageKind.JS_PLACEHOLDER_CAPTURE:
+        const MessageTemplate(
+            MessageKind.JS_PLACEHOLDER_CAPTURE,
+            "JS code must not use '#' placeholders inside functions.",
+            howToFix:
+            "Use an immediately called JavaScript function to capture the"
+            " the placeholder values as JavaScript function parameters."),
+
+      MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT:
+        const MessageTemplate(
+          MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT,
+          "Argument for 'JS_INTERCEPTOR_CONSTANT' must be a type constant."),
+
+      MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD:
+        const MessageTemplate(MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
+              "'#{keyword}' is a reserved word and can't be used here.",
+              howToFix: "Try using a different name.",
+              examples: const ["do() {} main() {}"]),
+
+      MessageKind. NAMED_FUNCTION_EXPRESSION:
+        const MessageTemplate(MessageKind.NAMED_FUNCTION_EXPRESSION,
+          "Function expression '#{name}' cannot be named.",
+          howToFix: "Try removing the name.",
+          examples: const ["main() { var f = func() {}; }"]),
+
+      MessageKind.UNUSED_METHOD:
+        const MessageTemplate(MessageKind.UNUSED_METHOD,
+          "The method '#{name}' is never called.",
+          howToFix: "Consider deleting it.",
+          examples: const ["deadCode() {} main() {}"]),
+
+      MessageKind.UNUSED_CLASS:
+        const MessageTemplate(MessageKind.UNUSED_CLASS,
+          "The class '#{name}' is never used.",
+          howToFix: "Consider deleting it.",
+          examples: const ["class DeadCode {} main() {}"]),
+
+      MessageKind.UNUSED_TYPEDEF:
+        const MessageTemplate(MessageKind.UNUSED_TYPEDEF,
+          "The typedef '#{name}' is never used.",
+          howToFix: "Consider deleting it.",
+          examples: const ["typedef DeadCode(); main() {}"]),
+
+      MessageKind.ABSTRACT_METHOD:
+        const MessageTemplate(MessageKind.ABSTRACT_METHOD,
+          "The method '#{name}' has no implementation in "
+          "class '#{class}'.",
+          howToFix: "Try adding a body to '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+class Class {
+  method();
+}
+main() => new Class().method();
+"""]),
+
+      MessageKind.ABSTRACT_GETTER:
+        const MessageTemplate(MessageKind.ABSTRACT_GETTER,
+          "The getter '#{name}' has no implementation in "
+          "class '#{class}'.",
+          howToFix: "Try adding a body to '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+class Class {
+  get getter;
+}
+main() => new Class();
+"""]),
+
+      MessageKind.ABSTRACT_SETTER:
+        const MessageTemplate(MessageKind.ABSTRACT_SETTER,
+          "The setter '#{name}' has no implementation in "
+          "class '#{class}'.",
+          howToFix: "Try adding a body to '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+class Class {
+  set setter(_);
+}
+main() => new Class();
+"""]),
+
+      MessageKind.INHERIT_GETTER_AND_METHOD:
+        const MessageTemplate(MessageKind.INHERIT_GETTER_AND_METHOD,
+          "The class '#{class}' can't inherit both getters and methods "
+          "by the named '#{name}'.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["""
+class A {
+  get member => null;
+}
+class B {
+  member() {}
+}
+class Class implements A, B {
+}
+main() => new Class();
+"""]),
+
+      MessageKind.INHERITED_METHOD:
+        const MessageTemplate(MessageKind.INHERITED_METHOD,
+          "The inherited method '#{name}' is declared here in class "
+          "'#{class}'."),
+
+      MessageKind.INHERITED_EXPLICIT_GETTER:
+        const MessageTemplate(MessageKind.INHERITED_EXPLICIT_GETTER,
+          "The inherited getter '#{name}' is declared here in class "
+          "'#{class}'."),
+
+      MessageKind.INHERITED_IMPLICIT_GETTER:
+        const MessageTemplate(MessageKind.INHERITED_IMPLICIT_GETTER,
+          "The inherited getter '#{name}' is implicitly declared by this "
+          "field in class '#{class}'."),
+
+      MessageKind.UNIMPLEMENTED_METHOD_ONE:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_METHOD_ONE,
+          "'#{class}' doesn't implement '#{method}' "
+          "declared in '#{declarer}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+abstract class I {
+  m();
+}
+class C implements I {}
+main() => new C();
+""", """
+abstract class I {
+  m();
+}
+class C extends I {}
+main() => new C();
+"""]),
+
+      MessageKind.UNIMPLEMENTED_METHOD:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_METHOD,
+          "'#{class}' doesn't implement '#{method}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+abstract class I {
+  m();
+}
+
+abstract class J {
+  m();
+}
+
+class C implements I, J {}
+
+main() {
+ new C();
+}
+""", """
+abstract class I {
+  m();
+}
+
+abstract class J {
+  m();
+}
+
+class C extends I implements J {}
+
+main() {
+ new C();
+}
+"""]),
+
+      MessageKind.UNIMPLEMENTED_METHOD_CONT:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_METHOD_CONT,
+          "The method '#{name}' is declared here in class '#{class}'."),
+
+      MessageKind.UNIMPLEMENTED_SETTER_ONE:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_SETTER_ONE,
+          "'#{class}' doesn't implement the setter '#{name}' "
+          "declared in '#{declarer}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+abstract class I {
+  set m(_);
+}
+class C implements I {}
+class D implements I {
+  set m(_) {}
+}
+main() {
+ new D().m = 0;
+ new C();
+}
+"""]),
+
+      MessageKind.UNIMPLEMENTED_SETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_SETTER,
+          "'#{class}' doesn't implement the setter '#{name}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+abstract class I {
+  set m(_);
+}
+abstract class J {
+  set m(_);
+}
+class C implements I, J {}
+main() => new C();
+""", """
+abstract class I {
+  set m(_);
+}
+abstract class J {
+  set m(_);
+}
+class C extends I implements J {}
+main() => new C();
+"""]),
+
+      MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER,
+          "The setter '#{name}' is declared here in class '#{class}'."),
+
+      MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER,
+          "The setter '#{name}' is implicitly declared by this field "
+          "in class '#{class}'."),
+
+      MessageKind.UNIMPLEMENTED_GETTER_ONE:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_GETTER_ONE,
+          "'#{class}' doesn't implement the getter '#{name}' "
+          "declared in '#{declarer}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+abstract class I {
+  get m;
+}
+class C implements I {}
+main() => new C();
+""", """
+abstract class I {
+  get m;
+}
+class C extends I {}
+main() => new C();
+"""]),
+
+      MessageKind.UNIMPLEMENTED_GETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_GETTER,
+          "'#{class}' doesn't implement the getter '#{name}'.",
+          howToFix: "Try adding an implementation of '#{name}' or declaring "
+                    "'#{class}' to be 'abstract'.",
+          examples: const ["""
+abstract class I {
+  get m;
+}
+abstract class J {
+  get m;
+}
+class C implements I, J {}
+main() => new C();
+""", """
+abstract class I {
+  get m;
+}
+abstract class J {
+  get m;
+}
+class C extends I implements J {}
+main() => new C();
+"""]),
+
+      MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER,
+          "The getter '#{name}' is declared here in class '#{class}'."),
+
+      MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER:
+        const MessageTemplate(MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER,
+          "The getter '#{name}' is implicitly declared by this field "
+          "in class '#{class}'."),
+
+      MessageKind.INVALID_METADATA:
+        const MessageTemplate(MessageKind.INVALID_METADATA,
+          "A metadata annotation must be either a reference to a compile-time "
+          "constant variable or a call to a constant constructor.",
+          howToFix:
+            "Try using a different constant value or referencing it through a "
+            "constant variable.",
+          examples: const [
+'@Object main() {}',
+'@print main() {}']),
+
+      MessageKind.INVALID_METADATA_GENERIC:
+        const MessageTemplate(MessageKind.INVALID_METADATA_GENERIC,
+          "A metadata annotation using a constant constructor cannot use type "
+          "arguments.",
+          howToFix:
+            "Try removing the type arguments or referencing the constant "
+            "through a constant variable.",
+          examples: const ['''
+class C<T> {
+  const C();
+}
+@C<int>() main() {}
+''']),
+
+      MessageKind.EQUAL_MAP_ENTRY_KEY:
+        const MessageTemplate(MessageKind.EQUAL_MAP_ENTRY_KEY,
+          "An entry with the same key already exists in the map.",
+          howToFix:
+            "Try removing the previous entry or changing the key in one "
+            "of the entries.",
+          examples: const ["""
+main() {
+  var m = const {'foo': 1, 'foo': 2};
+}"""]),
+
+      MessageKind.BAD_INPUT_CHARACTER:
+        const MessageTemplate(MessageKind.BAD_INPUT_CHARACTER,
+          "Character U+#{characterHex} isn't allowed here.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["""
+main() {
+  String x = ç;
+}
+"""]),
+
+      MessageKind.UNTERMINATED_STRING:
+        const MessageTemplate(MessageKind.UNTERMINATED_STRING,
+          "String must end with #{quote}.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const ["""
+main() {
+  return '
+;
+}
+""",
+"""
+main() {
+  return \"
+;
+}
+""",
+"""
+main() {
+  return r'
+;
+}
+""",
+"""
+main() {
+  return r\"
+;
+}
+""",
+"""
+main() => '''
+""",
+"""
+main() => \"\"\"
+""",
+"""
+main() => r'''
+""",
+"""
+main() => r\"\"\"
+"""]),
+
+      MessageKind.UNMATCHED_TOKEN:
+        const MessageTemplate(MessageKind.UNMATCHED_TOKEN,
+          "Can't find '#{end}' to match '#{begin}'.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const[
+              "main(",
+              "main(){",
+              "main(){]}",
+            ]),
+
+      MessageKind.UNTERMINATED_TOKEN:
+        const MessageTemplate(MessageKind.UNTERMINATED_TOKEN,
+          // This is a fall-back message that shouldn't happen.
+          "Incomplete token."),
+
+      MessageKind.EXPONENT_MISSING:
+        const MessageTemplate(MessageKind.EXPONENT_MISSING,
+          "Numbers in exponential notation should always contain an exponent"
+          " (an integer number with an optional sign).",
+          howToFix:
+            "Make sure there is an exponent, and remove any whitespace "
+            "before it.",
+          examples: const ["""
+main() {
+  var i = 1e;
+}
+"""]),
+
+      MessageKind.HEX_DIGIT_EXPECTED:
+        const MessageTemplate(MessageKind.HEX_DIGIT_EXPECTED,
+          "A hex digit (0-9 or A-F) must follow '0x'.",
+          howToFix:
+            DONT_KNOW_HOW_TO_FIX, // Seems obvious from the error message.
+          examples: const ["""
+main() {
+  var i = 0x;
+}
+"""]),
+
+      MessageKind.MALFORMED_STRING_LITERAL:
+        const MessageTemplate(MessageKind.MALFORMED_STRING_LITERAL,
+          r"A '$' has special meaning inside a string, and must be followed by "
+          "an identifier or an expression in curly braces ({}).",
+          howToFix: r"Try adding a backslash (\) to escape the '$'.",
+          examples: const [r"""
+main() {
+  return '$';
+}
+""",
+r'''
+main() {
+  return "$";
+}
+''',
+r"""
+main() {
+  return '''$''';
+}
+""",
+r'''
+main() {
+  return """$""";
+}
+''']),
+
+      MessageKind.UNTERMINATED_COMMENT:
+        const MessageTemplate(MessageKind.UNTERMINATED_COMMENT,
+          "Comment starting with '/*' must end with '*/'.",
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [r"""
+main() {
+}
+/*"""]),
+
+      MessageKind.MISSING_TOKEN_BEFORE_THIS:
+        const MessageTemplate(MessageKind.MISSING_TOKEN_BEFORE_THIS,
+          "Expected '#{token}' before this.",
+          // Consider the second example below: the parser expects a ')' before
+          // 'y', but a ',' would also have worked. We don't have enough
+          // information to give a good suggestion.
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+              "main() => true ? 1;",
+              "main() => foo(x: 1 y: 2);",
+            ]),
+
+      MessageKind.MISSING_TOKEN_AFTER_THIS:
+        const MessageTemplate(MessageKind.MISSING_TOKEN_AFTER_THIS,
+          "Expected '#{token}' after this.",
+          // See [MISSING_TOKEN_BEFORE_THIS], we don't have enough information
+          // to give a good suggestion.
+          howToFix: DONT_KNOW_HOW_TO_FIX,
+          examples: const [
+              "main(x) {x}",
+"""
+class S1 {}
+class S2 {}
+class S3 {}
+class A = S1 with S2, S3
+main() => new A();
+"""
+]),
+
+      MessageKind.CONSIDER_ANALYZE_ALL:
+        const MessageTemplate(MessageKind.CONSIDER_ANALYZE_ALL,
+          "Could not find '#{main}'.  Nothing will be analyzed.",
+          howToFix: "Try using '--analyze-all' to analyze everything.",
+          examples: const ['']),
+
+      MessageKind.MISSING_MAIN:
+        const MessageTemplate(MessageKind.MISSING_MAIN,
+          "Could not find '#{main}'.",
+          howToFix: "Try adding a method named '#{main}' to your program."
+          /* No example, test uses '--analyze-only' which will produce the above
+           * message [CONSIDER_ANALYZE_ALL].  An example for a human operator
+           * would be an empty file.*/),
+
+      MessageKind.MAIN_NOT_A_FUNCTION:
+        const MessageTemplate(MessageKind.MAIN_NOT_A_FUNCTION,
+          "'#{main}' is not a function.",
+          howToFix: DONT_KNOW_HOW_TO_FIX, /* Don't state the obvious. */
+          examples: const ['var main;']),
+
+      MessageKind.MAIN_WITH_EXTRA_PARAMETER:
+        const MessageTemplate(MessageKind.MAIN_WITH_EXTRA_PARAMETER,
+          "'#{main}' cannot have more than two parameters.",
+          howToFix: DONT_KNOW_HOW_TO_FIX, /* Don't state the obvious. */
+          examples: const ['main(a, b, c) {}']),
+
+      MessageKind.COMPILER_CRASHED:
+        const MessageTemplate(MessageKind.COMPILER_CRASHED,
+          "The compiler crashed when compiling this element."),
+
+      MessageKind.PLEASE_REPORT_THE_CRASH:
+        const MessageTemplate(MessageKind.PLEASE_REPORT_THE_CRASH, '''
+The compiler is broken.
+
+When compiling the above element, the compiler crashed. It is not
+possible to tell if this is caused by a problem in your program or
+not. Regardless, the compiler should not crash.
+
+The Dart team would greatly appreciate if you would take a moment to
+report this problem at http://dartbug.com/new.
+
+Please include the following information:
+
+* the name and version of your operating system,
+
+* the Dart SDK build number (#{buildId}), and
+
+* the entire message you see here (including the full stack trace
+  below as well as the source location above).
+'''),
+
+      MessageKind.POTENTIAL_MUTATION:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION,
+          "Variable '#{variableName}' is not known to be of type "
+          "'#{shownType}' because it is potentially mutated in the scope for "
+          "promotion."),
+
+      MessageKind.POTENTIAL_MUTATION_HERE:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION_HERE,
+          "Variable '#{variableName}' is potentially mutated here."),
+
+      MessageKind.POTENTIAL_MUTATION_IN_CLOSURE:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION_IN_CLOSURE,
+          "Variable '#{variableName}' is not known to be of type "
+          "'#{shownType}' because it is potentially mutated within a closure."),
+
+      MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE:
+        const MessageTemplate(MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE,
+              "Variable '#{variableName}' is potentially mutated in a "
+              "closure here."),
+
+      MessageKind.ACCESSED_IN_CLOSURE:
+        const MessageTemplate(MessageKind.ACCESSED_IN_CLOSURE,
+          "Variable '#{variableName}' is not known to be of type "
+          "'#{shownType}' because it is accessed by a closure in the scope for "
+          "promotion and potentially mutated in the scope of "
+          "'#{variableName}'."),
+
+      MessageKind.ACCESSED_IN_CLOSURE_HERE:
+        const MessageTemplate(MessageKind.ACCESSED_IN_CLOSURE_HERE,
+          "Variable '#{variableName}' is accessed in a closure here."),
+
+      MessageKind.NOT_MORE_SPECIFIC:
+        const MessageTemplate(MessageKind.NOT_MORE_SPECIFIC,
+          "Variable '#{variableName}' is not shown to have type "
+          "'#{shownType}' because '#{shownType}' is not more specific than the "
+          "known type '#{knownType}' of '#{variableName}'."),
+
+      MessageKind.NOT_MORE_SPECIFIC_SUBTYPE:
+        const MessageTemplate(MessageKind.NOT_MORE_SPECIFIC_SUBTYPE,
+          "Variable '#{variableName}' is not shown to have type "
+          "'#{shownType}' because '#{shownType}' is not a subtype of the "
+          "known type '#{knownType}' of '#{variableName}'."),
+
+      MessageKind.NOT_MORE_SPECIFIC_SUGGESTION:
+        const MessageTemplate(MessageKind.NOT_MORE_SPECIFIC_SUGGESTION,
+          "Variable '#{variableName}' is not shown to have type "
+          "'#{shownType}' because '#{shownType}' is not more specific than the "
+          "known type '#{knownType}' of '#{variableName}'.",
+          howToFix:
+            "Try replacing '#{shownType}' with '#{shownTypeSuggestion}'."),
+
+      MessageKind.NO_COMMON_SUBTYPES:
+        const MessageTemplate(MessageKind.NO_COMMON_SUBTYPES,
+           "Types '#{left}' and '#{right}' have no common subtypes."),
+
+      MessageKind.HIDDEN_WARNINGS_HINTS:
+        const MessageTemplate(MessageKind.HIDDEN_WARNINGS_HINTS,
+          "#{warnings} warning(s) and #{hints} hint(s) suppressed in #{uri}."),
+
+      MessageKind.HIDDEN_WARNINGS:
+        const MessageTemplate(MessageKind.HIDDEN_WARNINGS,
+          "#{warnings} warning(s) suppressed in #{uri}."),
+
+      MessageKind.HIDDEN_HINTS:
+        const MessageTemplate(MessageKind.HIDDEN_HINTS,
+          "#{hints} hint(s) suppressed in #{uri}."),
+
+      MessageKind.PREAMBLE:
+        const MessageTemplate(MessageKind.PREAMBLE,
+        "When run on the command-line, the compiled output might"
+        " require a preamble file located in:\n"
+        "  <sdk>/lib/_internal/js_runtime/lib/preambles."),
+
+      MessageKind.INVALID_SYNC_MODIFIER:
+        const MessageTemplate(MessageKind.INVALID_SYNC_MODIFIER,
+          "Invalid modifier 'sync'.",
+          howToFix: "Try replacing 'sync' with 'sync*'.",
+          examples: const [
+            "main() sync {}"
+          ]),
+
+      MessageKind.INVALID_AWAIT_FOR:
+        const MessageTemplate(MessageKind.INVALID_AWAIT_FOR,
+          "'await' is only supported on for-in loops.",
+          howToFix: "Try rewriting the loop as a for-in loop or removing the "
+                    "'await' keyword.",
+          examples: const ["""
+main() async* {
+  await for (int i = 0; i < 10; i++) {}
+}
+"""]),
+
+      MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD:
+        const MessageTemplate(MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
+          "The modifier '#{modifier}' is not allowed on an abstract method.",
+          options: const ['--enable-async'],
+          howToFix: "Try removing the '#{modifier}' modifier or adding a "
+                    "body to the method.",
+          examples: const ["""
+abstract class A {
+  method() async;
+}
+class B extends A {
+  method() {}
+}
+main() {
+  A a = new B();
+  a.method();
+}
+"""]),
+
+      MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR,
+              "The modifier '#{modifier}' is not allowed on constructors.",
+              options: const ['--enable-async'],
+              howToFix: "Try removing the '#{modifier}' modifier.",
+              examples: const ["""
+class A {
+  A() async;
+}
+main() => new A();""",
+
+"""
+class A {
+  A();
+  factory A.a() async* {}
+}
+main() => new A.a();"""]),
+
+      MessageKind.ASYNC_MODIFIER_ON_SETTER:
+        const MessageTemplate(MessageKind.ASYNC_MODIFIER_ON_SETTER,
+              "The modifier '#{modifier}' is not allowed on setters.",
+              options: const ['--enable-async'],
+              howToFix: "Try removing the '#{modifier}' modifier.",
+              examples: const ["""
+class A {
+  set foo(v) async {}
+}
+main() => new A().foo = 0;"""]),
+
+      MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY:
+        const MessageTemplate(MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
+          "The modifier '#{modifier}' is not allowed on methods implemented "
+          "using '=>'.",
+          options: const ['--enable-async'],
+          howToFix: "Try removing the '#{modifier}' modifier or implementing "
+                    "the method body using a block: '{ ... }'.",
+          examples: const ["main() sync* => null;", "main() async* => null;"]),
+
+      // TODO(johnniwinther): Check for 'async' as identifier.
+      MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER:
+        const MessageTemplate(MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER,
+          "'#{keyword}' cannot be used as an identifier in a function body "
+          "marked with '#{modifier}'.",
+          options: const ['--enable-async'],
+          howToFix: "Try removing the '#{modifier}' modifier or renaming the "
+                    "identifier.",
+          examples: const ["""
+main() async {
+ var await;
+}""",
+"""
+main() async* {
+ var yield;
+}""",
+"""
+main() sync* {
+ 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.",
+          howToFix: "Try removing the 'native' implementation or analyzing the "
+                    "code with the --allow-native-extensions option.",
+          examples: const ["""
+main() native "Main";
+"""]),
+
+      MessageKind.DART_EXT_NOT_SUPPORTED:
+        const MessageTemplate(MessageKind.DART_EXT_NOT_SUPPORTED,
+          "The 'dart-ext' scheme is not supported.",
+          howToFix: "Try analyzing the code with the --allow-native-extensions "
+                    "option.",
+          examples: const ["""
+import 'dart-ext:main';
+
+main() {}
+"""]),
+
+      MessageKind.LIBRARY_TAG_MUST_BE_FIRST:
+        const MessageTemplate(MessageKind.LIBRARY_TAG_MUST_BE_FIRST,
+          "The library declaration should come before other declarations.",
+          howToFix: "Try moving the declaration to the top of the file.",
+          examples: const [
+"""
+import 'dart:core';
+library foo;
+main() {}
+""",
+      ]),
+
+      MessageKind.ONLY_ONE_LIBRARY_TAG:
+        const MessageTemplate(MessageKind.ONLY_ONE_LIBRARY_TAG,
+          "There can only be one library declaration.",
+          howToFix: "Try removing all other library declarations.",
+          examples: const [
+"""
+library foo;
+library bar;
+main() {}
+""",
+"""
+library foo;
+import 'dart:core';
+library bar;
+main() {}
+""",
+      ]),
+
+      MessageKind.IMPORT_BEFORE_PARTS:
+        const MessageTemplate(MessageKind.IMPORT_BEFORE_PARTS,
+          "Import declarations should come before parts.",
+          howToFix: "Try moving this import further up in the file.",
+          examples: const [
+              const <String, String>{
+                'main.dart': """
+library test.main;
+part 'part.dart';
+import 'dart:core';
+main() {}
+""",
+                'part.dart': """
+part of test.main;
+""",
+          }]),
+
+      MessageKind.EXPORT_BEFORE_PARTS:
+        const MessageTemplate(MessageKind.EXPORT_BEFORE_PARTS,
+          "Export declarations should come before parts.",
+          howToFix: "Try moving this export further up in the file.",
+          examples: const [
+              const <String, String>{
+                'main.dart': """
+library test.main;
+part 'part.dart';
+export 'dart:core';
+main() {}
+""",
+               'part.dart': """
+part of test.main;
+""",
+          }]),
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Patch errors start.
+  //////////////////////////////////////////////////////////////////////////////
+
+      MessageKind.PATCH_RETURN_TYPE_MISMATCH:
+        const MessageTemplate(MessageKind.PATCH_RETURN_TYPE_MISMATCH,
+          "Patch return type '#{patchReturnType}' does not match "
+          "'#{originReturnType}' on origin method '#{methodName}'."),
+
+      MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH:
+        const MessageTemplate(
+          MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH,
+          "Required parameter count of patch method "
+          "(#{patchParameterCount}) does not match parameter count on origin "
+          "method '#{methodName}' (#{originParameterCount})."),
+
+      MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH:
+        const MessageTemplate(
+          MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH,
+          "Optional parameter count of patch method "
+          "(#{patchParameterCount}) does not match parameter count on origin "
+          "method '#{methodName}' (#{originParameterCount})."),
+
+      MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH:
+        const MessageTemplate(
+          MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH,
+          "Optional parameters of origin and patch method "
+          "'#{methodName}' must both be either named or positional."),
+
+      MessageKind.PATCH_PARAMETER_MISMATCH:
+        const MessageTemplate(MessageKind.PATCH_PARAMETER_MISMATCH,
+          "Patch method parameter '#{patchParameter}' does not match "
+          "'#{originParameter}' on origin method '#{methodName}'."),
+
+      MessageKind.PATCH_PARAMETER_TYPE_MISMATCH:
+        const MessageTemplate(MessageKind.PATCH_PARAMETER_TYPE_MISMATCH,
+          "Patch method parameter '#{parameterName}' type "
+          "'#{patchParameterType}' does not match '#{originParameterType}' on "
+          "origin method '#{methodName}'."),
+
+      MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION:
+        const MessageTemplate(MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION,
+          "External method without an implementation."),
+
+      MessageKind.PATCH_POINT_TO_FUNCTION:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_FUNCTION,
+          "This is the function patch '#{functionName}'."),
+
+      MessageKind.PATCH_POINT_TO_CLASS:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_CLASS,
+          "This is the class patch '#{className}'."),
+
+      MessageKind.PATCH_POINT_TO_GETTER:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_GETTER,
+          "This is the getter patch '#{getterName}'."),
+
+      MessageKind.PATCH_POINT_TO_SETTER:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_SETTER,
+          "This is the setter patch '#{setterName}'."),
+
+      MessageKind.PATCH_POINT_TO_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_CONSTRUCTOR,
+          "This is the constructor patch '#{constructorName}'."),
+
+      MessageKind.PATCH_POINT_TO_PARAMETER:
+        const MessageTemplate(MessageKind.PATCH_POINT_TO_PARAMETER,
+          "This is the patch parameter '#{parameterName}'."),
+
+      MessageKind.PATCH_NON_EXISTING:
+        const MessageTemplate(MessageKind.PATCH_NON_EXISTING,
+          "Origin does not exist for patch '#{name}'."),
+
+      // TODO(ahe): Eventually, this error should be removed as it will be
+      // handled by the regular parser.
+      MessageKind.PATCH_NONPATCHABLE:
+        const MessageTemplate(MessageKind.PATCH_NONPATCHABLE,
+          "Only classes and functions can be patched."),
+
+      MessageKind.PATCH_NON_EXTERNAL:
+        const MessageTemplate(MessageKind.PATCH_NON_EXTERNAL,
+          "Only external functions can be patched."),
+
+      MessageKind.PATCH_NON_CLASS:
+        const MessageTemplate(MessageKind.PATCH_NON_CLASS,
+          "Patching non-class with class patch '#{className}'."),
+
+      MessageKind.PATCH_NON_GETTER:
+        const MessageTemplate(MessageKind.PATCH_NON_GETTER,
+          "Cannot patch non-getter '#{name}' with getter patch."),
+
+      MessageKind.PATCH_NO_GETTER:
+        const MessageTemplate(MessageKind.PATCH_NO_GETTER,
+          "No getter found for getter patch '#{getterName}'."),
+
+      MessageKind.PATCH_NON_SETTER:
+        const MessageTemplate(MessageKind.PATCH_NON_SETTER,
+          "Cannot patch non-setter '#{name}' with setter patch."),
+
+      MessageKind.PATCH_NO_SETTER:
+        const MessageTemplate(MessageKind.PATCH_NO_SETTER,
+          "No setter found for setter patch '#{setterName}'."),
+
+      MessageKind.PATCH_NON_CONSTRUCTOR:
+        const MessageTemplate(MessageKind.PATCH_NON_CONSTRUCTOR,
+          "Cannot patch non-constructor with constructor patch "
+          "'#{constructorName}'."),
+
+      MessageKind.PATCH_NON_FUNCTION:
+        const MessageTemplate(MessageKind.PATCH_NON_FUNCTION,
+          "Cannot patch non-function with function patch "
+          "'#{functionName}'."),
+
+      MessageKind.INJECTED_PUBLIC_MEMBER:
+        const MessageTemplate(MessageKind.INJECTED_PUBLIC_MEMBER,
+            "Non-patch members in patch libraries must be private."),
+
+      MessageKind.EXTERNAL_WITH_BODY:
+        const MessageTemplate(MessageKind.EXTERNAL_WITH_BODY,
+          "External function '#{functionName}' cannot have a function body.",
+          options: const ["--output-type=dart"],
+          howToFix:
+            "Try removing the 'external' modifier or the function body.",
+          examples: const ["""
+external foo() => 0;
+main() => foo();
+""", """
+external foo() {}
+main() => foo();
+"""]),
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Patch errors end.
+  //////////////////////////////////////////////////////////////////////////////
+
+      MessageKind.EXPERIMENTAL_ASSERT_MESSAGE:
+        const MessageTemplate(MessageKind.EXPERIMENTAL_ASSERT_MESSAGE,
+          "Experimental language feature 'assertion with message'"
+          " is not supported.",
+          howToFix:
+            "Use option '--assert-message' to use assertions with messages.",
+          examples: const [r'''
+main() {
+  int n = -7;
+  assert(n > 0, 'must be positive: $n');
+}
+''']),
+
+      MessageKind.IMPORT_EXPERIMENTAL_MIRRORS:
+        const MessageTemplate(MessageKind.IMPORT_EXPERIMENTAL_MIRRORS, r'''
+
+****************************************************************
+* WARNING: dart:mirrors support in dart2js is experimental,
+*          and not recommended.
+*          This implementation of mirrors is incomplete,
+*          and often greatly increases the size of the generated
+*          JavaScript code.
+*
+* Your app imports dart:mirrors via:''''''
+$IMPORT_EXPERIMENTAL_MIRRORS_PADDING#{importChain}
+*
+* You can disable this message by using the --enable-experimental-mirrors
+* command-line flag.
+*
+* To learn what to do next, please visit:
+*    http://dartlang.org/dart2js-reflection
+****************************************************************
+'''),
+
+      MessageKind.DISALLOWED_LIBRARY_IMPORT:
+        const MessageTemplate(MessageKind.DISALLOWED_LIBRARY_IMPORT, '''
+Your app imports the unsupported library '#{uri}' via:
+''''''
+$DISALLOWED_LIBRARY_IMPORT_PADDING#{importChain}
+
+Use the --categories option to support import of '#{uri}'.
+'''),
+
+      MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND:
+        const MessageTemplate(
+          MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND,
+          """
+dart:mirrors library is not supported when using this backend.
+
+Your app imports dart:mirrors via:""""""
+$MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING#{importChain}"""),
+
+      MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS:
+        const MessageTemplate(MessageKind.CALL_NOT_SUPPORTED_ON_NATIVE_CLASS,
+          "Non-supported 'call' member on a native class, or a "
+          "subclass of a native class."),
+
+      MessageKind.DIRECTLY_THROWING_NSM:
+        const MessageTemplate(MessageKind.DIRECTLY_THROWING_NSM,
+          "This 'noSuchMethod' implementation is guaranteed to throw an "
+          "exception. The generated code will be smaller if it is "
+          "rewritten.",
+          howToFix: "Rewrite to "
+                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'."),
+
+      MessageKind.COMPLEX_THROWING_NSM:
+        const MessageTemplate(MessageKind.COMPLEX_THROWING_NSM,
+          "This 'noSuchMethod' implementation is guaranteed to throw an "
+          "exception. The generated code will be smaller and the compiler "
+          "will be able to perform more optimizations if it is rewritten.",
+          howToFix: "Rewrite to "
+                    "'noSuchMethod(Invocation i) => super.noSuchMethod(i);'."),
+
+      MessageKind.COMPLEX_RETURNING_NSM:
+        const MessageTemplate(MessageKind.COMPLEX_RETURNING_NSM,
+          "Overriding 'noSuchMethod' causes the compiler to generate "
+          "more code and prevents the compiler from doing some optimizations.",
+          howToFix: "Consider removing this 'noSuchMethod' implementation."),
+
+      MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP:
+        const MessageTemplate(MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP,
+          "Unsupported version of package:lookup_map.",
+          howToFix: DONT_KNOW_HOW_TO_FIX),
+
+  }); // End of TEMPLATES.
+
+  /// Padding used before and between import chains in the message for
+  /// [MessageKind.IMPORT_EXPERIMENTAL_MIRRORS].
+  static const String IMPORT_EXPERIMENTAL_MIRRORS_PADDING = '\n*   ';
+
+  /// Padding used before and between import chains in the message for
+  /// [MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND].
+  static const String MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING = '\n   ';
+
+  /// Padding used before and between import chains in the message for
+  /// [MessageKind.DISALLOWED_LIBRARY_IMPORT].
+  static const String DISALLOWED_LIBRARY_IMPORT_PADDING = '\n  ';
 
   toString() => template;
 
@@ -901,42 +3675,7 @@
     return new Message(this, arguments, terse);
   }
 
-  bool get hasHowToFix =>
-      howToFix != null && howToFix != dart2js_messages.DONT_KNOW_HOW_TO_FIX;
-
-  static final Map<MessageKind, MessageTemplate> TEMPLATES =
-      _constructMessageTemplates();
-
-  static String get IMPORT_EXPERIMENTAL_MIRRORS_PADDING =>
-      dart2js_messages.IMPORT_EXPERIMENTAL_MIRRORS_PADDING;
-
-  static String get MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING =>
-      dart2js_messages.MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING;
-
-  static String get DISALLOWED_LIBRARY_IMPORT_PADDING =>
-      dart2js_messages.DISALLOWED_LIBRARY_IMPORT_PADDING;
-
-  static Map<MessageKind, MessageTemplate> _constructMessageTemplates() {
-    Map<MessageKind, MessageTemplate> result = <MessageKind, MessageTemplate>{};
-    for (MessageKind kind in MessageKind.values) {
-      String name = _KIND_TO_STRING_MAP[kind];
-      if (name == null) {
-        throw new ArgumentError("No mapping for $kind in _KIND_TO_STRING_MAP");
-      }
-      Map data =
-          shared_messages.MESSAGES[name] ?? dart2js_messages.MESSAGES[name];
-      if (data == null) throw new ArgumentError.value(name);
-
-      String id = data['id'];
-      String template = data['template'];
-      String howToFix = data['howToFix'];
-      List examples = data['examples'];
-      List<String> options = data['options'] ?? const <String>[];
-      result[kind] =
-          new MessageTemplate(kind, id, template, howToFix, examples, options);
-    }
-    return result;
-  }
+  bool get hasHowToFix => howToFix != null && howToFix != DONT_KNOW_HOW_TO_FIX;
 }
 
 class Message {
@@ -946,13 +3685,10 @@
   String message;
 
   Message(this.template, this.arguments, this.terse) {
-    assert(() {
-      computeMessage();
-      return true;
-    });
+    assert(() { computeMessage(); return true; });
   }
 
-  MessageKind get kind => template.kind;
+  dynamic/*MessageKind | SharedMessageKind*/ get kind => template.kind;
 
   String computeMessage() {
     if (message == null) {
@@ -963,7 +3699,7 @@
       assert(invariant(
           CURRENT_ELEMENT_SPANNABLE,
           kind == MessageKind.GENERIC ||
-              !message.contains(new RegExp(r'#\{.+\}')),
+            !message.contains(new RegExp(r'#\{.+\}')),
           message: 'Missing arguments in error message: "$message"'));
       if (!terse && template.hasHowToFix) {
         String howToFix = template.howToFix;
@@ -980,8 +3716,8 @@
     return computeMessage();
   }
 
-  bool operator ==(other) {
-    if (other is! Message) return false;
+  bool operator==(other) {
+    if (other is !Message) return false;
     return (template == other.template) && (toString() == other.toString());
   }
 
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 207954d..d909a47 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -54,7 +54,7 @@
     compiler.dumpInfoTask._constantToNode.forEach((constant, node) {
       // TODO(sigmund): add dependencies on other constants
       var size = compiler.dumpInfoTask._nodeToSize[node];
-      var code = jsAst.prettyPrint(node, compiler).getText();
+      var code = jsAst.prettyPrint(node, compiler);
       var info = new ConstantInfo(
           size: size, code: code, outputUnit: _unitInfoForConstant(constant));
       _constantToInfo[constant] = info;
@@ -529,7 +529,7 @@
     // Concatenate rendered ASTs.
     StringBuffer sb = new StringBuffer();
     for (jsAst.Node ast in code) {
-      sb.writeln(jsAst.prettyPrint(ast, compiler).getText());
+      sb.writeln(jsAst.prettyPrint(ast, compiler));
     }
     return sb.toString();
   }
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index c25e955..469081c 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -11,6 +11,8 @@
     Compiler;
 import '../constants/constructors.dart';
 import '../constants/expressions.dart';
+import '../core_types.dart' show
+    CoreClasses;
 import '../dart_types.dart';
 import '../resolution/scope.dart' show
     Scope;
@@ -1430,7 +1432,7 @@
 
   /// Returns `true` if this class implements [Function] either by directly
   /// implementing the interface or by providing a [call] method.
-  bool implementsFunction(Compiler compiler);
+  bool implementsFunction(CoreClasses coreClasses);
 
   /// Returns `true` if this class extends [cls] directly or indirectly.
   ///
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 550b3c9..3f0d70c 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -13,6 +13,8 @@
 import '../constants/constant_constructors.dart';
 import '../constants/constructors.dart';
 import '../constants/expressions.dart';
+import '../core_types.dart' show
+    CoreClasses;
 import '../dart_types.dart';
 import '../diagnostics/messages.dart' show
     MessageTemplate;
@@ -2706,8 +2708,8 @@
     backendMembers.forEach(f);
   }
 
-  bool implementsFunction(Compiler compiler) {
-    return asInstanceOf(compiler.coreClasses.functionClass) != null ||
+  bool implementsFunction(CoreClasses coreClasses) {
+    return asInstanceOf(coreClasses.functionClass) != null ||
         callType != null;
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index f897876..f9608ba 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -413,6 +413,9 @@
     FunctionSignature signature = function.functionSignature;
     signature.forEachOptionalParameter((ParameterElement element) {
       ast.Expression defaultValue = element.initializer;
+      // TODO(25566): The default value of a parameter of a redirecting factory
+      // constructor comes from the corresponding parameter of the target.
+
       // If this is a default value from a different context (because
       // the current function is synthetic, e.g., a constructor from
       // a mixin application), we have to start a new inferrer visitor
@@ -1482,54 +1485,50 @@
     return super.handleTypeLiteralInvoke(arguments);
   }
 
-  /// Handle constructor invocation of [element].
-  T handleConstructorSend(ast.Send node, ConstructorElement element) {
+  /// Handle constructor invocation of [constructor].
+  T handleConstructorSend(ast.Send node, ConstructorElement constructor) {
+    ConstructorElement target = constructor.implementation;
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     if (visitingInitializers) {
       if (ast.Initializers.isConstructorRedirect(node)) {
         isConstructorRedirect = true;
       } else if (ast.Initializers.isSuperConstructorCall(node)) {
         seenSuperConstructorCall = true;
-        analyzeSuperConstructorCall(element, arguments);
+        analyzeSuperConstructorCall(constructor, arguments);
       }
     }
-    // If we are looking at a new expression on a forwarding factory,
-    // we have to forward the call to the effective target of the
-    // factory.
-    if (element.isFactoryConstructor) {
-      // TODO(herhut): Remove the while loop once effectiveTarget forwards to
-      //               patches.
-      while (element.isFactoryConstructor) {
-        ConstructorElement constructor = element;
-        if (!constructor.isRedirectingFactory) break;
-        element = constructor.effectiveTarget.implementation;
-      }
+    // If we are looking at a new expression on a forwarding factory, we have to
+    // forward the call to the effective target of the factory.
+    // TODO(herhut): Remove the loop once effectiveTarget forwards to patches.
+    while (target.isFactoryConstructor) {
+      if (!target.isRedirectingFactory) break;
+      target = target.effectiveTarget.implementation;
     }
-    if (compiler.backend.isForeign(element)) {
-      return handleForeignSend(node, element);
+    if (compiler.backend.isForeign(target)) {
+      return handleForeignSend(node, target);
     }
     Selector selector = elements.getSelector(node);
     TypeMask mask = elements.getTypeMask(node);
     // In erroneous code the number of arguments in the selector might not
     // match the function element.
     // TODO(polux): return nonNullEmpty and check it doesn't break anything
-    if (!selector.applies(element, compiler.world) ||
-        (mask != null && !mask.canHit(element, selector, compiler.world))) {
+    if (!selector.applies(target, compiler.world) ||
+        (mask != null && !mask.canHit(target, selector, compiler.world))) {
       return types.dynamicType;
     }
 
-    T returnType = handleStaticSend(node, selector, mask, element, arguments);
-    if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
+    T returnType = handleStaticSend(node, selector, mask, target, arguments);
+    if (Elements.isGrowableListConstructorCall(constructor, node, compiler)) {
       return inferrer.concreteTypes.putIfAbsent(
           node, () => types.allocateList(
               types.growableListType, node, outermostElement,
               types.nonNullEmpty(), 0));
-    } else if (Elements.isFixedListConstructorCall(element, node, compiler)
-        || Elements.isFilledListConstructorCall(element, node, compiler)) {
+    } else if (Elements.isFixedListConstructorCall(constructor, node, compiler)
+        || Elements.isFilledListConstructorCall(constructor, node, compiler)) {
 
       int length = findLength(node);
       T elementType =
-          Elements.isFixedListConstructorCall(element, node, compiler)
+          Elements.isFixedListConstructorCall(constructor, node, compiler)
               ? types.nullType
               : arguments.positional[1];
 
@@ -1537,15 +1536,14 @@
           node, () => types.allocateList(
               types.fixedListType, node, outermostElement,
               elementType, length));
-    } else if (Elements.isConstructorOfTypedArraySubclass(element, compiler)) {
+    } else if (
+        Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) {
       int length = findLength(node);
-      ConstructorElement constructor = element.implementation;
-      constructor = constructor.effectiveTarget;
       T elementType = inferrer.returnTypeOfElement(
-          constructor.enclosingClass.lookupMember('[]'));
+          target.enclosingClass.lookupMember('[]'));
       return inferrer.concreteTypes.putIfAbsent(
         node, () => types.allocateList(
-          types.nonNullExact(constructor.enclosingClass), node,
+          types.nonNullExact(target.enclosingClass), node,
           outermostElement, elementType, length));
     } else {
       return returnType;
diff --git a/pkg/compiler/lib/src/io/code_output.dart b/pkg/compiler/lib/src/io/code_output.dart
index 967de65..7f5b996 100644
--- a/pkg/compiler/lib/src/io/code_output.dart
+++ b/pkg/compiler/lib/src/io/code_output.dart
@@ -102,8 +102,12 @@
   }
 }
 
+abstract class BufferedCodeOutput {
+  String getText();
+}
+
 /// [CodeOutput] using a [StringBuffer] as backend.
-class CodeBuffer extends AbstractCodeOutput {
+class CodeBuffer extends AbstractCodeOutput implements BufferedCodeOutput {
   StringBuffer buffer = new StringBuffer();
 
   @override
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 0e384c3..2ef185b 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -18,6 +18,8 @@
     Node,
     Send;
 
+import 'code_output.dart' show
+    CodeBuffer;
 import 'source_file.dart';
 import 'source_information.dart';
 
@@ -113,6 +115,32 @@
   SourceInformationProcessor createProcessor(SourceMapper mapper) {
     return new PositionSourceInformationProcessor(mapper);
   }
+
+  @override
+  void onComplete() {}
+
+  @override
+  SourceInformation buildSourceMappedMarker() {
+    return const SourceMappedMarker();
+  }
+}
+
+/// Marker used to tag the root nodes of source-mapped code.
+///
+/// This is needed to be able to distinguish JavaScript nodes that shouldn't
+/// have source locations (like the premable) from the nodes that should
+/// (like functions compiled from Dart code).
+class SourceMappedMarker extends SourceInformation {
+  const SourceMappedMarker();
+
+  @override
+  String get shortText => '';
+
+  @override
+  List<SourceLocation> get sourceLocations => const <SourceLocation>[];
+
+  @override
+  SourceSpan get sourceSpan => new SourceSpan(null, null, null);
 }
 
 /// [SourceInformationBuilder] that generates [PositionSourceInformation].
@@ -225,10 +253,31 @@
   final int closingPosition;
 
   CodePosition(this.startPosition, this.endPosition, this.closingPosition);
+
+  int getPosition(CodePositionKind kind) {
+    switch (kind) {
+      case CodePositionKind.START:
+        return startPosition;
+      case CodePositionKind.END:
+        return endPosition;
+      case CodePositionKind.CLOSING:
+        return closingPosition;
+    }
+  }
+
+  String toString() {
+    return 'CodePosition(start=$startPosition,'
+           'end=$endPosition,closing=$closingPosition)';
+  }
+}
+
+/// A map from a [js.Node] to its [CodePosition].
+abstract class CodePositionMap {
+  CodePosition operator [](js.Node node);
 }
 
 /// Registry for mapping [js.Node]s to their [CodePosition].
-class CodePositionRecorder {
+class CodePositionRecorder implements CodePositionMap {
   Map<js.Node, CodePosition> _codePositionMap =
       new Map<js.Node, CodePosition>.identity();
 
@@ -247,204 +296,107 @@
   CodePosition operator [](js.Node node) => _codePositionMap[node];
 }
 
+/// Enum values for the part of a Dart node used for the source location offset.
 enum SourcePositionKind {
+  /// The source mapping should point to the start of the Dart node.
+  ///
+  /// For instance the first '(' for the `(*)()` call and 'f' of both the
+  /// `foo()` and the `*.bar()` call:
+  ///
+  ///     (foo().bar())()
+  ///     ^                       // the start of the `(*)()` node
+  ///      ^                      // the start of the `foo()` node
+  ///      ^                      // the start of the `*.bar()` node
+  ///
   START,
-  CLOSING,
-  END,
+
+  /// The source mapping should point an inner position of the Dart node.
+  ///
+  /// For instance the second '(' of the `(*)()` call, the 'f' of the `foo()`
+  /// call and the 'b' of the `*.bar()` call:
+  ///
+  ///     (foo().bar())()
+  ///                  ^          // the inner position of the `(*)()` node
+  ///      ^                      // the inner position of the `foo()` node
+  ///            ^                // the inner position of the `*.bar()` node
+  ///
+  /// For function expressions the inner position is the closing brace or the
+  /// arrow:
+  ///
+  ///     foo() => () {}
+  ///           ^                 // the inner position of the 'foo' function
+  ///                  ^          // the inner position of the closure
+  ///
+  INNER,
 }
 
+SourceLocation getSourceLocation(
+    SourceInformation sourceInformation,
+    [SourcePositionKind sourcePositionKind = SourcePositionKind.START]) {
+  if (sourceInformation == null) return null;
+  switch (sourcePositionKind) {
+    case SourcePositionKind.START:
+      return sourceInformation.startPosition;
+    case SourcePositionKind.INNER:
+      return sourceInformation.closingPosition;
+  }
+}
+
+/// Enum values for the part of the JavaScript node used for the JavaScript
+/// code offset of a source mapping.
 enum CodePositionKind {
+  /// The source mapping is put on left-most offset of the node.
+  ///
+  /// For instance on the 'f' of a function or 'r' of a return statement:
+  ///
+  ///     foo: function() { return 0; }
+  ///          ^                              // the function start position
+  ///                       ^                 // the return start position
   START,
+
+  /// The source mapping is put on the closing token.
+  ///
+  /// For instance on the '}' of a function or the ';' of a return statement:
+  ///
+  ///     foo: function() { return 0; }
+  ///                                 ^       // the function closing position
+  ///                               ^         // the return closing position
+  ///
   CLOSING,
+
+  /// The source mapping is put at the end of the code for the node.
+  ///
+  /// For instance after '}' of a function or after the ';' of a return
+  /// statement:
+  ///
+  ///     foo: function() { return 0; }
+  ///                                  ^       // the function end position
+  ///                                ^         // the return end position
+  ///
   END,
 }
 
 /// Processor that associates [SourceLocation]s from [SourceInformation] on
 /// [js.Node]s with the target offsets in a [SourceMapper].
-class PositionSourceInformationProcessor
-    extends js.BaseVisitor implements SourceInformationProcessor {
-  final CodePositionRecorder codePositions = new CodePositionRecorder();
-  final SourceMapper sourceMapper;
+class PositionSourceInformationProcessor implements SourceInformationProcessor {
+  final CodePositionRecorder codePositionRecorder = new CodePositionRecorder();
+  CodePositionMap codePositionMap;
+  List<TraceListener> traceListeners;
 
-  PositionSourceInformationProcessor(this.sourceMapper);
-
-  void process(js.Node node) {
-    node.accept(this);
-  }
-
-  void visitChildren(js.Node node) {
-    node.visitChildren(this);
-  }
-
-  CodePosition getCodePosition(js.Node node) {
-    return codePositions[node];
-  }
-
-  /// Associates [sourceInformation] with the JavaScript [node].
-  ///
-  /// The offset into the JavaScript code is computed by pulling the
-  /// [codePositionKind] from the code positions associated with
-  /// [codePositionNode].
-  ///
-  /// The mapped Dart source location is computed by pulling the
-  /// [sourcePositionKind] source location from [sourceInformation].
-  void apply(js.Node node,
-             js.Node codePositionNode,
-             CodePositionKind codePositionKind,
-             SourceInformation sourceInformation,
-             SourcePositionKind sourcePositionKind) {
-    if (sourceInformation != null) {
-      CodePosition codePosition = getCodePosition(codePositionNode);
-      // We should always have recorded the needed code positions.
-      assert(invariant(
-          NO_LOCATION_SPANNABLE,
-          codePosition != null,
-          message:
-            "Code position missing for "
-            "${nodeToString(codePositionNode)}:\n"
-            "${DebugPrinter.prettyPrint(node)}"));
-      if (codePosition == null) return;
-      int codeLocation;
-      SourceLocation sourceLocation;
-      switch (codePositionKind) {
-        case CodePositionKind.START:
-          codeLocation = codePosition.startPosition;
-          break;
-        case CodePositionKind.CLOSING:
-          codeLocation = codePosition.closingPosition;
-          break;
-        case CodePositionKind.END:
-          codeLocation = codePosition.endPosition;
-          break;
-      }
-      switch (sourcePositionKind) {
-        case SourcePositionKind.START:
-          sourceLocation = sourceInformation.startPosition;
-          break;
-        case SourcePositionKind.CLOSING:
-          sourceLocation = sourceInformation.closingPosition;
-          break;
-        case SourcePositionKind.END:
-          sourceLocation = sourceInformation.endPosition;
-          break;
-      }
-      if (codeLocation != null && sourceLocation != null) {
-        sourceMapper.register(node, codeLocation, sourceLocation);
-      }
+  PositionSourceInformationProcessor(
+      SourceMapper sourceMapper,
+      [Coverage coverage]) {
+    codePositionMap = coverage != null
+              ? new CodePositionCoverage(codePositionRecorder, coverage)
+              : codePositionRecorder;
+    traceListeners = [new PositionTraceListener(sourceMapper)];
+    if (coverage != null) {
+      traceListeners.add(new CoverageListener(coverage));
     }
   }
 
-  @override
-  visitNode(js.Node node) {
-    SourceInformation sourceInformation = node.sourceInformation;
-    if (sourceInformation != null) {
-      /// Associates the left-most position of the JS code with the left-most
-      /// position of the Dart code.
-      apply(node,
-          node, CodePositionKind.START,
-          sourceInformation, SourcePositionKind.START);
-    }
-    visitChildren(node);
-  }
-
-  @override
-  visitFun(js.Fun node) {
-    SourceInformation sourceInformation = node.sourceInformation;
-    if (sourceInformation != null) {
-      /// Associates the end brace of the JavaScript function with the end brace
-      /// of the Dart function (or the `;` in case of arrow notation).
-      apply(node,
-          node, CodePositionKind.CLOSING,
-          sourceInformation, SourcePositionKind.CLOSING);
-    }
-
-    visitChildren(node);
-  }
-
-  @override
-  visitExpressionStatement(js.ExpressionStatement node) {
-    visitChildren(node);
-  }
-
-  @override
-  visitBinary(js.Binary node) {
-    visitChildren(node);
-  }
-
-  @override
-  visitAccess(js.PropertyAccess node) {
-    visitChildren(node);
-  }
-
-  @override
-  visitCall(js.Call node) {
-    SourceInformation sourceInformation = node.sourceInformation;
-    if (sourceInformation != null) {
-      if (node.target is js.PropertyAccess) {
-        js.PropertyAccess access = node.target;
-        js.Node target = access;
-        bool pureAccess = false;
-        while (target is js.PropertyAccess) {
-          js.PropertyAccess targetAccess = target;
-          if (targetAccess.receiver is js.VariableUse ||
-              targetAccess.receiver is js.This) {
-            pureAccess = true;
-            break;
-          } else {
-            target = targetAccess.receiver;
-          }
-        }
-        if (pureAccess) {
-          // a.m()   this.m()  a.b.c.d.m()
-          // ^       ^         ^
-          apply(
-              node,
-              node,
-              CodePositionKind.START,
-              sourceInformation,
-              SourcePositionKind.START);
-        } else {
-          // *.m()  *.a.b.c.d.m()
-          //   ^              ^
-          apply(
-              node,
-              access.selector,
-              CodePositionKind.START,
-              sourceInformation,
-              SourcePositionKind.CLOSING);
-        }
-      } else if (node.target is js.VariableUse) {
-        // m()
-        // ^
-        apply(
-            node,
-            node,
-            CodePositionKind.START,
-            sourceInformation,
-            SourcePositionKind.START);
-      } else if (node.target is js.Fun || node.target is js.New) {
-        // function(){}()  new Function("...")()
-        //             ^                      ^
-        apply(
-            node,
-            node.target,
-            CodePositionKind.END,
-            sourceInformation,
-            SourcePositionKind.CLOSING);
-      } else {
-        assert(invariant(NO_LOCATION_SPANNABLE, false,
-            message: "Unexpected property access ${nodeToString(node)}:\n"
-                     "${DebugPrinter.prettyPrint(node)}"));
-        // Don't know....
-        apply(
-            node,
-            node,
-            CodePositionKind.START,
-            sourceInformation,
-            SourcePositionKind.START);
-      }
-    }
-    visitChildren(node);
+  void process(js.Node node, CodeBuffer codeBuffer) {
+    new JavaScriptTracer(codePositionMap, traceListeners).apply(node);
   }
 
   @override
@@ -452,7 +404,776 @@
                    int startPosition,
                    int endPosition,
                    int closingPosition) {
-    codePositions.registerPositions(
+    codePositionRecorder.registerPositions(
         node, startPosition, endPosition, closingPosition);
   }
 }
+
+/// [TraceListener] that register [SourceLocation]s with a [SourceMapper].
+class PositionTraceListener extends TraceListener {
+  final SourceMapper sourceMapper;
+
+  PositionTraceListener(this.sourceMapper);
+
+  @override
+  void onStep(js.Node node, Offset offset, StepKind kind) {
+    SourceInformation sourceInformation = node.sourceInformation;
+    if (sourceInformation == null) return;
+
+    SourcePositionKind sourcePositionKind = SourcePositionKind.START;
+    switch (kind) {
+      case StepKind.FUN:
+        sourcePositionKind = SourcePositionKind.INNER;
+        break;
+      case StepKind.CALL:
+        CallPosition callPosition =
+            CallPosition.getSemanticPositionForCall(node);
+        sourcePositionKind = callPosition.sourcePositionKind;
+        break;
+      case StepKind.NEW:
+      case StepKind.RETURN:
+      case StepKind.BREAK:
+      case StepKind.CONTINUE:
+      case StepKind.THROW:
+      case StepKind.EXPRESSION_STATEMENT:
+      case StepKind.IF_CONDITION:
+      case StepKind.FOR_INITIALIZER:
+      case StepKind.FOR_CONDITION:
+      case StepKind.FOR_UPDATE:
+      case StepKind.WHILE_CONDITION:
+      case StepKind.DO_CONDITION:
+      case StepKind.SWITCH_EXPRESSION:
+        break;
+    }
+    int codeLocation = offset.subexpressionOffset;
+    SourceLocation sourceLocation =
+        getSourceLocation(sourceInformation, sourcePositionKind);
+    if (codeLocation != null && sourceLocation != null) {
+      sourceMapper.register(node, codeLocation, sourceLocation);
+    }
+  }
+}
+
+/// The position of a [js.Call] node.
+class CallPosition {
+  final js.Node node;
+  final CodePositionKind codePositionKind;
+  final SourcePositionKind sourcePositionKind;
+
+  CallPosition(this.node, this.codePositionKind, this.sourcePositionKind);
+
+  /// Computes the [CallPosition] for [node].
+  static CallPosition getSemanticPositionForCall(js.Call node) {
+    if (node.target is js.PropertyAccess) {
+      js.PropertyAccess access = node.target;
+      js.Node target = access;
+      bool pureAccess = false;
+      while (target is js.PropertyAccess) {
+        js.PropertyAccess targetAccess = target;
+        if (targetAccess.receiver is js.VariableUse ||
+            targetAccess.receiver is js.This) {
+          pureAccess = true;
+          break;
+        } else {
+          target = targetAccess.receiver;
+        }
+      }
+      if (pureAccess) {
+        // a.m()   this.m()  a.b.c.d.m()
+        // ^       ^         ^
+        return new CallPosition(
+            node,
+            CodePositionKind.START,
+            SourcePositionKind.START);
+      } else {
+        // *.m()  *.a.b.c.d.m()
+        //   ^              ^
+        return new CallPosition(
+            access.selector,
+            CodePositionKind.START,
+            SourcePositionKind.INNER);
+      }
+    } else if (node.target is js.VariableUse) {
+      // m()
+      // ^
+      return new CallPosition(
+          node,
+          CodePositionKind.START,
+          SourcePositionKind.START);
+    } else if (node.target is js.Fun || node.target is js.New) {
+      // function(){}()  new Function("...")()
+      //             ^                      ^
+      return new CallPosition(
+          node.target,
+          CodePositionKind.END,
+          SourcePositionKind.INNER);
+    } else if (node.target is js.Binary || node.target is js.Call) {
+      // (0,a)()   m()()
+      //      ^       ^
+      return new CallPosition(
+          node.target,
+          CodePositionKind.END,
+          SourcePositionKind.INNER);
+    } else {
+      assert(invariant(NO_LOCATION_SPANNABLE, false,
+          message: "Unexpected property access ${nodeToString(node)}:\n"
+                   "${DebugPrinter.prettyPrint(node)}"));
+      // Don't know....
+      return new CallPosition(
+          node,
+          CodePositionKind.START,
+          SourcePositionKind.START);
+    }
+  }
+}
+
+class Offset {
+  /// The offset of the enclosing statement relative to the beginning of the
+  /// file.
+  ///
+  /// For instance:
+  ///
+  ///     foo().bar(baz());
+  ///     ^                  // the statement offset of the `foo()` call
+  ///     ^                  // the statement offset of the `*.bar()` call
+  ///     ^                  // the statement offset of the `baz()` call
+  ///
+  final int statementOffset;
+
+  /// The `subexpression` offset of the step. This is the (mostly) unique
+  /// offset relative to the beginning of the file, that identifies the
+  /// current of execution.
+  ///
+  /// For instance:
+  ///
+  ///     foo().bar(baz());
+  ///     ^                   // the subexpression offset of the `foo()` call
+  ///           ^             // the subexpression offset of the `*.bar()` call
+  ///               ^         // the subexpression offset of the `baz()` call
+  ///
+  /// Here, even though the JavaScript node for the `*.bar()` call contains
+  /// the `foo()` its execution is identified by the `bar` identifier more than
+  /// the foo identifier.
+  ///
+  final int subexpressionOffset;
+
+  /// The `left-to-right` offset of the step. This is like [subexpressionOffset]
+  /// bute restricted so that the offset of each subexpression in execution
+  /// order is monotonically increasing.
+  ///
+  /// For instance:
+  ///
+  ///     foo().bar(baz());
+  ///     ^                   // the left-to-right offset of the `foo()` call
+  ///           ^             // the left-to-right offset of the `*.bar()` call
+  ///     ^                   // the left-to-right offset of the `baz()` call
+  ///
+  /// Here, `baz()` is executed before `foo()` so we need to use 'f' as its best
+  /// position under the restriction.
+  ///
+  final int leftToRightOffset;
+
+  Offset(this.statementOffset, this.leftToRightOffset, this.subexpressionOffset);
+
+  String toString() {
+    return 'Offset[statementOffset=$statementOffset,'
+        'leftToRightOffset=$leftToRightOffset,'
+        'subexpressionOffset=$subexpressionOffset]';
+  }
+}
+
+enum BranchKind {
+  CONDITION,
+  LOOP,
+  CATCH,
+  FINALLY,
+  CASE,
+}
+
+enum StepKind {
+  FUN,
+  CALL,
+  NEW,
+  RETURN,
+  BREAK,
+  CONTINUE,
+  THROW,
+  EXPRESSION_STATEMENT,
+  IF_CONDITION,
+  FOR_INITIALIZER,
+  FOR_CONDITION,
+  FOR_UPDATE,
+  WHILE_CONDITION,
+  DO_CONDITION,
+  SWITCH_EXPRESSION,
+}
+
+/// Listener for the [JavaScriptTracer].
+abstract class TraceListener {
+  /// Called before [root] node is procesed by the [JavaScriptTracer].
+  void onStart(js.Node root) {}
+
+  /// Called after [root] node has been procesed by the [JavaScriptTracer].
+  void onEnd(js.Node root) {}
+
+  /// Called when a branch of the given [kind] is started. [value] is provided
+  /// to distinguish true/false branches of [BranchKind.CONDITION] and cases of
+  /// [Branch.CASE].
+  void pushBranch(BranchKind kind, [value]) {}
+
+  /// Called when the current branch ends.
+  void popBranch() {}
+
+  /// Called when [node] defines a step of the given [kind] at the given
+  /// [offset] when the generated JavaScript code.
+  void onStep(js.Node node, Offset offset, StepKind kind) {}
+}
+
+/// Visitor that computes the [js.Node]s the are part of the JavaScript
+/// steppable execution and thus needs source mapping locations.
+class JavaScriptTracer extends js.BaseVisitor  {
+  final CodePositionMap codePositions;
+  final List<TraceListener> listeners;
+
+  /// The steps added by subexpressions.
+  List steps = [];
+
+  /// The offset of the current statement.
+  int statementOffset;
+
+  /// The current offset in left-to-right progression.
+  int leftToRightOffset;
+
+  /// The offset of the surrounding statement, used for the first subexpression.
+  int offsetPosition;
+
+  bool active;
+
+  JavaScriptTracer(this.codePositions,
+           this.listeners,
+           {this.active: false});
+
+  void notifyStart(js.Node node) {
+    listeners.forEach((listener) => listener.onStart(node));
+  }
+
+  void notifyEnd(js.Node node) {
+    listeners.forEach((listener) => listener.onEnd(node));
+  }
+
+  void notifyPushBranch(BranchKind kind, [value]) {
+    if (active) {
+      listeners.forEach((listener) => listener.pushBranch(kind, value));
+    }
+  }
+
+  void notifyPopBranch() {
+    if (active) {
+      listeners.forEach((listener) => listener.popBranch());
+    }
+  }
+
+  void notifyStep(js.Node node, Offset offset, StepKind kind) {
+    if (active) {
+      listeners.forEach((listener) => listener.onStep(node, offset, kind));
+    }
+  }
+
+  void apply(js.Node node) {
+    notifyStart(node);
+    node.accept(this);
+    notifyEnd(node);
+  }
+
+  @override
+  visitNode(js.Node node) {
+    node.visitChildren(this);
+  }
+
+  visit(js.Node node, [BranchKind branch, value]) {
+    if (node != null) {
+      if (branch != null) {
+        notifyPushBranch(branch, value);
+        node.accept(this);
+        notifyPopBranch();
+      } else {
+        node.accept(this);
+      }
+    }
+  }
+
+  visitList(List<js.Node> nodeList) {
+    if (nodeList != null) {
+      for (js.Node node in nodeList) {
+        visit(node);
+      }
+    }
+  }
+
+  @override
+  visitFun(js.Fun node) {
+    bool activeBefore = active;
+    if (!active) {
+      active = node.sourceInformation != null;
+    }
+    visit(node.body);
+    leftToRightOffset = statementOffset =
+        getSyntaxOffset(node, kind: CodePositionKind.CLOSING);
+    Offset offset = getOffsetForNode(node, statementOffset);
+    notifyStep(node, offset, StepKind.FUN);
+    active = activeBefore;
+  }
+
+  @override
+  visitBlock(js.Block node) {
+    for (js.Statement statement in node.statements) {
+      visit(statement);
+    }
+  }
+
+  int getSyntaxOffset(js.Node node,
+                      {CodePositionKind kind: CodePositionKind.START}) {
+    CodePosition codePosition = codePositions[node];
+    if (codePosition != null) {
+      return codePosition.getPosition(kind);
+    }
+    return null;
+  }
+
+  visitSubexpression(js.Node parent,
+                     js.Expression child,
+                     int codeOffset,
+                     StepKind kind) {
+    var oldSteps = steps;
+    steps = [];
+    offsetPosition = codeOffset;
+    visit(child);
+    if (steps.isEmpty) {
+      notifyStep(parent,
+          getOffsetForNode(parent, offsetPosition),
+          kind);
+    }
+    steps = oldSteps;
+  }
+
+  @override
+  visitExpressionStatement(js.ExpressionStatement node) {
+    statementOffset = getSyntaxOffset(node);
+    visitSubexpression(
+        node, node.expression, statementOffset,
+        StepKind.EXPRESSION_STATEMENT);
+    statementOffset = null;
+    leftToRightOffset = null;
+  }
+
+  @override
+  visitEmptyStatement(js.EmptyStatement node) {}
+
+  @override
+  visitCall(js.Call node) {
+    visit(node.target);
+    int oldPosition = offsetPosition;
+    offsetPosition = null;
+    visitList(node.arguments);
+    offsetPosition = oldPosition;
+    CallPosition callPosition =
+        CallPosition.getSemanticPositionForCall(node);
+    js.Node positionNode = callPosition.node;
+    int callOffset = getSyntaxOffset(
+        positionNode, kind: callPosition.codePositionKind);
+    if (offsetPosition == null) {
+      offsetPosition = callOffset;
+    }
+    Offset offset = getOffsetForNode(positionNode, offsetPosition);
+    notifyStep(node, offset, StepKind.CALL);
+    steps.add(node);
+    offsetPosition = null;
+  }
+
+  @override
+  visitNew(js.New node) {
+    visit(node.target);
+    visitList(node.arguments);
+    notifyStep(
+        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.NEW);
+    steps.add(node);
+    offsetPosition = null;
+  }
+
+  @override
+  visitAccess(js.PropertyAccess node) {
+    visit(node.receiver);
+    visit(node.selector);
+  }
+
+  @override
+  visitVariableUse(js.VariableUse node) {}
+
+  @override
+  visitLiteralBool(js.LiteralBool node) {}
+
+  @override
+  visitLiteralString(js.LiteralString node) {}
+
+  @override
+  visitLiteralNumber(js.LiteralNumber node) {}
+
+  @override
+  visitLiteralNull(js.LiteralNull node) {}
+
+  @override
+  visitName(js.Name node) {}
+
+  @override
+  visitVariableDeclarationList(js.VariableDeclarationList node) {
+    visitList(node.declarations);
+  }
+
+  @override
+  visitVariableDeclaration(js.VariableDeclaration node) {}
+
+  @override
+  visitVariableInitialization(js.VariableInitialization node) {
+    visit(node.leftHandSide);
+    visit(node.value);
+  }
+
+  @override
+  visitAssignment(js.Assignment node) {
+    visit(node.leftHandSide);
+    visit(node.value);
+  }
+
+  @override
+  visitIf(js.If node) {
+    statementOffset = getSyntaxOffset(node);
+    visitSubexpression(node, node.condition, statementOffset,
+        StepKind.IF_CONDITION);
+    statementOffset = null;
+    visit(node.then, BranchKind.CONDITION, true);
+    visit(node.otherwise, BranchKind.CONDITION, false);
+  }
+
+  @override
+  visitFor(js.For node) {
+    int offset = statementOffset = getSyntaxOffset(node);
+    statementOffset = offset;
+    leftToRightOffset = null;
+    if (node.init != null) {
+      visitSubexpression(node, node.init, getSyntaxOffset(node),
+          StepKind.FOR_INITIALIZER);
+    }
+
+    if (node.condition != null) {
+      visitSubexpression(node, node.condition, getSyntaxOffset(node.condition),
+          StepKind.FOR_CONDITION);
+    }
+
+    notifyPushBranch(BranchKind.LOOP);
+    visit(node.body);
+
+    statementOffset = offset;
+    if (node.update != null) {
+      visitSubexpression(node, node.update, getSyntaxOffset(node.update),
+          StepKind.FOR_UPDATE);
+    }
+
+    notifyPopBranch();
+  }
+
+  @override
+  visitWhile(js.While node) {
+    statementOffset = getSyntaxOffset(node);
+    if (node.condition != null) {
+      visitSubexpression(node, node.condition, getSyntaxOffset(node.condition),
+          StepKind.WHILE_CONDITION);
+    }
+    statementOffset = null;
+    leftToRightOffset = null;
+
+    visit(node.body, BranchKind.LOOP);
+  }
+
+  @override
+  visitDo(js.Do node) {
+    statementOffset = getSyntaxOffset(node);
+    visit(node.body);
+    if (node.condition != null) {
+      visitSubexpression(node, node.condition, getSyntaxOffset(node.condition),
+          StepKind.DO_CONDITION);
+    }
+    statementOffset = null;
+    leftToRightOffset = null;
+  }
+
+  @override
+  visitBinary(js.Binary node) {
+    visit(node.left);
+    visit(node.right);
+  }
+
+  @override
+  visitThis(js.This node) {}
+
+  @override
+  visitReturn(js.Return node) {
+    statementOffset = getSyntaxOffset(node);
+    visit(node.value);
+    notifyStep(
+        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.RETURN);
+    statementOffset = null;
+    leftToRightOffset = null;
+  }
+
+  @override
+  visitThrow(js.Throw node) {
+    statementOffset = getSyntaxOffset(node);
+    visit(node.expression);
+    notifyStep(
+        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.THROW);
+    statementOffset = null;
+    leftToRightOffset = null;
+  }
+
+  @override
+  visitContinue(js.Continue node) {
+    statementOffset = getSyntaxOffset(node);
+    notifyStep(
+        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.CONTINUE);
+    statementOffset = null;
+    leftToRightOffset = null;
+  }
+
+  @override
+  visitBreak(js.Break node) {
+    statementOffset = getSyntaxOffset(node);
+    notifyStep(
+        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.BREAK);
+    statementOffset = null;
+    leftToRightOffset = null;
+  }
+
+  @override
+  visitTry(js.Try node) {
+    visit(node.body);
+    visit(node.catchPart, BranchKind.CATCH);
+    visit(node.finallyPart, BranchKind.FINALLY);
+  }
+
+  @override
+  visitCatch(js.Catch node) {
+    visit(node.body);
+  }
+
+  @override
+  visitConditional(js.Conditional node) {
+    visit(node.condition);
+    visit(node.then, BranchKind.CONDITION, true);
+    visit(node.otherwise, BranchKind.CONDITION, false);
+  }
+
+  @override
+  visitPrefix(js.Prefix node) {
+    visit(node.argument);
+  }
+
+  @override
+  visitPostfix(js.Postfix node) {
+    visit(node.argument);
+  }
+
+  @override
+  visitObjectInitializer(js.ObjectInitializer node) {
+    visitList(node.properties);
+  }
+
+  @override
+  visitProperty(js.Property node) {
+    visit(node.name);
+    visit(node.value);
+  }
+
+  @override
+  visitRegExpLiteral(js.RegExpLiteral node) {}
+
+  @override
+  visitSwitch(js.Switch node) {
+    statementOffset = getSyntaxOffset(node);
+    visitSubexpression(node, node.key, getSyntaxOffset(node),
+        StepKind.SWITCH_EXPRESSION);
+    statementOffset = null;
+    leftToRightOffset = null;
+    for (int i = 0; i < node.cases.length; i++) {
+      visit(node.cases[i], BranchKind.CASE, i);
+    }
+  }
+
+  @override
+  visitCase(js.Case node) {
+    visit(node.expression);
+    visit(node.body);
+  }
+
+  @override
+  visitDefault(js.Default node) {
+    visit(node.body);
+  }
+
+  @override
+  visitArrayInitializer(js.ArrayInitializer node) {
+    visitList(node.elements);
+  }
+
+  @override
+  visitArrayHole(js.ArrayHole node) {}
+
+  @override
+  visitLabeledStatement(js.LabeledStatement node) {
+    statementOffset = getSyntaxOffset(node);
+    visit(node.body);
+    statementOffset = null;
+  }
+
+  Offset getOffsetForNode(js.Node node, int codeOffset) {
+    if (codeOffset == null) {
+      CodePosition codePosition = codePositions[node];
+      if (codePosition != null) {
+        codeOffset = codePosition.startPosition;
+      }
+    }
+    if (leftToRightOffset != null && leftToRightOffset < codeOffset) {
+      leftToRightOffset = codeOffset;
+    }
+    if (leftToRightOffset == null) {
+      leftToRightOffset = statementOffset;
+    }
+    return new Offset(statementOffset, leftToRightOffset, codeOffset);
+  }
+}
+
+
+class Coverage {
+  Set<js.Node> _nodesWithInfo = new Set<js.Node>();
+  int _nodesWithInfoCount = 0;
+  Set<js.Node> _nodesWithoutInfo = new Set<js.Node>();
+  int _nodesWithoutInfoCount = 0;
+  Map<Type, int> _nodesWithoutInfoCountByType = <Type, int>{};
+  Set<js.Node> _nodesWithoutOffset = new Set<js.Node>();
+  int _nodesWithoutOffsetCount = 0;
+
+  void registerNodeWithInfo(js.Node node) {
+    _nodesWithInfo.add(node);
+  }
+
+  void registerNodeWithoutInfo(js.Node node) {
+    _nodesWithoutInfo.add(node);
+  }
+
+  void registerNodesWithoutOffset(js.Node node) {
+    _nodesWithoutOffset.add(node);
+  }
+
+  void collapse() {
+    _nodesWithInfoCount += _nodesWithInfo.length;
+    _nodesWithInfo.clear();
+    _nodesWithoutOffsetCount += _nodesWithoutOffset.length;
+    _nodesWithoutOffset.clear();
+
+    _nodesWithoutInfoCount += _nodesWithoutInfo.length;
+    for (js.Node node in _nodesWithoutInfo) {
+      if (node is js.ExpressionStatement) {
+        _nodesWithoutInfoCountByType.putIfAbsent(
+            node.expression.runtimeType, () => 0);
+        _nodesWithoutInfoCountByType[node.expression.runtimeType]++;
+      } else {
+        _nodesWithoutInfoCountByType.putIfAbsent(
+            node.runtimeType, () => 0);
+        _nodesWithoutInfoCountByType[node.runtimeType]++;
+      }
+    }
+    _nodesWithoutInfo.clear();
+  }
+
+  String getCoverageReport() {
+    collapse();
+    StringBuffer sb = new StringBuffer();
+    int total = _nodesWithInfoCount + _nodesWithoutInfoCount;
+    if (total > 0) {
+      sb.write(_nodesWithoutInfoCount);
+      sb.write('/');
+      sb.write(total);
+      sb.write(' (');
+      sb.write((100.0 * _nodesWithInfoCount / total).toStringAsFixed(2));
+      sb.write('%) nodes with info.');
+    } else {
+      sb.write('No nodes.');
+    }
+    if (_nodesWithoutOffsetCount > 0) {
+      sb.write(' ');
+      sb.write(_nodesWithoutOffsetCount);
+      sb.write(' node');
+      if (_nodesWithoutOffsetCount > 1) {
+        sb.write('s');
+      }
+      sb.write(' without offset.');
+    }
+    if (_nodesWithoutInfoCount > 0) {
+      sb.write('\nNodes without info (');
+      sb.write(_nodesWithoutInfoCount);
+      sb.write(') by runtime type:');
+      _nodesWithoutInfoCountByType.forEach((Type type, int count) {
+        sb.write('\n ');
+        sb.write(count);
+        sb.write(' ');
+        sb.write(type);
+        sb.write(' node');
+        if (count > 1) {
+          sb.write('s');
+        }
+      });
+      sb.write('\n');
+    }
+    return sb.toString();
+  }
+
+  String toString() => getCoverageReport();
+}
+
+/// [TraceListener] that registers [onStep] callbacks with [coverage].
+class CoverageListener extends TraceListener {
+  final Coverage coverage;
+
+  CoverageListener(this.coverage);
+
+  @override
+  void onStep(js.Node node, Offset offset, StepKind kind) {
+    SourceInformation sourceInformation = node.sourceInformation;
+    if (sourceInformation != null) {
+      coverage.registerNodeWithInfo(node);
+    } else {
+      coverage.registerNodeWithoutInfo(node);
+    }
+  }
+
+  @override
+  void onEnd(js.Node node) {
+    coverage.collapse();
+  }
+}
+
+/// [CodePositionMap] that registers calls with [Coverage].
+class CodePositionCoverage implements CodePositionMap {
+  final CodePositionMap codePositions;
+  final Coverage coverage;
+
+  CodePositionCoverage(this.codePositions, this.coverage);
+
+  @override
+  CodePosition operator [](js.Node node) {
+    CodePosition codePosition = codePositions[node];
+    if (codePosition == null) {
+      coverage.registerNodesWithoutOffset(node);
+   }
+    return codePosition;
+  }
+}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 1855755..0138b41 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -21,6 +21,8 @@
 /// Interface for passing source information, for instance for use in source
 /// maps, through the backend.
 abstract class SourceInformation extends JavaScriptNodeSourceInformation {
+  const SourceInformation();
+
   SourceSpan get sourceSpan;
 
   /// The source location associated with the start of the JS node.
@@ -47,6 +49,12 @@
   SourceInformationBuilder createBuilderForContext(AstElement element) {
     return const SourceInformationBuilder();
   }
+
+  /// Generate [SourceInformation] marker for non-preamble code.
+  SourceInformation buildSourceMappedMarker() => null;
+
+  /// Called when compilation has completed.
+  void onComplete() {}
 }
 
 /// Interface for generating [SourceInformation].
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index 988c77d..8cae566 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -116,7 +116,7 @@
 }
 
 class StartEndSourceInformationStrategy
-    implements JavaScriptSourceInformationStrategy {
+    extends JavaScriptSourceInformationStrategy {
   const StartEndSourceInformationStrategy();
 
   @override
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index 3a9fd2e..df510a8 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -20,12 +20,30 @@
 
 import 'js_source_mapping.dart';
 
-CodeBuffer prettyPrint(Node node,
-                       Compiler compiler,
-                       {DumpInfoTask monitor,
-                        bool allowVariableMinification: true,
-                        Renamer renamerForNames:
-                            JavaScriptPrintingOptions.identityRenamer}) {
+String prettyPrint(
+    Node node,
+    Compiler compiler,
+    {bool allowVariableMinification: true,
+     Renamer renamerForNames: JavaScriptPrintingOptions.identityRenamer}) {
+  // TODO(johnniwinther): Do we need all the options here?
+  JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
+      shouldCompressOutput: compiler.enableMinification,
+      minifyLocalVariables: allowVariableMinification,
+      preferSemicolonToNewlineInMinifiedOutput: USE_LAZY_EMITTER,
+      renamerForNames: renamerForNames);
+  SimpleJavaScriptPrintingContext context =
+      new SimpleJavaScriptPrintingContext();
+  Printer printer = new Printer(options, context);
+  printer.visit(node);
+  return context.getText();
+}
+
+CodeBuffer createCodeBuffer(
+    Node node,
+    Compiler compiler,
+    {DumpInfoTask monitor,
+     bool allowVariableMinification: true,
+     Renamer renamerForNames: JavaScriptPrintingOptions.identityRenamer}) {
   JavaScriptSourceInformationStrategy sourceInformationFactory =
       compiler.backend.sourceInformationStrategy;
   JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
@@ -35,14 +53,14 @@
       renamerForNames: renamerForNames);
   CodeBuffer outBuffer = new CodeBuffer();
   SourceInformationProcessor sourceInformationProcessor =
-      sourceInformationFactory.createProcessor(
-          new SourceLocationsMapper(outBuffer));
+        sourceInformationFactory.createProcessor(
+            new SourceLocationsMapper(outBuffer));
   Dart2JSJavaScriptPrintingContext context =
       new Dart2JSJavaScriptPrintingContext(
           compiler.reporter, monitor, outBuffer, sourceInformationProcessor);
   Printer printer = new Printer(options, context);
   printer.visit(node);
-  sourceInformationProcessor.process(node);
+  sourceInformationProcessor.process(node, outBuffer);
   return outBuffer;
 }
 
@@ -137,13 +155,13 @@
   /// A [js.Literal] that represents the string result of unparsing [ast].
   ///
   /// When its string [value] is requested, the node pretty-prints the given
-  /// [ast] and, if [protectForEval] is true, wraps the resulting
-  /// string in parenthesis. The result is also escaped.
+  /// [ast] and, if [protectForEval] is true, wraps the resulting string in
+  /// parenthesis. The result is also escaped.
   UnparsedNode(this.tree, this._compiler, this._protectForEval);
 
   LiteralString get _literal {
     if (_cachedLiteral == null) {
-      String text = prettyPrint(tree, _compiler).getText();
+      String text = prettyPrint(tree, _compiler);
       if (_protectForEval) {
         if (tree is Fun) text = '($text)';
         if (tree is LiteralExpression) {
@@ -164,6 +182,12 @@
   String get value => _literal.value;
 }
 
+/// True if the given template consists of just a placeholder. Such templates
+/// are sometimes used to manually promote the type of an expression.
+bool isIdentityTemplate(Template template) {
+  return template.ast is InterpolatedExpression;
+}
+
 /// Returns `true` if [template] will immediately give a TypeError if the first
 /// placeholder is `null` or `undefined`.
 bool isNullGuardOnFirstArgument(Template template) {
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index 43ec130..c8cbd0de 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -7,7 +7,12 @@
 library js.debug;
 
 import 'package:js_ast/js_ast.dart';
-import '../util/util.dart' show Indentation, Tagging;
+
+import '../io/code_output.dart' show
+    BufferedCodeOutput;
+import '../util/util.dart' show
+    Indentation,
+    Tagging;
 
 /// Unparse the JavaScript [node].
 String nodeToString(Node node) {
@@ -25,8 +30,8 @@
 class DebugPrinter extends BaseVisitor with Indentation, Tagging<Node> {
   StringBuffer sb = new StringBuffer();
 
-  void visitNodeWithChildren(Node node, String type) {
-    openNode(node, type);
+  void visitNodeWithChildren(Node node, String type, [Map params]) {
+    openNode(node, type, params);
     node.visitChildren(this);
     closeNode();
   }
@@ -42,6 +47,11 @@
   }
 
   @override
+  void visitBinary(Binary node) {
+    visitNodeWithChildren(node, '${node.runtimeType}', {'op': node.op});
+  }
+
+  @override
   void visitLiteralString(LiteralString node) {
     openAndCloseNode(node, '${node.runtimeType}', {'value': node.value});
   }
@@ -57,7 +67,8 @@
 }
 
 /// Simple printing context that doesn't throw on errors.
-class LenientPrintingContext extends SimpleJavaScriptPrintingContext {
+class LenientPrintingContext extends SimpleJavaScriptPrintingContext
+    implements BufferedCodeOutput {
   @override
   void error(String message) {
     buffer.write('>>$message<<');
diff --git a/pkg/compiler/lib/src/js/js_source_mapping.dart b/pkg/compiler/lib/src/js/js_source_mapping.dart
index 0378a58..cd72e35 100644
--- a/pkg/compiler/lib/src/js/js_source_mapping.dart
+++ b/pkg/compiler/lib/src/js/js_source_mapping.dart
@@ -5,7 +5,10 @@
 library js.source_mapping;
 
 import 'js.dart';
-import '../io/code_output.dart' show SourceLocations;
+import '../io/code_output.dart' show
+    BufferedCodeOutput,
+    CodeBuffer,
+    SourceLocations;
 import '../io/source_information.dart' show
     SourceLocation,
     SourceInformation,
@@ -64,5 +67,5 @@
 
   /// Process the source information and code positions for the [node] and all
   /// its children.
-  void process(Node node) {}
+  void process(Node node, BufferedCodeOutput code) {}
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 05b00d1..7407ef7 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -502,7 +502,7 @@
 
   bool enabledNoSuchMethod = false;
 
-  final SourceInformationStrategy sourceInformationStrategy;
+  SourceInformationStrategy sourceInformationStrategy;
 
   final BackendHelpers helpers;
   final BackendImpacts impacts;
@@ -520,7 +520,7 @@
         this.sourceInformationStrategy =
             generateSourceMap
                 ? (useNewSourceInfo
-                     ? const PositionSourceInformationStrategy()
+                     ? new PositionSourceInformationStrategy()
                      : const StartEndSourceInformationStrategy())
                 : const JavaScriptSourceInformationStrategy(),
         helpers = new BackendHelpers(compiler),
@@ -940,14 +940,14 @@
 
   final Map<String, Set<ClassElement>> interceptedClassesCache =
       new Map<String, Set<ClassElement>>();
+  final Set<ClassElement> _noClasses = new Set<ClassElement>();
 
-  /**
-   * Returns a set of interceptor classes that contain a member named
-   * [name]. Returns [:null:] if there is no class.
-   */
+  /// Returns a set of interceptor classes that contain a member named [name]
+  ///
+  /// Returns an empty set if there is no class. Do not modify the returned set.
   Set<ClassElement> getInterceptedClassesOn(String name) {
     Set<Element> intercepted = interceptedElements[name];
-    if (intercepted == null) return null;
+    if (intercepted == null) return _noClasses;
     return interceptedClassesCache.putIfAbsent(name, () {
       // Populate the cache by running through all the elements and
       // determine if the given selector applies to them.
@@ -974,13 +974,12 @@
     Iterable<MixinApplicationElement> uses = classWorld.mixinUsesOf(mixin);
     Set<ClassElement> result = null;
     for (MixinApplicationElement use in uses) {
-      Iterable<ClassElement> subclasses = classWorld.strictSubclassesOf(use);
-      for (ClassElement subclass in subclasses) {
+      classWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
         if (isNativeOrExtendsNative(subclass)) {
           if (result == null) result = new Set<ClassElement>();
           result.add(subclass);
         }
-      }
+      });
     }
     return result;
   }
@@ -1251,6 +1250,10 @@
       addInterceptors(helpers.jsFixedArrayClass, enqueuer, registry);
       addInterceptors(helpers.jsExtendableArrayClass, enqueuer, registry);
       addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer, registry);
+      // Literal lists can be translated into calls to these functions:
+      enqueueInResolution(helpers.jsArrayTypedConstructor, registry);
+      enqueueInResolution(helpers.setRuntimeTypeInfo, registry);
+      enqueueInResolution(helpers.getTypeArgumentByIndex, registry);
     } else if (cls == coreClasses.intClass ||
                cls == helpers.jsIntClass) {
       addInterceptors(helpers.jsIntClass, enqueuer, registry);
@@ -1630,7 +1633,12 @@
       }
     }
 
-    generatedCode[element] = functionCompiler.compile(work);
+    jsAst.Fun function = functionCompiler.compile(work);
+    if (function.sourceInformation == null) {
+      function = function.withSourceInformation(
+          sourceInformationStrategy.buildSourceMappedMarker());
+    }
+    generatedCode[element] = function;
     WorldImpact worldImpact =
         impactTransformer.transformCodegenImpact(work.registry.worldImpact);
     compiler.dumpInfoTask.registerImpact(element, worldImpact);
@@ -1661,7 +1669,7 @@
    */
   String getGeneratedCode(Element element) {
     assert(invariant(element, element.isDeclaration));
-    return jsAst.prettyPrint(generatedCode[element], compiler).getText();
+    return jsAst.prettyPrint(generatedCode[element], compiler);
   }
 
   int assembleProgram() {
@@ -2191,7 +2199,7 @@
         });
         // 4) all overriding members of subclasses/subtypes (should be resolved)
         if (compiler.world.hasAnyStrictSubtype(cls)) {
-          for (ClassElement subcls in compiler.world.strictSubtypesOf(cls)) {
+          compiler.world.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
             subcls.forEachClassMember((Member member) {
               if (memberNames.contains(member.name)) {
                 // TODO(20993): find out why this assertion fails.
@@ -2202,7 +2210,7 @@
                 }
               }
             });
-          }
+          });
         }
         // 5) all its closures
         List<LocalFunctionElement> closures = closureMap[cls];
@@ -2509,13 +2517,13 @@
       compiler.enabledInvokeOn = true;
     }
   }
-
+/*
   CodeBuffer codeOf(Element element) {
     return generatedCode.containsKey(element)
         ? jsAst.prettyPrint(generatedCode[element], compiler)
         : null;
   }
-
+*/
   FunctionElement helperForBadMain() => helpers.badMain;
 
   FunctionElement helperForMissingMain() => helpers.missingMain;
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index f25e13b..29e6743 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -652,4 +652,4 @@
     }
     return _closure;
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index bc8ed93..1815ee2 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -91,7 +91,10 @@
   js.Fun buildFunction(tree_ir.FunctionDefinition function) {
     registerDefaultParameterValues(function.element);
     currentFunction = function.element;
-    visitStatement(function.body);
+    tree_ir.Statement statement = function.body;
+    while (statement != null) {
+      statement = visitStatement(statement);
+    }
 
     List<js.Parameter> parameters = new List<js.Parameter>();
     Set<tree_ir.Variable> parameterSet = new Set<tree_ir.Variable>();
@@ -121,6 +124,9 @@
       if (assign.op != null) break; // Compound assignment.
       js.VariableUse use = assign.leftHandSide;
 
+      // Do not touch non-local variables.
+      if (!usedVariableNames.contains(use.name)) break;
+
       // We cannot declare a variable more than once.
       if (!declaredVariables.add(use.name)) break;
 
@@ -144,6 +150,9 @@
       if (assign.op != null) break pullFromForLoop; // Compound assignment.
       js.VariableUse use = assign.leftHandSide;
 
+      // Do not touch non-local variables.
+      if (!usedVariableNames.contains(use.name)) break pullFromForLoop;
+
       // We cannot declare a variable more than once.
       if (!declaredVariables.add(use.name)) break pullFromForLoop;
 
@@ -218,9 +227,11 @@
 
   List<js.Expression> visitExpressionList(
       List<tree_ir.Expression> expressions) {
-    return new List<js.Expression>.generate(expressions.length,
-        (int index) => visitExpression(expressions[index]),
-        growable: false);
+    List<js.Expression> result = new List<js.Expression>(expressions.length);
+    for (int i = 0; i < expressions.length; ++i) {
+      result[i] = visitExpression(expressions[i]);
+    }
+    return result;
   }
 
   giveup(tree_ir.Node node,
@@ -364,26 +375,6 @@
   }
 
   @override
-  js.Expression visitLiteralMap(tree_ir.LiteralMap node) {
-    ConstructorElement constructor;
-    if (node.entries.isEmpty) {
-      constructor = glue.mapLiteralConstructorEmpty;
-    } else {
-      constructor = glue.mapLiteralConstructor;
-    }
-    List<js.Expression> entries =
-        new List<js.Expression>(2 * node.entries.length);
-    for (int i = 0; i < node.entries.length; i++) {
-      entries[2 * i] = visitExpression(node.entries[i].key);
-      entries[2 * i + 1] = visitExpression(node.entries[i].value);
-    }
-    List<js.Expression> args = entries.isEmpty
-         ? <js.Expression>[]
-         : <js.Expression>[new js.ArrayInitializer(entries)];
-    return buildStaticInvoke(constructor, args);
-  }
-
-  @override
   js.Expression visitLogicalOperator(tree_ir.LogicalOperator node) {
     return new js.Binary(
         node.operator,
@@ -405,13 +396,19 @@
   ///
   /// Even if the class is never instantiated, a JS constructor must be emitted
   /// so the 'instanceof' expression does not throw an exception at runtime.
-  ///
-  /// It does not help to ask the class world if the class is instantiated,
-  /// because it could still get tree-shaken if it is unused after optimization.
-  void registerInstanceofCheck(ClassElement class_) {
-    // TODO(asgerf): This is the only hook we have to ensure the JS constructor
-    //   gets emitted, but it is very imprecise. We should do better.
-    registry.registerInstantiatedClass(class_);
+  bool tryRegisterInstanceofCheck(ClassElement class_) {
+    if (glue.classWorld.isInstantiated(class_)) {
+      // Ensure the class remains instantiated during backend tree-shaking.
+      // TODO(asgerf): We could have a more precise hook to inform the emitter
+      // that the JS constructor function is needed, without the class being
+      // instantiated.
+      registry.registerInstantiatedClass(class_);
+      return true;
+    }
+    // Will throw if the JS constructor is not emitted, so do not allow the
+    // instanceof check.  This should only happen when certain optimization
+    // passes are disabled, as the type check itself is trivial.
+    return false;
   }
 
   @override
@@ -435,8 +432,8 @@
         // TODO(sra): Implement fast cast via calling 'boolTypeCast'.
       } else if (node.isTypeTest &&
                  node.typeArguments.isEmpty &&
-                 glue.mayGenerateInstanceofCheck(type)) {
-        registerInstanceofCheck(clazz);
+                 glue.mayGenerateInstanceofCheck(type) &&
+                 tryRegisterInstanceofCheck(clazz)) {
         return js.js('# instanceof #', [value, glue.constructorAccess(clazz)]);
       }
 
@@ -618,14 +615,15 @@
   }
 
   @override
-  void visitExpressionStatement(tree_ir.ExpressionStatement node) {
+  visitExpressionStatement(tree_ir.ExpressionStatement node) {
     js.Expression exp = visitExpression(node.expression);
     if (node.next is tree_ir.Unreachable && emitUnreachableAsReturn.last) {
       // Emit as 'return exp' to assist local analysis in the VM.
       accumulator.add(new js.Return(exp));
+      return null;
     } else {
       accumulator.add(new js.ExpressionStatement(exp));
-      visitStatement(node.next);
+      return node.next;
     }
   }
 
@@ -639,7 +637,7 @@
   }
 
   @override
-  void visitIf(tree_ir.If node) {
+  visitIf(tree_ir.If node) {
     js.Expression condition = visitExpression(node.condition);
     int usesBefore = fallthrough.useCount;
     // Unless the 'else' part ends the method. make sure to terminate any
@@ -651,21 +649,22 @@
     if (thenHasFallthrough) {
       js.Statement elseBody = buildBodyStatement(node.elseStatement);
       accumulator.add(new js.If(condition, thenBody, elseBody));
+      return null;
     } else {
       // The 'then' body cannot complete normally, so emit a short 'if'
       // and put the 'else' body after it.
       accumulator.add(new js.If.noElse(condition, thenBody));
-      visitStatement(node.elseStatement);
+      return node.elseStatement;
     }
   }
 
   @override
-  void visitLabeledStatement(tree_ir.LabeledStatement node) {
+  visitLabeledStatement(tree_ir.LabeledStatement node) {
     fallthrough.push(node.next);
     js.Statement body = buildBodyStatement(node.body);
     fallthrough.pop();
     accumulator.add(insertLabel(node.label, body));
-    visitStatement(node.next);
+    return node.next;
   }
 
   /// Creates a name for [label] if it does not already have one.
@@ -697,7 +696,9 @@
   js.Statement buildBodyStatement(tree_ir.Statement statement) {
     List<js.Statement> savedAccumulator = accumulator;
     accumulator = <js.Statement>[];
-    visitStatement(statement);
+    while (statement != null) {
+      statement = visitStatement(statement);
+    }
     js.Statement result = _bodyAsStatement();
     accumulator = savedAccumulator;
     return result;
@@ -706,7 +707,9 @@
   js.Block buildBodyBlock(tree_ir.Statement statement) {
     List<js.Statement> savedAccumulator = accumulator;
     accumulator = <js.Statement>[];
-    visitStatement(statement);
+    while (statement != null) {
+      statement = visitStatement(statement);
+    }
     js.Statement result = new js.Block(accumulator);
     accumulator = savedAccumulator;
     return result;
@@ -717,7 +720,7 @@
   }
 
   @override
-  void visitFor(tree_ir.For node) {
+  visitFor(tree_ir.For node) {
     js.Expression condition = visitExpression(node.condition);
     shortBreak.push(node.next);
     shortContinue.push(node);
@@ -744,12 +747,11 @@
       loopNode = new js.For(init, condition, update, body);
     }
     accumulator.add(insertLabel(node.label, loopNode));
-    visitStatement(node.next);
+    return node.next;
   }
 
   @override
   void visitWhileTrue(tree_ir.WhileTrue node) {
-    js.Expression condition = new js.LiteralBool(true);
     // A short break in the while will jump to the current fallthrough target.
     shortBreak.push(fallthrough.target);
     shortContinue.push(node);
@@ -764,7 +766,8 @@
       fallthrough.use();
     }
     shortBreak.pop();
-    accumulator.add(insertLabel(node.label, new js.While(condition, jsBody)));
+    accumulator.add(
+        insertLabel(node.label, new js.For(null, null, null, jsBody)));
   }
 
   bool isNull(tree_ir.Expression node) {
@@ -824,17 +827,14 @@
       registry.registerInstantiatedClosure(classElement.methodElement);
     }
     js.Expression instance = new js.New(
-        glue.constructorAccess(classElement),
-        visitExpressionList(node.arguments))
+            glue.constructorAccess(classElement),
+            visitExpressionList(node.arguments))
         .withSourceInformation(node.sourceInformation);
 
-    List<tree_ir.Expression> typeInformation = node.typeInformation;
-    assert(typeInformation.isEmpty ||
-        typeInformation.length == classElement.typeVariables.length);
-    if (typeInformation.isNotEmpty) {
+    tree_ir.Expression typeInformation = node.typeInformation;
+    if (typeInformation != null) {
       FunctionElement helper = glue.getAddRuntimeTypeInformation();
-      js.Expression typeArguments = new js.ArrayInitializer(
-          visitExpressionList(typeInformation));
+      js.Expression typeArguments = visitExpression(typeInformation);
       return buildStaticHelperInvocation(helper,
           <js.Expression>[instance, typeArguments],
           sourceInformation: node.sourceInformation);
@@ -921,8 +921,7 @@
     registry.registerStaticUse(
         new StaticUse.staticSet(node.element.declaration));
     js.Expression field = glue.staticFieldAccess(node.element);
-    js.Expression value = visitExpression(node.value);
-    return new js.Assignment(field, value);
+    return makeAssignment(field, node.value, compound: node.compound);
   }
 
   @override
@@ -987,7 +986,17 @@
   @override
   js.Expression visitTypeExpression(tree_ir.TypeExpression node) {
     List<js.Expression> arguments = visitExpressionList(node.arguments);
-    return glue.generateTypeRepresentation(node.dartType, arguments, registry);
+    switch (node.kind) {
+      case tree_ir.TypeExpressionKind.COMPLETE:
+        return glue.generateTypeRepresentation(
+            node.dartType, arguments, registry);
+      case tree_ir.TypeExpressionKind.INSTANCE:
+        // We expect only flat types for the INSTANCE representation.
+        assert(node.dartType ==
+               (node.dartType.element as ClassElement).thisType);
+        registry.registerInstantiatedClass(glue.listClass);
+        return new js.ArrayInitializer(arguments);
+    }
   }
 
   js.Node handleForeignCode(tree_ir.ForeignCode node) {
@@ -1015,14 +1024,14 @@
   }
 
   @override
-  void visitYield(tree_ir.Yield node) {
+  visitYield(tree_ir.Yield node) {
     js.Expression value = visitExpression(node.input);
     accumulator.add(new js.DartYield(value, node.hasStar));
-    visitStatement(node.next);
+    return node.next;
   }
 
   @override
-  void visitNullCheck(tree_ir.NullCheck node) {
+  visitNullCheck(tree_ir.NullCheck node) {
     js.Expression value = visitExpression(node.value);
     // TODO(sra): Try to use the selector even when [useSelector] is false. The
     // reason we use 'toString' is that it is always defined so avoids a slow
@@ -1044,7 +1053,7 @@
     } else {
       accumulator.add(new js.ExpressionStatement(access));
     }
-    visitStatement(node.next);
+    return node.next;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/codegen/glue.dart b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
index b7d4c24..46ef1a5 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/glue.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/glue.dart
@@ -228,8 +228,7 @@
     ClassWorld classWorld = _compiler.world;
     if (classWorld.isUsedAsMixin(cls)) return true;
 
-    Iterable<ClassElement> subclasses = _compiler.world.strictSubclassesOf(cls);
-    return subclasses.any((ClassElement subclass) {
+    return _compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
       return !_backend.rti.isTrivialSubstitution(subclass, cls);
     });
   }
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 034dd10..6e0619b 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -103,7 +103,7 @@
         }
 
         if (tracer != null) {
-          tracer.traceCompilation(element.name, null);
+          tracer.traceCompilation('$element', null);
         }
         cps.FunctionDefinition cpsFunction = compileToCpsIr(element);
         optimizeCpsBeforeInlining(cpsFunction);
@@ -131,6 +131,49 @@
     }
   }
 
+  String stringify(cps.FunctionDefinition node) {
+    return new SExpressionStringifier().withTypes().visit(node);
+  }
+
+  /// For debugging purposes, replace a call to [applyCpsPass] with a call
+  /// to [debugCpsPass] to check that this pass is idempotent.
+  ///
+  /// This runs [pass] followed by shrinking reductions, and then checks that
+  /// one more run of [pass] does not change the IR.  The intermediate shrinking
+  /// reductions pass is omitted if [pass] itself is shrinking reductions.
+  ///
+  /// If [targetName] is given, functions whose name contains that substring
+  /// will be dumped out if the idempotency test fails.
+  void debugCpsPass(cps_opt.Pass makePass(),
+                    cps.FunctionDefinition cpsFunction,
+                    [String targetName]) {
+    String original = stringify(cpsFunction);
+    cps_opt.Pass pass = makePass();
+    pass.rewrite(cpsFunction);
+    assert(checkCpsIntegrity(cpsFunction, pass.passName));
+    if (pass is! ShrinkingReducer) {
+      new ShrinkingReducer().rewrite(cpsFunction);
+    }
+    String before = stringify(cpsFunction);
+    makePass().rewrite(cpsFunction);
+    String after = stringify(cpsFunction);
+    if (before != after) {
+      print('SExpression changed for ${cpsFunction.element}');
+      if (targetName != null && '${cpsFunction.element}'.contains(targetName)) {
+        print(original);
+        print('\n-->\n');
+        print(before);
+        print('\n-->\n');
+        print(after);
+        compiler.outputProvider('original', 'dump')..add(original)..close();
+        compiler.outputProvider('before', 'dump')..add(before)..close();
+        compiler.outputProvider('after', 'dump')..add(after)..close();
+      }
+    }
+    traceGraph(pass.passName, cpsFunction);
+    dumpTypedIr(pass.passName, cpsFunction);
+  }
+
   void applyCpsPass(cps_opt.Pass pass, cps.FunctionDefinition cpsFunction) {
     cpsOptimizationTask.measureSubtask(pass.passName, () {
       pass.rewrite(cpsFunction);
@@ -141,8 +184,10 @@
   }
 
   cps.FunctionDefinition compileToCpsIr(AstElement element) {
-    cps.FunctionDefinition cpsFunction =
-        cpsBuilderTask.buildNode(element, typeSystem);
+    cps.FunctionDefinition cpsFunction = inliner.cache.getUnoptimized(element);
+    if (cpsFunction != null) return cpsFunction;
+
+    cpsFunction = cpsBuilderTask.buildNode(element, typeSystem);
     if (cpsFunction == null) {
       if (cpsBuilderTask.bailoutMessage == null) {
         giveUp('unable to build cps definition of $element');
@@ -157,6 +202,11 @@
     // insert fewer getInterceptor calls.
     applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
     applyCpsPass(new UnsugarVisitor(glue), cpsFunction);
+    applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
+    applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
+    applyCpsPass(new InsertRefinements(typeSystem), cpsFunction);
+
+    inliner.cache.putUnoptimized(element, cpsFunction);
     return cpsFunction;
   }
 
@@ -208,9 +258,6 @@
 
   void optimizeCpsBeforeInlining(cps.FunctionDefinition cpsFunction) {
     cpsOptimizationTask.measure(() {
-      applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
-      applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
-      applyCpsPass(new InsertRefinements(typeSystem), cpsFunction);
       applyCpsPass(new TypePropagator(this), cpsFunction);
       applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
       applyCpsPass(new ShrinkingReducer(), cpsFunction);
@@ -219,9 +266,16 @@
 
   void optimizeCpsAfterInlining(cps.FunctionDefinition cpsFunction) {
     cpsOptimizationTask.measure(() {
+      applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
+      applyCpsPass(new ShrinkingReducer(), cpsFunction);
       applyCpsPass(new RedundantRefinementEliminator(typeSystem), cpsFunction);
+      applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
+      applyCpsPass(new TypePropagator(this, recomputeAll: true), cpsFunction);
+      applyCpsPass(new ShrinkingReducer(), cpsFunction);
       applyCpsPass(new EagerlyLoadStatics(), cpsFunction);
       applyCpsPass(new GVN(compiler, typeSystem), cpsFunction);
+      applyCpsPass(new DuplicateBranchEliminator(), cpsFunction);
+      applyCpsPass(new ShrinkingReducer(), cpsFunction);
       applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
       applyCpsPass(new BoundsChecker(typeSystem, compiler.world), cpsFunction);
       applyCpsPass(new LoopInvariantBranchMotion(), cpsFunction);
@@ -230,6 +284,7 @@
       applyCpsPass(new MutableVariableEliminator(), cpsFunction);
       applyCpsPass(new RedundantJoinEliminator(), cpsFunction);
       applyCpsPass(new RedundantPhiEliminator(), cpsFunction);
+      applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction);
       applyCpsPass(new ShrinkingReducer(), cpsFunction);
       applyCpsPass(new OptimizeInterceptors(backend, typeSystem), cpsFunction);
       applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction);
@@ -267,7 +322,7 @@
 
     treeOptimizationTask.measure(() {
       applyTreePass(new StatementRewriter());
-      applyTreePass(new VariableMerger());
+      applyTreePass(new VariableMerger(minifying: compiler.enableMinification));
       applyTreePass(new LoopRewriter());
       applyTreePass(new LogicalRewriter());
       applyTreePass(new PullIntoInitializers());
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 290d563..f6ebd07 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -274,8 +274,17 @@
         compiler.backend.typeImplementation.computeType(compiler.resolution));
   }
 
-  // Integer checks don't verify that the number is not -0.0.
-  bool isInt(ConstantValue constant) => constant.isInt || constant.isMinusZero;
+  // Integer checks report true for -0.0, INFINITY, and -INFINITY.  At
+  // runtime an 'X is int' check is implemented as:
+  //
+  // typeof(X) === "number" && Math.floor(X) === X
+  //
+  // We consistently match that runtime semantics at compile time as well.
+  bool isInt(ConstantValue constant) {
+    return constant.isInt || constant.isMinusZero ||
+        constant.isPositiveInfinity ||
+        constant.isNegativeInfinity;
+  }
   bool isDouble(ConstantValue constant)
       => constant.isDouble && !constant.isMinusZero;
   bool isString(ConstantValue constant) => constant.isString;
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 99d383c..eca1917 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -49,6 +49,8 @@
 import '../dart_types.dart';
 import '../deferred_load.dart' show
     DeferredLoadTask;
+import '../diagnostics/invariant.dart' show
+    DEBUG_MODE;
 import '../dump_info.dart' show
     DumpInfoTask;
 import '../elements/elements.dart';
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index 60e1597..31a1747 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -8,7 +8,12 @@
   int get _kind;
   _NamerName get _target => this;
 
-  toString() => throw new UnsupportedError("Cannot convert a name to a string");
+  String toString() {
+    if (DEBUG_MODE) {
+      return 'Name($key)';
+    }
+    throw new UnsupportedError("Cannot convert a name to a string");
+  }
 }
 
 enum _NamerNameKinds {
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 849fae3..1501a93 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -236,8 +236,7 @@
       classesNeedingRti.add(cls);
 
       // TODO(ngeoffray): This should use subclasses, not subtypes.
-      Iterable<ClassElement> classes = compiler.world.strictSubtypesOf(cls);
-      classes.forEach((ClassElement sub) {
+      compiler.world.forEachStrictSubtypeOf(cls, (ClassElement sub) {
         potentiallyAddForRti(sub);
       });
 
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index fb34fae..f2c1ded 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -74,6 +74,7 @@
     TypeCheck,
     TypeChecks,
     TypeVariableHandler;
+import '../../js/js_debug.dart';
 import '../../universe/call_structure.dart' show
     CallStructure;
 import '../../universe/selector.dart' show
@@ -1609,9 +1610,8 @@
     outputBuffers[mainOutputUnit] = mainOutput;
 
 
-    mainOutput.addBuffer(jsAst.prettyPrint(program,
-                                           compiler,
-                                           monitor: compiler.dumpInfoTask));
+    mainOutput.addBuffer(jsAst.createCodeBuffer(
+        program, compiler, monitor: compiler.dumpInfoTask));
 
     if (compiler.deferredMapUri != null) {
       outputDeferredMap();
@@ -2055,9 +2055,8 @@
 
       outputBuffers[outputUnit] = output;
 
-      output.addBuffer(jsAst.prettyPrint(outputAsts[outputUnit],
-                                         compiler,
-                                         monitor: compiler.dumpInfoTask));
+      output.addBuffer(jsAst.createCodeBuffer(
+          outputAsts[outputUnit], compiler, monitor: compiler.dumpInfoTask));
 
       // Make a unique hash of the code (before the sourcemaps are added)
       // This will be used to retrieve the initializing function from the global
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index dbc6c9b..eb66c1a 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -22,6 +22,8 @@
     ClosureClassMap,
     ClosureFieldElement,
     CapturedVariable;
+import '../core_types.dart' show
+    CoreClasses;
 import '../dart_types.dart' show
     DartType,
     FunctionType,
@@ -34,6 +36,7 @@
 import '../elements/elements.dart' show
     ClassElement,
     ConstructorBodyElement,
+    ConstructorElement,
     Element,
     Elements,
     ElementKind,
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
index 96838ac..a0b9b48 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
@@ -159,15 +159,16 @@
 
     program.finalizers.forEach((js.TokenFinalizer f) => f.finalizeTokens());
 
+    // TODO(johnnniwinther): Support source maps in this emitter.
     for (int i = 0; i < fragmentsCode.length; ++i) {
-      String code = js.prettyPrint(fragmentsCode[i], compiler).getText();
+      String code = js.createCodeBuffer(fragmentsCode[i], compiler).getText();
       totalSize += code.length;
       compiler.outputProvider(fragments[i+1].outputFileName, deferredExtension)
         ..add(code)
         ..close();
     }
 
-    String mainCode = js.prettyPrint(mainAst, compiler).getText();
+    String mainCode = js.createCodeBuffer(mainAst, compiler).getText();
     compiler.outputProvider(mainFragment.outputFileName, 'js')
         ..add(buildGeneratedBy(compiler))
         ..add(mainCode)
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 43aa528..fdea7ff 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -178,12 +178,42 @@
   }
 
   List<jsAst.DeferredNumber> reifyDefaultArguments(FunctionElement function) {
+    function = function.implementation;
     FunctionSignature signature = function.functionSignature;
     if (signature.optionalParameterCount == 0) return const [];
+
+    // Optional parameters of redirecting factory constructors take their
+    // defaults from the corresponding parameters of the redirection target.
+    Map<ParameterElement, ParameterElement> targetParameterMap;
+    if (function is ConstructorElement) {
+      // TODO(sra): dart2js generates a redirecting factory constructor body
+      // that has the signature of the redirecting constructor that calls the
+      // redirection target. This is wrong - it should have the signature of the
+      // target. This would make the reified default arguments trivial.
+
+      ConstructorElement constructor = function;
+      while (constructor.isRedirectingFactory &&
+             !constructor.isCyclicRedirection) {
+        // TODO(sra): Remove the loop once effectiveTarget forwards to patches.
+        constructor = constructor.effectiveTarget.implementation;
+      }
+
+      if (constructor != function) {
+        if (signature.hasOptionalParameters) {
+          targetParameterMap =
+              mapRedirectingFactoryConstructorOptionalParameters(
+                  signature, constructor.functionSignature);
+        }
+      }
+    }
+
     List<jsAst.DeferredNumber> defaultValues = <jsAst.DeferredNumber>[];
     for (ParameterElement element in signature.optionalParameters) {
-      ConstantValue constant =
-          _backend.constants.getConstantValueForVariable(element);
+      ParameterElement parameter =
+          (targetParameterMap == null) ? element : targetParameterMap[element];
+      ConstantValue constant = (parameter == null)
+          ? null
+          : _backend.constants.getConstantValueForVariable(parameter);
       jsAst.Expression expression = (constant == null)
           ? new jsAst.LiteralNull()
           : _emitter.constantReference(constant);
@@ -192,6 +222,40 @@
     return defaultValues;
   }
 
+  Map<ParameterElement, ParameterElement>
+  mapRedirectingFactoryConstructorOptionalParameters(
+      FunctionSignature source, FunctionSignature target) {
+    var map = <ParameterElement, ParameterElement>{};
+
+    if (source.optionalParametersAreNamed !=
+        target.optionalParametersAreNamed) {
+      // No legal optional arguments due to mismatch between named vs positional
+      // optional arguments.
+      return map;
+    }
+
+    if (source.optionalParametersAreNamed) {
+      for (ParameterElement element in source.optionalParameters) {
+        for (ParameterElement redirectedElement in target.optionalParameters) {
+          if (element.name == redirectedElement.name) {
+            map[element] = redirectedElement;
+            break;
+          }
+        }
+      }
+    } else {
+      int i = source.requiredParameterCount;
+      for (ParameterElement element in source.orderedOptionalParameters) {
+        if (i >= target.requiredParameterCount && i < target.parameterCount) {
+          map[element] =
+              target.orderedOptionalParameters[i - target.requiredParameterCount];
+        }
+        ++i;
+      }
+    }
+    return map;
+  }
+
   jsAst.Expression reifyMetadata(MetadataAnnotation annotation) {
     ConstantValue constant =
         _backend.constants.getConstantValueForMetadata(annotation);
@@ -229,9 +293,8 @@
 
   _MetadataEntry _addGlobalMetadata(jsAst.Node node) {
     String nameToKey(jsAst.Name name) => "${name.key}";
-    String printed = jsAst.prettyPrint(node, _compiler,
-                                       renamerForNames: nameToKey)
-                          .getText();
+    String printed = jsAst.prettyPrint(
+        node, _compiler, renamerForNames: nameToKey);
     return _globalMetadataMap.putIfAbsent(printed, () {
       _BoundMetadataEntry result = new _BoundMetadataEntry(node);
       if (_compiler.hasIncrementalSupport) {
@@ -366,4 +429,4 @@
     node.accept(this);
     return _foundUnboundToken;
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index 61c1b08..9c48f4d 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -35,6 +35,7 @@
 
   JavaScriptBackend get backend => compiler.backend;
   TypeTestRegistry get typeTestRegistry => emitterTask.typeTestRegistry;
+  CoreClasses get coreClasses => compiler.coreClasses;
 
   Set<ClassElement> get checkedClasses =>
       typeTestRegistry.checkedClasses;
@@ -181,7 +182,7 @@
     }
 
     if (superclass != null &&
-        superclass != compiler.coreClasses.objectClass &&
+        superclass != coreClasses.objectClass &&
         !haveSameTypeVariables(cls, superclass)) {
       // We cannot inherit the generated substitutions, because the type
       // variable layout for this class is different.  Instead we generate
@@ -217,7 +218,7 @@
 
     // A class that defines a `call` method implicitly implements
     // [Function] and needs checks for all typedefs that are used in is-checks.
-    if (checkedClasses.contains(compiler.coreClasses.functionClass) ||
+    if (checkedClasses.contains(coreClasses.functionClass) ||
         checkedFunctionTypes.isNotEmpty) {
       Element call = cls.lookupLocalMember(Identifiers.call);
       if (call == null) {
@@ -228,8 +229,8 @@
         FunctionElement callFunction = call;
         // A superclass might already implement the Function interface. In such
         // a case, we can avoid emiting the is test here.
-        if (!cls.superclass.implementsFunction(compiler)) {
-          _generateInterfacesIsTests(compiler.coreClasses.functionClass,
+        if (!cls.superclass.implementsFunction(coreClasses)) {
+          _generateInterfacesIsTests(coreClasses.functionClass,
                                     generateIsTest,
                                     generateSubstitution,
                                     generated);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 9e81bca..65d0519 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -281,7 +281,7 @@
         isSplit ? buildDeferredInitializerGlobal() : new js.Block.empty(),
         code]);
 
-    mainOutput.addBuffer(js.prettyPrint(program, compiler,
+    mainOutput.addBuffer(js.createCodeBuffer(program, compiler,
         monitor: compiler.dumpInfoTask));
 
     if (shouldGenerateSourceMap) {
@@ -335,7 +335,7 @@
         buildDeferredInitializerGlobal(),
         js.js.statement('$deferredInitializersGlobal.current = #', code)]);
 
-    output.addBuffer(js.prettyPrint(program, compiler,
+    output.addBuffer(js.createCodeBuffer(program, compiler,
         monitor: compiler.dumpInfoTask));
 
     // Make a unique hash of the code (before the sourcemaps are added)
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 438dbe6..cd61a71 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -111,6 +111,9 @@
   static NativeBehavior get PURE => NativeBehavior._makePure();
   static NativeBehavior get PURE_ALLOCATION =>
       NativeBehavior._makePure(isAllocation: true);
+  static NativeBehavior get CHANGES_OTHER => NativeBehavior._makeChangesOther();
+  static NativeBehavior get DEPENDS_OTHER => NativeBehavior._makeDependsOther();
+
 
   String toString() {
     return 'NativeBehavior('
@@ -132,6 +135,18 @@
     return behavior;
   }
 
+  static NativeBehavior _makeChangesOther() {
+    // TODO(25544): Have a distinct effect instead of using static properties to
+    // model 'other' effects.
+    return _makePure()..sideEffects.setChangesStaticProperty();
+  }
+
+  static NativeBehavior _makeDependsOther() {
+    // TODO(25544): Have a distinct effect instead of using static properties to
+    // model 'other' effects.
+    return _makePure()..sideEffects.setDependsOnStaticPropertyStore();
+  }
+
   /// Processes the type specification string of a call to JS and stores the
   /// result in the [typesReturned] and [typesInstantiated]. It furthermore
   /// computes the side effects, and, if given, invokes [setSideEffects] with
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index a23a490..36feaa4 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -6,7 +6,8 @@
 
 import '../common.dart';
 import '../common/names.dart' show
-    Identifiers;
+    Identifiers,
+    Names;
 import '../common/resolution.dart' show
     Resolution;
 import '../compiler.dart' show
@@ -76,9 +77,12 @@
   /// Compute all members of [cls] and checked that [cls] implements its
   /// interface unless it is abstract or declares a `noSuchMethod` method.
   void computeAllMembers() {
-    Map<Name, Member> declaredMembers = computeMembers(null, null);
-    if (!cls.isAbstract &&
-        !declaredMembers.containsKey(const PublicName('noSuchMethod'))) {
+    computeMembers(null, null);
+    if (!cls.isAbstract) {
+      Member member = classMembers[Names.noSuchMethod_];
+      if (member != null && !member.declarer.isObject) {
+        return;
+      }
       // Check for unimplemented members on concrete classes that neither have
       // a `@proxy` annotation nor declare a `noSuchMethod` method.
       checkInterfaceImplementation();
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 540ba50..0c8e57c 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -4198,9 +4198,11 @@
       // If the isolate library is not used, we just generate code
       // to fetch the static state.
       String name = backend.namer.staticStateHolder;
-      push(new HForeignCode(js.js.parseForeignJS(name),
-                            backend.dynamicType,
-                            <HInstruction>[]));
+      push(new HForeignCode(
+          js.js.parseForeignJS(name),
+          backend.dynamicType,
+          <HInstruction>[],
+          nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
     } else {
       // Call a helper method from the isolate library. The isolate
       // library uses its own isolate structure, that encapsulates
@@ -4478,7 +4480,7 @@
         js.js.parseForeignJS("$isolateName = #"),
         backend.dynamicType,
         <HInstruction>[pop()],
-        nativeBehavior: native.NativeBehavior.PURE,
+        nativeBehavior: native.NativeBehavior.CHANGES_OTHER,
         effects: sideEffects));
   }
 
@@ -4488,7 +4490,8 @@
     }
     push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder),
                           backend.dynamicType,
-                          <HInstruction>[]));
+                          <HInstruction>[],
+                          nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
   }
 
   void handleForeignSend(ast.Send node, FunctionElement element) {
@@ -4837,8 +4840,7 @@
     ClassWorld classWorld = compiler.world;
     if (classWorld.isUsedAsMixin(cls)) return true;
 
-    Iterable<ClassElement> subclasses = compiler.world.strictSubclassesOf(cls);
-    return subclasses.any((ClassElement subclass) {
+    return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) {
       return !rti.isTrivialSubstitution(subclass, cls);
     });
   }
@@ -7147,21 +7149,64 @@
     FunctionSignature targetSignature = targetConstructor.functionSignature;
     FunctionSignature redirectingSignature =
         redirectingConstructor.functionSignature;
-    redirectingSignature.forEachRequiredParameter((ParameterElement element) {
-      inputs.add(localsHandler.readLocal(element));
-    });
+
+    List<Element> targetRequireds = targetSignature.requiredParameters;
+    List<Element> redirectingRequireds
+        = redirectingSignature.requiredParameters;
+
     List<Element> targetOptionals =
         targetSignature.orderedOptionalParameters;
     List<Element> redirectingOptionals =
         redirectingSignature.orderedOptionalParameters;
-    int i = 0;
-    for (; i < redirectingOptionals.length; i++) {
-      ParameterElement parameter = redirectingOptionals[i];
+
+    // TODO(25579): This code can do the wrong thing redirecting constructor and
+    // the target do not correspond. It is correct if there is no
+    // warning. Ideally the redirecting constructor and the target would be the
+    // same function.
+
+    void loadLocal(ParameterElement parameter) {
       inputs.add(localsHandler.readLocal(parameter));
     }
-    for (; i < targetOptionals.length; i++) {
-      inputs.add(handleConstantForOptionalParameter(targetOptionals[i]));
+    void loadPosition(int position, ParameterElement optionalParameter) {
+      if (position < redirectingRequireds.length) {
+        loadLocal(redirectingRequireds[position]);
+      } else if (position < redirectingSignature.parameterCount &&
+                 !redirectingSignature.optionalParametersAreNamed) {
+        loadLocal(redirectingOptionals[position - redirectingRequireds.length]);
+      } else if (optionalParameter != null) {
+        inputs.add(handleConstantForOptionalParameter(optionalParameter));
+      } else {
+        // Wrong.
+        inputs.add(graph.addConstantNull(compiler));
+      }
     }
+
+    int position = 0;
+
+    for (ParameterElement targetParameter in targetRequireds) {
+      loadPosition(position++, null);
+    }
+
+    if (targetOptionals.isNotEmpty) {
+      if (targetSignature.optionalParametersAreNamed) {
+        for (ParameterElement parameter in targetOptionals) {
+          ParameterElement redirectingParameter =
+              redirectingOptionals.firstWhere(
+                  (p) => p.name == parameter.name,
+                  orElse: () => null);
+          if (redirectingParameter == null) {
+            inputs.add(handleConstantForOptionalParameter(parameter));
+          } else {
+            inputs.add(localsHandler.readLocal(redirectingParameter));
+          }
+        }
+      } else {
+        for (ParameterElement parameter in targetOptionals) {
+          loadPosition(position++, parameter);
+        }
+      }
+    }
+
     ClassElement targetClass = targetConstructor.enclosingClass;
     if (backend.classNeedsRti(targetClass)) {
       ClassElement cls = redirectingConstructor.enclosingClass;
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 9cfb66b..8d5e08f 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -100,8 +100,7 @@
     // All intercepted classes extend `Interceptor`, so if the receiver can't be
     // a class extending `Interceptor` then it can be called directly.
     return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld)
-        .intersection(receiver.instructionType, classWorld)
-        .isEmpty;
+        .isDisjoint(receiver.instructionType, classWorld);
   }
 
   HInstruction tryComputeConstantInterceptor(
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index c98ceb1..a8d82ae 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -593,8 +593,7 @@
     // Intersection of int and double return conflicting, so
     // we don't optimize on numbers to preserve the runtime semantics.
     if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) {
-      TypeMask intersection = leftType.intersection(rightType, compiler.world);
-      if (intersection.isEmpty && !intersection.isNullable) {
+      if (leftType.isDisjoint(rightType, compiler.world)) {
         return makeFalse();
       }
     }
@@ -737,8 +736,7 @@
           : new TypeMask.nonNullSubtype(element, classWorld);
       if (expressionMask.union(typeMask, classWorld) == typeMask) {
         return graph.addConstantBool(true, compiler);
-      } else if (expressionMask.intersection(typeMask,
-                                             compiler.world).isEmpty) {
+      } else if (expressionMask.isDisjoint(typeMask, compiler.world)) {
         return graph.addConstantBool(false, compiler);
       }
     }
@@ -2154,10 +2152,8 @@
     if (nonEscapingReceivers.contains(second)) return false;
     // Typed arrays of different types might have a shared buffer.
     if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true;
-    TypeMask intersection = first.instructionType.intersection(
+    return !first.instructionType.isDisjoint(
         second.instructionType, compiler.world);
-    if (intersection.isEmpty) return false;
-    return true;
   }
 
   bool isFinal(Element element) {
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index a940e71..7cd149e 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -682,6 +682,9 @@
     } else {
       constantNum = constant;
     }
+    if (constantNum.isPositiveInfinity || constantNum.isNegativeInfinity) {
+      return info.newUnboundRange();
+    }
     if (constantNum.isMinusZero) constantNum = new IntConstantValue(0);
     Value value = info.newIntValue(constantNum.primitiveValue);
     return info.newNormalizedRange(value, value);
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index 3b3a74a..1ada85b 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -292,14 +292,6 @@
     return node;
   }
 
-  Expression visitLiteralMap(LiteralMap node) {
-    super.visitLiteralMap(node);
-    if (node.type != null) {
-      ++impureCounter; // Type casts can throw.
-    }
-    return node;
-  }
-
   Expression visitTypeOperator(TypeOperator node) {
     super.visitTypeOperator(node);
     if (!node.isTypeTest) {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index f23533c..1c92ff5 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -372,6 +372,7 @@
            exp is CreateInvocationMirror ||
            exp is CreateInstance ||
            exp is CreateBox ||
+           exp is TypeExpression ||
            exp is GetStatic && exp.element.isFunction ||
            exp is Interceptor ||
            exp is ApplyBuiltinOperator ||
@@ -579,13 +580,11 @@
   }
 
   Expression visitLogicalOperator(LogicalOperator node) {
-    node.left = visitExpression(node.left);
-
     // Impure expressions may not propagate across the branch.
     inEmptyEnvironment(() {
       node.right = visitExpression(node.right);
     });
-
+    node.left = visitExpression(node.left);
     return node;
   }
 
@@ -739,31 +738,32 @@
     return node;
   }
 
-  Expression visitLiteralMap(LiteralMap node) {
-    // Process arguments right-to-left, the opposite of evaluation order.
-    for (LiteralMapEntry entry in node.entries.reversed) {
-      entry.value = visitExpression(entry.value);
-      entry.key = visitExpression(entry.key);
-    }
-    return node;
-  }
-
   Expression visitTypeOperator(TypeOperator node) {
     _rewriteList(node.typeArguments);
     node.value = visitExpression(node.value);
     return node;
   }
 
-  bool sameVariable(Expression e1, Expression e2) {
-    return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable;
-  }
-
   bool isCompoundableBuiltin(Expression e) {
     return e is ApplyBuiltinOperator &&
-           e.arguments.length == 2 &&
+           e.arguments.length >= 2 &&
            isCompoundableOperator(e.operator);
   }
 
+  /// Converts a compoundable operator application into the right-hand side for
+  /// use in a compound assignment, discarding the left-hand value.
+  ///
+  /// For example, for `x + y + z` it returns `y + z`.
+  Expression contractCompoundableBuiltin(ApplyBuiltinOperator e) {
+    assert(isCompoundableBuiltin(e));
+    if (e.arguments.length > 2) {
+      assert(e.operator == BuiltinOperator.StringConcatenate);
+      return new ApplyBuiltinOperator(e.operator, e.arguments.skip(1).toList());
+    } else {
+      return e.arguments[1];
+    }
+  }
+
   void destroyVariableUse(VariableUse node) {
     --node.variable.readCount;
   }
@@ -774,13 +774,12 @@
     if (isCompoundableBuiltin(node.value)) {
       ApplyBuiltinOperator rhs = node.value;
       Expression left = rhs.arguments[0];
-      Expression right = rhs.arguments[1];
       if (left is GetField &&
           left.field == node.field &&
-          sameVariable(left.object, node.object)) {
-        destroyVariableUse(left.object);
+          samePrimary(left.object, node.object)) {
+        destroyPrimaryExpression(left.object);
         node.compound = rhs.operator;
-        node.value = right;
+        node.value = contractCompoundableBuiltin(rhs);
       }
     }
     node.object = visitExpression(node.object);
@@ -800,6 +799,16 @@
   Expression visitSetStatic(SetStatic node) {
     allowRhsPropagation.add(true);
     node.value = visitExpression(node.value);
+    if (isCompoundableBuiltin(node.value)) {
+      ApplyBuiltinOperator rhs = node.value;
+      Expression left = rhs.arguments[0];
+      if (left is GetStatic &&
+          left.element == node.element &&
+          !left.useLazyGetter) {
+        node.compound = rhs.operator;
+        node.value = contractCompoundableBuiltin(rhs);
+      }
+    }
     allowRhsPropagation.removeLast();
     return node;
   }
@@ -814,6 +823,9 @@
   }
 
   Expression visitCreateInstance(CreateInstance node) {
+    if (node.typeInformation != null) {
+      node.typeInformation = visitExpression(node.typeInformation);
+    }
     _rewriteList(node.arguments);
     return node;
   }
@@ -859,14 +871,13 @@
     if (isCompoundableBuiltin(node.value)) {
       ApplyBuiltinOperator rhs = node.value;
       Expression left = rhs.arguments[0];
-      Expression right = rhs.arguments[1];
       if (left is GetIndex &&
-          sameVariable(left.object, node.object) &&
-          sameVariable(left.index, node.index)) {
-        destroyVariableUse(left.object);
-        destroyVariableUse(left.index);
+          samePrimary(left.object, node.object) &&
+          samePrimary(left.index, node.index)) {
+        destroyPrimaryExpression(left.object);
+        destroyPrimaryExpression(left.index);
         node.compound = rhs.operator;
-        node.value = right;
+        node.value = contractCompoundableBuiltin(rhs);
       }
     }
     node.index = visitExpression(node.index);
@@ -1244,8 +1255,8 @@
 
   @override
   Statement visitYield(Yield node) {
-    node.input = visitExpression(node.input);
     node.next = visitStatement(node.next);
+    node.input = visitExpression(node.input);
     return node;
   }
 
@@ -1358,3 +1369,22 @@
     new VariableUseVisitor(callback).visitExpression(node);
   }
 }
+
+bool sameVariable(Expression e1, Expression e2) {
+  return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable;
+}
+
+/// True if [e1] and [e2] are primary expressions (expressions without
+/// subexpressions) with the same value.
+bool samePrimary(Expression e1, Expression e2) {
+  return sameVariable(e1, e2) || (e1 is This && e2 is This);
+}
+
+/// Decrement the reference count for [e] if it is a variable use.
+void destroyPrimaryExpression(Expression e) {
+  if (e is VariableUse) {
+    --e.variable.readCount;
+  } else {
+    assert(e is This);
+  }
+}
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
index fb31f02..bcc16ca 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
@@ -12,22 +12,19 @@
 /// This phase cleans up artifacts introduced by the translation through CPS,
 /// where each source variable is translated into several copies. The copies
 /// are merged again when they are not live simultaneously.
-class VariableMerger extends RecursiveVisitor implements Pass {
+class VariableMerger implements Pass {
   String get passName => 'Variable merger';
 
-  void rewrite(FunctionDefinition node) {
-    rewriteFunction(node);
-    visitStatement(node.body);
-  }
+  final bool minifying;
 
-  /// Rewrites the given function.
-  /// This is called for the outermost function and inner functions.
-  void rewriteFunction(FunctionDefinition node) {
-    BlockGraphBuilder builder = new BlockGraphBuilder();
-    builder.build(node);
+  VariableMerger({this.minifying: false});
+
+  void rewrite(FunctionDefinition node) {
+    BlockGraphBuilder builder = new BlockGraphBuilder()..build(node);
     _computeLiveness(builder.blocks);
-    Map<Variable, Variable> subst =
-        _computeRegisterAllocation(builder.blocks, node.parameters);
+    PriorityPairs priority = new PriorityPairs()..build(node);
+    Map<Variable, Variable> subst = _computeRegisterAllocation(
+        builder.blocks, node.parameters, priority, minifying: minifying);
     new SubstituteVariables(subst).apply(node);
   }
 }
@@ -248,6 +245,54 @@
   }
 }
 
+/// Collects prioritized variable pairs -- pairs that lead to significant code
+/// reduction if merged into one variable.
+///
+/// These arise from moving assigments `v1 = v2`, and compoundable assignments
+/// `v1 = v2 [+] E` where [+] is a compoundable operator.
+//
+// TODO(asgerf): We could have a more fine-grained priority level. All pairs
+//   are treated as equally important, but some pairs can eliminate more than
+//   one assignment.
+//   Also, some assignments are more important to remove than others, as they
+//   can block a later optimization, such rewriting a loop, or removing the
+//   'else' part of an 'if'.
+//
+class PriorityPairs extends RecursiveVisitor {
+  final Map<Variable, List<Variable>> _priority = <Variable, List<Variable>>{};
+
+  void build(FunctionDefinition node) {
+    visitStatement(node.body);
+  }
+
+  void _prioritize(Variable x, Variable y) {
+    _priority.putIfAbsent(x, () => new List<Variable>()).add(y);
+    _priority.putIfAbsent(y, () => new List<Variable>()).add(x);
+  }
+
+  visitAssign(Assign node) {
+    super.visitAssign(node);
+    Expression value = node.value;
+    if (value is VariableUse) {
+      _prioritize(node.variable, value.variable);
+    } else if (value is ApplyBuiltinOperator &&
+               isCompoundableOperator(value.operator) &&
+               value.arguments[0] is VariableUse) {
+      VariableUse use = value.arguments[0];
+      _prioritize(node.variable, use.variable);
+    }
+  }
+
+  /// Returns the other half of every priority pair containing [variable].
+  List<Variable> getPriorityPairsWith(Variable variable) {
+    return _priority[variable] ?? const <Variable>[];
+  }
+
+  bool hasPriorityPairs(Variable variable) {
+    return _priority.containsKey(variable);
+  }
+}
+
 /// Computes liveness information of the given control-flow graph.
 ///
 /// The results are stored in [Block.liveIn] and [Block.liveOut].
@@ -331,14 +376,6 @@
   }
 }
 
-/// For testing purposes, this flag can be passed to merge variables that
-/// originated from different source variables.
-///
-/// Correctness should not depend on the fact that we only merge variables
-/// originating from the same source variable. Setting this flag makes a bug
-/// more likely to provoke a test case failure.
-const bool NO_PRESERVE_VARS = const bool.fromEnvironment('NO_PRESERVE_VARS');
-
 /// Based on liveness information, computes a map of variable substitutions to
 /// merge variables.
 ///
@@ -348,23 +385,30 @@
 ///
 /// We then compute a graph coloring, where the color of a node denotes which
 /// variable it will be substituted by.
-///
-/// We never merge variables that originated from distinct source variables,
-/// so we build a separate register interference graph for each source variable.
 Map<Variable, Variable> _computeRegisterAllocation(List<Block> blocks,
-                                                   List<Variable> parameters) {
+                                                   List<Variable> parameters,
+                                                   PriorityPairs priority,
+                                                   {bool minifying}) {
   Map<Variable, Set<Variable>> interference = <Variable, Set<Variable>>{};
 
-  /// Group for the given variable. We attempt to merge variables in the same
-  /// group.
-  /// By default, variables are grouped based on their source variable name,
-  /// but this can be disabled for testing purposes.
-  String group(Variable variable) {
-    if (NO_PRESERVE_VARS) return '';
-    // Group variables based on the source variable's name, not its element,
-    // so if multiple locals are declared with the same name, they will
-    // map to the same (hoisted) variable in the output.
-    return variable.element == null ? '' : variable.element.name;
+  bool allowUnmotivatedMerge(Variable x, Variable y) {
+    if (minifying) return true;
+    // Do not allow merging temporaries with named variables if they are
+    // not connected by a phi.  That would leads to confusing mergings like:
+    //    var v0 = receiver.length;
+    //        ==>
+    //    receiver = receiver.length;
+    return x.element?.name == y.element?.name;
+  }
+
+  bool allowPhiMerge(Variable x, Variable y) {
+    if (minifying) return true;
+    // Temporaries may be merged with a named variable if this eliminates a phi.
+    // The presence of the phi implies that the two variables can contain the
+    // same value, so it is not that confusing that they get the same name.
+    return x.element == null ||
+           y.element == null ||
+           x.element.name == y.element.name;
   }
 
   Set<Variable> empty = new Set<Variable>();
@@ -372,12 +416,10 @@
   // At the assignment to a variable x, add an edge to every variable that is
   // live after the assignment (if it came from the same source variable).
   for (Block block in blocks) {
-    // Group the liveOut set by source variable.
-    Map<String, Set<Variable>> liveOut = <String, Set<Variable>>{};
+    // Track the live set while traversing the block.
+    Set<Variable> live = new Set<Variable>();
     for (Variable variable in block.liveOut) {
-      liveOut.putIfAbsent(
-          group(variable),
-          () => new Set<Variable>()).add(variable);
+      live.add(variable);
       interference.putIfAbsent(variable, () => new Set<Variable>());
     }
     // Get variables that are live at the catch block.
@@ -388,8 +430,6 @@
     for (VariableAccess access in block.accesses.reversed) {
       Variable variable = access.variable;
       interference.putIfAbsent(variable, () => new Set<Variable>());
-      Set<Variable> live =
-          liveOut.putIfAbsent(group(variable), () => new Set<Variable>());
       if (access.isRead) {
         live.add(variable);
       } else {
@@ -410,42 +450,89 @@
   List<Variable> variables = interference.keys.toList();
   variables.sort((x, y) => interference[y].length - interference[x].length);
 
-  Map<String, List<Variable>> registers = <String, List<Variable>>{};
+  List<Variable> registers = <Variable>[];
   Map<Variable, Variable> subst = <Variable, Variable>{};
 
-  // Parameters are special in that they must have a ParameterElement and
-  // cannot be merged with each other. Ensure that they are not substituted.
-  // Other variables can still be substituted by a parameter.
-  for (Variable parameter in parameters) {
-    if (parameter.isCaptured) continue;
-    subst[parameter] = parameter;
-    registers[group(parameter)] = <Variable>[parameter];
+  /// Called when [variable] has been assigned [target] as its register/color.
+  /// Will immediately try to satisfy its priority pairs by assigning the same
+  /// color the other half of each pair.
+  void searchPriorityPairs(Variable variable, Variable target) {
+    if (!priority.hasPriorityPairs(variable)) {
+      return; // Most variables (around 90%) do not have priority pairs.
+    }
+    List<Variable> worklist = <Variable>[variable];
+    while (worklist.isNotEmpty) {
+      Variable v1 = worklist.removeLast();
+      for (Variable v2 in priority.getPriorityPairsWith(v1)) {
+        // If v2 already has a color, we cannot change it.
+        if (subst.containsKey(v2)) continue;
+
+        // Do not merge differently named variables.
+        if (!allowPhiMerge(v1, v2)) continue;
+
+        // Ensure the graph coloring remains valid. If a neighbour of v2 already
+        // has the desired color, we cannot assign the same color to v2.
+        if (interference[v2].any((v3) => subst[v3] == target)) continue;
+
+        subst[v2] = target;
+        target.element ??= v2.element; // Preserve the name.
+        worklist.add(v2);
+      }
+    }
   }
 
+  void assignRegister(Variable variable, Variable registerRepresentative) {
+    subst[variable] = registerRepresentative;
+    // Ensure this register is never assigned to a variable with another name.
+    // This also ensures that named variables keep their name when merged
+    // with a temporary.
+    registerRepresentative.element ??= variable.element;
+    searchPriorityPairs(variable, registerRepresentative);
+  }
+
+  void assignNewRegister(Variable variable) {
+    registers.add(variable);
+    subst[variable] = variable;
+    searchPriorityPairs(variable, variable);
+  }
+
+  // Parameters cannot be merged with each other. Ensure that they are not
+  // substituted.  Other variables can still be substituted by a parameter.
+  for (Variable parameter in parameters) {
+    if (parameter.isCaptured) continue;
+    registers.add(parameter);
+    subst[parameter] = parameter;
+  }
+
+  // Try to merge parameters with locals to eliminate phis.
+  for (Variable parameter in parameters) {
+    searchPriorityPairs(parameter, parameter);
+  }
+
+  v1loop:
   for (Variable v1 in variables) {
-    // Parameters have already been assigned a substitute; skip those.
+    // Ignore if the variable has already been assigned a register.
     if (subst.containsKey(v1)) continue;
 
-    List<Variable> register = registers[group(v1)];
-
-    // Optimization: For the first variable in a group, allocate a new color
-    // without iterating over its interference edges.
-    if (register == null) {
-      registers[group(v1)] = <Variable>[v1];
-      subst[v1] = v1;
-      continue;
-    }
-
     // Optimization: If there are no interference edges for this variable,
-    // assign it the first color without copying the register list.
+    // find a color for it without copying the register list.
     Set<Variable> interferenceSet = interference[v1];
     if (interferenceSet.isEmpty) {
-      subst[v1] = register[0];
+      // Use the first register where naming constraints allow the merge.
+      for (Variable v2 in registers) {
+        if (allowUnmotivatedMerge(v1, v2)) {
+          assignRegister(v1, v2);
+          continue v1loop;
+        }
+      }
+      // No register allows merging with this one, create a new register.
+      assignNewRegister(v1);
       continue;
     }
 
     // Find an unused color.
-    Set<Variable> potential = new Set<Variable>.from(register);
+    Set<Variable> potential = new Set<Variable>.from(
+          registers.where((v2) => allowUnmotivatedMerge(v1, v2)));
     for (Variable v2 in interferenceSet) {
       Variable v2subst = subst[v2];
       if (v2subst != null) {
@@ -456,10 +543,9 @@
 
     if (potential.isEmpty) {
       // If no free color was found, add this variable as a new color.
-      register.add(v1);
-      subst[v1] = v1;
+      assignNewRegister(v1);
     } else {
-      subst[v1] = potential.first;
+      assignRegister(v1, potential.first);
     }
   }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index b846c87..15dc292 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -504,7 +504,7 @@
     return new CreateInstance(
         node.classElement,
         translateArguments(node.arguments),
-        translateArguments(node.typeInformation),
+        getVariableUseOrNull(node.typeInformation),
         node.sourceInformation);
   }
 
@@ -543,17 +543,6 @@
             translateArguments(node.values));
   }
 
-  Expression visitLiteralMap(cps_ir.LiteralMap node) {
-    return new LiteralMap(
-        node.dartType,
-        new List<LiteralMapEntry>.generate(node.entries.length, (int index) {
-          return new LiteralMapEntry(
-              getVariableUse(node.entries[index].key),
-              getVariableUse(node.entries[index].value));
-        })
-    );
-  }
-
   Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
     return new ReifyRuntimeType(
         getVariableUse(node.value), node.sourceInformation);
@@ -568,6 +557,7 @@
 
   Expression visitTypeExpression(cps_ir.TypeExpression node) {
     return new TypeExpression(
+        node.kind,
         node.dartType,
         node.arguments.map(getVariableUse).toList());
   }
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
index 19eeb05..2b4d301 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
@@ -13,6 +13,8 @@
 
 import '../cps_ir/builtin_operator.dart';
 export '../cps_ir/builtin_operator.dart';
+import '../cps_ir/cps_ir_nodes.dart' show TypeExpressionKind;
+export '../cps_ir/cps_ir_nodes.dart' show TypeExpressionKind;
 
 // These imports are only used for the JavaScript specific nodes.  If we want to
 // support more than one native backend, we should probably create better
@@ -114,7 +116,8 @@
     assert(host != null);
   }
 
-  String toString() => element == null ? 'Variable' : element.toString();
+  String toString() =>
+      element == null ? 'Variable.${hashCode}' : element.toString();
 }
 
 /// Read the value of a variable.
@@ -312,25 +315,6 @@
   }
 }
 
-class LiteralMapEntry {
-  Expression key;
-  Expression value;
-
-  LiteralMapEntry(this.key, this.value);
-}
-
-class LiteralMap extends Expression {
-  final InterfaceType type;
-  final List<LiteralMapEntry> entries;
-
-  LiteralMap(this.type, this.entries);
-
-  accept(ExpressionVisitor visitor) => visitor.visitLiteralMap(this);
-  accept1(ExpressionVisitor1 visitor, arg) {
-    return visitor.visitLiteralMap(this, arg);
-  }
-}
-
 /// Type test or type cast.
 ///
 /// Note that if this is a type test, then [type] cannot be `Object`, `dynamic`,
@@ -688,7 +672,7 @@
 class CreateInstance extends Expression {
   ClassElement classElement;
   List<Expression> arguments;
-  List<Expression> typeInformation;
+  Expression typeInformation;
   SourceInformation sourceInformation;
 
   CreateInstance(this.classElement, this.arguments,
@@ -760,8 +744,9 @@
   Element element;
   Expression value;
   SourceInformation sourceInformation;
+  BuiltinOperator compound;
 
-  SetStatic(this.element, this.value, this.sourceInformation);
+  SetStatic(this.element, this.value, this.sourceInformation, {this.compound});
 
   accept(ExpressionVisitor visitor) => visitor.visitSetStatic(this);
   accept1(ExpressionVisitor1 visitor, arg) => visitor.visitSetStatic(this, arg);
@@ -920,10 +905,11 @@
 /// are replaced by the values in [arguments].
 /// (See documentation on the TypeExpression CPS node for more details.)
 class TypeExpression extends Expression {
+  final TypeExpressionKind kind;
   final DartType dartType;
   final List<Expression> arguments;
 
-  TypeExpression(this.dartType, this.arguments);
+  TypeExpression(this.kind, this.dartType, this.arguments);
 
   accept(ExpressionVisitor visitor) {
     return visitor.visitTypeExpression(this);
@@ -999,7 +985,6 @@
   E visitLogicalOperator(LogicalOperator node);
   E visitNot(Not node);
   E visitLiteralList(LiteralList node);
-  E visitLiteralMap(LiteralMap node);
   E visitTypeOperator(TypeOperator node);
   E visitGetField(GetField node);
   E visitSetField(SetField node);
@@ -1037,7 +1022,6 @@
   E visitLogicalOperator(LogicalOperator node, A arg);
   E visitNot(Not node, A arg);
   E visitLiteralList(LiteralList node, A arg);
-  E visitLiteralMap(LiteralMap node, A arg);
   E visitTypeOperator(TypeOperator node, A arg);
   E visitGetField(GetField node, A arg);
   E visitSetField(SetField node, A arg);
@@ -1156,13 +1140,6 @@
     node.values.forEach(visitExpression);
   }
 
-  visitLiteralMap(LiteralMap node) {
-    node.entries.forEach((LiteralMapEntry entry) {
-      visitExpression(entry.key);
-      visitExpression(entry.value);
-    });
-  }
-
   visitTypeOperator(TypeOperator node) {
     visitExpression(node.value);
     node.typeArguments.forEach(visitExpression);
@@ -1243,7 +1220,7 @@
 
   visitCreateInstance(CreateInstance node) {
     node.arguments.forEach(visitExpression);
-    node.typeInformation.forEach(visitExpression);
+    if (node.typeInformation != null) visitExpression(node.typeInformation);
   }
 
   visitReifyRuntimeType(ReifyRuntimeType node) {
@@ -1390,14 +1367,6 @@
     return node;
   }
 
-  visitLiteralMap(LiteralMap node) {
-    node.entries.forEach((LiteralMapEntry entry) {
-      entry.key = visitExpression(entry.key);
-      entry.value = visitExpression(entry.value);
-    });
-    return node;
-  }
-
   visitTypeOperator(TypeOperator node) {
     node.value = visitExpression(node.value);
     _replaceExpressions(node.typeArguments);
@@ -1492,7 +1461,9 @@
 
   visitCreateInstance(CreateInstance node) {
     _replaceExpressions(node.arguments);
-    _replaceExpressions(node.typeInformation);
+    if (node.typeInformation != null) {
+      node.typeInformation = visitExpression(node.typeInformation);
+    }
     return node;
   }
 
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index 979647a..6d2ce7e 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -414,16 +414,6 @@
     return "list [$values]";
   }
 
-  String visitLiteralMap(LiteralMap node) {
-    List<String> entries = new List<String>();
-    node.entries.forEach((LiteralMapEntry entry) {
-      String key = visitExpression(entry.key);
-      String value = visitExpression(entry.value);
-      entries.add("$key: $value");
-    });
-    return "map [${entries.join(', ')}]";
-  }
-
   String visitConstant(Constant node) {
     return "${node.value.toStructuredString()}";
   }
@@ -533,7 +523,9 @@
 
   @override
   String visitTypeExpression(TypeExpression node) {
-    return node.dartType.toString();
+    String kind = '${node.kind}'.split('.').last;
+    String args = node.arguments.map(visitExpression).join(', ');
+    return 'TypeExpression($kind, ${node.dartType}, $args)';
   }
 
   @override
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index 1129465..e7ecab1 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -36,15 +36,15 @@
 
   @override
   TypeMask visitDouble(DoubleConstantValue constant, Compiler compiler) {
-    // We have to distinguish -0.0 from 0, but for all practical purposes
-    // -0.0 is an integer.
-    // TODO(17235): this kind of special casing should only happen in the
-    // backend.
-    if (constant.isMinusZero &&
-        compiler.backend.constantSystem.isInt(constant)) {
-      return compiler.typesTask.uint31Type;
+    // We have to recognize double constants that are 'is int'.
+    if (compiler.backend.constantSystem.isInt(constant)) {
+      if (constant.isMinusZero) {
+        return compiler.typesTask.uint31Type;
+      } else {
+        assert(constant.isPositiveInfinity || constant.isNegativeInfinity);
+        return compiler.typesTask.intType;
+      }
     }
-    assert(!compiler.backend.constantSystem.isInt(constant));
     return compiler.typesTask.doubleType;
   }
 
diff --git a/pkg/compiler/lib/src/types/flat_type_mask.dart b/pkg/compiler/lib/src/types/flat_type_mask.dart
index 6516d96..914e673 100644
--- a/pkg/compiler/lib/src/types/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/types/flat_type_mask.dart
@@ -358,6 +358,47 @@
     }
   }
 
+  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
+    if (other is! FlatTypeMask) return other.isDisjoint(this, classWorld);
+    FlatTypeMask flatOther = other;
+
+    if (isNullable && flatOther.isNullable) return false;
+    if (isEmpty || flatOther.isEmpty) return true;
+    if (base == flatOther.base) return false;
+    if (isExact && flatOther.isExact) return true;
+
+    if (isExact) return !flatOther.contains(base, classWorld);
+    if (flatOther.isExact) return !contains(flatOther.base, classWorld);
+
+    // Normalization guarantees that isExact === !isSubclass && !isSubtype.
+    // Both are subclass or subtype masks, so if there is a subclass
+    // relationship, they are not disjoint.
+    if (classWorld.isSubclassOf(flatOther.base, base)) return false;
+    if (classWorld.isSubclassOf(base, flatOther.base)) return false;
+
+    // Two different base classes have no common subclass unless one is a
+    // subclass of the other (checked above).
+    if (isSubclass && flatOther.isSubclass) return true;
+
+    return _isDisjointHelper(this, flatOther, classWorld);
+  }
+
+  static bool _isDisjointHelper(
+      FlatTypeMask a, FlatTypeMask b, ClassWorld classWorld) {
+    if (!a.isSubclass && b.isSubclass) {
+      return _isDisjointHelper(b, a, classWorld);
+    }
+    assert(a.isSubclass || a.isSubtype);
+    assert(b.isSubtype);
+    var elements = a.isSubclass
+      ? classWorld.strictSubclassesOf(a.base)
+      : classWorld.strictSubtypesOf(a.base);
+    for (var element in elements) {
+      if (classWorld.isSubtypeOf(element, b.base)) return false;
+    }
+    return true;
+  }
+
   TypeMask intersectionSame(FlatTypeMask other, ClassWorld classWorld) {
     assert(base == other.base);
     // The two masks share the base type, so we must chose the most
@@ -685,16 +726,7 @@
     if (xSubset == null) return null;
     Iterable<ClassElement> ySubset = containedSubset(y, classWorld);
     if (ySubset == null) return null;
-    Iterable<ClassElement> smallSet, largeSet;
-    if (xSubset.length <= ySubset.length) {
-      smallSet = xSubset;
-      largeSet = ySubset;
-    } else {
-      smallSet = ySubset;
-      largeSet = xSubset;
-    }
-    var result = smallSet.where((ClassElement each) => largeSet.contains(each));
-    return result.toSet();
+    return xSubset.toSet().intersection(ySubset.toSet());
   }
 
   static Iterable<ClassElement> containedSubset(FlatTypeMask x,
diff --git a/pkg/compiler/lib/src/types/forwarding_type_mask.dart b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
index ce29f50..a4400c6 100644
--- a/pkg/compiler/lib/src/types/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/types/forwarding_type_mask.dart
@@ -84,6 +84,10 @@
     return forwardTo.union(other, classWorld);
   }
 
+  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
+    return forwardTo.isDisjoint(other, classWorld);
+  }
+
   TypeMask intersection(TypeMask other, ClassWorld classWorld) {
     return forwardTo.intersection(other, classWorld);
   }
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index 3339738..736df0d 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -329,6 +329,10 @@
    */
   TypeMask union(TypeMask other, ClassWorld classWorld);
 
+
+  /// Returns whether the intersection of this and [other] is empty.
+  bool isDisjoint(TypeMask other, ClassWorld classWorld);
+
   /**
    * Returns a type mask representing the intersection of [this] and [other].
    */
diff --git a/pkg/compiler/lib/src/types/union_type_mask.dart b/pkg/compiler/lib/src/types/union_type_mask.dart
index 4a8397e..6166349 100644
--- a/pkg/compiler/lib/src/types/union_type_mask.dart
+++ b/pkg/compiler/lib/src/types/union_type_mask.dart
@@ -118,11 +118,11 @@
         // TODO(sigmund, johnniwinther): computing length here (and below) is
         // expensive. If we can't prevent `flatten` from being called a lot, it
         // might be worth caching results.
-        size = classWorld.strictSubclassesOf(candidate).length;
-        assert(size <= classWorld.strictSubtypesOf(candidate).length);
+        size = classWorld.strictSubclassCount(candidate);
+        assert(size <= classWorld.strictSubtypeCount(candidate));
       } else {
         kind = FlatTypeMask.SUBTYPE;
-        size = classWorld.strictSubtypesOf(candidate).length;
+        size = classWorld.strictSubtypeCount(candidate);
       }
       // Update the best candidate if the new one is better.
       if (bestElement == null || size < bestSize) {
@@ -152,12 +152,17 @@
   TypeMask intersection(var other, ClassWorld classWorld) {
     other = TypeMask.nonForwardingMask(other);
     if (!other.isUnion && disjointMasks.contains(other)) return other;
+    if (other.isUnion && this == other) return this;
 
     List<TypeMask> intersections = <TypeMask>[];
     for (TypeMask current in disjointMasks) {
       if (other.isUnion) {
-        for (FlatTypeMask flatOther in other.disjointMasks) {
-          intersections.add(current.intersection(flatOther, classWorld));
+        if (other.disjointMasks.contains(current)) {
+          intersections.add(current);
+        } else {
+          for (FlatTypeMask flatOther in other.disjointMasks) {
+            intersections.add(current.intersection(flatOther, classWorld));
+          }
         }
       } else {
         intersections.add(current.intersection(other, classWorld));
@@ -166,6 +171,13 @@
     return new TypeMask.unionOf(intersections, classWorld);
   }
 
+  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
+    for (var current in disjointMasks) {
+      if (!current.isDisjoint(other, classWorld)) return false;
+    }
+    return true;
+  }
+
   TypeMask nullable() {
     if (isNullable) return this;
     List<FlatTypeMask> newList = new List<FlatTypeMask>.from(disjointMasks);
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index d895de2..3790a03 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -6,6 +6,7 @@
 
 import 'dart:collection' show
     IterableBase;
+import '../common.dart';
 import '../elements/elements.dart' show
     ClassElement;
 import '../util/enumset.dart' show
@@ -92,12 +93,14 @@
     return mask;
   }
 
+  final ClassHierarchyNode parentNode;
   final ClassElement cls;
   final EnumSet<Instantiation> _mask =
       new EnumSet<Instantiation>.fromValues(
           const <Instantiation>[Instantiation.UNINSTANTIATED]);
 
   ClassElement _leastUpperInstantiatedSubclass;
+  int _instantiatedSubclassCount = 0;
 
   /// `true` if [cls] has been directly instantiated.
   ///
@@ -111,14 +114,23 @@
 
   void set isDirectlyInstantiated(bool value) {
     if (value != isDirectlyInstantiated) {
+      ClassHierarchyNode parent = parentNode;
       if (value) {
         _mask.remove(Instantiation.UNINSTANTIATED);
         _mask.add(Instantiation.DIRECTLY_INSTANTIATED);
+        while (parent != null) {
+          parent._updateInstantiatedSubclassCount(1);
+          parent = parent.parentNode;
+        }
       } else {
         _mask.remove(Instantiation.DIRECTLY_INSTANTIATED);
         if (_mask.isEmpty) {
           _mask.add(Instantiation.UNINSTANTIATED);
         }
+        while (parent != null) {
+          parent._updateInstantiatedSubclassCount(-1);
+          parent = parent.parentNode;
+        }
       }
     }
   }
@@ -131,12 +143,18 @@
   ///   class C extends B {}
   ///   main() => [new B(), new C()];
   ///
-  bool get isIndirectlyInstantiated =>
-      _mask.contains(Instantiation.INDIRECTLY_INSTANTIATED);
+  bool get isIndirectlyInstantiated => _instantiatedSubclassCount > 0;
 
-  void set isIndirectlyInstantiated(bool value) {
-    if (value != isIndirectlyInstantiated) {
-      if (value) {
+  /// The number of strict subclasses that are directly or indirectly
+  /// instantiated.
+  int get instantiatedSubclassCount => _instantiatedSubclassCount;
+
+  void _updateInstantiatedSubclassCount(int change) {
+    bool before = isIndirectlyInstantiated;
+    _instantiatedSubclassCount += change;
+    bool after = isIndirectlyInstantiated;
+    if (before != after) {
+      if (after) {
         _mask.remove(Instantiation.UNINSTANTIATED);
         _mask.add(Instantiation.INDIRECTLY_INSTANTIATED);
       } else {
@@ -151,7 +169,11 @@
   /// The nodes for the direct subclasses of [cls].
   Link<ClassHierarchyNode> _directSubclasses = const Link<ClassHierarchyNode>();
 
-  ClassHierarchyNode(this.cls);
+  ClassHierarchyNode(this.parentNode, this.cls) {
+    if (parentNode != null) {
+      parentNode.addDirectSubclass(this);
+    }
+  }
 
   /// Adds [subclass] as a direct subclass of [cls].
   void addDirectSubclass(ClassHierarchyNode subclass) {
@@ -177,24 +199,6 @@
 
   /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
   ///
-  /// The directly instantiated, indirectly instantiated and uninstantiated
-  /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
-  /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
-  /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
-  Iterable<ClassElement> subclasses(
-      {bool includeDirectlyInstantiated: true,
-       bool includeIndirectlyInstantiated: true,
-       bool includeUninstantiated: true,
-       bool strict: false}) {
-    EnumSet<Instantiation> mask = createMask(
-        includeDirectlyInstantiated: includeDirectlyInstantiated,
-        includeIndirectlyInstantiated:includeIndirectlyInstantiated,
-        includeUninstantiated: includeUninstantiated);
-    return subclassesByMask(mask, strict: strict);
-  }
-
-  /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
-  ///
   /// Subclasses are included if their instantiation properties intersect with
   /// their corresponding [Instantiation] values in [mask]. If [strict] is
   /// `true`, [cls] itself is _not_ returned.
@@ -205,6 +209,65 @@
         this, mask, includeRoot: !strict);
   }
 
+  /// Applies [predicate] to each subclass of [cls] matching the criteria
+  /// specified by [mask] and [strict]. If [predicate] returns `true` on a
+  /// class, visitation is stopped immediately and the function returns `true`.
+  ///
+  /// [predicate] is applied to subclasses if their instantiation properties
+  /// intersect with their corresponding [Instantiation] values in [mask]. If
+  /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
+  bool anySubclass(
+      bool predicate(ClassElement cls),
+      EnumSet<Instantiation> mask,
+      {bool strict: false}) {
+
+    ForEach wrapper(ClassElement cls) {
+      return predicate(cls) ? ForEach.STOP : ForEach.CONTINUE;
+    }
+    return forEachSubclass(wrapper, mask, strict: strict) == ForEach.STOP;
+  }
+
+  /// Applies [f] to each subclass of [cls] matching the criteria specified by
+  /// [mask] and [strict].
+  ///
+  /// [f] is a applied to subclasses if their instantiation properties intersect
+  /// with their corresponding [Instantiation] values in [mask]. If [strict] is
+  /// `true`, [f] is _not_ called on [cls] itself.
+  ///
+  /// The visitation of subclasses can be cut short by the return value of [f].
+  /// If [ForEach.STOP] is returned, no further classes are visited and the
+  /// function stops immediately. If [ForEach.SKIP_SUBCLASSES] is returned, the
+  /// subclasses of the last visited class are skipped, but visitation
+  /// continues. The return value of the function is either [ForEach.STOP], if
+  /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
+  /// the end.
+  ForEach forEachSubclass(
+      ForEachFunction f,
+      EnumSet<Instantiation> mask,
+      {bool strict: false}) {
+    ForEach forEach;
+    if (!strict && mask.intersects(_mask)) {
+      forEach = f(cls);
+    }
+    // Interpret `forEach == null` as `forEach == ForEach.CONTINUE`.
+    forEach ??= ForEach.CONTINUE;
+
+    if (forEach == ForEach.CONTINUE) {
+      if (mask.contains(Instantiation.UNINSTANTIATED) || isInstantiated) {
+        for (ClassHierarchyNode subclass in _directSubclasses) {
+          ForEach subForEach = subclass.forEachSubclass(f, mask);
+          if (subForEach == ForEach.STOP) {
+            return subForEach;
+          }
+        }
+      }
+    }
+    if (forEach == ForEach.STOP) {
+      return forEach;
+    }
+    return ForEach.CONTINUE;
+  }
+
   /// Returns the most specific subclass of [cls] (including [cls]) that is
   /// directly instantiated or a superclass of all directly instantiated
   /// subclasses. If [cls] is not instantiated, `null` is returned.
@@ -275,7 +338,8 @@
         if (instantiatedOnly && !child.isInstantiated) {
           continue;
         }
-        if (withRespectTo != null && !child.subclasses().any(isRelatedTo)) {
+        if (withRespectTo != null &&
+            !child.anySubclass(isRelatedTo, ClassHierarchyNode.ALL)) {
           continue;
         }
         if (needsComma) {
@@ -367,22 +431,31 @@
 
   ClassElement get cls => node.cls;
 
-  /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
-  ///
-  /// The directly instantiated, indirectly instantiated and uninstantiated
-  /// subclasses of [cls] are returned if [includeDirectlyInstantiated],
-  /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
-  /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
-  Iterable<ClassElement> subclasses(
-      {bool includeDirectlyInstantiated: true,
-       bool includeIndirectlyInstantiated: true,
-       bool includeUninstantiated: true,
-       bool strict: false}) {
-    EnumSet<Instantiation> mask = ClassHierarchyNode.createMask(
-        includeDirectlyInstantiated: includeDirectlyInstantiated,
-        includeIndirectlyInstantiated:includeIndirectlyInstantiated,
-        includeUninstantiated: includeUninstantiated);
-    return subclassesByMask(mask, strict: strict);
+  /// Returns the number of directly instantiated subtypes of [cls].
+  int get instantiatedSubtypeCount {
+    int count = node.instantiatedSubclassCount;
+    if (_directSubtypes != null) {
+      for (ClassHierarchyNode subtypeNode in _directSubtypes) {
+        if (subtypeNode.isDirectlyInstantiated) {
+          count++;
+        }
+        count += subtypeNode.instantiatedSubclassCount;
+      }
+    }
+    return count;
+  }
+
+  /// Returns `true` if all instantiated subtypes of [cls] are subclasses of
+  /// [cls].
+  bool get hasOnlyInstantiatedSubclasses {
+    if (_directSubtypes != null) {
+      for (ClassHierarchyNode subtypeNode in _directSubtypes) {
+        if (subtypeNode.isInstantiated) {
+          return false;
+        }
+      }
+    }
+    return true;
   }
 
   /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
@@ -414,7 +487,6 @@
     return subtypesByMask(mask, strict: strict);
   }
 
-
   /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls].
   ///
   /// Subtypes are included if their instantiation properties intersect with
@@ -434,6 +506,91 @@
         includeRoot: !strict);
   }
 
+  /// Applies [predicate] to each subclass of [cls] matching the criteria
+  /// specified by [mask] and [strict]. If [predicate] returns `true` on a
+  /// class, visitation is stopped immediately and the function returns `true`.
+  ///
+  /// [predicate] is applied to subclasses if their instantiation properties
+  /// intersect with their corresponding [Instantiation] values in [mask]. If
+  /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
+  bool anySubclass(
+      bool predicate(ClassElement cls),
+      EnumSet<Instantiation> mask,
+      {bool strict: false}) {
+    return node.anySubclass(predicate, mask, strict: strict);
+  }
+
+  /// Applies [f] to each subclass of [cls] matching the criteria specified by
+  /// [mask] and [strict].
+  ///
+  /// [f] is a applied to subclasses if their instantiation properties intersect
+  /// with their corresponding [Instantiation] values in [mask]. If [strict] is
+  /// `true`, [f] is _not_ called on [cls] itself.
+  ///
+  /// The visitation of subclasses can be cut short by the return value of [f].
+  /// If [ForEach.STOP] is returned, no further classes are visited and the
+  /// function stops immediately. If [ForEach.SKIP_SUBCLASSES] is returned, the
+  /// subclasses of the last visited class are skipped, but visitation
+  /// continues. The return value of the function is either [ForEach.STOP], if
+  /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
+  /// the end.
+  ForEach forEachSubclass(
+      ForEachFunction f,
+      EnumSet<Instantiation> mask,
+      {bool strict: false}) {
+    return node.forEachSubclass(f, mask, strict: strict);
+  }
+
+  /// Applies [predicate] to each subtype of [cls] matching the criteria
+  /// specified by [mask] and [strict]. If [predicate] returns `true` on a
+  /// class, visitation is stopped immediately and the function returns `true`.
+  ///
+  /// [predicate] is applied to subtypes if their instantiation properties
+  /// intersect with their corresponding [Instantiation] values in [mask]. If
+  /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
+  bool anySubtype(
+      bool predicate(ClassElement cls),
+      EnumSet<Instantiation> mask,
+      {bool strict: false}) {
+
+    ForEach wrapper(ClassElement cls) {
+      return predicate(cls) ? ForEach.STOP : ForEach.CONTINUE;
+    }
+    return forEachSubtype(wrapper, mask, strict: strict) == ForEach.STOP;
+  }
+
+  /// Applies [f] to each subtype of [cls] matching the criteria specified by
+  /// [mask] and [strict].
+  ///
+  /// [f] is a applied to subtypes if their instantiation properties intersect
+  /// with their corresponding [Instantiation] values in [mask]. If [strict] is
+  /// `true`, [f] is _not_ called on [cls] itself.
+  ///
+  /// The visitation of subtypes can be cut short by the return value of [f].
+  /// If [ForEach.STOP] is returned, no further classes are visited and the
+  /// function stops immediately. If [ForEach.SKIP_SUBCLASSES] is returned, the
+  /// subclasses of the last visited class are skipped, but visitation
+  /// continues. The return value of the function is either [ForEach.STOP], if
+  /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
+  /// the end.
+  ForEach forEachSubtype(
+      ForEachFunction f,
+      EnumSet<Instantiation> mask,
+      {bool strict: false}) {
+    ForEach forEach = node.forEachSubclass(f, mask, strict: strict);
+    forEach ??= ForEach.CONTINUE;
+    if (forEach == ForEach.CONTINUE && _directSubtypes != null) {
+      for (ClassHierarchyNode subclass in _directSubtypes) {
+        ForEach subForEach = subclass.forEachSubclass(f, mask);
+        if (subForEach == ForEach.STOP) {
+          return subForEach;
+        }
+      }
+    }
+    assert(forEach != ForEach.SKIP_SUBCLASSES);
+    return forEach;
+  }
+
   /// Adds [subtype] as a subtype of [cls].
   void addSubtype(ClassHierarchyNode subtype) {
     if (node.contains(subtype.cls)) {
@@ -695,3 +852,20 @@
     return false;
   }
 }
+
+/// Enum values returned from the [ForEachFunction] provided to the `forEachX`
+/// functions of [ClassHierarchyNode] and [ClassSet]. The value is used to
+/// control the continued iteration.
+enum ForEach {
+  /// Iteration continues.
+  CONTINUE,
+  /// Iteration stops immediately.
+  STOP,
+  /// Iteration skips the subclasses of the current class.
+  SKIP_SUBCLASSES,
+}
+
+/// Visiting function used for the `forEachX` functions of [ClassHierarchyNode]
+/// and [ClassSet]. The return value controls the continued iteration. If `null`
+/// is returned, iteration continues to the end.
+typedef ForEach ForEachFunction(ClassElement cls);
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 30b2081..da08fb6 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -93,6 +93,18 @@
   /// including [cls] itself.
   Iterable<ClassElement> strictSubclassesOf(ClassElement cls);
 
+  /// Returns the number of live classes that extend [cls] _not_
+  /// including [cls] itself.
+  int strictSubclassCount(ClassElement cls);
+
+  /// Applies [f] to each live class that extend [cls] _not_ including [cls]
+  /// itself.
+  void forEachStrictSubclassOf(ClassElement cls, ForEach f(ClassElement cls));
+
+  /// Returns `true` if [predicate] applies to any live class that extend [cls]
+  /// _not_ including [cls] itself.
+  bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls));
+
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// possibly including [cls] itself, if it is live.
   Iterable<ClassElement> subtypesOf(ClassElement cls);
@@ -101,6 +113,18 @@
   /// including [cls] if it is live.
   Iterable<ClassElement> strictSubtypesOf(ClassElement cls);
 
+  /// Returns the number of live classes that implement [cls] _not_
+  /// including [cls] itself.
+  int strictSubtypeCount(ClassElement cls);
+
+  /// Applies [f] to each live class that implements [cls] _not_ including [cls]
+  /// itself.
+  void forEachStrictSubtypeOf(ClassElement cls, ForEach f(ClassElement cls));
+
+  /// Returns `true` if [predicate] applies to any live class that implements
+  /// [cls] _not_ including [cls] itself.
+  bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls));
+
   /// Returns `true` if [a] and [b] have any known common subtypes.
   bool haveAnyCommonSubtypes(ClassElement a, ClassElement b);
 
@@ -248,6 +272,36 @@
         ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true);
   }
 
+  /// Returns the number of live classes that extend [cls] _not_
+  /// including [cls] itself.
+  int strictSubclassCount(ClassElement cls) {
+    ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
+    if (subclasses == null) return 0;
+    return subclasses.instantiatedSubclassCount;
+  }
+
+  /// Applies [f] to each live class that extend [cls] _not_ including [cls]
+  /// itself.
+  void forEachStrictSubclassOf(ClassElement cls, ForEach f(ClassElement cls)) {
+    ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
+    if (subclasses == null) return;
+    subclasses.forEachSubclass(
+        f,
+        ClassHierarchyNode.DIRECTLY_INSTANTIATED,
+        strict: true);
+  }
+
+  /// Returns `true` if [predicate] applies to any live class that extend [cls]
+  /// _not_ including [cls] itself.
+  bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) {
+    ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
+    if (subclasses == null) return false;
+    return subclasses.anySubclass(
+        predicate,
+        ClassHierarchyNode.DIRECTLY_INSTANTIATED,
+        strict: true);
+  }
+
   /// Returns an iterable over the directly instantiated that implement [cls]
   /// possibly including [cls] itself, if it is live.
   Iterable<ClassElement> subtypesOf(ClassElement cls) {
@@ -272,6 +326,36 @@
     }
   }
 
+  /// Returns the number of live classes that implement [cls] _not_
+  /// including [cls] itself.
+  int strictSubtypeCount(ClassElement cls) {
+    ClassSet classSet = _classSets[cls.declaration];
+    if (classSet == null) return 0;
+    return classSet.instantiatedSubtypeCount;
+  }
+
+  /// Applies [f] to each live class that implements [cls] _not_ including [cls]
+  /// itself.
+  void forEachStrictSubtypeOf(ClassElement cls, ForEach f(ClassElement cls)) {
+    ClassSet classSet = _classSets[cls.declaration];
+    if (classSet == null) return;
+    classSet.forEachSubtype(
+        f,
+        ClassHierarchyNode.DIRECTLY_INSTANTIATED,
+        strict: true);
+  }
+
+  /// Returns `true` if [predicate] applies to any live class that extend [cls]
+  /// _not_ including [cls] itself.
+  bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) {
+    ClassSet classSet = _classSets[cls.declaration];
+    if (classSet == null) return false;
+    return classSet.anySubtype(
+        predicate,
+        ClassHierarchyNode.DIRECTLY_INSTANTIATED,
+        strict: true);
+  }
+
   /// Returns `true` if [a] and [b] have any known common subtypes.
   bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) {
     ClassSet classSetA = _classSets[a.declaration];
@@ -298,7 +382,7 @@
   /// Returns `true` if any directly instantiated class other than [cls]
   /// implements [cls].
   bool hasAnyStrictSubtype(ClassElement cls) {
-    return !strictSubtypesOf(cls).isEmpty;
+    return strictSubtypeCount(cls) > 0;
   }
 
   /// Returns `true` if all directly instantiated classes that implement [cls]
@@ -306,10 +390,12 @@
   bool hasOnlySubclasses(ClassElement cls) {
     // TODO(johnniwinther): move this to ClassSet?
     if (cls == objectClass) return true;
-    Iterable<ClassElement> subtypes = strictSubtypesOf(cls);
-    if (subtypes == null) return true;
-    Iterable<ClassElement> subclasses = strictSubclassesOf(cls);
-    return subclasses != null && (subclasses.length == subtypes.length);
+    ClassSet classSet = _classSets[cls.declaration];
+    if (classSet == null) {
+      // Vacuously true.
+      return true;
+    }
+    return classSet.hasOnlyInstantiatedSubclasses;
   }
 
   @override
@@ -501,11 +587,11 @@
   ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
     cls = cls.declaration;
     return _classHierarchyNodes.putIfAbsent(cls, () {
-      ClassHierarchyNode node = new ClassHierarchyNode(cls);
+      ClassHierarchyNode parentNode;
       if (cls.superclass != null) {
-        _ensureClassHierarchyNode(cls.superclass).addDirectSubclass(node);
+        parentNode = _ensureClassHierarchyNode(cls.superclass);
       }
-      return node;
+      return new ClassHierarchyNode(parentNode, cls);
     });
   }
 
@@ -534,31 +620,28 @@
     });
   }
 
-  void _updateClassHierarchyNodeForClass(
-      ClassElement cls,
-      {bool directlyInstantiated: false,
-       bool indirectlyInstantiated: false}) {
-    ClassHierarchyNode node = getClassHierarchyNode(cls);
-    bool changed = false;
-    if (directlyInstantiated && !node.isDirectlyInstantiated) {
-      node.isDirectlyInstantiated = true;
-      changed = true;
-    }
-    if (indirectlyInstantiated && !node.isIndirectlyInstantiated) {
-      node.isIndirectlyInstantiated = true;
-      changed = true;
-    }
-    if (changed && cls.superclass != null) {
-      _updateClassHierarchyNodeForClass(
-          cls.superclass, indirectlyInstantiated: true);
-    }
+  void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
     // Ensure that classes implicitly implementing `Function` are in its
     // subtype set.
+    ClassElement cls = node.cls;
     if (cls != coreClasses.functionClass &&
-        cls.implementsFunction(compiler)) {
+        cls.implementsFunction(coreClasses)) {
       ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass);
       subtypeSet.addSubtype(node);
     }
+    if (!node.isInstantiated && node.parentNode != null) {
+      _updateSuperClassHierarchyNodeForClass(node.parentNode);
+    }
+  }
+
+  void _updateClassHierarchyNodeForClass(
+      ClassElement cls,
+      {bool directlyInstantiated: false}) {
+    ClassHierarchyNode node = getClassHierarchyNode(cls);
+    _updateSuperClassHierarchyNodeForClass(node);
+    if (directlyInstantiated) {
+      node.isDirectlyInstantiated = true;
+    }
   }
 
   void populate() {
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index 3b7e3ea..922f69a 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -13,12 +13,9 @@
     path: ../../sdk/lib/_internal/js_runtime
   sdk_library_metadata:
     path: ../../sdk/lib/_internal/sdk_library_metadata
-  dart2js_info:
-    path: ../../../../dart2js_info
+  dart2js_info: ^0.2.4
   lookup_map:
     path: ../lookup_map
-  dart_messages:
-    path: ../dart_messages
 
 # Uncomment if running gclient, so you can depend directly on the downloaded
 # versions of dart2js's transitive dependencies:
diff --git a/pkg/dart_messages/bin/json_converter.dart b/pkg/dart_messages/bin/json_converter.dart
deleted file mode 100644
index 8d9b8ca..0000000
--- a/pkg/dart_messages/bin/json_converter.dart
+++ /dev/null
@@ -1,20 +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.
-
-import 'dart:convert';
-import 'dart:io';
-
-import '../lib/shared_messages.dart' as shared_messages;
-
-/// Translates the shared messages in `../lib/shared_messages` to JSON and
-/// emits it into `../lib/shared_messages.json`.
-void main() {
-  var input = shared_messages.MESSAGES;
-  var outPath =
-      Platform.script.resolve('../lib/shared_messages.json').toFilePath();
-  print("Input: ${input.length} entries");
-  print("Output: $outPath");
-  new File(outPath).writeAsStringSync(JSON.encode(shared_messages.MESSAGES));
-  print("Done");
-}
diff --git a/pkg/dart_messages/bin/message_id.dart b/pkg/dart_messages/bin/message_id.dart
index 2d7ed53..f94b384 100644
--- a/pkg/dart_messages/bin/message_id.dart
+++ b/pkg/dart_messages/bin/message_id.dart
@@ -23,7 +23,7 @@
 /// Computes a random message ID that hasn't been used before.
 void main() {
   var usedIds =
-      shared_messages.MESSAGES.values.map((entry) => entry['id']).toSet();
+      shared_messages.MESSAGES.values.map((entry) => entry.id).toSet();
 
   print("${usedIds.length} existing ids");
 
diff --git a/pkg/dart_messages/bin/publish.dart b/pkg/dart_messages/bin/publish.dart
new file mode 100644
index 0000000..c7b9c11
--- /dev/null
+++ b/pkg/dart_messages/bin/publish.dart
@@ -0,0 +1,224 @@
+// 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.
+
+import 'dart:convert';
+import 'dart:io';
+
+import '../lib/shared_messages.dart';
+
+const String jsonPath = '../lib/generated/shared_messages.json';
+const String dart2jsPath =
+    '../../compiler/lib/src/diagnostics/generated/shared_messages.dart';
+const String analyzerPath =
+    '../../analyzer/lib/src/generated/generated/shared_messages.dart';
+
+final String dontEditWarning = """
+/*
+DON'T EDIT. GENERATED. DON'T EDIT.
+This file has been generated by 'publish.dart' in the dart_messages package.
+
+Messages are maintained in `lib/shared_messages.dart` of that same package.
+After any change to that file, run `bin/publish.dart` to generate a new version
+of the json, dart2js and analyzer representations.
+*/""";
+
+const String copyrightHeader = '''
+// 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.''';
+
+void markAsReadonly(String path) {
+  // TODO(15078): mark as read-only. Currently not possible:
+  // http://dartbug.com/15078.
+}
+
+void emitJson() {
+  var input = MESSAGES;
+  var outPath = Platform.script.resolve(jsonPath).toFilePath();
+  print("Emitting JSON:");
+  print("  Input: ${input.length} entries");
+  print("  Output: $outPath");
+  new File(outPath).writeAsStringSync(messagesAsJson);
+  print("Emitting JSON done.");
+}
+
+/// Escapes the given string [str].
+///
+/// The parameter [str] may be `null` in which case the result is "null".
+String escapeString(String str) {
+  return JSON.encode(str);
+}
+
+/// Emits the messages in dart2js format.
+///
+/// The dart2js-format consists of two entities:
+///   1. the `MessageKind` enum, and
+///   2. the MessageKind-to-Template map `TEMPLATES`.
+///
+/// The template is an instance of MessageTemplate:
+///
+///     const MessageTemplate(
+///        this.kind,
+///        this.template,
+///        {this.howToFix,
+///         this.examples,
+///         this.options: const <String>[]});
+///
+/// A sample output thus looks as follows:
+///
+///     enum MessageKind {
+///       EXAMPLE_MESSAGE,
+///     }
+///
+///     const Map<MessageKind, MessageTemplate> {
+///       EXAMPLE_MESSAGE: const MessageTemplate(
+///         EXAMPLE_MESSAGE,
+///         "Don't use #foo with #bar",
+///         howToFix: "Just don't do it",
+///         options: const ['--some-flag']),
+///         examples: const ['''
+///     some example with bad code;'''],
+///     };
+void emitDart2js() {
+  var input = MESSAGES;
+  var outPath = Platform.script.resolve(dart2jsPath).toFilePath();
+  print("Emitting dart2js:");
+  print("  Input: ${input.length} entries");
+  print("  Output: $outPath");
+
+  var enumIds = input.keys.toList();
+
+  StringBuffer out = new StringBuffer();
+  out.writeln(copyrightHeader);
+  out.writeln(dontEditWarning);
+  out.writeln("import '../messages.dart' show MessageTemplate;");
+  out.writeln();
+  out.write(("enum SharedMessageKind {\n  "));
+  // We generate on one line on purpose, so that users are less likely to
+  // modify the generated file.
+  out.writeln(enumIds.join(",\n  "));
+  out.writeln("}");
+  out.writeln();
+  out.writeln("const Map<SharedMessageKind, MessageTemplate> TEMPLATES = "
+      "const <SharedMessageKind, MessageTemplate>{ ");
+  input.forEach((name, message) {
+    out.writeln("  SharedMessageKind.$name: const MessageTemplate(");
+    // TODO(floitsch): include id.
+    out.writeln("    SharedMessageKind.$name,");
+    out.write("    ");
+    out.write(escapeString(message.template));
+    if (message.howToFix != null) {
+      out.write(",\n    howToFix: ${escapeString(message.howToFix)}");
+    }
+    if (message.options != null) {
+      out.write(",\n    options: const [");
+      out.write(message.options.map(escapeString).join(","));
+      out.writeln("]");
+    }
+    if (message.examples != null) {
+      out.writeln(",\n    examples: const [");
+      for (var example in message.examples) {
+        if (example is String) {
+          out.writeln("      r'''");
+          out.write(example);
+          out.write("'''");
+        } else if (example is Map) {
+          out.writeln("      const {");
+          example.forEach((String fileName, String content) {
+            out.writeln("      '$fileName': r'''");
+            out.write(content);
+            out.writeln("''',");
+          });
+          out.write("      }");
+        }
+        out.writeln(",");
+      }
+      out.writeln("    ]");
+    }
+    out.writeln("  ),  // Generated. Don't edit.");
+  });
+  out.writeln("};");
+
+  new File(outPath).writeAsStringSync(out.toString());
+  print("Emitting dart2js done.");
+}
+
+String convertToAnalyzerTemplate(String template, holeOrder) {
+  var holeMap;
+  if (holeOrder != null) {
+    holeMap = {};
+    for (int i = 0; i < holeOrder.length; i++) {
+      holeMap[holeOrder[i]] = i;
+    }
+  }
+  int seenHoles = 0;
+  return template.replaceAllMapped(new RegExp(r"#\w+"), (Match match) {
+    if (holeMap != null) {
+      String holeName = match[0].substring(1);
+      int index = holeMap[holeName];
+      if (index == null) {
+        throw "Couldn't find hole-position for $holeName $holeMap";
+      }
+      return "{$index}";
+    } else {
+      return "{${seenHoles++}}";
+    }
+  });
+}
+
+/// Emits the messages in analyzer format.
+///
+/// Messages are encoded as instances of `ErrorCode` classes where the
+/// corresponding class is given by the `category` field of the Message.
+///
+/// All instances are stored as top-level const variables.
+///
+/// A sample output looks as follows:
+///
+///     const FooCategoryErrorCode EXAMPLE_MESSAGE = const FooCategoryErrorCode(
+///         "EXAMPLE_MESSAGE",
+///         "Don't use {0} with {1}",
+///         "Just don't do it");
+void emitAnalyzer() {
+  var input = MESSAGES;
+  var outPath = Platform.script.resolve(analyzerPath).toFilePath();
+  print("Emitting analyzer:");
+  print("  Input: ${input.length} entries");
+  print("  Output: $outPath");
+
+  StringBuffer out = new StringBuffer();
+  out.writeln(copyrightHeader);
+  out.writeln(dontEditWarning);
+  out.writeln("import 'package:analyzer/src/generated/error.dart';");
+  out.writeln();
+  input.forEach((name, message) {
+    Category category = message.category;
+    String className = category.name + "Code";
+    out.writeln("const $className $name = const $className(");
+    out.writeln("    '$name',");
+
+    String template = message.template;
+    List holeOrder = message.templateHoleOrder;
+    String analyzerTemplate = convertToAnalyzerTemplate(template, holeOrder);
+    out.write("    ");
+    out.write(escapeString(analyzerTemplate));
+    out.write(",\n    ");
+    out.write(escapeString(message.howToFix));
+    out.writeln(");  // Generated. Don't edit.");
+  });
+
+  new File(outPath).writeAsStringSync(out.toString());
+  print("Emitting analyzer done.");
+}
+
+/// Translates the shared messages in `../lib/shared_messages.dart` to JSON,
+/// dart2js, and analyzer formats.
+///
+/// Emits the json-output to [jsonPath], the dart2js-output to [dart2jsPath],
+/// and the analyzer-output to [analyzerPath].
+void main() {
+  emitJson();
+  emitDart2js();
+  emitAnalyzer();
+}
diff --git a/pkg/dart_messages/lib/generated/shared_messages.json b/pkg/dart_messages/lib/generated/shared_messages.json
new file mode 100644
index 0000000..606bc60
--- /dev/null
+++ b/pkg/dart_messages/lib/generated/shared_messages.json
@@ -0,0 +1 @@
+{"exampleMessage":{"id":"use an Id generated by bin/message_id.dart","category":"AnalysisOptionsError","template":"#use #named #arguments","howToFix":"an explanation on how to fix things"}}
\ 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 bd51f58..896f52a 100644
--- a/pkg/dart_messages/lib/shared_messages.dart
+++ b/pkg/dart_messages/lib/shared_messages.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // An update to this file must be followed by regenerating the corresponding
-// json file. Use `json_converter.dart` in the bin directory.
+// json, dart2js and analyzer file. Use `publish.dart` in the bin directory.
 //
 // Every message in this file must have an id. Use `message_id.dart` in the
 // bin directory to generate a fresh one.
@@ -58,5 +58,78 @@
 // 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we
 // combine the first two in [template] and the last in [howToFix].
 
-final Map<String, Map> MESSAGES = {
+import 'dart:convert';
+
+/// Encodes the category of the message.
+///
+/// This is currently only used in the analyzer.
+// TODO(floitsch): encode severity and type in the category, so we can generate
+// the corresponding ErrorCode subclasses.
+class Category {
+  static final analysisOptionsError = new Category("AnalysisOptionsError");
+
+  static final analysisOptionsWarning = new Category("AnalysisOptionsWarning");
+
+  static final checkedModeCompileTimeError = new Category(
+      "CheckedModeCompileTimeError");
+
+  final String name;
+
+  Category(this.name);
+}
+
+
+class Message {
+  final String id;
+  final Category category;
+  final String template;
+  // The analyzer fills holes positionally (and not named). The following field
+  // overrides the order of the holes.
+  // For example the template "The argument #field in #cls is bad", could have
+  // the order `["cls", "field"]', which means that the analyzer would first
+  // provide the class `cls` and then only `field`.
+  // This list is generally `null`, but when it is provided it must contain all
+  // holes.
+  final List templateHoleOrder;
+  final String howToFix;
+  final List<String> options;
+  final List examples;
+
+  Message({this.id, this.category, this.template, this.templateHoleOrder,
+      this.howToFix, this.options, this.examples});
+}
+
+String get messagesAsJson {
+  var jsonified = {};
+  MESSAGES.forEach((String name, Message message) {
+    jsonified[name] =  {
+      'id': message.id,
+      'category': message.category.name,
+      'template': message.template,
+      'howToFix': message.howToFix
+    };
+  });
+  return JSON.encode(jsonified);
+}
+
+final Map<String, Message> MESSAGES = {
+  'exampleMessage': new Message(
+      id: 'use an Id generated by bin/message_id.dart',
+      category: Category.analysisOptionsError,
+      template: "#use #named #arguments",
+      templateHoleOrder: ["arguments", "named", "use"],
+      howToFix: "an explanation on how to fix things",
+      examples: [r'''
+      Some multiline example;
+      That generates the bug.''',
+      {
+      'fileA.dart': '''
+        or a map from file to content.
+        again multiline''',
+      'fileB.dart': '''
+        with possibly multiple files.
+        muliline too'''
+      }
+    ]
+  ),
 };
diff --git a/pkg/dart_messages/lib/shared_messages.json b/pkg/dart_messages/lib/shared_messages.json
deleted file mode 100644
index 9e26dfe..0000000
--- a/pkg/dart_messages/lib/shared_messages.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
\ No newline at end of file
diff --git a/pkg/dart_messages/test/dart_messages_test.dart b/pkg/dart_messages/test/dart_messages_test.dart
index 3983773..b0ef4a5 100644
--- a/pkg/dart_messages/test/dart_messages_test.dart
+++ b/pkg/dart_messages/test/dart_messages_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:convert';
 import 'dart:io';
 
 import '../lib/shared_messages.dart';
@@ -12,14 +11,14 @@
   if (packageRoot == null || packageRoot == "") {
     throw new UnsupportedError("This test requires a package root.");
   }
-  var jsonUri =
-      Uri.parse(packageRoot).resolve('dart_messages/shared_messages.json');
+  var jsonUri = Uri.parse(packageRoot).resolve(
+      'dart_messages/generated/shared_messages.json');
   var jsonPath = jsonUri.toFilePath();
   var content = new File(jsonPath).readAsStringSync();
-  if (JSON.encode(MESSAGES) != content) {
+  if (messagesAsJson != content) {
     print("The content of the Dart messages and the corresponding JSON file");
     print("is not the same.");
-    print("Please run bin/json_converter to update the JSON file.");
+    print("Please run bin/publish.dart to update the JSON file.");
     throw "Content is not the same";
   }
 }
@@ -27,7 +26,7 @@
 void testIdsAreUnique() {
   var usedIds = new Set();
   for (var entry in MESSAGES.values) {
-    var id = entry['id'];
+    var id = entry.id;
     if (!usedIds.add(id)) {
       throw "Id appears twice: $id";
     }
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index b6d11aa..07a20f1 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -195,7 +195,9 @@
 
 /// This tag interface has no behaviour but must be implemented by any class
 /// that is to be stored on a [Node] as source information.
-abstract class JavaScriptNodeSourceInformation {}
+abstract class JavaScriptNodeSourceInformation {
+  const JavaScriptNodeSourceInformation();
+}
 
 abstract class Node {
   JavaScriptNodeSourceInformation get sourceInformation => _sourceInformation;
@@ -1075,7 +1077,7 @@
   LiteralNumber(this.value);
 
   int get precedenceLevel => value.startsWith('-') ? UNARY : PRIMARY;
-  
+
   accept(NodeVisitor visitor) => visitor.visitLiteralNumber(this);
   LiteralNumber _clone() => new LiteralNumber(value);
 }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 8f29f55..4f93259 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -26,6 +26,7 @@
 analysis_server/test/analysis/get_errors_test: Skip # runtime error, Issue 22180
 analysis_server/test/integration/analysis/analysis_options_test: RuntimeError # Issue 24796
 analyzer/test/generated/all_the_rest_test: Fail # Issue 21772
+analyzer_cli/test/driver_test: Fail # Issue 25471
 
 [ $compiler == dart2js ]
 analyzer_cli/test/*: SkipByDesign # Only meant to run on vm
@@ -44,11 +45,15 @@
 analysis_server/test/services/index/store/codec_test: Pass, Slow
 analysis_server/test/socket_server_test: Pass, Slow # Issue 19756, 21628
 analyzer/test/dart/element/element_test: Pass, Slow # Issue 24914
+analyzer/test/dart/ast/ast_test: Pass, Slow # Issue 19756, 21628
+analyzer/test/dart/ast/utilities_test: Pass, Slow # Issue 19756, 21628
+analyzer/test/dart/ast/visitor_test: Pass, Slow # Issue 19756, 21628
 analyzer/test/enum_test: Slow, Pass, Fail # Issue 21323
 analyzer/test/generated/all_the_rest_test: Pass, Slow # Issue 21628
 analyzer/test/generated/ast_test: Pass, Slow # Issue 21628
 analyzer/test/generated/compile_time_error_code_test: Pass, Slow
 analyzer/test/generated/compile_time_error_code_test: Pass, Slow # Issue 21628
+analyzer/test/generated/constant_test.dart: Pass, Slow # Issue 24914
 analyzer/test/generated/declaration_resolver_test: Pass, Slow # Issue 24914
 analyzer/test/generated/element_test: Pass, Slow # Issue 21628
 analyzer/test/generated/engine_test: SkipSlow
@@ -66,9 +71,13 @@
 analyzer/test/src/context/cache_test: Pass, Slow # Issue 21628
 analyzer/test/src/context/context_test: Pass, Timeout # dartbug.com/23658
 analyzer/test/src/dart/element/element_test: Pass, Slow # Issue 24914
+analyzer/test/src/summary/prelinker_test: Pass, Slow # Issue 24914
+analyzer/test/src/summary/resynthesize_strong_test: Pass, Slow
 analyzer/test/src/summary/resynthesize_test: Pass, Slow
 analyzer/test/src/summary/summary_sdk_test: Pass, Slow # Issue 24914
-analyzer/test/src/summary/summary_test: Pass, Slow # Issue 24914
+analyzer/test/src/summary/summarize_ast_test: Pass, Slow # Issue 24914
+analyzer/test/src/summary/summarize_elements_strong_test: Pass, Slow # Issue 24914
+analyzer/test/src/summary/summarize_elements_test: Pass, Slow # Issue 24914
 analyzer/test/src/task/dart_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/dart_work_manager_test: Pass, Slow # Issue 21628
 analyzer/test/src/task/driver_test: Pass, Slow # Issue 21628
@@ -152,12 +161,13 @@
 observe/test/unique_message_test: SkipByDesign  # Uses dart:io.
 dart_messages/test/dart_messages_test: Skip  # Uses dart:io.
 
-[ $runtime == vm && ($arch == simarm64 || $arch == simarm || $arch == simarmv5te || $arch == simmips || $arch == armv5te) ]
+[ $runtime == vm && ($arch == simarm64 || $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips || $arch == armv6 || $arch == armv5te) ]
 # Timeout. These are not unit tests. They do not run efficiently on our
 # simulator or low-end devices.
 *: Skip
 
 [ $runtime == vm ]
+analyzer/test/file_system/physical_resource_provider_test: Pass, Fail # Issue 25472
 # Skip tests on the VM if the package depends on dart:html
 mutation_observer: Skip
 
diff --git a/pkg/typed_mock/README.md b/pkg/typed_mock/README.md
index 2414318..2b24907 100644
--- a/pkg/typed_mock/README.md
+++ b/pkg/typed_mock/README.md
@@ -2,6 +2,213 @@
 
 It is inspired by [Mockito](https://code.google.com/p/mockito/).
 
-The existing "mock" package suffers from using method names as strings,
-which makes it impossible to use code-completion, static validation,
-search and refactoring.
+Features of this package:
+- Code-completion, static validation, search and refactoring all work properly with mocks.
+- Much better error messages for unit testing.
+- Works with concrete and abstract classes.
+- Does not use mirrors.
+- No dependent packages.
+
+Other Mock libraries for Dart:
+- https://pub.dartlang.org/packages/mockito
+- https://pub.dartlang.org/packages/mock (deprecated)
+
+## Tutorial
+
+Let's take the simple case of making sure that a method is called. The first step is to create a mock of the object, as shown below. One nice feature of Dart is that all classes automatically define interfaces, so you don't need to separately define the interface.
+
+```dart
+import 'package:typed_mock/typed_mock.dart';
+
+class Dog {
+  String speak() => "Woof!";
+}
+
+class MockDog extends TypedMock implements Dog {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+```
+
+All of the magic happens because of the noSuchMethod() function. None of the functions for Animal are actually defined because we used `implements` instead of `extends`. Therefore, all calls to this object will end up in `noSuchMethod()`.
+
+#### Verify a function is called
+
+Here's the code to verify that the function is called:
+
+```dart
+
+void main() {
+  final dog = new MockDog();
+  verifyZeroInteractions(dog);
+  dog.speak();
+  verify(dog.speak()).once();
+  verifyNoMoreInteractions(dog);
+}
+```
+
+One of the interesting features of typed_mock is that it internally tracks all calls to each mock object, then tracks which calls have been matched with a verify() call and which not. Therefore, typed_mock is able to detect unexpected calls, even if those calls are made to methods that didn't exist when the test was written. This can be a good incentive to update your tests whenever you change a class.
+
+After creating the `MockAnimal` object, we call `verifyZeroInteractions()` to make sure that the object starts in a clean state. Next we call the `speak()` method, then prove that the speak function was actually called with `verify().once()`.
+
+There are several other functions for verifying calls that can be used instead of `once()`:
+- `atLeastOnce()` Ensure the function was called one or more times.
+- `times(n)` Ensure the function was called exactly `n` times.
+- `atLeast(n)` Ensure the function was called `n` or more times.
+- `atMost(n)` Ensure the function was called no more than `n` times.
+- `any()` Mark the function call as verified if it was called, but don't fail if it wasn't called.
+- `never()` Ensure the function was never called. It's often better to use `verifyNoMoreInteractions()` instead.
+
+#### Configure the mock to return a value
+
+Here's how to return a value from `speak()`:
+
+```dart
+void main() {
+  final dog = new MockDog();
+  when(dog.speak()).thenReturn("woof");
+  final s = dog.speak();
+  print("$s");
+  verify(dog.speak()).once();
+  verifyNoMoreInteractions(dog);
+}
+```
+
+What if `speak()` took the name of an animal as a parameter? When typed_mock tracks a function call, the call tracking is based on the function name and the parameters. For example:
+
+
+```dart
+import 'package:typed_mock/typed_mock.dart';
+
+abstract class Animal {
+  String speak();
+}
+
+class MockAnimal extends TypedMock implements Animal {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+void main() {
+  final animal = new MockAnimal();
+  when(animal.speak("dog")).thenReturn("woof");
+  final s = animal.speak();
+  print("$s");
+  verify(animal.speak("dog")).once();
+}
+```
+
+Note that you can reset the call and verify tracking using `resetInteractions()`. However, there is no way to reset the `when()` calls. Create a new mock instead.
+
+You can define different results based on the value of the parameter. Notice that the calls to `verify()` explicitly states the parameter value:
+
+```dart
+void main() {
+  final animal = new MockAnimal();
+  when(animal.speak("cat")).thenReturn("meow");
+  when(animal.speak("dog")).thenReturn("woof");
+  final s = animal.speak("cat"); // Prints: meow
+  verify(animal.speak("cat")).once();
+  verify(animal.speak("dog")).never();
+}
+```
+
+#### Match any value for a parameter
+
+Sometimes you don't care about the exact value of the parameter. That's when `anyString` is used, along with its siblings `anyInt`, `anyBool` and `anyObject`.
+
+The value `anyString` is a matcher that matches any String value. For example, here's how to use `anyString` in a call to `when()`:
+
+```dart
+void main() {
+  final animal = new MockAnimal();
+  when(animal.speak(anyString)).thenReturn("meow");
+  final s1 = animal.speak("cat");
+  final s2 = animal.speak("dog");
+  print("$s1 $s2"); // Prints: meow meow
+  verify(animal.speak(anyString)).times(2);
+}
+```
+
+You can also use `anyString` in `verify()` calls, even if the `when()` calls use exact values. For example:
+
+```dart
+void main() {
+  final animal = new MockAnimal();
+  when(animal.speak("cat")).thenReturn("meow");
+  when(animal.speak("dog")).thenReturn("woof");
+  var s
+  s = animal.speak("cat");
+  s = animal.speak("cat");
+  s = animal.speak("dog");
+  verify(animal.speak(anyString)).times(3);
+}
+```
+
+You can use `anyString` as the parameter for calculated values:
+```dart
+  when(animal.speak(anyString)).thenInvoke((String s) => 'The $s speaks!');
+```
+
+In addition to `thenReturn()` and `thenInvoke()`, typed_mock supports `thenReturnList()` and `thenThrow()`. See the link at the end of this document for examples.
+
+#### Mocking operator[] and operator[]=
+
+The typed_mock package is able to track set and get access with operators `[]=` and `[]`, respectively. There's nothing special about these operators - they are just functions with non-alphanumeric names that takes two or one parameters. As with other functions, typed_mock tracks both the index and the value as needed. Note the syntax to verify that a particular array element was assigned a particular value. The act of assigning true is tracked separately from the act of assigning false. The syntax is straightforward.
+
+```dart
+import 'package:typed_mock/typed_mock.dart';
+
+abstract class Tracker {
+  operator [](int index);
+  operator []=(int index, bool b);
+}
+
+class MockTracker extends TypedMock implements Tracker {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+void main() {
+  final tracker = new MockTracker();
+  tracker[2] = true;
+  when(tracker[3]).thenReturn(false);
+  when(tracker[4]).thenReturn(true);
+  bool x = tracker[3];
+  bool y = tracker[4];
+  print("$x $y");
+  verify(tracker[1] = true).never();
+  verify(tracker[2] = false).never();
+  verify(tracker[2] = true).once();
+  verify(tracker[3]).once();
+  verify(tracker[4]).once();
+  verify(tracker[5]).never();
+}
+```
+
+#### Passing mocks as closures
+
+Passing a mock as a function parameter may not behave as you expect because a hidden function is called in the mock to get the closure. The solution is to wrap the call in a separate closure. For example, the call to `verifyNoMoreInteractions()` fails because the reference to `dog.speak` caused a hidden function to be called in `MockDog`.
+
+```dart
+void doSomething(String myfunc()) {}
+
+void main() {
+  final dog = new MockDog();
+  doSomething(dog.speak);
+  verifyNoMoreInteractions(dog);
+}
+```
+
+The solution is as follows:
+
+```dart
+void doSomething(String myfunc()) {}
+
+void main() {
+  final dog = new MockDog();
+  doSomething(() => dog.speak());
+  verifyNoMoreInteractions(dog);
+}
+```
+
+## More Information
+
+For additional examples, see the [unit tests](https://github.com/dart-lang/sdk/blob/master/pkg/typed_mock/test/typed_mock_test.dart).
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 78c5a58..11f84fc 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -629,10 +629,10 @@
     },
     {
       # dart binary for running precompiled snapshots without the compiler.
-      'target_name': 'dart_precompiled',
+      'target_name': 'dart_precompiled_runtime',
       'type': 'executable',
       'dependencies': [
-        'libdart_precompiled',
+        'libdart_precompiled_runtime',
         'libdart_builtin',
         'libdart_io',
         'build_observatory#host',
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index 29d2884..e8b8d73 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -21,9 +21,9 @@
 // when the isolate shuts down.
 class IsolateData {
  public:
-  explicit IsolateData(const char* url,
-                       const char* package_root,
-                       const char* packages_file)
+  IsolateData(const char* url,
+              const char* package_root,
+              const char* packages_file)
       : script_url(strdup(url)),
         package_root(NULL),
         packages_file(NULL),
@@ -36,14 +36,17 @@
       this->packages_file = strdup(packages_file);
     }
   }
-#if 0
+
   ~IsolateData() {
     free(script_url);
+    script_url = NULL;
     free(package_root);
+    package_root = NULL;
     free(packages_file);
+    packages_file = NULL;
     free(udp_receive_buffer);
+    udp_receive_buffer = NULL;
   }
-#endif
 
   char* script_url;
   char* package_root;
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index 707686f..f542dde 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -17,6 +17,7 @@
 
     'libdart_deps': ['libdart_lib_nosnapshot', 'libdart_lib',
                      'libdart_vm_nosnapshot', 'libdart_vm',
+                     'libdart_vm_precompiled_runtime',
                      'libdouble_conversion',],
   },
   'targets': [
@@ -55,11 +56,11 @@
       },
     },
     {
-      'target_name': 'libdart_precompiled',
+      'target_name': 'libdart_precompiled_runtime',
       'type': 'static_library',
       'dependencies': [
         'libdart_lib',
-        'libdart_vm_precompiled',
+        'libdart_vm_precompiled_runtime',
         'libdouble_conversion',
         'generate_version_cc_file#host',
       ],
@@ -81,7 +82,7 @@
       'defines': [
         # The only effect of DART_SHARED_LIB is to export the Dart API entries.
         'DART_SHARED_LIB',
-        'DART_PRECOMPILED',
+        'DART_PRECOMPILED_RUNTIME',
       ],
       'direct_dependent_settings': {
         'include_dirs': [
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index c7a2164..aa985da 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -67,8 +67,8 @@
       String::CheckedHandle(arguments->NativeArgAt(2));
   const String& dst_name = String::CheckedHandle(arguments->NativeArgAt(3));
   const String& error_msg = String::CheckedHandle(arguments->NativeArgAt(4));
-  const String& src_type_name =
-      String::Handle(Type::Handle(src_value.GetType()).UserVisibleName());
+  const String& src_type_name = String::Handle(
+      AbstractType::Handle(src_value.GetType()).UserVisibleName());
   Exceptions::CreateAndThrowTypeError(location, src_type_name,
                                       dst_type_name, dst_name, error_msg);
   UNREACHABLE();
diff --git a/runtime/lib/expando_patch.dart b/runtime/lib/expando_patch.dart
index 0c9427c..df0234d 100644
--- a/runtime/lib/expando_patch.dart
+++ b/runtime/lib/expando_patch.dart
@@ -131,7 +131,8 @@
          (object is bool) ||
          (object is num) ||
          (object is String)) {
-      throw new ArgumentError(object);
+      throw new ArgumentError.value(object,
+          "Expandos are not allowed on strings, numbers, booleans or null");
     }
   }
 
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index 607e29e..b7424f5 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -28,21 +28,21 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(FunctionImpl_equals, 2) {
-  const Instance& receiver = Instance::CheckedHandle(
+DEFINE_NATIVE_ENTRY(Closure_equals, 2) {
+  const Closure& receiver = Closure::CheckedHandle(
       zone, arguments->NativeArgAt(0));
-  ASSERT(receiver.IsClosure());
   GET_NATIVE_ARGUMENT(Instance, other, arguments->NativeArgAt(1));
   ASSERT(!other.IsNull());
   if (receiver.raw() == other.raw()) return Bool::True().raw();
   if (other.IsClosure()) {
-    const Function& func_a = Function::Handle(Closure::function(receiver));
-    const Function& func_b = Function::Handle(Closure::function(other));
+    const Function& func_a = Function::Handle(receiver.function());
+    const Function& func_b = Function::Handle(Closure::Cast(other).function());
     if (func_a.raw() == func_b.raw()) {
       ASSERT(!func_a.IsImplicitStaticClosureFunction());
       if (func_a.IsImplicitInstanceClosureFunction()) {
-        const Context& context_a = Context::Handle(Closure::context(receiver));
-        const Context& context_b = Context::Handle(Closure::context(other));
+        const Context& context_a = Context::Handle(receiver.context());
+        const Context& context_b = Context::Handle(
+            Closure::Cast(other).context());
         const Object& receiver_a = Object::Handle(context_a.At(0));
         const Object& receiver_b = Object::Handle(context_b.At(0));
         if (receiver_a.raw() == receiver_b.raw()) return Bool::True().raw();
@@ -53,48 +53,38 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(FunctionImpl_hashCode, 1) {
-  const Instance& receiver = Instance::CheckedHandle(
+DEFINE_NATIVE_ENTRY(Closure_hashCode, 1) {
+  const Closure& receiver = Closure::CheckedHandle(
       zone, arguments->NativeArgAt(0));
-  if (receiver.IsClosure()) {
-    const Function& func = Function::Handle(Closure::function(receiver));
-    // Hash together name, class name and signature.
-    const Class& cls = Class::Handle(func.Owner());
-    intptr_t result = String::Handle(func.name()).Hash();
-    result += String::Handle(func.Signature()).Hash();
-    result += String::Handle(cls.Name()).Hash();
-    // Finalize hash value like for strings so that it fits into a smi.
-    result += result << 3;
-    result ^= result >> 11;
-    result += result << 15;
-    result &= ((static_cast<intptr_t>(1) << String::kHashBits) - 1);
-    return Smi::New(result);
-  }
-  UNREACHABLE();
-  return Object::null();
+  const Function& func = Function::Handle(receiver.function());
+  // Hash together name, class name and signature.
+  const Class& cls = Class::Handle(func.Owner());
+  intptr_t result = String::Handle(func.name()).Hash();
+  result += String::Handle(func.Signature()).Hash();
+  result += String::Handle(cls.Name()).Hash();
+  // Finalize hash value like for strings so that it fits into a smi.
+  result += result << 3;
+  result ^= result >> 11;
+  result += result << 15;
+  result &= ((static_cast<intptr_t>(1) << String::kHashBits) - 1);
+  return Smi::New(result);
 }
 
 
-DEFINE_NATIVE_ENTRY(FunctionImpl_clone, 1) {
-  const Instance& receiver = Instance::CheckedHandle(
+DEFINE_NATIVE_ENTRY(Closure_clone, 1) {
+  const Closure& receiver = Closure::CheckedHandle(
       zone, arguments->NativeArgAt(0));
-  ASSERT(receiver.IsClosure());
-  if (receiver.IsClosure()) {
-    const Function& func =
-        Function::Handle(zone, Closure::function(receiver));
-    const Context& ctx =
-        Context::Handle(zone, Closure::context(receiver));
-    Context& cloned_ctx =
-        Context::Handle(zone, Context::New(ctx.num_variables()));
-    cloned_ctx.set_parent(Context::Handle(zone, ctx.parent()));
-    Object& inst = Object::Handle(zone);
-    for (int i = 0; i < ctx.num_variables(); i++) {
-      inst = ctx.At(i);
-      cloned_ctx.SetAt(i, inst);
-    }
-    return Closure::New(func, cloned_ctx);
+  const Function& func = Function::Handle(zone, receiver.function());
+  const Context& ctx = Context::Handle(zone, receiver.context());
+  Context& cloned_ctx =
+      Context::Handle(zone, Context::New(ctx.num_variables()));
+  cloned_ctx.set_parent(Context::Handle(zone, ctx.parent()));
+  Object& inst = Object::Handle(zone);
+  for (int i = 0; i < ctx.num_variables(); i++) {
+    inst = ctx.At(i);
+    cloned_ctx.SetAt(i, inst);
   }
-  return Object::null();
+  return Closure::New(func, cloned_ctx);
 }
 
 
diff --git a/runtime/lib/function.dart b/runtime/lib/function.dart
index d91ce66..6c1d5cc 100644
--- a/runtime/lib/function.dart
+++ b/runtime/lib/function.dart
@@ -2,13 +2,15 @@
 // 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.
 
-class _FunctionImpl implements Function {
+class _Closure implements Function {
 
-  bool operator ==(other) native "FunctionImpl_equals";
+  bool operator ==(other) native "Closure_equals";
 
-  int get hashCode native "FunctionImpl_hashCode";
+  int get hashCode native "Closure_hashCode";
 
-  _FunctionImpl get call => this;
+  _Closure get call => this;
 
-  _FunctionImpl _clone() native "FunctionImpl_clone";
+  _Closure _clone() native "Closure_clone";
+
+  // The type_arguments_, function_, and context_ fields are not declared here.
 }
diff --git a/runtime/lib/immutable_map.dart b/runtime/lib/immutable_map.dart
index 2377c8c..b8d0d3c 100644
--- a/runtime/lib/immutable_map.dart
+++ b/runtime/lib/immutable_map.dart
@@ -11,8 +11,9 @@
 
 
   V operator [](Object key) {
-    // TODO(hausner): Since the keys are sorted, we could do a binary
-    // search. But is it worth it?
+    // To preserve the key-value order of the map literal, the keys are
+    // not sorted. Need to do linear search or implement an additional
+    // lookup table.
     for (int i = 0; i < _kvPairs.length - 1; i += 2) {
       if (key == _kvPairs[i]) {
         return _kvPairs[i+1];
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 773bac4..4e1fce8 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -226,11 +226,11 @@
 
   if (closure.IsClosure()) {
     Function& func = Function::Handle();
-    func = Closure::function(closure);
+    func = Closure::Cast(closure).function();
     if (func.IsImplicitClosureFunction() && func.is_static()) {
 #if defined(DEBUG)
       Context& ctx = Context::Handle();
-      ctx = Closure::context(closure);
+      ctx = Closure::Cast(closure).context();
       ASSERT(ctx.num_variables() == 0);
 #endif
       // Get the parent function so that we get the right function name.
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 05453f8..564db22 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -139,12 +139,18 @@
     // This covers the default constructor and forwarding constructors.
     has_extra_parameter_info = false;
   }
+  if (func.IsSignatureFunction() &&
+      (func.token_pos() == Token::kNoSourcePos)) {
+    // Signature functions (except those describing typedefs) get canonicalized,
+    // hence do not have a token position, and therefore cannot be reparsed.
+    has_extra_parameter_info = false;
+  }
 
   Array& param_descriptor = Array::Handle();
   if (has_extra_parameter_info) {
     // Reparse the function for the following information:
     // * The default value of a parameter.
-    // * Whether a parameters has been deflared as final.
+    // * Whether a parameters has been declared as final.
     // * Any metadata associated with the parameter.
     const Object& result =
         Object::Handle(Parser::ParseFunctionParameters(func));
@@ -237,18 +243,21 @@
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
   args.SetAt(1, type);
   args.SetAt(2, String::Handle(cls.Name()));
-  args.SetAt(3, Bool::Get(cls.NumTypeParameters() != 0));
-  args.SetAt(4, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
+  args.SetAt(3, Bool::Get(cls.IsGeneric()));
+  args.SetAt(4, cls.IsGeneric() ? is_declaration : Bool::False());
   args.SetAt(5, owner_mirror);
   return CreateMirror(Symbols::_LocalTypedefMirror(), args);
 }
 
 
-static RawInstance* CreateFunctionTypeMirror(const Class& cls,
-                                             const AbstractType& type) {
-  const Array& args = Array::Handle(Array::New(2));
+static RawInstance* CreateFunctionTypeMirror(const AbstractType& type) {
+  ASSERT(type.IsFunctionType());
+  const Class& cls = Class::Handle(FunctionType::Cast(type).scope_class());
+  const Function& func = Function::Handle(FunctionType::Cast(type).signature());
+  const Array& args = Array::Handle(Array::New(3));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
-  args.SetAt(1, type);
+  args.SetAt(1, MirrorReference::Handle(MirrorReference::New(func)));
+  args.SetAt(2, type);
   return CreateMirror(Symbols::_LocalFunctionTypeMirror(), args);
 }
 
@@ -304,22 +313,6 @@
   return CreateMirror(Symbols::_LocalVariableMirror(), args);
 }
 
-static RawFunction* CallMethod(const Class& cls) {
-  if (cls.IsSignatureClass()) {
-    return cls.signature_function();
-  }
-
-  Class& lookup_cls = Class::Handle(cls.raw());
-  Function& call_function = Function::Handle();
-  do {
-    call_function = lookup_cls.LookupDynamicFunction(Symbols::Call());
-    if (!call_function.IsNull()) {
-      return call_function.raw();
-    }
-    lookup_cls = lookup_cls.SuperClass();
-  } while (!lookup_cls.IsNull());
-  return Function::null();
-}
 
 static RawInstance* CreateClassMirror(const Class& cls,
                                       const AbstractType& type,
@@ -335,14 +328,8 @@
   ASSERT(!type.IsNull());
   ASSERT(type.IsFinalized());
 
-  if (cls.IsSignatureClass()) {
-    if (cls.IsCanonicalSignatureClass()) {
-      // We represent function types as canonical signature classes.
-      return CreateFunctionTypeMirror(cls, type);
-    } else {
-      // We represent typedefs as non-canonical signature classes.
-      return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
-    }
+  if (cls.IsTypedefClass()) {
+    return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
   }
 
   const Error& error = Error::Handle(cls.EnsureIsFinalized(Thread::Current()));
@@ -554,6 +541,16 @@
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsCanonical() || type.IsTypeParameter() || type.IsBoundedType());
 
+  if (type.IsFunctionType()) {
+    const Class& scope_class =
+        Class::Handle(FunctionType::Cast(type).scope_class());
+    if (scope_class.IsTypedefClass()) {
+      return CreateTypedefMirror(scope_class,
+                                 type, Bool::False(), Object::null_instance());
+    } else {
+      return CreateFunctionTypeMirror(type);
+    }
+  }
   if (type.HasResolvedTypeClass()) {
     const Class& cls = Class::Handle(type.type_class());
     // Handle void and dynamic types.
@@ -785,8 +782,8 @@
   const TypeArguments& type_args =
       TypeArguments::Handle(instantiator.arguments());
   Error& bound_error = Error::Handle();
-  AbstractType& result =
-      AbstractType::Handle(type.InstantiateFrom(type_args, &bound_error));
+  AbstractType& result = AbstractType::Handle(
+      type.InstantiateFrom(type_args, &bound_error, NULL, Heap::kOld));
   if (!bound_error.IsNull()) {
     Exceptions::PropagateError(bound_error);
     UNREACHABLE();
@@ -828,12 +825,10 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  ASSERT(type.HasResolvedTypeClass());
+  ASSERT(type.IsFunctionType() || type.HasResolvedTypeClass());
   const Class& cls = Class::Handle(type.type_class());
   ASSERT(!cls.IsNull());
-  if (cls.IsDynamicClass() ||
-      cls.IsVoidClass() ||
-      (cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass())) {
+  if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsTypedefClass()) {
     Exceptions::ThrowArgumentError(type);
     UNREACHABLE();
   }
@@ -911,8 +906,9 @@
                                owner_mirror,
                                arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
-  const Class& cls = Class::Handle(ref.GetClassReferent());
-  const Function& func = Function::Handle(CallMethod(cls));
+  // TODO(rmacnak): Return get:call() method on class _Closure instead?
+  // This now returns the result of invoking that call getter.
+  const Function& func = Function::Handle(ref.GetFunctionReferent());
   ASSERT(!func.IsNull());
   return CreateMethodMirror(func, owner_mirror, AbstractType::Handle());
 }
@@ -921,8 +917,7 @@
 DEFINE_NATIVE_ENTRY(FunctionTypeMirror_parameters, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
-  const Class& cls = Class::Handle(ref.GetClassReferent());
-  const Function& func = Function::Handle(cls.signature_function());
+  const Function& func = Function::Handle(ref.GetFunctionReferent());
   return CreateParameterMirrorList(func, owner);
 }
 
@@ -932,8 +927,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType,
                                instantiator,
                                arguments->NativeArgAt(1));
-  const Class& cls = Class::Handle(ref.GetClassReferent());
-  const Function& func = Function::Handle(CallMethod(cls));
+  const Function& func = Function::Handle(ref.GetFunctionReferent());
   ASSERT(!func.IsNull());
   AbstractType& type = AbstractType::Handle(func.result_type());
   return InstantiateType(type, instantiator);
@@ -953,10 +947,6 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  if (!type.HasResolvedTypeClass()) {
-    Exceptions::ThrowArgumentError(type);
-    UNREACHABLE();
-  }
   const Class& cls = Class::Handle(type.type_class());
   const AbstractType& super_type = AbstractType::Handle(cls.super_type());
   ASSERT(super_type.IsNull() || super_type.IsFinalized());
@@ -968,10 +958,6 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  if (!type.HasResolvedTypeClass()) {
-    Exceptions::ThrowArgumentError(type);
-    UNREACHABLE();
-  }
   const Class& cls = Class::Handle(type.type_class());
   const AbstractType& super_type = AbstractType::Handle(cls.super_type());
   return InstantiateType(super_type, type);
@@ -982,10 +968,6 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  if (!type.HasResolvedTypeClass()) {
-    Exceptions::ThrowArgumentError(type);
-    UNREACHABLE();
-  }
   const Class& cls = Class::Handle(type.type_class());
   const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
   if (!error.IsNull()) {
@@ -999,10 +981,6 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  if (!type.HasResolvedTypeClass()) {
-    Exceptions::ThrowArgumentError(type);
-    UNREACHABLE();
-  }
   const Class& cls = Class::Handle(type.type_class());
   const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
   if (!error.IsNull()) {
@@ -1027,10 +1005,6 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  if (!type.HasResolvedTypeClass()) {
-    Exceptions::ThrowArgumentError(type);
-    UNREACHABLE();
-  }
   const Class& cls = Class::Handle(type.type_class());
   const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
   ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
@@ -1045,10 +1019,6 @@
                                arguments->NativeArgAt(1));
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
-  if (!type.HasResolvedTypeClass()) {
-    Exceptions::ThrowArgumentError(type);
-    UNREACHABLE();
-  }
   const Class& cls = Class::Handle(type.type_class());
   const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
   if (mixin_type.IsNull()) {
@@ -1166,13 +1136,11 @@
     entry = entries.GetNext();
     if (entry.IsClass()) {
       const Class& klass = Class::Cast(entry);
-      // We filter out function signature classes and dynamic.
+      // We filter out mixin application classes and dynamic.
       // TODO(12478): Should not need to filter out dynamic.
       // Note that the VM does not consider mixin application aliases to be
       // mixin applications.
-      if (!klass.IsCanonicalSignatureClass() &&
-          !klass.IsDynamicClass() &&
-          !klass.IsMixinApplication()) {
+      if (!klass.IsDynamicClass() && !klass.IsMixinApplication()) {
         type = klass.DeclarationType();
         member_mirror = CreateClassMirror(klass,
                                           type,
@@ -1307,9 +1275,8 @@
   // setters, assume the result is a closure and mark its function as invisible,
   // so it will not appear in stack traces. Whenever we support
   // ObjectMirror.evaluate this will need to be separated.
-  ASSERT(Instance::Cast(result).IsClosure());
-  const Function& func =
-      Function::Handle(Closure::function(Instance::Cast(result)));
+  ASSERT(result.IsClosure());
+  const Function& func = Function::Handle(Closure::Cast(result).function());
   func.set_is_visible(false);
   func.set_is_debuggable(false);
 
@@ -1317,10 +1284,9 @@
 }
 
 DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
-  const Class& cls = Class::Handle(type.type_class());
-  // We represent typedefs as non-canonical signature classes.
-  ASSERT(cls.IsSignatureClass() && !cls.IsCanonicalSignatureClass());
+  GET_NON_NULL_NATIVE_ARGUMENT(FunctionType, type, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(type.scope_class());
+  ASSERT(cls.IsTypedefClass());
   return CreateTypedefMirror(cls,
                              AbstractType::Handle(cls.DeclarationType()),
                              Bool::True(),  // is_declaration
@@ -1454,7 +1420,7 @@
 
 DEFINE_NATIVE_ENTRY(InstanceMirror_computeType, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
-  const Type& type = Type::Handle(instance.GetType());
+  const AbstractType& type = AbstractType::Handle(instance.GetType());
   // The static type of null is specified to be the bottom type, however, the
   // runtime type of null is the Null type, which we correctly return here.
   return type.Canonicalize();
@@ -1479,10 +1445,10 @@
     Type& instantiator = Type::Handle();
     if (closure.IsClosure()) {
       const TypeArguments& arguments =
-          TypeArguments::Handle(Closure::GetTypeArguments(closure));
+          TypeArguments::Handle(closure.GetTypeArguments());
       const Class& cls =
           Class::Handle(Isolate::Current()->object_store()->object_class());
-      instantiator = Type::New(cls, arguments, Scanner::kNoSourcePos);
+      instantiator = Type::New(cls, arguments, Token::kNoSourcePos);
       instantiator.SetIsFinalized();
     }
     return CreateMethodMirror(function,
@@ -1708,8 +1674,8 @@
       // The type arguments of the redirection type are instantiated from the
       // type arguments of the type reflected by the class mirror.
       Error& bound_error = Error::Handle();
-      redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
-                                                     &bound_error);
+      redirect_type ^= redirect_type.InstantiateFrom(
+          type_arguments, &bound_error, NULL, Heap::kOld);
       if (!bound_error.IsNull()) {
         Exceptions::PropagateError(bound_error);
         UNREACHABLE();
@@ -2003,7 +1969,7 @@
   }
 
   Script& script = Script::Handle();
-  intptr_t token_pos = Scanner::kNoSourcePos;
+  intptr_t token_pos = Token::kNoSourcePos;
 
   if (decl.IsFunction()) {
     const Function& func = Function::Cast(decl);
@@ -2015,8 +1981,7 @@
     token_pos = func.token_pos();
   } else if (decl.IsClass()) {
     const Class& cls = Class::Cast(decl);
-    const bool is_typedef = cls.IsSignatureClass() &&
-                            !cls.IsCanonicalSignatureClass();
+    const bool is_typedef = cls.IsTypedefClass();
     if (cls.is_synthesized_class() &&
         !is_typedef &&
         !cls.is_mixin_app_alias() &&
@@ -2058,7 +2023,7 @@
   }
 
   ASSERT(!script.IsNull());
-  ASSERT(token_pos != Scanner::kNoSourcePos);
+  ASSERT(token_pos != Token::kNoSourcePos);
 
   const String& uri = String::Handle(script.url());
   intptr_t from_line = 0;
@@ -2077,15 +2042,25 @@
 
 
 DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
-  const Class& cls = Class::Handle(type.type_class());
+  GET_NON_NULL_NATIVE_ARGUMENT(FunctionType, type, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(type.scope_class());
+  ASSERT(cls.IsTypedefClass());
   const Function& sig_func = Function::Handle(cls.signature_function());
-  const Class& sig_cls = Class::Handle(sig_func.signature_class());
-
-  AbstractType& referent_type = AbstractType::Handle(sig_cls.DeclarationType());
-  referent_type = InstantiateType(referent_type, type);
-
-  return CreateFunctionTypeMirror(sig_cls, referent_type);
+  FunctionType& referent_type = FunctionType::Handle(sig_func.SignatureType());
+  // If the scope class of the function type is not generic, replace it with
+  // Closure class (Function::SignatureType() keeps it).
+  ASSERT(cls.raw() == referent_type.scope_class());
+  if (!cls.IsGeneric()) {
+    referent_type = FunctionType::New(
+        Class::Handle(Isolate::Current()->object_store()->closure_class()),
+        TypeArguments::Handle(referent_type.arguments()),
+        sig_func,
+        referent_type.token_pos());
+    referent_type ^= ClassFinalizer::FinalizeType(
+        cls, referent_type, ClassFinalizer::kCanonicalize);
+  }
+  referent_type ^= InstantiateType(referent_type, type);
+  return CreateFunctionTypeMirror(referent_type);
 }
 
 
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 0a839fb..78835a4 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -945,7 +945,8 @@
 
 class _LocalFunctionTypeMirror extends _LocalClassMirror
     implements FunctionTypeMirror {
-  _LocalFunctionTypeMirror(reflectee, reflectedType)
+  final _functionReflectee;
+  _LocalFunctionTypeMirror(reflectee, this._functionReflectee, reflectedType)
       : super(reflectee, reflectedType, null, null, false, false, false, false, false);
 
   bool get _isAnonymousMixinApplication => false;
@@ -962,7 +963,7 @@
   MethodMirror _callMethod;
   MethodMirror get callMethod {
     if (_callMethod == null) {
-      _callMethod = this._FunctionTypeMirror_call_method(_reflectee);
+      _callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
     }
     return _callMethod;
   }
@@ -971,7 +972,7 @@
   TypeMirror get returnType {
     if (_returnType == null) {
       _returnType = reflectType(
-          _FunctionTypeMirror_return_type(_reflectee, _instantiator));
+          _FunctionTypeMirror_return_type(_functionReflectee, _instantiator));
     }
     return _returnType;
   }
@@ -979,7 +980,7 @@
   List<ParameterMirror> _parameters = null;
   List<ParameterMirror> get parameters {
     if (_parameters == null) {
-      _parameters = _FunctionTypeMirror_parameters(_reflectee);
+      _parameters = _FunctionTypeMirror_parameters(_functionReflectee);
       _parameters = new UnmodifiableListView(_parameters);
     }
     return _parameters;
@@ -990,16 +991,17 @@
   get typeVariables => emptyList;
   get typeArguments => emptyList;
   get metadata => emptyList;
+  get location => null;
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 
-  MethodMirror _FunctionTypeMirror_call_method(reflectee)
+  MethodMirror _FunctionTypeMirror_call_method(functionReflectee)
       native "FunctionTypeMirror_call_method";
 
-  static Type _FunctionTypeMirror_return_type(reflectee, instantiator)
+  static Type _FunctionTypeMirror_return_type(functionReflectee, instantiator)
       native "FunctionTypeMirror_return_type";
 
-  List<ParameterMirror> _FunctionTypeMirror_parameters(reflectee)
+  List<ParameterMirror> _FunctionTypeMirror_parameters(functionReflectee)
       native "FunctionTypeMirror_parameters";
 }
 
@@ -1648,7 +1650,7 @@
       native "Mirrors_makeLocalTypeMirror";
 
   static Expando<ClassMirror> _declarationCache = new Expando("ClassMirror");
-  static Expando<TypeMirror> _instanitationCache = new Expando("TypeMirror");
+  static Expando<TypeMirror> _instantiationCache = new Expando("TypeMirror");
 
   static ClassMirror reflectClass(Type key) {
     var classMirror = _declarationCache[key];
@@ -1656,17 +1658,17 @@
       classMirror = makeLocalClassMirror(key);
       _declarationCache[key] = classMirror;
       if (!classMirror._isGeneric) {
-        _instanitationCache[key] = classMirror;
+        _instantiationCache[key] = classMirror;
       }
     }
     return classMirror;
   }
 
   static TypeMirror reflectType(Type key) {
-    var typeMirror = _instanitationCache[key];
+    var typeMirror = _instantiationCache[key];
     if (typeMirror == null) {
       typeMirror = makeLocalTypeMirror(key);
-      _instanitationCache[key] = typeMirror;
+      _instantiationCache[key] = typeMirror;
       if (typeMirror is ClassMirror && !typeMirror._isGeneric) {
         _declarationCache[key] = typeMirror;
       }
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 72fcc3e..d0eb27c 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -88,7 +88,7 @@
     // found.
     Function& function = Function::Handle();
     if (instance.IsClosure()) {
-      function = Closure::function(instance);
+      function = Closure::Cast(instance).function();
     } else {
       Class& instance_class = Class::Handle(instance.clazz());
       function = instance_class.LookupDynamicFunction(member_name);
@@ -179,7 +179,8 @@
   if (FLAG_trace_type_checks) {
     const char* result_str = is_instance_of ? "true" : "false";
     OS::Print("Native Object.instanceOf: result %s\n", result_str);
-    const Type& instance_type = Type::Handle(instance.GetType());
+    const AbstractType& instance_type =
+        AbstractType::Handle(instance.GetType());
     OS::Print("  instance type: %s\n",
               String::Handle(instance_type.Name()).ToCString());
     OS::Print("  test type: %s\n", String::Handle(type.Name()).ToCString());
@@ -289,7 +290,8 @@
   if (FLAG_trace_type_checks) {
     const char* result_str = is_instance_of ? "true" : "false";
     OS::Print("Object.as: result %s\n", result_str);
-    const Type& instance_type = Type::Handle(instance.GetType());
+    const AbstractType& instance_type =
+        AbstractType::Handle(instance.GetType());
     OS::Print("  instance type: %s\n",
               String::Handle(instance_type.Name()).ToCString());
     OS::Print("  cast type: %s\n", String::Handle(type.Name()).ToCString());
diff --git a/runtime/lib/type_patch.dart b/runtime/lib/type_patch.dart
index 67d7db5..5d0f305 100644
--- a/runtime/lib/type_patch.dart
+++ b/runtime/lib/type_patch.dart
@@ -13,6 +13,10 @@
 class _Type extends _AbstractType {
 }
 
+// Equivalent of RawFunctionType.
+class _FunctionType extends _AbstractType {
+}
+
 // Equivalent of RawTypeRef.
 class _TypeRef extends _AbstractType {
 }
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index caf5f57..7688712 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -401,13 +401,14 @@
         // Complete the line.
         var sharedPrefix = '${script.name}:';
         List completions = [];
-        for (var line in script.lines) {
-          if (line.possibleBpt) {
-            var currentLineStr = line.line.toString();
-            if (currentLineStr.startsWith(lineStr)) {
-              completions.add('${sharedPrefix}${currentLineStr} ');
-              completions.add('${sharedPrefix}${currentLineStr}:');
-            }
+        var report = await script.isolate.getSourceReport(
+            [Isolate.kPossibleBreakpointsReport], script);
+        Set<int> possibleBpts = getPossibleBreakpointLines(report, script);
+        for (var line in possibleBpts) {
+          var currentLineStr = line.toString();
+          if (currentLineStr.startsWith(lineStr)) {
+            completions.add('${sharedPrefix}${currentLineStr} ');
+            completions.add('${sharedPrefix}${currentLineStr}:');
           }
         }
         return completions;
@@ -416,9 +417,6 @@
         // Complete the column.
         int lineNum = int.parse(lineStr);
         var scriptLine = script.getLine(lineNum);
-        if (!scriptLine.possibleBpt) {
-          return [];
-        }
         var sharedPrefix = '${script.name}:${lineStr}:';
         List completions = [];
         int maxCol = scriptLine.text.trimRight().runes.length;
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index 8c67ebc..d50b092 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -88,10 +88,6 @@
     return Future.wait(loads);
   }
 
-  Future refreshCoverage() {
-    return cls.refreshCoverage();
-  }
-
   onSampleBufferChange(CpuProfile sampleBuffer) {
     stackTraceTreeConfigElement.show = sampleBuffer.sampleCount > 0;
     cpuProfileTreeElement.show = sampleBuffer.sampleCount > 0;
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 6e59887..60e8ee0 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -24,7 +24,6 @@
       <library-nav-menu library="{{ cls.library }}"></library-nav-menu>
       <class-nav-menu cls="{{ cls }}" last="{{ true }}"></class-nav-menu>
       <nav-refresh callback="{{ refreshAllocationProfile }}" label="Refresh Allocation Profile"></nav-refresh>
-      <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
     </nav-bar>
 
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index cf78a26..06f91e7 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -8,6 +8,7 @@
 import 'dart:html';
 import 'dart:math';
 import 'observatory_element.dart';
+import 'nav_bar.dart';
 import 'package:observatory/app.dart';
 import 'package:observatory/cli.dart';
 import 'package:observatory/debugger.dart';
@@ -1067,28 +1068,6 @@
       'Syntax: info <subcommand>\n';
 }
 
-class RefreshCoverageCommand extends DebuggerCommand {
-  RefreshCoverageCommand(Debugger debugger) : super(debugger, 'coverage', []);
-
-  Future run(List<String> args) {
-    Set<Script> scripts = debugger.stackElement.activeScripts();
-    List pending = [];
-    for (var script in scripts) {
-      pending.add(script.refreshCoverage().then((_) {
-          debugger.console.print('Refreshed coverage for ${script.name}');
-        }));
-    }
-    return Future.wait(pending);
-  }
-
-  String helpShort = 'Refresh code coverage information for current frames';
-
-  String helpLong =
-      'Refresh code coverage information for current frames.\n'
-      '\n'
-      'Syntax: refresh coverage\n\n';
-}
-
 class RefreshStackCommand extends DebuggerCommand {
   RefreshStackCommand(Debugger debugger) : super(debugger, 'stack', []);
 
@@ -1106,7 +1085,6 @@
 
 class RefreshCommand extends DebuggerCommand {
   RefreshCommand(Debugger debugger) : super(debugger, 'refresh', [
-      new RefreshCoverageCommand(debugger),
       new RefreshStackCommand(debugger),
   ]);
 
@@ -1400,7 +1378,6 @@
       if ((breakOnException != iso.exceptionsPauseInfo) &&
           (iso.exceptionsPauseInfo != null)) {
         breakOnException = iso.exceptionsPauseInfo;
-        console.print("Now pausing for exceptions: $breakOnException");
       }
 
       _isolate.reload().then((response) {
@@ -1515,6 +1492,25 @@
     warnOutOfDate();
   }
 
+  void _reportIsolateError(Isolate isolate) {
+    if (isolate == null) {
+      return;
+    }
+    DartError error = isolate.error;
+    if (error == null) {
+      return;
+    }
+    console.newline();
+    console.printBold('Isolate exited due to an unhandled exception:');
+    console.print(error.message);
+    console.newline();
+    console.printBold("Type 'set break-on-exception Unhandled' to pause the"
+                      " isolate when an unhandled exception occurs.");
+    console.newline();
+    console.printBold("You can make this the default by running with "
+                      "--pause-isolates-on-unhandled-exceptions");
+  }
+
   void _reportPause(ServiceEvent event) {
     if (event.kind == ServiceEvent.kPauseStart) {
       console.print(
@@ -1524,6 +1520,7 @@
       console.print(
           "Paused at isolate exit "
           "(type 'continue' or [F7] to exit the isolate')");
+      _reportIsolateError(isolate);
     } else if (stack['frames'].length > 0) {
       Frame frame = stack['frames'][0];
       var script = frame.location.script;
@@ -1640,8 +1637,11 @@
       case ServiceEvent.kPauseInterrupted:
       case ServiceEvent.kPauseException:
         if (event.owner == isolate) {
-          _refreshStack(event).then((_) {
+          _refreshStack(event).then((_) async {
             flushStdio();
+            if (isolate != null) {
+              await isolate.reload();
+            }
             _reportPause(event);
           });
         }
@@ -1896,6 +1896,7 @@
     var stackElement = $['stackElement'];
     debugger.stackElement = stackElement;
     stackElement.debugger = debugger;
+    stackElement.scroller = $['stackDiv'];
     debugger.console = $['console'];
     debugger.input = $['commandline'];
     debugger.input.debugger = debugger;
@@ -1952,7 +1953,8 @@
     var splitterDiv = $['splitterDiv'];
     var cmdDiv = $['commandDiv'];
 
-    int navbarHeight = navbarDiv.clientHeight;
+    // For now, force navbar height to 40px in the debugger.
+    int navbarHeight = NavBarElement.height;
     int splitterHeight = splitterDiv.clientHeight;
     int cmdHeight = cmdDiv.clientHeight;
 
@@ -1960,6 +1962,7 @@
     int fixedHeight = navbarHeight + splitterHeight + cmdHeight;
     int available = windowHeight - fixedHeight;
     int stackHeight = available ~/ 1.6;
+    navbarDiv.style.setProperty('height', '${navbarHeight}px');
     stackDiv.style.setProperty('height', '${stackHeight}px');
   }
 
@@ -1987,6 +1990,7 @@
 @CustomTag('debugger-stack')
 class DebuggerStackElement extends ObservatoryElement {
   @published Isolate isolate;
+  @published Element scroller;
   @observable bool hasStack = false;
   @observable bool hasMessages = false;
   @observable bool isSampled = false;
@@ -1996,6 +2000,7 @@
   _addFrame(List frameList, Frame frameInfo) {
     DebuggerFrameElement frameElement = new Element.tag('debugger-frame');
     frameElement.frame = frameInfo;
+    frameElement.scroller = scroller;
 
     if (frameInfo.index == currentFrame) {
       frameElement.setCurrent(true);
@@ -2122,15 +2127,6 @@
     }
   }
 
-  Set<Script> activeScripts() {
-    var s = new Set<Script>();
-    List frameElements = $['frameList'].children;
-    for (var frameElement in frameElements) {
-      s.add(frameElement.children[0].script);
-    }
-    return s;
-  }
-
   Future doPauseIsolate() {
     if (debugger != null) {
       return debugger.isolate.pause();
@@ -2153,6 +2149,7 @@
 @CustomTag('debugger-frame')
 class DebuggerFrameElement extends ObservatoryElement {
   @published Frame frame;
+  @published Element scroller;
 
   // Is this the current frame?
   bool _current = false;
@@ -2167,17 +2164,14 @@
       var frameOuter = $['frameOuter'];
       if (_current) {
         frameOuter.classes.add('current');
-        expanded = true;
-        frameOuter.classes.add('shadow');
+        _expand();
         scrollIntoView();
       } else {
         frameOuter.classes.remove('current');
         if (_pinned) {
-          expanded = true;
-          frameOuter.classes.add('shadow');
+          _expand();
         } else {
-          expanded = false;
-          frameOuter.classes.remove('shadow');
+          _unexpand();
         }
       }
       busy = false;
@@ -2190,7 +2184,6 @@
 
   DebuggerFrameElement.created() : super.created();
 
-
   String makeExpandKey(String key) {
     return '${frame.function.qualifiedName}/${key}';
   }
@@ -2206,11 +2199,87 @@
 
   Script get script => frame.location.script;
 
+  int _varsTop(varsDiv) {
+    const minTop = 5;
+    if (varsDiv == null) {
+      return minTop;
+    }
+    const navbarHeight = NavBarElement.height;
+    const bottomPad = 6;
+    var parent = varsDiv.parent.getBoundingClientRect();
+    var varsHeight = varsDiv.clientHeight;
+    var maxTop = parent.height - (varsHeight + bottomPad);
+    var adjustedTop = navbarHeight - parent.top;
+    return (max(minTop, min(maxTop, adjustedTop)));
+  }
+
+  void _onScroll(event) {
+    if (!expanded) {
+      return;
+    }
+    var varsDiv = shadowRoot.querySelector('#vars');
+    if (varsDiv == null) {
+      return;
+    }
+    var currentTop = varsDiv.style.top;
+    var newTop = _varsTop(varsDiv);
+    if (currentTop != newTop) {
+      varsDiv.style.top = '${newTop}px';
+    }
+  }
+
+  void _expand() {
+    var frameOuter = $['frameOuter'];
+    expanded = true;
+    frameOuter.classes.add('shadow');
+    _subscribeToScroll();
+  }
+
+  void _unexpand() {
+    var frameOuter = $['frameOuter'];
+    expanded = false;
+    _unsubscribeToScroll();
+    frameOuter.classes.remove('shadow');
+  }
+
+  StreamSubscription _scrollSubscription;
+  StreamSubscription _resizeSubscription;
+
+  void _subscribeToScroll() {
+    if (scroller != null) {
+      if (_scrollSubscription == null) {
+        _scrollSubscription = scroller.onScroll.listen(_onScroll);
+      }
+      if (_resizeSubscription == null) {
+        _resizeSubscription = window.onResize.listen(_onScroll);
+      }
+    }
+  }
+
+  void _unsubscribeToScroll() {
+    if (_scrollSubscription != null) {
+      _scrollSubscription.cancel();
+      _scrollSubscription = null;
+    }
+    if (_resizeSubscription != null) {
+      _resizeSubscription.cancel();
+      _resizeSubscription = null;
+    }
+  }
+
   @override
   void attached() {
     super.attached();
     int windowHeight = window.innerHeight;
     scriptHeight = '${windowHeight ~/ 1.6}px';
+    if (expanded) {
+      _subscribeToScroll();
+    }
+  }
+
+  void detached() {
+    _unsubscribeToScroll();
+    super.detached();
   }
 
   void toggleExpand(var a, var b, var c) {
@@ -2220,13 +2289,10 @@
     busy = true;
     frame.function.load().then((func) {
         _pinned = !_pinned;
-        var frameOuter = $['frameOuter'];
         if (_pinned) {
-          expanded = true;
-          frameOuter.classes.add('shadow');
+          _expand();
         } else {
-          expanded = false;
-          frameOuter.classes.remove('shadow');
+          _unexpand();
         }
         busy = false;
       });
diff --git a/runtime/observatory/lib/src/elements/debugger.html b/runtime/observatory/lib/src/elements/debugger.html
index 981f260..20e2e4d 100644
--- a/runtime/observatory/lib/src/elements/debugger.html
+++ b/runtime/observatory/lib/src/elements/debugger.html
@@ -238,6 +238,12 @@
         flex-basis: 250px;
         overflow-x: hidden;
       }
+      #vars {
+        position: relative;
+        top: 5px;
+        padding-left:2em;
+        padding-bottom: 5px;
+      }
     </style>
     <div id="frameOuter" class="frameOuter">
       <a on-click="{{ toggleExpand }}">
@@ -263,11 +269,12 @@
                             location="{{ frame.function.location }}"
                             currentPos="{{ frame.location.tokenPos }}"
                             inDebuggerContext="{{ true }}"
+                            scroller="{{ scroller }}"
                             variables="{{ frame.variables }}">
               </source-inset>
             </div>
             <div class="flex-item-vars">
-              <div style="padding-left:2em;" class="memberList">
+              <div id="vars" class="memberList">
                 <template repeat="{{ v in properLocals }}">
                   {{ v['name']}}&nbsp;:&nbsp;
                   <any-service-ref ref="{{ v['value'] }}"
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index 5b0d8ec..58f206b 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -18,8 +18,4 @@
   Future refresh() {
     return function.reload();
   }
-
-  Future refreshCoverage() {
-    return function.refreshCoverage();
-  }
 }
diff --git a/runtime/observatory/lib/src/elements/function_view.html b/runtime/observatory/lib/src/elements/function_view.html
index 57e2c8c..a087382 100644
--- a/runtime/observatory/lib/src/elements/function_view.html
+++ b/runtime/observatory/lib/src/elements/function_view.html
@@ -21,7 +21,6 @@
         <class-nav-menu cls="{{ function.dartOwner }}"></class-nav-menu>
       </template>
       <nav-menu link="{{ makeLink('/inspect', function) }}" anchor="{{ function.name }}" last="{{ true }}"></nav-menu>
-      <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
     </nav-bar>
 
diff --git a/runtime/observatory/lib/src/elements/isolate_view.dart b/runtime/observatory/lib/src/elements/isolate_view.dart
index fe4fd95..40738a1 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.dart
+++ b/runtime/observatory/lib/src/elements/isolate_view.dart
@@ -33,8 +33,4 @@
       await isolate.topFrame.function.load();
     }
   }
-
-  Future refreshCoverage() {
-    return isolate.refreshCoverage();
-  }
 }
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index 915930fc..b090fdd 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -28,7 +28,6 @@
       <top-nav-menu></top-nav-menu>
       <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
       <isolate-nav-menu isolate="{{ isolate }}" last="{{ true }}"></isolate-nav-menu>
-      <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
     </nav-bar>
 
diff --git a/runtime/observatory/lib/src/elements/library_view.dart b/runtime/observatory/lib/src/elements/library_view.dart
index 6b43ae3..3c9a256 100644
--- a/runtime/observatory/lib/src/elements/library_view.dart
+++ b/runtime/observatory/lib/src/elements/library_view.dart
@@ -30,8 +30,4 @@
     library.variables.forEach((variable) => loads.add(variable.reload()));
     return Future.wait(loads);
   }
-
-  Future refreshCoverage() {
-    return library.refreshCoverage();
-  }
 }
diff --git a/runtime/observatory/lib/src/elements/library_view.html b/runtime/observatory/lib/src/elements/library_view.html
index d43fe3e..51d2da8 100644
--- a/runtime/observatory/lib/src/elements/library_view.html
+++ b/runtime/observatory/lib/src/elements/library_view.html
@@ -20,7 +20,6 @@
       <vm-nav-menu vm="{{ library.isolate.vm }}"></vm-nav-menu>
       <isolate-nav-menu isolate="{{ library.isolate }}"></isolate-nav-menu>
       <library-nav-menu library="{{ library }}" last="{{ true }}"></library-nav-menu>
-      <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
       <nav-refresh callback="{{ refresh }}"></nav-refresh>
     </nav-bar>
 
diff --git a/runtime/observatory/lib/src/elements/nav_bar.dart b/runtime/observatory/lib/src/elements/nav_bar.dart
index db77700..3999db87 100644
--- a/runtime/observatory/lib/src/elements/nav_bar.dart
+++ b/runtime/observatory/lib/src/elements/nav_bar.dart
@@ -17,6 +17,9 @@
   @published bool notifyOnPause = true;
   @published bool pad = true;
 
+  // Desired nav var height in pixels.
+  static const height = 40;
+
   NavBarElement.created() : super.created();
 }
 
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 47bbff7..aa3c0a8 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -6,7 +6,9 @@
 
 import 'dart:async';
 import 'dart:html';
+import 'dart:math';
 import 'observatory_element.dart';
+import 'nav_bar.dart';
 import 'service_ref.dart';
 import 'package:observatory/service.dart';
 import 'package:observatory/utils.dart';
@@ -244,7 +246,7 @@
 
         for (var entry in callSite.entries) {
           var r = row();
-          r.append(cell(serviceRef(entry.receiverContainer)));
+          r.append(cell(serviceRef(entry.receiver)));
           r.append(cell(entry.count.toString()));
           r.append(cell(serviceRef(entry.target)));
           details.append(r);
@@ -374,16 +376,24 @@
   @published bool inDebuggerContext = false;
   @published ObservableList variables;
 
+  @published Element scroller;
+  RefreshButtonElement _refreshButton;
+
   int _currentLine;
   int _currentCol;
   int _startLine;
   int _endLine;
 
+  Map<int, List<ServiceMap>> _rangeMap = {};
+  Set _callSites = new Set<CallSite>();
+  Set _possibleBreakpointLines = new Set<int>();
+
   var annotations = [];
   var annotationsCursor;
 
   StreamSubscription _scriptChangeSubscription;
   Future<StreamSubscription> _debugSubscriptionFuture;
+  StreamSubscription _scrollSubscription;
 
   bool hasLoadedLibraryDeclarations = false;
 
@@ -402,11 +412,20 @@
     super.attached();
     _debugSubscriptionFuture =
         app.vm.listenEventStream(VM.kDebugStream, _onDebugEvent);
+    if (scroller != null) {
+      _scrollSubscription = scroller.onScroll.listen(_onScroll);
+    } else {
+      _scrollSubscription = window.onScroll.listen(_onScroll);
+    }
   }
 
   void detached() {
     cancelFutureSubscription(_debugSubscriptionFuture);
     _debugSubscriptionFuture = null;
+    if (_scrollSubscription != null) {
+      _scrollSubscription.cancel();
+      _scrollSubscription = null;
+    }
     if (_scriptChangeSubscription != null) {
       // Don't leak. If only Dart and Javascript exposed weak references...
       _scriptChangeSubscription.cancel();
@@ -415,6 +434,17 @@
     super.detached();
   }
 
+  void _onScroll(event) {
+    if (_refreshButton == null) {
+      return;
+    }
+    var currentTop = _refreshButton.style.top;
+    var newTop = _refreshButtonTop();
+    if (currentTop != newTop) {
+      _refreshButton.style.top = '${newTop}px';
+    }
+  }
+
   void _onDebugEvent(event) {
     if (script == null) {
       return;
@@ -486,11 +516,55 @@
     element.title = "Line did execute";
     return element;
   }
+  Element hitsCompiled(Element element) {
+    element.classes.add('hitsCompiled');
+    element.title = "Line in compiled function";
+    return element;
+  }
+  Element hitsNotCompiled(Element element) {
+    element.classes.add('hitsNotCompiled');
+    element.title = "Line in uncompiled function";
+    return element;
+  }
 
   Element container;
 
+  Future _refresh() async {
+    await update();
+  }
+
+  // Build _rangeMap and _callSites from a source report.
+  Future _refreshSourceReport() async {
+    var sourceReport = await script.isolate.getSourceReport(
+        [Isolate.kCallSitesReport, Isolate.kPossibleBreakpointsReport],
+        script, startPos, endPos);
+    _possibleBreakpointLines = getPossibleBreakpointLines(sourceReport, script);
+    _rangeMap.clear();
+    _callSites.clear();
+    for (var range in sourceReport['ranges']) {
+      int startLine = script.tokenToLine(range['startPos']);
+      int endLine = script.tokenToLine(range['endPos']);
+      for (var line = startLine; line <= endLine; line++) {
+        var rangeList = _rangeMap[line];
+        if (rangeList == null) {
+          _rangeMap[line] = [range];
+        } else {
+          rangeList.add(range);
+        }
+      }
+      if (range['compiled']) {
+        var rangeCallSites = range['callSites'];
+        if (rangeCallSites != null) {
+          for (var callSiteMap in rangeCallSites) {
+            _callSites.add(new CallSite.fromMap(callSiteMap, script));
+          }
+        }
+      }
+    }
+  }
+
   Task _updateTask;
-  void update() {
+  Future update() async {
     assert(_updateTask != null);
     if (script == null) {
       // We may have previously had a script.
@@ -500,13 +574,12 @@
       return;
     }
     if (!script.loaded) {
-      script.load().then((_) => update());
-      return;
+      await script.load();
     }
-
     if (_scriptChangeSubscription == null) {
       _scriptChangeSubscription = script.changes.listen((_) => update());
     }
+    await _refreshSourceReport();
 
     computeAnnotations();
 
@@ -803,7 +876,7 @@
   }
 
   void addCallSiteAnnotations() {
-    for (var callSite in script.callSites) {
+    for (var callSite in _callSites) {
       annotations.add(new CallSiteAnnotation(callSite));
     }
   }
@@ -828,10 +901,35 @@
     }
   }
 
+  int _refreshButtonTop() {
+    if (_refreshButton == null) {
+      return 5;
+    }
+    const padding = 5;
+    const navbarHeight = NavBarElement.height;
+    var rect = getBoundingClientRect();
+    var buttonHeight = _refreshButton.clientHeight;
+    return min(max(0, navbarHeight - rect.top) + padding,
+               rect.height - (buttonHeight + padding));
+  }
+
+  RefreshButtonElement _newRefreshButton() {
+    var button = new Element.tag('refresh-button');
+    button.style.position = 'absolute';
+    button.style.display = 'inline-block';
+    button.style.top = '${_refreshButtonTop()}px';
+    button.style.right = '5px';
+    button.callback = _refresh;
+    return button;
+  }
+
   Element linesTable() {
     var table = new DivElement();
     table.classes.add("sourceTable");
 
+    _refreshButton = _newRefreshButton();
+    table.append(_refreshButton);
+
     if (_startLine == null || _endLine == null) {
       return table;
     }
@@ -904,35 +1002,38 @@
 
   Element lineBreakpointElement(ScriptLine line) {
     var e = new DivElement();
-    var busy = false;
-    if (line == null || !line.possibleBpt) {
-      e.classes.add("emptyBreakpoint");
+    if (line == null || !_possibleBreakpointLines.contains(line.line)) {
       e.classes.add('noCopy');
+      e.classes.add("emptyBreakpoint");
       e.text = nbsp;
       return e;
     }
+
     e.text = 'B';
-    update() {
+    var busy = false;
+    void update() {
       e.classes.clear();
       e.classes.add('noCopy');
-
-      if (!line.possibleBpt) {
-        e.classes.add("emptyBreakpoint");
-        e.text = nbsp;
-      } else if (busy) {
+      if (busy) {
         e.classes.add("busyBreakpoint");
-      } else {
-        if (line.breakpoints != null) {
-          if (line.breakpointResolved) {
-            e.classes.add("resolvedBreakpoint");
-          } else {
-            e.classes.add("unresolvedBreakpoint");
+      } else if (line.breakpoints != null) {
+        bool resolved = false;
+        for (var bpt in line.breakpoints) {
+          if (bpt.resolved) {
+            resolved = true;
+            break;
           }
-        } else {
-          e.classes.add("possibleBreakpoint");
         }
+        if (resolved) {
+          e.classes.add("resolvedBreakpoint");
+        } else {
+          e.classes.add("unresolvedBreakpoint");
+        }
+      } else {
+        e.classes.add("possibleBreakpoint");
       }
     }
+
     line.changes.listen((_) => update());
     e.onClick.listen((event) {
       if (busy) {
@@ -973,17 +1074,51 @@
     var lineNumber = line == null ? "..." : line.line;
     var e = span("$nbsp${lineNumber.toString().padLeft(lineNumPad,nbsp)}$nbsp");
     e.classes.add('noCopy');
-
     if (lineNumber == _currentLine) {
       hitsCurrent(e);
-    } else if ((line == null) || (line.hits == null)) {
-      hitsUnknown(e);
-    } else if (line.hits == 0) {
-      hitsNotExecuted(e);
-    } else {
-      hitsExecuted(e);
+      return e;
     }
-
+    var ranges = _rangeMap[lineNumber];
+    if ((ranges == null) || ranges.isEmpty) {
+      // This line is not code.
+      hitsUnknown(e);
+      return e;
+    }
+    bool compiled = true;
+    bool hasCallInfo = false;
+    bool executed = false;
+    for (var range in ranges) {
+      if (range['compiled']) {
+        for (var callSite in range['callSites']) {
+          var callLine = line.script.tokenToLine(callSite['tokenPos']);
+          if (lineNumber == callLine) {
+            // The call site is on the current line.
+            hasCallInfo = true;
+            for (var cacheEntry in callSite['cacheEntries']) {
+              if (cacheEntry['count'] > 0) {
+                // If any call site on the line has been executed, we
+                // mark the line as executed.
+                executed = true;
+                break;
+              }
+            }
+          }
+        }
+      } else {
+        // If any range isn't compiled, show the line as not compiled.
+        // This is necessary so that nested functions appear to be uncompiled.
+        compiled = false;
+      }
+    }
+    if (executed) {
+      hitsExecuted(e);
+    } else if (hasCallInfo) {
+      hitsNotExecuted(e);
+    } else if (compiled) {
+      hitsCompiled(e);
+    } else {
+      hitsNotCompiled(e);
+    }
     return e;
   }
 
@@ -1036,6 +1171,26 @@
   }
 }
 
+@CustomTag('refresh-button')
+class RefreshButtonElement extends PolymerElement {
+  RefreshButtonElement.created() : super.created();
+
+  @published var callback = null;
+  bool busy = false;
+
+  Future buttonClick(var event, var b, var c) async {
+    if (busy) {
+      return;
+    }
+    busy = true;
+    if (callback != null) {
+      await callback();
+    }
+    busy = false;
+  }
+}
+
+
 @CustomTag('source-inset')
 class SourceInsetElement extends PolymerElement {
   SourceInsetElement.created() : super.created();
@@ -1045,4 +1200,5 @@
   @published int currentPos;
   @published bool inDebuggerContext = false;
   @published ObservableList variables;
+  @published Element scroller;
 }
diff --git a/runtime/observatory/lib/src/elements/script_inset.html b/runtime/observatory/lib/src/elements/script_inset.html
index a76ae42..92d2940 100644
--- a/runtime/observatory/lib/src/elements/script_inset.html
+++ b/runtime/observatory/lib/src/elements/script_inset.html
@@ -1,6 +1,19 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="observatory_element.html">
 
+<polymer-element name="icon-refresh" noscript>
+  <template>
+    <style>
+      svg {
+        fill: currentColor
+      }
+    </style>
+    <svg width="24" height="24">
+      <path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/>
+    </svg>
+  </template>
+</polymer-element>
+
 <polymer-element name="script-inset" extends="observatory-element">
   <template>
     <style>
@@ -14,6 +27,7 @@
       .sourceInset {
       }
       .sourceTable {
+        position: relative;
         background-color: #f5f5f5;
         border: 1px solid #ccc;
         padding: 10px;
@@ -39,7 +53,7 @@
       .currentCol {
         background-color: #6cf;
       }
-      .hitsCurrent, .hitsNone, .hitsNotExecuted, .hitsExecuted {
+      .hitsCurrent, .hitsNone, .hitsNotExecuted, .hitsExecuted, .hitsCompiled, .hitsNotCompiled {
         display: table-cell;
         vertical-align: top;
         font: 400 14px consolas, courier, monospace;
@@ -58,6 +72,13 @@
       .hitsExecuted {
         background-color: #aea;
       }
+      .hitsCompiled {
+        background-color: #e0e0e0;
+      }
+      .hitsNotCompiled {
+        background-color: #f0c5c5;
+      }
+
       .noCopy {}
       .emptyBreakpoint, .possibleBreakpoint, .busyBreakpoint, .unresolvedBreakpoint, .resolvedBreakpoint  {
         display: table-cell;
@@ -99,12 +120,40 @@
   </template>
 </polymer-element>
 
+<polymer-element name="refresh-button">
+  <template>
+    <style>
+      .refreshButton {
+        color: rgba(0,0,0,.3);
+      }
+      .refreshButton:hover {
+        color: black;
+      }
+      .refreshButtonDisabled {
+        color: white;
+        cursor: wait;
+      }
+    </style>
+    <template if="{{ callback != null }}">
+      <template if="{{ busy }}">
+        <icon-refresh id="refreshIcon" class="refreshButtonDisabled">
+        </icon-refresh>
+      </template>
+      <template if="{{ !busy }}">
+        <a on-click="{{ buttonClick }}">
+          <icon-refresh id="refreshIcon" class="refreshButton"></icon-refresh>
+        </a>
+      </template>
+    </template>
+  </template>
+</polymer-element>
 
 <polymer-element name="source-inset">
 <template>
   <template if="{{ location != null }}">
     <script-inset script="{{ location.script }}"
                   startPos="{{ location.tokenPos }}"
+                  scroller="{{ scroller }}"
                   endPos="{{ location.endTokenPos }}"
                   height="{{ height }}"
                   currentPos="{{ currentPos }}"
diff --git a/runtime/observatory/lib/src/elements/script_view.dart b/runtime/observatory/lib/src/elements/script_view.dart
index ff07a80..c896b8d 100644
--- a/runtime/observatory/lib/src/elements/script_view.dart
+++ b/runtime/observatory/lib/src/elements/script_view.dart
@@ -20,8 +20,4 @@
   Future refresh() {
     return script.reload();
   }
-
-  Future refreshCoverage() {
-    return script.refreshCoverage();
-  }
 }
diff --git a/runtime/observatory/lib/src/elements/script_view.html b/runtime/observatory/lib/src/elements/script_view.html
index 1dc23b4..c65fa49 100644
--- a/runtime/observatory/lib/src/elements/script_view.html
+++ b/runtime/observatory/lib/src/elements/script_view.html
@@ -13,7 +13,6 @@
     <isolate-nav-menu isolate="{{ script.isolate }}"></isolate-nav-menu>
     <library-nav-menu library="{{ script.library }}"></library-nav-menu>
     <nav-menu link="{{ makeLink('/inspect', script) }}" anchor="{{ script.name }}" last="{{ true }}"></nav-menu>
-    <nav-refresh callback="{{ refreshCoverage }}" label="Refresh Coverage"></nav-refresh>
     <nav-refresh callback="{{ refresh }}"></nav-refresh>
   </nav-bar>
 
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index e45cb8d..abc1ea4 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -395,40 +395,6 @@
   }
 }
 
-abstract class Coverage {
-  // Following getters and functions will be provided by [ServiceObject].
-  String get id;
-  Isolate get isolate;
-
-  Future refreshCoverage() {
-    return refreshCallSiteData();
-  }
-
-  /// Default handler for coverage data.
-  void processCallSiteData(List coverageData) {
-    coverageData.forEach((scriptCoverage) {
-      assert(scriptCoverage['script'] != null);
-      scriptCoverage['script']._processCallSites(scriptCoverage['callSites']);
-    });
-  }
-
-  Future refreshCallSiteData() {
-    Map params = {};
-    if (this is! Isolate) {
-      params['targetId'] = id;
-    }
-    return isolate.invokeRpcNoUpgrade('_getCallSiteData', params).then(
-        (ObservableMap map) {
-          var coverage = new ServiceObject._fromMap(isolate, map);
-          assert(coverage.type == 'CodeCoverage');
-          var coverageList = coverage['coverage'];
-          assert(coverageList != null);
-          processCallSiteData(coverageList);
-          return this;
-        });
-  }
-}
-
 abstract class ServiceObjectOwner extends ServiceObject {
   /// Creates an empty [ServiceObjectOwner].
   ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner);
@@ -1135,7 +1101,7 @@
 }
 
 /// State for a running isolate.
-class Isolate extends ServiceObjectOwner with Coverage {
+class Isolate extends ServiceObjectOwner {
   static const kLoggingStream = '_Logging';
   static const kExtensionStream = 'Extension';
 
@@ -1194,6 +1160,26 @@
     });
   }
 
+  static const kCallSitesReport = '_CallSites';
+  static const kPossibleBreakpointsReport = 'PossibleBreakpoints';
+
+  Future<ServiceMap> getSourceReport(List<String> report_kinds,
+                                     [Script script,
+                                      int startPos,
+                                      int endPos]) {
+    var params = { 'reports' : report_kinds };
+    if (script != null) {
+      params['scriptId'] = script.id;
+    }
+    if (startPos != null) {
+      params['tokenPos'] = startPos;
+    }
+    if (endPos != null) {
+      params['endTokenPos'] = endPos;
+    }
+    return invokeRpc('_getSourceReport', params);
+  }
+
   /// Fetches and builds the class hierarchy for this isolate. Returns the
   /// Object class object.
   Future<Class> getClassHierarchy() {
@@ -1536,34 +1522,15 @@
     }
   }
 
-  Future<ServiceObject> addBreakpoint(
-      Script script, int line, [int col]) async {
-    // TODO(turnidge): Pass line as an int instead of a string.
-    try {
-      Map params = {
-        'scriptId': script.id,
-        'line': line.toString(),
-      };
-      if (col != null) {
-        params['column'] = col.toString();
-      }
-      Breakpoint bpt = await invokeRpc('addBreakpoint', params);
-      if (bpt.resolved && script.loaded) {
-        SourceLocation loc = bpt.location;
-        if (script.tokenToLine(loc.tokenPos) != line) {
-          script.getLine(line).possibleBpt = false;
-        }
-      }
-      return bpt;
-    } on ServerRpcException catch(e) {
-      if (e.code == ServerRpcException.kCannotAddBreakpoint) {
-        // Unable to set a breakpoint at the desired line.
-        if (script.loaded) {
-          script.getLine(line).possibleBpt = false;
-        }
-      }
-      rethrow;
+  Future<ServiceObject> addBreakpoint(Script script, int line, [int col]) {
+    Map params = {
+      'scriptId': script.id,
+      'line': line,
+    };
+    if (col != null) {
+      params['column'] = col;
     }
+    return invokeRpc('addBreakpoint', params);
   }
 
   Future<ServiceObject> addBreakpointByScriptUri(
@@ -2115,7 +2082,7 @@
 }
 
 
-class Library extends HeapObject with Coverage {
+class Library extends HeapObject {
   @observable String uri;
   @reflectable final dependencies = new ObservableList<LibraryDependency>();
   @reflectable final scripts = new ObservableList<Script>();
@@ -2213,7 +2180,7 @@
   bool get empty => accumulated.empty && current.empty;
 }
 
-class Class extends HeapObject with Coverage {
+class Class extends HeapObject {
   @observable Library library;
 
   @observable bool isAbstract;
@@ -2592,7 +2559,7 @@
   static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN');
 }
 
-class ServiceFunction extends HeapObject with Coverage {
+class ServiceFunction extends HeapObject {
   // owner is a Library, Class, or ServiceFunction.
   @observable ServiceObject dartOwner;
   @observable Library library;
@@ -2738,21 +2705,21 @@
   final Script script;
   final int line;
   final String text;
-  @observable int hits;
-  @observable bool possibleBpt = true;
-  @observable bool breakpointResolved = false;
   @observable Set<Breakpoint> breakpoints;
 
-  bool get isBlank {
-    // Compute isBlank on demand.
-    if (_isBlank == null) {
-      _isBlank = text.trim().isEmpty;
-    }
-    return _isBlank;
-  }
-  bool _isBlank;
+  ScriptLine(this.script, this.line, this.text);
 
-  bool get isTrivialLine => !possibleBpt;
+  bool get isBlank {
+    return text.isEmpty || text.trim().isEmpty;
+  }
+
+  bool _isTrivial = null;
+  bool get isTrivial {
+    if (_isTrivial == null) {
+      _isTrivial = _isTrivialLine(text);
+    }
+    return _isTrivial;
+  }
 
   static bool _isTrivialToken(String token) {
     if (token == 'else') {
@@ -2789,16 +2756,11 @@
     return true;
   }
 
-  ScriptLine(this.script, this.line, this.text) {
-    possibleBpt = !_isTrivialLine(text);
-  }
-
   void addBreakpoint(Breakpoint bpt) {
     if (breakpoints == null) {
       breakpoints = new Set<Breakpoint>();
     }
     breakpoints.add(bpt);
-    breakpointResolved = breakpointResolved || bpt.resolved;
   }
 
   void removeBreakpoint(Breakpoint bpt) {
@@ -2806,7 +2768,6 @@
     breakpoints.remove(bpt);
     if (breakpoints.isEmpty) {
       breakpoints = null;
-      breakpointResolved = false;
     }
   }
 }
@@ -2850,19 +2811,19 @@
 }
 
 class CallSiteEntry {
-  final /* Class | Library */ receiverContainer;
+  final /* Class | Library */ receiver;
   final int count;
   final ServiceFunction target;
 
-  CallSiteEntry(this.receiverContainer, this.count, this.target);
+  CallSiteEntry(this.receiver, this.count, this.target);
 
   factory CallSiteEntry.fromMap(Map entryMap) {
-    return new CallSiteEntry(entryMap['receiverContainer'],
+    return new CallSiteEntry(entryMap['receiver'],
                              entryMap['count'],
                              entryMap['target']);
   }
 
-  String toString() => "CallSiteEntry(${receiverContainer.name}, $count)";
+  String toString() => "CallSiteEntry(${receiver.name}, $count)";
 }
 
 /// The location of a local variable reference in a script.
@@ -2873,10 +2834,8 @@
   LocalVarLocation(this.line, this.column, this.endColumn);
 }
 
-class Script extends HeapObject with Coverage {
-  Set<CallSite> callSites = new Set<CallSite>();
+class Script extends HeapObject {
   final lines = new ObservableList<ScriptLine>();
-  final _hits = new Map<int, int>();
   @observable String uri;
   @observable String kind;
   @observable int firstTokenPos;
@@ -3021,36 +2980,6 @@
         _tokenToCol[tokenOffset] = colNumber;
       }
     }
-
-    for (var line in lines) {
-      // Remove possible breakpoints on lines with no tokens.
-      if (!lineSet.contains(line.line)) {
-        line.possibleBpt = false;
-      }
-    }
-  }
-
-  void _processCallSites(List newCallSiteMaps) {
-    var mergedCallSites = new Set<CallSite>();
-    for (var callSiteMap in newCallSiteMaps) {
-      var newSite = new CallSite.fromMap(callSiteMap, this);
-      mergedCallSites.add(newSite);
-
-      var line = newSite.line;
-      var hit = newSite.aggregateCount;
-      assert(line >= 1); // Lines start at 1.
-      var oldHits = _hits[line];
-      if (oldHits != null) {
-        hit += oldHits;
-      }
-      _hits[line] = hit;
-    }
-
-    mergedCallSites.addAll(callSites);
-    callSites = mergedCallSites;
-    _applyHitsToLines();
-    // Notify any Observers that this Script's state has changed.
-    notifyChange(null);
   }
 
   void _processSource(String source) {
@@ -3072,18 +3001,10 @@
       }
     }
 
-    _applyHitsToLines();
     // Notify any Observers that this Script's state has changed.
     notifyChange(null);
   }
 
-  void _applyHitsToLines() {
-    for (var line in lines) {
-      var hits = _hits[line.line];
-      line.hits = hits;
-    }
-  }
-
   void _addBreakpoint(Breakpoint bpt) {
     var line;
     if (bpt.location.tokenPos != null) {
@@ -3174,7 +3095,7 @@
 
     if (line == lastLine) {
       // Only one line.
-      if (!getLine(line).isTrivialLine) {
+      if (!getLine(line).isTrivial) {
         // TODO(johnmccutchan): end token pos -> column can lie for snapshotted
         // code. e.g.:
         // io_sink.dart source line 23 ends at column 39
@@ -3190,7 +3111,7 @@
     }
 
     // Scan first line.
-    if (!getLine(line).isTrivialLine) {
+    if (!getLine(line).isTrivial) {
       lineContents = getLine(line).text.substring(column);
       r.addAll(scanLineForLocalVariableLocations(pattern,
                                                   name,
@@ -3201,7 +3122,7 @@
 
     // Scan middle lines.
     while (line < (lastLine - 1)) {
-      if (getLine(line).isTrivialLine) {
+      if (getLine(line).isTrivial) {
         line++;
         continue;
       }
@@ -3215,7 +3136,7 @@
     }
 
     // Scan last line.
-    if (!getLine(line).isTrivialLine) {
+    if (!getLine(line).isTrivial) {
       // TODO(johnmccutchan): end token pos -> column can lie for snapshotted
       // code. e.g.:
       // io_sink.dart source line 23 ends at column 39
@@ -4025,6 +3946,48 @@
 }
 
 
+// Helper function to extract possible breakpoint locations from a
+// SourceReport for some script.
+Set<int> getPossibleBreakpointLines(ServiceMap report, Script script) {
+  var result = new Set<int>();
+  int scriptIndex;
+  int numScripts = report['scripts'].length;
+  for (scriptIndex = 0; scriptIndex < numScripts; scriptIndex++) {
+    if (report['scripts'][scriptIndex].id == script.id) {
+      break;
+    }
+  }
+  if (scriptIndex == numScripts) {
+    return result;
+  }
+  var ranges = report['ranges'];
+  if (ranges != null) {
+    for (var range in ranges) {
+      if (range['scriptIndex'] != scriptIndex) {
+        continue;
+      }
+      if (range['compiled']) {
+        var possibleBpts = range['possibleBreakpoints'];
+        if (possibleBpts != null) {
+          for (var tokenPos in possibleBpts) {
+            result.add(script.tokenToLine(tokenPos));
+          }
+        }
+      } else {
+        int startLine = script.tokenToLine(range['startPos']);
+        int endLine = script.tokenToLine(range['endPos']);
+        for (int line = startLine; line <= endLine; line++) {
+          if (!script.getLine(line).isTrivial) {
+            result.add(line);
+          }
+        }
+      }
+    }
+  }
+  return result;
+}
+
+
 // Returns true if [map] is a service map. i.e. it has the following keys:
 // 'id' and a 'type'.
 bool _isServiceMap(ObservableMap m) {
diff --git a/runtime/observatory/tests/service/caching_test.dart b/runtime/observatory/tests/service/caching_test.dart
index 8a72447..6194ba6 100644
--- a/runtime/observatory/tests/service/caching_test.dart
+++ b/runtime/observatory/tests/service/caching_test.dart
@@ -13,27 +13,14 @@
 import 'package:unittest/unittest.dart';
 import 'test_helper.dart';
 
-script() {
-  print("This executed");
-}
-
-hasSomeCoverageData(Script script) {
-  for (var line in script.lines) {
-    if (line.hits != null) return true;
-  }
-  return false;
-}
-
 var tests = [
 (Isolate isolate) async {
   Library lib = await isolate.rootLibrary.load();
   Script script = await lib.scripts.single.load();
-  expect(hasSomeCoverageData(script), isFalse);
-  Script script2 = await script.refreshCoverage();
+  Script script2 = await isolate.getObject(script.id);
   expect(identical(script, script2), isTrue);
-  expect(hasSomeCoverageData(script), isTrue);
 },
 
 ];
 
-main(args) => runIsolateTests(args, tests, testeeBefore: script);
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/coverage_test.dart b/runtime/observatory/tests/service/coverage_test.dart
index 0255687..d1c71eb 100644
--- a/runtime/observatory/tests/service/coverage_test.dart
+++ b/runtime/observatory/tests/service/coverage_test.dart
@@ -69,7 +69,7 @@
   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]));
+                 24, 1, 25, 1, 27, 0, 13, 0]));
 
   // Library
   coverage = await isolate.invokeRpcNoUpgrade('_getCoverage',
@@ -78,7 +78,7 @@
   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]));
+                 24, 1, 25, 1, 27, 0, 13, 0]));
   expect(coverage['coverage'][1]['hits'],
          equals([33, 1, 34, 1, 105, 2]));
 
@@ -90,7 +90,7 @@
   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]));
+                 24, 1, 25, 1, 27, 0, 13, 0]));
   expect(coverage['coverage'][1]['hits'],
          equals([33, 1, 34, 1, 105, 2]));
 
@@ -102,4 +102,6 @@
 
 ];
 
-main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
+main(args) => runIsolateTests(args, tests,
+                              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 7825ae6..ab50f4d 100644
--- a/runtime/observatory/tests/service/debugger_location_test.dart
+++ b/runtime/observatory/tests/service/debugger_location_test.dart
@@ -236,9 +236,7 @@
       await DebuggerLocation.complete(debugger,
                                       'debugger_location_test.dart:11');
   expect(completions.toString(), equals(
-      '[debugger_location_test.dart:11 ,'
-      ' debugger_location_test.dart:11:,'
-      ' debugger_location_test.dart:110 ,'
+      '[debugger_location_test.dart:110 ,'
       ' debugger_location_test.dart:110:,'
       ' debugger_location_test.dart:111 ,'
       ' debugger_location_test.dart:111:,'
diff --git a/runtime/observatory/tests/service/get_allocation_samples_test.dart b/runtime/observatory/tests/service/get_allocation_samples_test.dart
index 698fce5..a21ed9c 100644
--- a/runtime/observatory/tests/service/get_allocation_samples_test.dart
+++ b/runtime/observatory/tests/service/get_allocation_samples_test.dart
@@ -67,7 +67,7 @@
     var tree = cpuProfile.loadCodeTree('exclusive');
     var node = tree.root;
     var expected =
-        ['Root', 'test', 'test', '_FunctionImpl.call', 'runIsolateTests'];
+        ['Root', 'test', 'test', '_Closure.call', 'runIsolateTests'];
     for (var i = 0; i < expected.length; i++) {
       expect(node.profileCode.code.name, equals(expected[i]));
       // Depth first traversal.
diff --git a/runtime/observatory/tests/service/get_source_report_test.dart b/runtime/observatory/tests/service/get_source_report_test.dart
index 71345ee..d306bca 100644
--- a/runtime/observatory/tests/service/get_source_report_test.dart
+++ b/runtime/observatory/tests/service/get_source_report_test.dart
@@ -110,7 +110,7 @@
   expect(coverage['scripts'].length, greaterThan(1));
 
   // Multiple reports (make sure enum list parameter parsing works).
-  params = { 'reports' : ['CallSites', 'Coverage'],
+  params = { 'reports' : ['_CallSites', 'Coverage', 'PossibleBreakpoints'],
              'scriptId' : func.location.script.id,
              'tokenPos' : func.location.tokenPos,
              'endTokenPos' : func.location.endTokenPos };
@@ -120,6 +120,7 @@
   var range = coverage['ranges'][0];
   expect(range.containsKey('callSites'), isTrue);
   expect(range.containsKey('coverage'), isTrue);
+  expect(range.containsKey('possibleBreakpoints'), isTrue);
 
   // missing scriptId with tokenPos.
   bool caughtException = false;
diff --git a/runtime/observatory/tests/service/graph_test.dart b/runtime/observatory/tests/service/graph_test.dart
index 3cf8c46..fe31d16 100644
--- a/runtime/observatory/tests/service/graph_test.dart
+++ b/runtime/observatory/tests/service/graph_test.dart
@@ -71,9 +71,15 @@
                                       bVertex.shallowSize +
                                       rVertex.shallowSize));
 
-  const int fixedSizeListCid = 62;
+  Library corelib =
+      isolate.libraries.singleWhere((lib) => lib.uri == 'dart:core');
+  await corelib.load();
+  Class _List =
+      corelib.classes.singleWhere((cls) => cls.vmName.startsWith('_List'));
+  int kArrayCid = _List.vmCid;
+  // startsWith to ignore the private mangling
   List<ObjectVertex> lists = new List.from(graph.vertices.where(
-      (ObjectVertex obj) => obj.vmCid == fixedSizeListCid));
+      (ObjectVertex obj) => obj.vmCid == kArrayCid));
   expect(lists.length >= 2, isTrue);
   // Order by decreasing retained size.
   lists.sort((u, v) => v.retainedSize - u.retainedSize);
diff --git a/runtime/observatory/tests/service/issue_25465_test.dart b/runtime/observatory/tests/service/issue_25465_test.dart
new file mode 100644
index 0000000..3a739f0
--- /dev/null
+++ b/runtime/observatory/tests/service/issue_25465_test.dart
@@ -0,0 +1,71 @@
+// 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
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+testMain() {
+  var foo;      // line 11
+  foo = 42;     // line 12
+  print(foo);
+}
+
+var tests = [
+  hasPausedAtStart,
+
+  // Add breakpoints at line 11 and line 12.
+  (Isolate isolate) async {
+    var rootLib = isolate.rootLibrary;
+    await rootLib.load();
+    var script = rootLib.scripts[0];
+
+    var bpt1 = await isolate.addBreakpoint(script, 11);
+    var bpt2 = await isolate.addBreakpoint(script, 12);
+    expect(await bpt1.location.getLine(), equals(11));
+    expect(await bpt2.location.getLine(), equals(12));
+
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    Completer completer = new Completer();
+    var subscription;
+    var breakCount = 0;
+    subscription = stream.listen((ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        breakCount++;
+        print('break count is $breakCount');
+        if (breakCount == 1) {
+          // We are stopped at breakpoint 1.
+          expect(event.breakpoint.number, equals(bpt1.number));
+
+          // Remove both breakpoints
+          var result = await isolate.removeBreakpoint(bpt1);
+          expect(result.type, equals("Success"));
+
+          result = await isolate.removeBreakpoint(bpt2);
+          expect(result.type, equals("Success"));
+
+          isolate.stepOver();
+        } else {
+          // No breakpoint.
+          expect(event.breakpoint, isNull);
+
+          // We expect the next step to take us to line 12.
+          var stack = await isolate.getStack();
+          expect(await stack['frames'][0].location.getLine(), equals(12));
+
+          subscription.cancel();
+          completer.complete(null);
+        }
+      }
+    });
+    isolate.resume();
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+                              testeeConcurrent: testMain,
+                              pause_on_start: true);
diff --git a/runtime/observatory/tests/service/pause_on_unhandled_exceptions_test.dart b/runtime/observatory/tests/service/pause_on_unhandled_exceptions_test.dart
new file mode 100644
index 0000000..4a6b2dd
--- /dev/null
+++ b/runtime/observatory/tests/service/pause_on_unhandled_exceptions_test.dart
@@ -0,0 +1,27 @@
+// 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
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+doThrow() {
+  throw "TheException"; // Line 13.
+  return "end of doThrow";
+}
+
+var tests = [
+  hasStoppedWithUnhandledException,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    expect(stack['frames'][0].function.name, equals('doThrow'));
+  }
+];
+
+main(args) => runIsolateTests(args,
+                              tests,
+                              pause_on_unhandled_exceptions: true,
+                              testeeConcurrent: doThrow);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 7562cf4..8a572de 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -22,4 +22,7 @@
 process_service_test: Pass, Fail # Issue 24344
 
 [ ($noopt || $compiler == precompiler) ]
-*: Skip # Issue 24651
\ No newline at end of file
+*: Skip # Issue 24651
+
+[ $runtime == vm ]
+coverage_test: Pass Slow
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index 58de4e6..6e64180 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -26,7 +26,10 @@
                             Platform.script.toFilePath(),
                             _TESTEE_MODE_FLAG] {}
 
-  Future<int> launch(bool pause_on_start, bool pause_on_exit, bool trace_service) {
+  Future<int> launch(bool pause_on_start,
+                     bool pause_on_exit,
+                     bool pause_on_unhandled_exceptions,
+                     bool trace_service) {
     assert(pause_on_start != null);
     assert(pause_on_exit != null);
     assert(trace_service != null);
@@ -41,6 +44,9 @@
     if (pause_on_exit) {
       fullArgs.add('--pause-isolates-on-exit');
     }
+    if (pause_on_unhandled_exceptions) {
+      fullArgs.add('--pause-isolates-on-unhandled-exceptions');
+    }
     fullArgs.addAll(Platform.executableArguments);
     fullArgs.addAll(args);
     print('** Launching $dartExecutable ${fullArgs.join(' ')}');
@@ -110,7 +116,8 @@
                       bool pause_on_start: false,
                       bool pause_on_exit: false,
                       bool trace_service: false,
-                      bool verbose_vm: false}) {
+                      bool verbose_vm: false,
+                      bool pause_on_unhandled_exceptions: false}) {
   assert(!pause_on_start || testeeBefore == null);
   if (mainArgs.contains(_TESTEE_MODE_FLAG)) {
     if (!pause_on_start) {
@@ -128,7 +135,8 @@
     }
   } else {
     var process = new _TestLauncher();
-    process.launch(pause_on_start, pause_on_exit, trace_service).then((port) {
+    process.launch(pause_on_start, pause_on_exit,
+                   pause_on_unhandled_exceptions, trace_service).then((port) {
       if (mainArgs.contains("--gdb")) {
         port = 8181;
       }
@@ -157,15 +165,14 @@
   }
 }
 
-
-Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) {
+Future<Isolate> hasPausedFor(Isolate isolate, String kind) {
   // Set up a listener to wait for breakpoint events.
   Completer completer = new Completer();
   isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
     var subscription;
     subscription = stream.listen((ServiceEvent event) {
-        if (event.kind == ServiceEvent.kPauseBreakpoint) {
-          print('Breakpoint reached');
+        if (event.kind == kind) {
+          print('Paused with $kind');
           subscription.cancel();
           if (completer != null) {
             // Reload to update isolate.pauseEvent.
@@ -178,9 +185,9 @@
     // Pause may have happened before we subscribed.
     isolate.reload().then((_) {
       if ((isolate.pauseEvent != null) &&
-         (isolate.pauseEvent.kind == ServiceEvent.kPauseBreakpoint)) {
+         (isolate.pauseEvent.kind == kind)) {
         // Already waiting at a breakpoint.
-        print('Breakpoint reached');
+        print('Paused with $kind');
         subscription.cancel();
         if (completer != null) {
           completer.complete(isolate);
@@ -193,6 +200,13 @@
   return completer.future;  // Will complete when breakpoint hit.
 }
 
+Future<Isolate> hasStoppedAtBreakpoint(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint);
+}
+
+Future<Isolate> hasStoppedWithUnhandledException(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseException);
+}
 
 Future<Isolate> hasPausedAtStart(Isolate isolate) {
   // Set up a listener to wait for breakpoint events.
@@ -255,11 +269,13 @@
 
     Frame top = frames[0];
     Script script = await top.location.script.load();
-    if (script.tokenToLine(top.location.tokenPos) != line) {
+    int actualLine = script.tokenToLine(top.location.tokenPos);
+    if (actualLine != line) {
       var sb = new StringBuffer();
-      sb.write("Expected to be at line $line, but got stack trace:\n");
+      sb.write("Expected to be at line $line but actually at line $actualLine");
+      sb.write("\nFull stack trace:\n");
       for (Frame f in stack['frames']) {
-        sb.write(" $f\n");
+        sb.write(" $f [${await f.location.getLine()}]\n");
       }
       throw sb.toString();
     }
@@ -341,7 +357,8 @@
                    bool pause_on_start: false,
                    bool pause_on_exit: false,
                    bool trace_service: false,
-                   bool verbose_vm: false}) async {
+                   bool verbose_vm: false,
+                   bool pause_on_unhandled_exceptions: false}) async {
   if (mainArgs.contains(_TESTEE_MODE_FLAG)) {
     if (!pause_on_start) {
       if (testeeBefore != null) {
@@ -360,6 +377,7 @@
     var process = new _TestLauncher();
     process.launch(pause_on_start,
                    pause_on_exit,
+                   pause_on_unhandled_exceptions,
                    trace_service).then((port) async {
       if (mainArgs.contains("--gdb")) {
         port = 8181;
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index f5163a0..ade646c 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -21,6 +21,8 @@
 # TODO(koda): Improve support for negative tests.
 cc/VerifyImplicit_Crash: Crash, Timeout  # Timeout: Issue #24596
 cc/VerifyExplicit_Crash: Crash, Timeout  # Timeout: Issue #24596
+# It can take some time for all the isolates to shutdown in a Debug build.
+dart/spawn_shutdown_test: Pass, Slow  # VM Shutdown test
 
 # The following section refers to the dart vm tests which live under
 # runtime/tests/vm/dart.
@@ -31,7 +33,7 @@
 cc/Dart2JSCompilerStats: Skip
 cc/CorelibCompilerStats: Skip
 
-[ $arch == simarm || $arch == simarmv5te || $arch == simarm64 || $arch == simmips ]
+[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simarm64 || $arch == simmips ]
 cc/Service_Profile: Skip
 
 [ $arch == arm ]
diff --git a/runtime/tools/gyp/runtime-configurations.gypi b/runtime/tools/gyp/runtime-configurations.gypi
index 4f88987..0b053c4 100644
--- a/runtime/tools/gyp/runtime-configurations.gypi
+++ b/runtime/tools/gyp/runtime-configurations.gypi
@@ -92,6 +92,20 @@
         },
       },
 
+      'Dart_simarmv6_Base': {
+        'abstract': 1,
+        'xcode_settings': {
+          'ARCHS': [ 'i386' ],
+        },
+      },
+
+      'Dart_simarmv5te_Base': {
+        'abstract': 1,
+        'xcode_settings': {
+          'ARCHS': [ 'i386' ],
+        },
+      },
+
       'Dart_simmips_Base': {
         'abstract': 1,
         'xcode_settings': {
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 12f470a..1e6e6ef 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -1798,10 +1798,20 @@
 
 ASSEMBLER_TEST_RUN(IntDiv_supported, test) {
   EXPECT(test != NULL);
+#if defined(USING_SIMULATOR)
+  bool orig = TargetCPUFeatures::integer_division_supported();
+  HostCPUFeatures::set_integer_division_supported(true);
   if (TargetCPUFeatures::can_divide()) {
     typedef int (*Tst)() DART_UNUSED;
     EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
   }
+  HostCPUFeatures::set_integer_division_supported(orig);
+#else
+  if (TargetCPUFeatures::can_divide()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
+#endif
 }
 
 
@@ -1829,10 +1839,20 @@
 
 ASSEMBLER_TEST_RUN(IntDiv_unsupported, test) {
   EXPECT(test != NULL);
+#if defined(USING_SIMULATOR)
+  bool orig = TargetCPUFeatures::integer_division_supported();
+  HostCPUFeatures::set_integer_division_supported(false);
   if (TargetCPUFeatures::can_divide()) {
     typedef int (*Tst)() DART_UNUSED;
     EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
   }
+  HostCPUFeatures::set_integer_division_supported(orig);
+#else
+  if (TargetCPUFeatures::can_divide()) {
+    typedef int (*Tst)() DART_UNUSED;
+    EXPECT_EQ(3, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+  }
+#endif
 }
 
 
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 19542b3..2deefa2 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -121,6 +121,36 @@
   }
 }
 
+bool LetNode::IsPotentiallyConst() const {
+  for (intptr_t i = 0; i < num_temps(); i++) {
+    if (!initializers_[i]->IsPotentiallyConst()) {
+      return false;
+    }
+  }
+  for (intptr_t i = 0; i < nodes_.length(); i++) {
+    if (!nodes_[i]->IsPotentiallyConst()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+const Instance* LetNode::EvalConstExpr() const {
+  for (intptr_t i = 0; i < num_temps(); i++) {
+    if (initializers_[i]->EvalConstExpr() == NULL) {
+      return NULL;
+    }
+  }
+  const Instance* last = NULL;
+  for (intptr_t i = 0; i < nodes_.length(); i++) {
+    last = nodes_[i]->EvalConstExpr();
+    if (last == NULL) {
+      return NULL;
+    }
+  }
+  return last;
+}
+
 
 void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const {
   for (intptr_t i = 0; i < this->length(); i++) {
@@ -329,6 +359,7 @@
     case Token::kBIT_AND:
     case Token::kSHL:
     case Token::kSHR:
+    case Token::kIFNULL:
       return this->left()->IsPotentiallyConst() &&
           this->right()->IsPotentiallyConst();
     default:
@@ -343,7 +374,8 @@
   if (left_val == NULL) {
     return NULL;
   }
-  if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString()) {
+  if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString() &&
+      kind_ != Token::kIFNULL) {
     return NULL;
   }
   const Instance* right_val = this->right()->EvalConstExpr();
@@ -388,6 +420,11 @@
         return left_val;
       }
       return NULL;
+    case Token::kIFNULL:
+      if (left_val->IsNull()) {
+        return right_val;
+      }
+      return left_val;
     default:
       UNREACHABLE();
       return NULL;
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 01ae0cf..494d768 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -99,7 +99,8 @@
  public:
   explicit AstNode(intptr_t token_pos)
       : token_pos_(token_pos) {
-    ASSERT(Scanner::ValidSourcePosition(token_pos_));
+    ASSERT(!Token::IsClassifying(token_pos_) ||
+           (token_pos_ == ClassifyingTokenPositions::kMethodExtractor));
   }
   virtual ~AstNode() { }
 
@@ -327,6 +328,9 @@
   LocalVariable* TempAt(intptr_t i) const { return vars_[i]; }
   AstNode* InitializerAt(intptr_t i) const { return initializers_[i]; }
 
+  virtual bool IsPotentiallyConst() const;
+  virtual const Instance* EvalConstExpr() const;
+
   LocalVariable* AddInitializer(AstNode* node);
 
   const GrowableArray<AstNode*>& nodes() const { return nodes_; }
diff --git a/runtime/vm/ast_printer_test.cc b/runtime/vm/ast_printer_test.cc
index 872d5bb..9ac8d72 100644
--- a/runtime/vm/ast_printer_test.cc
+++ b/runtime/vm/ast_printer_test.cc
@@ -13,7 +13,7 @@
 namespace dart {
 
 TEST_CASE(AstPrinter) {
-  const intptr_t kPos = Scanner::kNoSourcePos;
+  const intptr_t kPos = Token::kNoSourcePos;
   LocalVariable* v =
       new LocalVariable(kPos,
                         String::ZoneHandle(Symbols::New("wurscht")),
diff --git a/runtime/vm/ast_test.cc b/runtime/vm/ast_test.cc
index 83fea1b..afe4bdb 100644
--- a/runtime/vm/ast_test.cc
+++ b/runtime/vm/ast_test.cc
@@ -13,10 +13,10 @@
 namespace dart {
 
 TEST_CASE(Ast) {
-  LocalVariable* v = new LocalVariable(Scanner::kNoSourcePos,
+  LocalVariable* v = new LocalVariable(Token::kNoSourcePos,
                                        String::ZoneHandle(Symbols::New("v")),
                                        Type::ZoneHandle(Type::DynamicType()));
-  AstNode* ll = new LoadLocalNode(Scanner::kNoSourcePos, v);
+  AstNode* ll = new LoadLocalNode(Token::kNoSourcePos, v);
   EXPECT(ll->IsLoadLocalNode());
   EXPECT(!ll->IsLiteralNode());
   LoadLocalNode* lln = ll->AsLoadLocalNode();
@@ -24,7 +24,7 @@
   v->set_index(1);
   EXPECT_EQ(1, v->index());
 
-  LocalVariable* p = new LocalVariable(Scanner::kNoSourcePos,
+  LocalVariable* p = new LocalVariable(Token::kNoSourcePos,
                                        String::ZoneHandle(Symbols::New("p")),
                                        Type::ZoneHandle(Type::DynamicType()));
   EXPECT(!p->HasIndex());
@@ -32,22 +32,22 @@
   EXPECT(p->HasIndex());
   EXPECT_EQ(-1, p->index());
 
-  ReturnNode* r = new ReturnNode(Scanner::kNoSourcePos, lln);
+  ReturnNode* r = new ReturnNode(Token::kNoSourcePos, lln);
   EXPECT_EQ(lln, r->value());
 
   LiteralNode* l =
-      new LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(3)));
+      new LiteralNode(Token::kNoSourcePos, Smi::ZoneHandle(Smi::New(3)));
   EXPECT(l->literal().IsSmi());
   EXPECT_EQ(Smi::New(3), l->literal().raw());
 
   BinaryOpNode* b =
-      new BinaryOpNode(Scanner::kNoSourcePos, Token::kADD, l, lln);
+      new BinaryOpNode(Token::kNoSourcePos, Token::kADD, l, lln);
   EXPECT_EQ(Token::kADD, b->kind());
   EXPECT_EQ(l, b->left());
   EXPECT_EQ(lln, b->right());
 
   UnaryOpNode* u =
-      new UnaryOpNode(Scanner::kNoSourcePos, Token::kNEGATE, b);
+      new UnaryOpNode(Token::kNoSourcePos, Token::kNEGATE, b);
   EXPECT_EQ(Token::kNEGATE, u->kind());
   EXPECT_EQ(b, u->operand());
 
diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
index 32ec3f9..8954f0a 100644
--- a/runtime/vm/ast_transformer.cc
+++ b/runtime/vm/ast_transformer.cc
@@ -13,6 +13,9 @@
 // Quick access to the current zone.
 #define Z (thread()->zone())
 
+// Quick synthetic token position.
+#define ST(token_pos) Token::ToSynthetic(token_pos)
+
 // Nodes that are unreachable from already parsed expressions.
 #define FOR_EACH_UNREACHABLE_NODE(V)                                           \
   V(AwaitMarker)                                                               \
@@ -71,7 +74,7 @@
   if (await_tmp == NULL) {
     // We need a new temp variable; add it to the function's top scope.
     await_tmp = new (Z) LocalVariable(
-        Scanner::kNoSourcePos, symbol, Object::dynamic_type());
+        Token::kNoSourcePos, symbol, Object::dynamic_type());
     async_temp_scope_->AddVariable(await_tmp);
     // After adding it to the top scope, we can look it up from the preamble.
     // The following call includes an ASSERT check.
@@ -89,9 +92,11 @@
 }
 
 
-LocalVariable* AwaitTransformer::AddToPreambleNewTempVar(AstNode* node) {
+LocalVariable* AwaitTransformer::AddToPreambleNewTempVar(AstNode* node,
+                                                         intptr_t token_pos) {
   LocalVariable* tmp_var = EnsureCurrentTempVar();
-  preamble_->Add(new(Z) StoreLocalNode(Scanner::kNoSourcePos, tmp_var, node));
+  ASSERT(Token::IsSynthetic(token_pos) || Token::IsNoSource(token_pos));
+  preamble_->Add(new(Z) StoreLocalNode(token_pos, tmp_var, node));
   NextTempVar();
   return tmp_var;
 }
@@ -119,7 +124,7 @@
   //   :saved_try_ctx_var = :await_saved_try_ctx_var_y;
   //   :await_temp_var_(X+1) = :result_param;
 
-  const intptr_t token_pos = node->token_pos();
+  const intptr_t token_pos = ST(node->token_pos());
   LocalVariable* async_op = GetVariableInScope(
       preamble_->scope(), Symbols::AsyncOperation());
   LocalVariable* async_then_callback = GetVariableInScope(
@@ -134,7 +139,8 @@
       preamble_->scope(), Symbols::AsyncOperationStackTraceParam());
 
   AstNode* transformed_expr = Transform(node->expr());
-  LocalVariable* await_temp = AddToPreambleNewTempVar(transformed_expr);
+  LocalVariable* await_temp = AddToPreambleNewTempVar(transformed_expr,
+                                                      ST(node->token_pos()));
 
   AwaitMarkerNode* await_marker =
       new (Z) AwaitMarkerNode(async_temp_scope_, node->scope(), token_pos);
@@ -146,23 +152,23 @@
   const Function& async_await_helper = Function::ZoneHandle(
       Z, async_lib.LookupFunctionAllowPrivate(Symbols::AsyncAwaitHelper()));
   ASSERT(!async_await_helper.IsNull());
-  ArgumentListNode* async_await_helper_args = new (Z) ArgumentListNode(
-      Scanner::kNoSourcePos);
+  ArgumentListNode* async_await_helper_args =
+      new (Z) ArgumentListNode(token_pos);
   async_await_helper_args->Add(
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, await_temp));
+      new(Z) LoadLocalNode(token_pos, await_temp));
   async_await_helper_args->Add(
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_then_callback));
+      new(Z) LoadLocalNode(token_pos, async_then_callback));
   async_await_helper_args->Add(
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, async_catch_error_callback));
+      new(Z) LoadLocalNode(token_pos, async_catch_error_callback));
   StaticCallNode* await_helper_call = new (Z) StaticCallNode(
       node->token_pos(),
       async_await_helper,
       async_await_helper_args);
 
   preamble_->Add(new(Z) StoreLocalNode(
-      Scanner::kNoSourcePos, result_param, await_helper_call));
+      token_pos, result_param, await_helper_call));
 
-  ReturnNode* continuation_return = new(Z) ReturnNode(Scanner::kNoSourcePos);
+  ReturnNode* continuation_return = new(Z) ReturnNode(token_pos);
   continuation_return->set_return_type(ReturnNode::kContinuationTarget);
   preamble_->Add(continuation_return);
 
@@ -171,15 +177,15 @@
   // saved try context of the outer try block.
   if (node->saved_try_ctx() != NULL) {
     preamble_->Add(new (Z) StoreLocalNode(
-        Scanner::kNoSourcePos,
+        token_pos,
         node->saved_try_ctx(),
-        new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+        new (Z) LoadLocalNode(token_pos,
                               node->async_saved_try_ctx())));
     if (node->outer_saved_try_ctx() != NULL) {
       preamble_->Add(new (Z) StoreLocalNode(
-          Scanner::kNoSourcePos,
+          token_pos,
           node->outer_saved_try_ctx(),
-          new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+          new (Z) LoadLocalNode(token_pos,
                                 node->outer_async_saved_try_ctx())));
     }
   } else {
@@ -188,34 +194,33 @@
 
   // Load the async_op variable. It is unused, but the observatory uses it
   // to determine if a breakpoint is inside an asynchronous function.
-  LoadLocalNode* load_async_op = new (Z) LoadLocalNode(
-      Scanner::kNoSourcePos, async_op);
+  LoadLocalNode* load_async_op = new (Z) LoadLocalNode(token_pos, async_op);
   preamble_->Add(load_async_op);
 
   LoadLocalNode* load_error_param = new (Z) LoadLocalNode(
-      Scanner::kNoSourcePos, error_param);
+      token_pos, error_param);
   LoadLocalNode* load_stack_trace_param = new (Z) LoadLocalNode(
-      Scanner::kNoSourcePos, stack_trace_param);
+      token_pos, stack_trace_param);
   SequenceNode* error_ne_null_branch = new (Z) SequenceNode(
-      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
+      token_pos, ChainNewScope(preamble_->scope()));
   error_ne_null_branch->Add(new (Z) ThrowNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       load_error_param,
       load_stack_trace_param));
   preamble_->Add(new (Z) IfNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       new (Z) ComparisonNode(
-          Scanner::kNoSourcePos,
+          token_pos,
           Token::kNE,
           load_error_param,
-          new (Z) LiteralNode(Scanner::kNoSourcePos,
+          new (Z) LiteralNode(token_pos,
                               Object::null_instance())),
           error_ne_null_branch,
           NULL));
 
   LocalVariable* result = AddToPreambleNewTempVar(new(Z) LoadLocalNode(
-      Scanner::kNoSourcePos, result_param));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+      token_pos, result_param), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(token_pos, result);
 }
 
 
@@ -242,18 +247,18 @@
   const Token::Kind compare_logical_op = (logical_op == Token::kAND) ?
       Token::kEQ : Token::kNE;
   SequenceNode* eval = new (Z) SequenceNode(
-      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
+      ST(new_left->token_pos()), ChainNewScope(preamble_->scope()));
   SequenceNode* saved_preamble = preamble_;
   preamble_ = eval;
   result = Transform(right);
   preamble_ = saved_preamble;
   IfNode* right_body = new(Z) IfNode(
-      Scanner::kNoSourcePos,
+      ST(new_left->token_pos()),
       new(Z) ComparisonNode(
-          Scanner::kNoSourcePos,
+          ST(new_left->token_pos()),
           compare_logical_op,
           new_left,
-          new(Z) LiteralNode(Scanner::kNoSourcePos, Bool::True())),
+          new(Z) LiteralNode(ST(new_left->token_pos()), Bool::True())),
       eval,
       NULL);
   preamble_->Add(right_body);
@@ -280,8 +285,8 @@
       new(Z) BinaryOpNode(node->token_pos(),
                           node->kind(),
                           new_left,
-                          new_right));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                          new_right), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -295,8 +300,8 @@
                                     node->kind(),
                                     new_left,
                                     new_right,
-                                    node->mask32()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                                    node->mask32()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -307,16 +312,17 @@
       new(Z) ComparisonNode(node->token_pos(),
                             node->kind(),
                             new_left,
-                            new_right));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                            new_right), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
 void AwaitTransformer::VisitUnaryOpNode(UnaryOpNode* node) {
   AstNode* new_operand = Transform(node->operand());
   LocalVariable* result = AddToPreambleNewTempVar(
-      new(Z) UnaryOpNode(node->token_pos(), node->kind(), new_operand));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+      new(Z) UnaryOpNode(node->token_pos(), node->kind(), new_operand),
+      ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -325,26 +331,26 @@
 void AwaitTransformer::VisitConditionalExprNode(ConditionalExprNode* node) {
   AstNode* new_condition = Transform(node->condition());
   SequenceNode* new_true = new (Z) SequenceNode(
-      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
+      ST(node->true_expr()->token_pos()), ChainNewScope(preamble_->scope()));
   SequenceNode* saved_preamble = preamble_;
   preamble_ = new_true;
   AstNode* new_true_result = Transform(node->true_expr());
   SequenceNode* new_false = new (Z) SequenceNode(
-      Scanner::kNoSourcePos, ChainNewScope(preamble_->scope()));
+      ST(node->false_expr()->token_pos()), ChainNewScope(preamble_->scope()));
   preamble_ = new_false;
   AstNode* new_false_result = Transform(node->false_expr());
   preamble_ = saved_preamble;
-  IfNode* new_if = new(Z) IfNode(Scanner::kNoSourcePos,
+  IfNode* new_if = new(Z) IfNode(ST(node->token_pos()),
                                  new_condition,
                                  new_true,
                                  new_false);
   preamble_->Add(new_if);
   LocalVariable* result = AddToPreambleNewTempVar(
-      new(Z) ConditionalExprNode(Scanner::kNoSourcePos,
+      new(Z) ConditionalExprNode(ST(node->token_pos()),
                                  new_condition,
                                  new_true_result,
-                                 new_false_result));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                                 new_false_result), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -371,8 +377,8 @@
   ArrayNode* new_value = Transform(node->value())->AsArrayNode();
   LocalVariable* result = AddToPreambleNewTempVar(
       new(Z) StringInterpolateNode(node->token_pos(),
-                                   new_value));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                                   new_value), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -385,8 +391,8 @@
       new(Z) ClosureNode(node->token_pos(),
                          node->function(),
                          new_receiver,
-                         node->scope()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                         node->scope()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -399,8 +405,8 @@
                               new_receiver,
                               node->function_name(),
                               new_args,
-                              node->is_conditional()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                              node->is_conditional()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -410,8 +416,8 @@
   LocalVariable* result = AddToPreambleNewTempVar(
       new(Z) StaticCallNode(node->token_pos(),
                             node->function(),
-                            new_args));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                            new_args), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -422,8 +428,8 @@
       new(Z) ConstructorCallNode(node->token_pos(),
                                  node->type_arguments(),
                                  node->constructor(),
-                                 new_args));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                                 new_args), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -433,8 +439,8 @@
       new(Z) InstanceGetterNode(node->token_pos(),
                                 new_receiver,
                                 node->field_name(),
-                                node->is_conditional()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                                node->is_conditional()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -449,8 +455,8 @@
                                 new_receiver,
                                 node->field_name(),
                                 new_value,
-                                node->is_conditional()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                                node->is_conditional()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -465,8 +471,9 @@
                               node->cls(),
                               node->field_name());
   new_getter->set_owner(node->owner());
-  LocalVariable* result = AddToPreambleNewTempVar(new_getter);
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+  LocalVariable* result =
+      AddToPreambleNewTempVar(new_getter, ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -489,8 +496,9 @@
                                 node->function(),
                                 new_value);
 
-  LocalVariable* result = AddToPreambleNewTempVar(new_setter);
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+  LocalVariable* result =
+      AddToPreambleNewTempVar(new_setter, ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -525,8 +533,8 @@
       new(Z) LoadIndexedNode(node->token_pos(),
                              new_array,
                              new_index,
-                             node->super_class()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                             node->super_class()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -539,8 +547,8 @@
                               new_array,
                               new_index,
                               new_value,
-                              node->super_class()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                              node->super_class()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -550,8 +558,8 @@
       new(Z) AssignableNode(node->token_pos(),
                             new_expr,
                             node->type(),
-                            node->dst_name()));
-  result_ = new(Z) LoadLocalNode(Scanner::kNoSourcePos, result);
+                            node->dst_name()), ST(node->token_pos()));
+  result_ = new(Z) LoadLocalNode(ST(node->token_pos()), result);
 }
 
 
@@ -565,8 +573,8 @@
     async_temp_scope_->AddVariable(node->TempAt(i));
     AstNode* new_init_val = Transform(node->InitializerAt(i));
     preamble_->Add(new(Z) StoreLocalNode(node->token_pos(),
-                   node->TempAt(i),
-                   new_init_val));
+                                         node->TempAt(i),
+                                         new_init_val));
   }
 
   // Add all expressions but the last to the preamble. We must do
diff --git a/runtime/vm/ast_transformer.h b/runtime/vm/ast_transformer.h
index e9f6791..d8c01d0 100644
--- a/runtime/vm/ast_transformer.h
+++ b/runtime/vm/ast_transformer.h
@@ -51,7 +51,7 @@
 
  private:
   LocalVariable* EnsureCurrentTempVar();
-  LocalVariable* AddToPreambleNewTempVar(AstNode* node);
+  LocalVariable* AddToPreambleNewTempVar(AstNode* node, intptr_t token_pos);
   ArgumentListNode* TransformArguments(ArgumentListNode* node);
   AstNode* LazyTransform(const Token::Kind kind,
                          AstNode* new_left,
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 7596920..f7bd22d 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -339,13 +339,11 @@
     SetupNativeResolver();
     ClassFinalizer::ProcessPendingClasses();
 
-    Class& cls = Class::Handle(zone);
-    // Eagerly compile the function implementation class as it is the super
-    // class of signature classes. This allows us to just finalize signature
-    // classes without going through the hoops of trying to compile them.
-    const Type& type =
-        Type::Handle(zone, isolate->object_store()->function_impl_type());
-    cls = type.type_class();
+    // Eagerly compile the _Closure class as it is the class of all closure
+    // instances. This allows us to just finalize function types
+    // without going through the hoops of trying to compile their scope class.
+    const Class& cls =
+        Class::Handle(zone, isolate->object_store()->closure_class());
     Compiler::CompileClass(cls);
   }
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 8803755..26e4d5d 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -28,9 +28,9 @@
   V(Object_instanceOfString, 2)                                                \
   V(Object_as, 3)                                                              \
   V(Function_apply, 2)                                                         \
-  V(FunctionImpl_equals, 2)                                                    \
-  V(FunctionImpl_hashCode, 1)                                                  \
-  V(FunctionImpl_clone, 1)                                                     \
+  V(Closure_equals, 2)                                                         \
+  V(Closure_hashCode, 1)                                                       \
+  V(Closure_clone, 1)                                                          \
   V(AbstractType_toString, 1)                                                  \
   V(Identical_comparison, 2)                                                   \
   V(Integer_bitAndFromInteger, 2)                                              \
diff --git a/runtime/vm/cha.cc b/runtime/vm/cha.cc
index 667d598..ed5255e 100644
--- a/runtime/vm/cha.cc
+++ b/runtime/vm/cha.cc
@@ -49,8 +49,8 @@
 
 
 bool CHA::IsImplemented(const Class& cls) {
-  // Signature classes have different type checking rules.
-  ASSERT(!cls.IsSignatureClass());
+  // Function type aliases have different type checking rules.
+  ASSERT(!cls.IsTypedefClass());
   // Can't track dependencies for classes on the VM heap since those are
   // read-only.
   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap
diff --git a/runtime/vm/cha_test.cc b/runtime/vm/cha_test.cc
index a7c998d..7712324 100644
--- a/runtime/vm/cha_test.cc
+++ b/runtime/vm/cha_test.cc
@@ -98,10 +98,9 @@
   EXPECT(ContainsCid(cha.leaf_classes(), class_c.id()));
   EXPECT(ContainsCid(cha.leaf_classes(), class_d.id()));
 
-  const Class& function_impl_class =
-      Class::Handle(Type::Handle(Isolate::Current()->object_store()->
-          function_impl_type()).type_class());
-  EXPECT(cha.HasSubclasses(function_impl_class.id()));
+  const Class& closure_class =
+      Class::Handle(Isolate::Current()->object_store()->closure_class());
+  EXPECT(!cha.HasSubclasses(closure_class.id()));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 8ef3511..67b3683 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -440,7 +440,8 @@
     if (!target_type.IsInstantiated()) {
       const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
       Error& bound_error = Error::Handle();
-      target_type ^= target_type.InstantiateFrom(type_args, &bound_error);
+      target_type ^= target_type.InstantiateFrom(
+          type_args, &bound_error, NULL, Heap::kOld);
       if (bound_error.IsNull()) {
         target_type ^= FinalizeType(cls, target_type, kCanonicalize);
       } else {
@@ -457,10 +458,10 @@
 }
 
 
-void ClassFinalizer::ResolveTypeClass(const Class& cls,
-                                      const AbstractType& type) {
-  if (type.IsFinalized() || type.HasResolvedTypeClass()) {
-    return;
+RawAbstractType* ClassFinalizer::ResolveTypeClass(const Class& cls,
+                                                  const Type& type) {
+  if (type.IsFinalized()) {
+    return type.raw();
   }
   if (FLAG_trace_type_finalization) {
     THR_Print("Resolve type class of '%s'\n",
@@ -473,55 +474,77 @@
   // that the type parameter appeared in a static scope. Leaving the type as
   // unresolved is the correct thing to do.
 
-  // Lookup the type class.
-  const UnresolvedClass& unresolved_class =
-      UnresolvedClass::Handle(type.unresolved_class());
-  const Class& type_class =
-      Class::Handle(ResolveClass(cls, unresolved_class));
-
-  // Replace unresolved class with resolved type class.
-  const Type& parameterized_type = Type::Cast(type);
-  if (type_class.IsNull()) {
-    // The type class could not be resolved. The type is malformed.
-    FinalizeMalformedType(
-        Error::Handle(),  // No previous error.
-        Script::Handle(cls.script()),
-        parameterized_type,
-        "cannot resolve class '%s' from '%s'",
-        String::Handle(unresolved_class.Name()).ToCString(),
-        String::Handle(cls.Name()).ToCString());
-    return;
+  // Lookup the type class if necessary.
+  Class& type_class = Class::Handle();
+  if (type.HasResolvedTypeClass()) {
+    type_class = type.type_class();
+  } else {
+    const UnresolvedClass& unresolved_class =
+        UnresolvedClass::Handle(type.unresolved_class());
+    type_class = ResolveClass(cls, unresolved_class);
+    if (type_class.IsNull()) {
+      // The type class could not be resolved. The type is malformed.
+      FinalizeMalformedType(
+          Error::Handle(),  // No previous error.
+          Script::Handle(cls.script()),
+          type,
+          "cannot resolve class '%s' from '%s'",
+          String::Handle(unresolved_class.Name()).ToCString(),
+          String::Handle(cls.Name()).ToCString());
+      return type.raw();
+    }
   }
-  parameterized_type.set_type_class(type_class);
+  // Promote the Type to a FunctionType in case its type class is a typedef.
+  if (type_class.IsTypedefClass()) {
+    return FunctionType::New(type_class,
+                             TypeArguments::Handle(type.arguments()),
+                             Function::Handle(type_class.signature_function()),
+                             type.token_pos());
+  }
+  // Replace unresolved class with resolved type class.
+  type.set_type_class(type_class);
+  return type.raw();
 }
 
 
-void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
+RawAbstractType* ClassFinalizer::ResolveType(const Class& cls,
+                                             const AbstractType& type) {
   if (type.IsResolved()) {
-    return;
+    return type.raw();
   }
-  ASSERT(type.IsType());
   if (FLAG_trace_type_finalization) {
     THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
   }
-  ResolveTypeClass(cls, type);
-  if (type.IsMalformed()) {
-    ASSERT(type.IsResolved());
-    return;
+  AbstractType& resolved_type = AbstractType::Handle();
+  if (type.IsType()) {
+    resolved_type = ResolveTypeClass(cls, Type::Cast(type));
+    if (resolved_type.IsMalformed()) {
+      ASSERT(resolved_type.IsResolved());
+      return resolved_type.raw();
+    }
+  } else {
+    ASSERT(type.IsFunctionType());
+    const Function& signature =
+        Function::Handle(FunctionType::Cast(type).signature());
+    ResolveSignature(cls, signature);
+    resolved_type = type.raw();
   }
   // Mark type as resolved before resolving its type arguments in order to avoid
   // repeating resolution of recursive types.
-  Type::Cast(type).set_is_resolved();
+  resolved_type.SetIsResolved();
   // Resolve type arguments, if any.
-  const TypeArguments& arguments = TypeArguments::Handle(type.arguments());
+  const TypeArguments& arguments =
+      TypeArguments::Handle(resolved_type.arguments());
   if (!arguments.IsNull()) {
     const intptr_t num_arguments = arguments.Length();
     AbstractType& type_argument = AbstractType::Handle();
     for (intptr_t i = 0; i < num_arguments; i++) {
       type_argument = arguments.TypeAt(i);
-      ResolveType(cls, type_argument);
+      type_argument = ResolveType(cls, type_argument);
+      arguments.SetTypeAt(i, type_argument);
     }
   }
+  return resolved_type.raw();
 }
 
 
@@ -564,7 +587,7 @@
 // A non-contractive type can be detected by looking at the queue of types
 // pending finalization that are mutually recursive with the checked type.
 void ClassFinalizer::CheckRecursiveType(const Class& cls,
-                                        const Type& type,
+                                        const AbstractType& type,
                                         PendingTypes* pending_types) {
   Zone* zone = Thread::Current()->zone();
   if (FLAG_trace_type_finalization) {
@@ -620,6 +643,127 @@
 }
 
 
+// Expand the type arguments of the given type and finalize its full type
+// argument vector. Return the number of type arguments (0 for a raw type).
+intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
+    const Class& cls,
+    const AbstractType& type,
+    PendingTypes* pending_types) {
+  Zone* Z = Thread::Current()->zone();
+  // The type class does not need to be finalized in order to finalize the type,
+  // however, it must at least be resolved (this was done as part of resolving
+  // the type itself, a precondition to calling FinalizeType).
+  // Also, the interfaces of the type class must be resolved and the type
+  // parameters of the type class must be finalized.
+  Class& type_class = Class::Handle(Z, type.type_class());
+  if (!type_class.is_type_finalized()) {
+    FinalizeTypeParameters(type_class, pending_types);
+    ResolveUpperBounds(type_class);
+  }
+
+  // The finalized type argument vector needs num_type_arguments types.
+  const intptr_t num_type_arguments = type_class.NumTypeArguments();
+  // The class has num_type_parameters type parameters.
+  const intptr_t num_type_parameters = type_class.NumTypeParameters();
+
+  // Initialize the type argument vector.
+  // Check the number of parsed type arguments, if any.
+  // Specifying no type arguments indicates a raw type, which is not an error.
+  // However, type parameter bounds are checked below, even for a raw type.
+  TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
+  if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
+    // Wrong number of type arguments. The type is mapped to the raw type.
+    if (Isolate::Current()->flags().error_on_bad_type()) {
+      const String& type_class_name = String::Handle(Z, type_class.Name());
+      ReportError(cls, type.token_pos(),
+                  "wrong number of type arguments for class '%s'",
+                  type_class_name.ToCString());
+    }
+    // Make the type raw and continue without reporting any error.
+    // A static warning should have been reported.
+    arguments = TypeArguments::null();
+    type.set_arguments(arguments);
+  }
+
+  // Mark the type as being finalized in order to detect self reference and
+  // postpone bound checking until after all types in the graph of
+  // mutually recursive types are finalized.
+  type.SetIsBeingFinalized();
+  pending_types->Add(type);
+
+  // The full type argument vector consists of the type arguments of the
+  // super types of type_class, which are initialized from the parsed
+  // type arguments, followed by the parsed type arguments.
+  TypeArguments& full_arguments = TypeArguments::Handle(Z);
+  if (num_type_arguments > 0) {
+    // If no type arguments were parsed and if the super types do not prepend
+    // type arguments to the vector, we can leave the vector as null.
+    if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
+      full_arguments = TypeArguments::New(num_type_arguments);
+      // Copy the parsed type arguments at the correct offset in the full type
+      // argument vector.
+      const intptr_t offset = num_type_arguments - num_type_parameters;
+      AbstractType& type_arg =
+          AbstractType::Handle(Z, Type::DynamicType());
+      // Leave the temporary type arguments at indices [0..offset[ as null.
+      for (intptr_t i = 0; i < num_type_parameters; i++) {
+        // If no type parameters were provided, a raw type is desired, so we
+        // create a vector of dynamic.
+        if (!arguments.IsNull()) {
+          type_arg = arguments.TypeAt(i);
+          // The parsed type_arg may or may not be finalized.
+        }
+        full_arguments.SetTypeAt(offset + i, type_arg);
+      }
+      // Replace the compile-time argument vector (of length zero or
+      // num_type_parameters) of this type being finalized with the still
+      // unfinalized run-time argument vector (of length num_type_arguments).
+      // This type being finalized may be recursively reached via bounds
+      // checking or type arguments of its super type.
+      type.set_arguments(full_arguments);
+      // Finalize the current type arguments of the type, which are still the
+      // parsed type arguments.
+      if (!arguments.IsNull()) {
+        for (intptr_t i = 0; i < num_type_parameters; i++) {
+          type_arg = full_arguments.TypeAt(offset + i);
+          ASSERT(!type_arg.IsBeingFinalized());
+          type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
+          if (type_arg.IsMalformed()) {
+            // Malformed type arguments are mapped to dynamic.
+            type_arg = Type::DynamicType();
+          }
+          full_arguments.SetTypeAt(offset + i, type_arg);
+        }
+      }
+      if (offset > 0) {
+        TrailPtr trail = new Trail(Z, 4);
+        Error& bound_error = Error::Handle();
+        FinalizeTypeArguments(type_class, full_arguments, offset,
+                              &bound_error, pending_types, trail);
+      }
+      if (full_arguments.IsRaw(0, num_type_arguments)) {
+        // The parameterized_type is raw. Set its argument vector to null, which
+        // is more efficient in type tests.
+        full_arguments = TypeArguments::null();
+      }
+      type.set_arguments(full_arguments);
+    } else {
+      ASSERT(full_arguments.IsNull());  // Use null vector for raw type.
+    }
+  }
+
+  // Self referencing types may get finalized indirectly.
+  if (!type.IsFinalized()) {
+    ASSERT(full_arguments.IsNull() ||
+           !full_arguments.IsRaw(0, num_type_arguments));
+    // Mark the type as finalized.
+    type.SetIsFinalized();
+    // Do not yet remove the type from the pending_types array.
+  }
+  return full_arguments.IsNull() ? 0 : full_arguments.Length();
+}
+
+
 // Finalize the type argument vector 'arguments' of the type defined by the
 // class 'cls' parameterized with the type arguments 'cls_args'.
 // The vector 'cls_args' is already initialized as a subvector at the correct
@@ -687,8 +831,8 @@
         super_type_arg = super_type_args.TypeAt(i);
         if (!super_type_arg.IsTypeRef()) {
           if (super_type_arg.IsBeingFinalized()) {
-            ASSERT(super_type_arg.IsType());
-            CheckRecursiveType(cls, Type::Cast(super_type_arg), pending_types);
+            ASSERT(super_type_arg.IsType() || super_type_arg.IsFunctionType());
+            CheckRecursiveType(cls, super_type_arg, pending_types);
             if (FLAG_trace_type_finalization) {
               THR_Print("Creating TypeRef '%s': '%s'\n",
                         String::Handle(super_type_arg.Name()).ToCString(),
@@ -737,7 +881,7 @@
             if (super_type_arg.IsTypeRef()) {
               super_type_arg = TypeRef::Cast(super_type_arg).type();
             }
-            Type::Cast(super_type_arg).set_is_being_finalized();
+            Type::Cast(super_type_arg).SetIsBeingFinalized();
             pending_types->Add(super_type_arg);
             const Class& cls = Class::Handle(super_type_arg.type_class());
             FinalizeTypeArguments(
@@ -844,9 +988,10 @@
         if (type_arg.IsTypeParameter()) {
           const Class& type_arg_cls = Class::Handle(
               TypeParameter::Cast(type_arg).parameterized_class());
-          const AbstractType& bound = AbstractType::Handle(
+          AbstractType& bound = AbstractType::Handle(
               TypeParameter::Cast(type_arg).bound());
-          ResolveType(type_arg_cls, bound);
+          bound = ResolveType(type_arg_cls, bound);
+          TypeParameter::Cast(type_arg).set_bound(bound);
         }
         // This may be called only if type needs to be finalized, therefore
         // seems OK to allocate finalized types in old space.
@@ -870,24 +1015,17 @@
 }
 
 
-void ClassFinalizer::CheckTypeBounds(const Class& cls, const Type& type) {
+void ClassFinalizer::CheckTypeBounds(const Class& cls,
+                                     const AbstractType& type) {
+  ASSERT(type.IsType() || type.IsFunctionType());
   ASSERT(type.IsFinalized());
   TypeArguments& arguments = TypeArguments::Handle(type.arguments());
   if (arguments.IsNull()) {
     return;
   }
-  Class& owner_class = Class::Handle();
-  Class& type_class = Class::Handle(type.type_class());
-  if (type_class.IsSignatureClass()) {
-    const Function& signature_fun =
-        Function::Handle(type_class.signature_function());
-    ASSERT(!signature_fun.is_static());
-    owner_class = signature_fun.Owner();
-  } else {
-    owner_class = type_class.raw();
-  }
+  const Class& type_class = Class::Handle(type.type_class());
   Error& bound_error = Error::Handle();
-  CheckTypeArgumentBounds(owner_class, arguments, &bound_error);
+  CheckTypeArgumentBounds(type_class, arguments, &bound_error);
   type.set_arguments(arguments);
   // If a bound error occurred, mark the type as malbounded.
   // The bound error will be ignored in production mode.
@@ -936,22 +1074,23 @@
   // encountered here.
   ASSERT(!type.IsBeingFinalized());
 
+  Zone* Z = Thread::Current()->zone();
+  const AbstractType& resolved_type =
+      AbstractType::Handle(Z, ResolveType(cls, type));
   // A malformed type gets mapped to a finalized type.
-  ResolveType(cls, type);
-  if (type.IsMalformed()) {
-    ASSERT(type.IsFinalized());
-    return type.raw();
+  if (resolved_type.IsMalformed()) {
+    ASSERT(resolved_type.IsFinalized());
+    return resolved_type.raw();
   }
 
-  Zone* Z = Thread::Current()->zone();
   if (FLAG_trace_type_finalization) {
     THR_Print("Finalizing type '%s' for class '%s'\n",
-              String::Handle(Z, type.Name()).ToCString(),
+              String::Handle(Z, resolved_type.Name()).ToCString(),
               cls.ToCString());
   }
 
-  if (type.IsTypeParameter()) {
-    const TypeParameter& type_parameter = TypeParameter::Cast(type);
+  if (resolved_type.IsTypeParameter()) {
+    const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type);
     const Class& parameterized_class =
         Class::Handle(Z, type_parameter.parameterized_class());
     ASSERT(!parameterized_class.IsNull());
@@ -966,7 +1105,7 @@
     // belongs to a mixin application class.
     if (!type_parameter.IsFinalized()) {
       type_parameter.set_index(type_parameter.index() + offset);
-      type_parameter.set_is_finalized();
+      type_parameter.SetIsFinalized();
     } else {
       ASSERT(cls.IsMixinApplication());
     }
@@ -981,8 +1120,8 @@
     return type_parameter.raw();
   }
 
-  // At this point, we can only have a parameterized_type.
-  const Type& parameterized_type = Type::Cast(type);
+  // At this point, we can only have a Type or a FunctionType.
+  ASSERT(resolved_type.IsType() || resolved_type.IsFunctionType());
 
   // This type is the root type of the type graph if no pending types queue is
   // allocated yet.
@@ -991,197 +1130,93 @@
     pending_types = new PendingTypes(Z, 4);
   }
 
-  // The type class does not need to be finalized in order to finalize the type,
-  // however, it must at least be resolved (this was done as part of resolving
-  // the type itself, a precondition to calling FinalizeType).
-  // Also, the interfaces of the type class must be resolved and the type
-  // parameters of the type class must be finalized.
-  Class& type_class = Class::Handle(Z, parameterized_type.type_class());
-  if (!type_class.is_type_finalized()) {
-    FinalizeTypeParameters(type_class, pending_types);
-    ResolveUpperBounds(type_class);
-  }
-
-  // The finalized type argument vector needs num_type_arguments types.
-  const intptr_t num_type_arguments = type_class.NumTypeArguments();
-  // The type class has num_type_parameters type parameters.
-  const intptr_t num_type_parameters = type_class.NumTypeParameters();
-
-  // Initialize the type argument vector.
-  // Check the number of parsed type arguments, if any.
-  // Specifying no type arguments indicates a raw type, which is not an error.
-  // However, type parameter bounds are checked below, even for a raw type.
-  TypeArguments& arguments =
-      TypeArguments::Handle(Z, parameterized_type.arguments());
-  if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
-    // Wrong number of type arguments. The type is mapped to the raw type.
-    if (Isolate::Current()->flags().error_on_bad_type()) {
-      const String& type_class_name =
-          String::Handle(Z, type_class.Name());
-      ReportError(cls, parameterized_type.token_pos(),
-                  "wrong number of type arguments for class '%s'",
-                  type_class_name.ToCString());
-    }
-    // Make the type raw and continue without reporting any error.
-    // A static warning should have been reported.
-    arguments = TypeArguments::null();
-    parameterized_type.set_arguments(arguments);
-  }
-
-  // Mark the type as being finalized in order to detect self reference and
-  // postpone bound checking until after all types in the graph of
-  // mutually recursive types are finalized.
-  parameterized_type.set_is_being_finalized();
-  pending_types->Add(parameterized_type);
-
-  // The full type argument vector consists of the type arguments of the
-  // super types of type_class, which are initialized from the parsed
-  // type arguments, followed by the parsed type arguments.
-  TypeArguments& full_arguments = TypeArguments::Handle(Z);
-  Error& bound_error = Error::Handle(Z);
-  if (num_type_arguments > 0) {
-    // If no type arguments were parsed and if the super types do not prepend
-    // type arguments to the vector, we can leave the vector as null.
-    if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
-      full_arguments = TypeArguments::New(num_type_arguments);
-      // Copy the parsed type arguments at the correct offset in the full type
-      // argument vector.
-      const intptr_t offset = num_type_arguments - num_type_parameters;
-      AbstractType& type_arg =
-          AbstractType::Handle(Z, Type::DynamicType());
-      // Leave the temporary type arguments at indices [0..offset[ as null.
-      for (intptr_t i = 0; i < num_type_parameters; i++) {
-        // If no type parameters were provided, a raw type is desired, so we
-        // create a vector of dynamic.
-        if (!arguments.IsNull()) {
-          type_arg = arguments.TypeAt(i);
-          // The parsed type_arg may or may not be finalized.
-        }
-        full_arguments.SetTypeAt(offset + i, type_arg);
-      }
-      // Replace the compile-time argument vector (of length zero or
-      // num_type_parameters) of this type being finalized with the still
-      // unfinalized run-time argument vector (of length num_type_arguments).
-      // This type being finalized may be recursively reached via bounds
-      // checking or type arguments of its super type.
-      parameterized_type.set_arguments(full_arguments);
-      // Finalize the current type arguments of the type, which are still the
-      // parsed type arguments.
-      if (!arguments.IsNull()) {
-        for (intptr_t i = 0; i < num_type_parameters; i++) {
-          type_arg = full_arguments.TypeAt(offset + i);
-          ASSERT(!type_arg.IsBeingFinalized());
-          type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
-          if (type_arg.IsMalformed()) {
-            // Malformed type arguments are mapped to dynamic.
-            type_arg = Type::DynamicType();
-          }
-          full_arguments.SetTypeAt(offset + i, type_arg);
-        }
-      }
-      // If the type class is a signature class, the full argument vector
-      // must include the argument vector of the super type.
-      // If the signature class is a function type alias, it is also the owner
-      // of its signature function and no super type is involved.
-      // If the signature class is canonical (not an alias), the owner of its
-      // signature function may either be an alias or the enclosing class of a
-      // local function, in which case the super type of the enclosing class is
-      // also considered when filling up the argument vector.
-      Class& owner_class = Class::Handle(Z);
-      if (type_class.IsSignatureClass()) {
-        const Function& signature_fun =
-            Function::Handle(Z, type_class.signature_function());
-        ASSERT(!signature_fun.is_static());
-        owner_class = signature_fun.Owner();
-      } else {
-        owner_class = type_class.raw();
-      }
-      if (offset > 0) {
-        TrailPtr trail = new Trail(Z, 4);
-        FinalizeTypeArguments(owner_class, full_arguments, offset,
-                              &bound_error, pending_types, trail);
-      }
-      if (full_arguments.IsRaw(0, num_type_arguments)) {
-        // The parameterized_type is raw. Set its argument vector to null, which
-        // is more efficient in type tests.
-        full_arguments = TypeArguments::null();
-      }
-      parameterized_type.set_arguments(full_arguments);
-    } else {
-      ASSERT(full_arguments.IsNull());  // Use null vector for raw type.
-    }
-  }
-
-  // Self referencing types may get finalized indirectly.
-  if (!parameterized_type.IsFinalized()) {
-    ASSERT(full_arguments.IsNull() ||
-           !full_arguments.IsRaw(0, num_type_arguments));
-    // Mark the type as finalized.
-    parameterized_type.SetIsFinalized();
-    // Do not yet remove the type from the pending_types array.
-  }
+  const intptr_t num_expanded_type_arguments =
+      ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types);
 
   // If we are done finalizing a graph of mutually recursive types, check their
   // bounds.
   if (is_root_type) {
     for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
-      CheckTypeBounds(cls, Type::Cast(pending_types->At(i)));
-      if (FLAG_trace_type_finalization && type.IsRecursive()) {
+      CheckTypeBounds(cls, pending_types->At(i));
+      if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) {
         THR_Print("Done finalizing recursive type '%s': %s\n",
-                  String::Handle(Z, type.Name()).ToCString(),
-                  type.ToCString());
+                  String::Handle(Z, resolved_type.Name()).ToCString(),
+                  resolved_type.ToCString());
       }
     }
   }
 
-  // If the type class is a signature class, we are currently finalizing a
-  // signature type, i.e. finalizing the result type and parameter types of the
-  // signature function of this signature type.
+  // If the type is a FunctionType, we also need to finalize the types in its
+  // signature, i.e. finalize the result type and parameter types of the
+  // signature function of this function type.
   // We do this after marking this type as finalized in order to allow a
   // function type to refer to itself via its parameter types and result type.
-  if (type_class.IsSignatureClass()) {
-    // The class may be created while parsing a function body, after all
-    // pending classes have already been finalized.
-    FinalizeTypesInClass(type_class);
+  // Note that we do not instantiate these types according to the type
+  // arguments. This will happen on demand when executing a type test.
+  if (resolved_type.IsFunctionType()) {
+    const Function& signature =
+        Function::Handle(Z, FunctionType::Cast(resolved_type).signature());
+    FinalizeSignature(cls, signature);
   }
 
   if (FLAG_trace_type_finalization) {
     THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
-              String::Handle(Z, parameterized_type.Name()).ToCString(),
-              parameterized_type.arguments() == TypeArguments::null() ?
-                  0 : num_type_arguments,
-              parameterized_type.ToCString());
+              String::Handle(Z, resolved_type.Name()).ToCString(),
+              num_expanded_type_arguments,
+              resolved_type.ToCString());
   }
 
   if (finalization >= kCanonicalize) {
-    if (FLAG_trace_type_finalization && parameterized_type.IsRecursive()) {
-      AbstractType& type = Type::Handle(Z);
-      type = parameterized_type.Canonicalize();
+    if (FLAG_trace_type_finalization && resolved_type.IsRecursive()) {
+      AbstractType& recursive_type =
+          AbstractType::Handle(Z, resolved_type.Canonicalize());
       THR_Print("Done canonicalizing recursive type '%s': %s\n",
-                String::Handle(Z, type.Name()).ToCString(),
-                type.ToCString());
-      return type.raw();
+                String::Handle(Z, recursive_type.Name()).ToCString(),
+                recursive_type.ToCString());
+      return recursive_type.raw();
     }
-    return parameterized_type.Canonicalize();
+    return resolved_type.Canonicalize();
   } else {
-    return parameterized_type.raw();
+    return resolved_type.raw();
   }
 }
 
 
-void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls,
-                                                 const Function& function) {
+void ClassFinalizer::ResolveSignature(const Class& cls,
+                                      const Function& function) {
   // Resolve result type.
   AbstractType& type = AbstractType::Handle(function.result_type());
   // It is not a compile time error if this name does not resolve to a class or
   // interface.
+  AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
+  if (resolved_type.raw() != type.raw()) {
+    function.set_result_type(resolved_type);
+  }
+  // Resolve formal parameter types.
+  const intptr_t num_parameters = function.NumParameters();
+  for (intptr_t i = 0; i < num_parameters; i++) {
+    type = function.ParameterTypeAt(i);
+    resolved_type = ResolveType(cls, type);
+    if (resolved_type.raw() != type.raw()) {
+      function.SetParameterTypeAt(i, resolved_type);
+    }
+  }
+}
+
+
+void ClassFinalizer::FinalizeSignature(const Class& cls,
+                                       const Function& function) {
+  // Finalize result type.
+  AbstractType& type = AbstractType::Handle(function.result_type());
+  // It is not a compile time error if this name does not resolve to a class or
+  // interface.
   AbstractType& finalized_type =
       AbstractType::Handle(FinalizeType(cls, type, kCanonicalize));
   // The result type may be malformed or malbounded.
-  if (type.raw() != finalized_type.raw()) {
+  if (finalized_type.raw() != type.raw()) {
     function.set_result_type(finalized_type);
   }
-  // Resolve formal parameter types.
+  // Finalize formal parameter types.
   const intptr_t num_parameters = function.NumParameters();
   for (intptr_t i = 0; i < num_parameters; i++) {
     type = function.ParameterTypeAt(i);
@@ -1255,7 +1290,8 @@
   for (intptr_t i = 0; i < num_type_params; i++) {
     type_param ^= type_params.TypeAt(i);
     bound = type_param.bound();
-    ResolveType(cls, bound);
+    bound = ResolveType(cls, bound);
+    type_param.set_bound(bound);
   }
 }
 
@@ -1445,7 +1481,7 @@
   Error& error = Error::Handle(Z);
   for (intptr_t i = 0; i < num_functions; i++) {
     function ^= array.At(i);
-    ResolveAndFinalizeSignature(cls, function);
+    FinalizeSignature(cls, function);
     name = function.name();
     // Report signature conflicts only.
     if (Isolate::Current()->flags().error_on_bad_override() &&
@@ -1718,8 +1754,8 @@
                   FinalizeType(mixin_app_class, param_bound, kCanonicalize);
               param.set_bound(param_bound);  // In case part of recursive type.
             }
-            param_bound = param_bound.InstantiateFrom(instantiator,
-                                                      &bound_error);
+            param_bound = param_bound.InstantiateFrom(
+                instantiator, &bound_error, NULL, Heap::kOld);
             // The instantiator contains only TypeParameter objects and no
             // BoundedType objects, so no bound error may occur.
             ASSERT(!param_bound.IsBoundedType());
@@ -1947,19 +1983,21 @@
         // the BoundedType in another BoundedType.
         if (type.IsBoundedType()) {
           bounded_type = BoundedType::Cast(type).type();
-          bounded_type = bounded_type.InstantiateFrom(instantiator,
-                                                      &bound_error);
+          bounded_type = bounded_type.InstantiateFrom(
+              instantiator, &bound_error, NULL, Heap::kOld);
           // The instantiator contains only TypeParameter objects and no
           // BoundedType objects, so no bound error may occur.
           ASSERT(bound_error.IsNull());
           upper_bound = BoundedType::Cast(type).bound();
-          upper_bound = upper_bound.InstantiateFrom(instantiator, &bound_error);
+          upper_bound = upper_bound.InstantiateFrom(
+              instantiator, &bound_error, NULL, Heap::kOld);
           ASSERT(bound_error.IsNull());
           type_parameter = BoundedType::Cast(type).type_parameter();
           // The type parameter that declared the bound does not change.
           type = BoundedType::New(bounded_type, upper_bound, type_parameter);
         } else {
-          type = type.InstantiateFrom(instantiator, &bound_error);
+          type = type.InstantiateFrom(
+              instantiator, &bound_error, NULL, Heap::kOld);
           ASSERT(bound_error.IsNull());
         }
       }
@@ -2172,12 +2210,23 @@
   const intptr_t num_functions = functions.Length();
   for (intptr_t i = 0; i < num_functions; i++) {
     func ^= functions.At(i);
-    if (func.IsGenerativeConstructor()) {
+    if (func.IsFactory() || func.IsGenerativeConstructor()) {
       // A mixin class must not have explicit constructors.
       if (!func.IsImplicitConstructor()) {
-        ReportError(cls, cls.token_pos(),
-                    "mixin class '%s' must not have constructors\n",
-                    String::Handle(zone, mixin_cls.Name()).ToCString());
+        const char* ctr_kind = func.IsFactory() ? "factory" : "constructor";
+        const Script& script = Script::Handle(cls.script());
+        const Error& error = Error::Handle(
+            LanguageError::NewFormatted(Error::Handle(),
+                script, func.token_pos(), Report::AtLocation,
+                Report::kError, Heap::kNew,
+                "%s '%s' is illegal in mixin class %s",
+                ctr_kind,
+                String::Handle(func.PrettyName()).ToCString(),
+                String::Handle(zone, mixin_cls.Name()).ToCString()));
+
+        ReportErrors(error, cls, cls.token_pos(),
+                     "mixin class '%s' must not have constructors",
+                     String::Handle(zone, mixin_cls.Name()).ToCString());
       }
       continue;  // Skip the implicit constructor.
     }
@@ -2245,6 +2294,8 @@
   // Only resolving rather than finalizing the upper bounds here would result in
   // instantiated type parameters of the super type to temporarily have
   // unfinalized bounds. It is more efficient to finalize them early.
+  // Finalize bounds even if running in production mode, so that a snapshot
+  // contains them.
   FinalizeUpperBounds(cls);
   // Finalize super type.
   AbstractType& super_type = AbstractType::Handle(cls.super_type());
@@ -2265,10 +2316,13 @@
     mixin_type ^= FinalizeType(cls, mixin_type, kCanonicalizeWellFormed);
     cls.set_mixin(mixin_type);
   }
-  if (cls.IsSignatureClass()) {
+  if (cls.IsTypedefClass()) {
+    const Function& signature = Function::Handle(cls.signature_function());
+    FunctionType& type = FunctionType::Handle(signature.SignatureType());
+
     // Check for illegal self references.
     GrowableArray<intptr_t> visited_aliases;
-    if (!IsAliasCycleFree(cls, &visited_aliases)) {
+    if (!IsTypedefCycleFree(cls, type, &visited_aliases)) {
       const String& name = String::Handle(cls.Name());
       ReportError(cls, cls.token_pos(),
                   "typedef '%s' illegally refers to itself",
@@ -2276,26 +2330,22 @@
     }
     cls.set_is_type_finalized();
 
-    // The type parameters of signature classes may have bounds.
-    FinalizeUpperBounds(cls);
-
     // Resolve and finalize the result and parameter types of the signature
-    // function of this signature class.
-    const Function& sig_function = Function::Handle(cls.signature_function());
-    ResolveAndFinalizeSignature(cls, sig_function);
+    // function of this typedef class.
+    FinalizeSignature(cls, signature);  // Does not modify signature type.
+    ASSERT(signature.SignatureType() == type.raw());
 
-    // Resolve and finalize the signature type of this signature class.
-    const Type& sig_type = Type::Handle(cls.SignatureType());
-    FinalizeType(cls, sig_type, kCanonicalizeWellFormed);
+    // Resolve and finalize the signature type of this typedef.
+    type ^= FinalizeType(cls, type, kCanonicalizeWellFormed);
+    signature.SetSignatureType(type);
 
-    // Add this class to the subclasses of the superclass (_FunctionImpl).
-    if (!super_type.IsNull()) {
-      ASSERT(!super_type.IsObjectType());
-      ASSERT(!super_class.IsNull());
-      super_class.AddDirectSubclass(cls);
-    }
+    // Closure instances do not refer to this typedef as their class, so there
+    // is no need to add this typedef class to the subclasses of _Closure.
+    ASSERT(super_type.IsNull() || super_type.IsObjectType());
+
     return;
   }
+
   // Finalize interface types (but not necessarily interface classes).
   Array& interface_types = Array::Handle(cls.interfaces());
   AbstractType& interface_type = AbstractType::Handle();
@@ -2332,9 +2382,6 @@
   // Mark as type finalized before resolving type parameter upper bounds
   // in order to break cycles.
   cls.set_is_type_finalized();
-  // Finalize bounds even if running in production mode, so that a snapshot
-  // contains them.
-  FinalizeUpperBounds(cls);
   // Add this class to the direct subclasses of the superclass, unless the
   // superclass is Object.
   if (!super_type.IsNull() && !super_type.IsObjectType()) {
@@ -2401,9 +2448,9 @@
     cls.SetFunctions(functions);
   }
   // Every class should have at least a constructor, unless it is a top level
-  // class or a signature class.
+  // class or a typedef class.
   ASSERT(cls.IsTopLevel() ||
-         cls.IsSignatureClass() ||
+         cls.IsTypedefClass() ||
          (Array::Handle(cls.functions()).Length() > 0));
   // Resolve and finalize all member types.
   ResolveAndFinalizeMemberTypes(cls);
@@ -2494,82 +2541,74 @@
 }
 
 
-// Helper function called by IsAliasCycleFree.
-bool ClassFinalizer::IsTypeCycleFree(
-    const Class& cls,
-    const AbstractType& type,
-    GrowableArray<intptr_t>* visited) {
+// Returns false if a function type alias illegally refers to itself.
+bool ClassFinalizer::IsTypedefCycleFree(const Class& cls,
+                                        const AbstractType& type,
+                                        GrowableArray<intptr_t>* visited) {
   ASSERT(visited != NULL);
-  ResolveType(cls, type);
-  if (type.IsType() && !type.IsMalformed()) {
-    const Class& type_class = Class::Handle(type.type_class());
-    if (!type_class.is_type_finalized() &&
-        type_class.IsSignatureClass() &&
-        !IsAliasCycleFree(type_class, visited)) {
-      return false;
-    }
-    const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
-    if (!type_args.IsNull()) {
-      AbstractType& type_arg = AbstractType::Handle();
-      for (intptr_t i = 0; i < type_args.Length(); i++) {
-        type_arg = type_args.TypeAt(i);
-        if (!IsTypeCycleFree(cls, type_arg, visited)) {
+  AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
+  bool checking_typedef = false;
+  if ((resolved_type.IsType() || resolved_type.IsFunctionType()) &&
+      !resolved_type.IsMalformed()) {
+    AbstractType& other_type = AbstractType::Handle();
+    if (resolved_type.IsFunctionType()) {
+      const Class& scope_class = Class::Handle(resolved_type.type_class());
+      if (!scope_class.is_type_finalized() && scope_class.IsTypedefClass()) {
+        checking_typedef = true;
+        const intptr_t scope_class_id = scope_class.id();
+        ASSERT(visited != NULL);
+        for (intptr_t i = 0; i < visited->length(); i++) {
+          if ((*visited)[i] == scope_class_id) {
+            // We have already visited alias 'scope_class'. We found a cycle.
+            return false;
+          }
+        }
+        visited->Add(scope_class_id);
+      }
+      // Check the bounds of this function type.
+      const intptr_t num_type_params = scope_class.NumTypeParameters();
+      TypeParameter& type_param = TypeParameter::Handle();
+      const TypeArguments& type_params =
+          TypeArguments::Handle(scope_class.type_parameters());
+      ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
+             (type_params.Length() == num_type_params));
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type_param ^= type_params.TypeAt(i);
+        other_type = type_param.bound();
+        if (!IsTypedefCycleFree(cls, other_type, visited)) {
+          return false;
+        }
+      }
+      // Check the result type of the signature of this function type.
+      const Function& function =
+          Function::Handle(FunctionType::Cast(resolved_type).signature());
+      other_type = function.result_type();
+      if (!IsTypedefCycleFree(cls, other_type, visited)) {
+        return false;
+      }
+      // Check the parameter types of the signature of this function type.
+      const intptr_t num_parameters = function.NumParameters();
+      for (intptr_t i = 0; i < num_parameters; i++) {
+        other_type = function.ParameterTypeAt(i);
+        if (!IsTypedefCycleFree(cls, other_type, visited)) {
           return false;
         }
       }
     }
-  }
-  return true;
-}
-
-
-// Returns false if the function type alias illegally refers to itself.
-bool ClassFinalizer::IsAliasCycleFree(const Class& cls,
-                                      GrowableArray<intptr_t>* visited) {
-  ASSERT(cls.IsSignatureClass());
-  ASSERT(!cls.is_type_finalized());
-  ASSERT(visited != NULL);
-  const intptr_t cls_index = cls.id();
-  for (intptr_t i = 0; i < visited->length(); i++) {
-    if ((*visited)[i] == cls_index) {
-      // We have already visited alias 'cls'. We found a cycle.
-      return false;
+    const TypeArguments& type_args =
+        TypeArguments::Handle(resolved_type.arguments());
+    if (!type_args.IsNull()) {
+      for (intptr_t i = 0; i < type_args.Length(); i++) {
+        other_type = type_args.TypeAt(i);
+        if (!IsTypedefCycleFree(cls, other_type, visited)) {
+          return false;
+        }
+      }
+    }
+    if (checking_typedef) {
+      visited->RemoveLast();
     }
   }
-
-  // Visit the bounds, result type, and parameter types of this signature type.
-  visited->Add(cls.id());
-  AbstractType& type = AbstractType::Handle();
-
-  // Check the bounds of this signature type.
-  const intptr_t num_type_params = cls.NumTypeParameters();
-  TypeParameter& type_param = TypeParameter::Handle();
-  const TypeArguments& type_params =
-      TypeArguments::Handle(cls.type_parameters());
-  ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
-         (type_params.Length() == num_type_params));
-  for (intptr_t i = 0; i < num_type_params; i++) {
-    type_param ^= type_params.TypeAt(i);
-    type = type_param.bound();
-    if (!IsTypeCycleFree(cls, type, visited)) {
-      return false;
-    }
-  }
-  // Check the result type of the function of this signature type.
-  const Function& function = Function::Handle(cls.signature_function());
-  type = function.result_type();
-  if (!IsTypeCycleFree(cls, type, visited)) {
-    return false;
-  }
-  // Check the formal parameter types of the function of this signature type.
-  const intptr_t num_parameters = function.NumParameters();
-  for (intptr_t i = 0; i < num_parameters; i++) {
-    type = function.ParameterTypeAt(i);
-    if (!IsTypeCycleFree(cls, type, visited)) {
-      return false;
-    }
-  }
-  visited->RemoveLast();
   return true;
 }
 
@@ -2657,8 +2696,16 @@
       GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
   AbstractType& mixin_super_type =
       AbstractType::Handle(zone, mixin_app_type.super_type());
-  ResolveType(cls, mixin_super_type);
+  mixin_super_type = ResolveType(cls, mixin_super_type);
   ASSERT(mixin_super_type.HasResolvedTypeClass());  // Even if malformed.
+  if (mixin_super_type.IsMalformedOrMalbounded()) {
+    ReportError(Error::Handle(zone, mixin_super_type.error()));
+  }
+  if (mixin_super_type.IsDynamicType()) {
+    ReportError(cls, cls.token_pos(),
+                "class '%s' may not extend 'dynamic'",
+                String::Handle(zone, cls.Name()).ToCString());
+  }
   // The super type may have a BoundedType as type argument, but cannot be
   // a BoundedType itself.
   CollectTypeArguments(cls, Type::Cast(mixin_super_type), type_args);
@@ -2673,7 +2720,7 @@
   for (intptr_t i = 0; i < depth; i++) {
     mixin_type = mixin_app_type.MixinTypeAt(i);
     ASSERT(!mixin_type.IsNull());
-    ResolveType(cls, mixin_type);
+    mixin_type = ResolveType(cls, mixin_type);
     ASSERT(mixin_type.HasResolvedTypeClass());  // Even if malformed.
     ASSERT(mixin_type.IsType());
     const intptr_t num_super_type_args = type_args.Length();
@@ -2834,7 +2881,7 @@
   Class& interface_class = Class::Handle(zone);
 
   // Resolve super type. Failures lead to a longjmp.
-  ResolveType(cls, super_type);
+  super_type = ResolveType(cls, super_type);
   if (super_type.IsMalformedOrMalbounded()) {
     ReportError(Error::Handle(zone, super_type.error()));
   }
@@ -2844,7 +2891,7 @@
                 String::Handle(zone, cls.Name()).ToCString());
   }
   interface_class = super_type.type_class();
-  if (interface_class.IsSignatureClass()) {
+  if (interface_class.IsTypedefClass()) {
     ReportError(cls, cls.token_pos(),
                 "class '%s' may not extend function type alias '%s'",
                 String::Handle(zone, cls.Name()).ToCString(),
@@ -2914,7 +2961,7 @@
   // Resolve interfaces. Failures lead to a longjmp.
   for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
     interface ^= super_interfaces.At(i);
-    ResolveType(cls, interface);
+    interface = ResolveType(cls, interface);
     ASSERT(!interface.IsTypeParameter());  // Should be detected by parser.
     // A malbounded interface is only reported when involved in a type test.
     if (interface.IsMalformed()) {
@@ -2925,7 +2972,7 @@
                   "'dynamic' may not be used as interface");
     }
     interface_class = interface.type_class();
-    if (interface_class.IsSignatureClass()) {
+    if (interface_class.IsTypedefClass()) {
       const String& interface_name = String::Handle(zone,
                                                     interface_class.Name());
       ReportError(cls, cls.token_pos(),
@@ -3048,7 +3095,7 @@
                                        va_list args) {
   LanguageError& error = LanguageError::Handle(
       LanguageError::NewFormattedV(
-          prev_error, script, type.token_pos(),
+          prev_error, script, type.token_pos(), Report::AtLocation,
           Report::kMalformedType, Heap::kOld,
           format, args));
   if (Isolate::Current()->flags().error_on_bad_type()) {
@@ -3061,7 +3108,7 @@
   type.set_arguments(Object::null_type_arguments());
   if (!type.IsFinalized()) {
     type.SetIsFinalized();
-    // Do not canonicalize malformed types, since they may not be resolved.
+    // Do not canonicalize malformed types, since they contain an error field.
   } else {
     // The only case where the malformed type was already finalized is when its
     // type arguments are not within bounds. In that case, we have a prev_error.
@@ -3103,13 +3150,13 @@
 
 void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error,
                                             const Script& script,
-                                            const Type& type,
+                                            const AbstractType& type,
                                             const char* format, ...) {
   va_list args;
   va_start(args, format);
   LanguageError& error = LanguageError::Handle(
       LanguageError::NewFormattedV(
-          prev_error, script, type.token_pos(),
+          prev_error, script, type.token_pos(), Report::AtLocation,
           Report::kMalboundedType, Heap::kOld,
           format, args));
   va_end(args);
@@ -3149,7 +3196,8 @@
   va_list args;
   va_start(args, format);
   const Script& script = Script::Handle(cls.script());
-  Report::MessageV(Report::kError, script, token_pos, format, args);
+  Report::MessageV(Report::kError,
+                   script, token_pos, Report::AtLocation, format, args);
   va_end(args);
   UNREACHABLE();
 }
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index 3aa7c2c..a8c59a2 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -60,7 +60,7 @@
   // string and its arguments.
   static void FinalizeMalboundedType(const Error& prev_error,
                                      const Script& script,
-                                     const Type& type,
+                                     const AbstractType& type,
                                      const char* format, ...)
        PRINTF_ATTRIBUTE(4, 5);
 
@@ -89,7 +89,8 @@
 #endif  // defined(DART_NO_SNAPSHOT).
 
   // Resolve the class of the type, but not the type's type arguments.
-  static void ResolveTypeClass(const Class& cls, const AbstractType& type);
+  // May promote the type from Type to FunctionType.
+  static RawAbstractType* ResolveTypeClass(const Class& cls, const Type& type);
 
   // Resolve the type and target of the redirecting factory.
   static void ResolveRedirectingFactory(const Class& cls,
@@ -102,17 +103,16 @@
  private:
   static void AllocateEnumValues(const Class& enum_cls);
   static bool IsSuperCycleFree(const Class& cls);
-  static bool IsTypeCycleFree(const Class& cls,
-                              const AbstractType& type,
-                              GrowableArray<intptr_t>* visited);
-  static bool IsAliasCycleFree(const Class& cls,
-                               GrowableArray<intptr_t>* visited);
+  static bool IsTypedefCycleFree(const Class& cls,
+                                 const AbstractType& type,
+                                 GrowableArray<intptr_t>* visited);
   static bool IsMixinCycleFree(const Class& cls,
                                GrowableArray<intptr_t>* visited);
   static void CheckForLegalConstClass(const Class& cls);
   static RawClass* ResolveClass(const Class& cls,
                                 const UnresolvedClass& unresolved_class);
-  static void ResolveType(const Class& cls, const AbstractType& type);
+  static RawAbstractType* ResolveType(const Class& cls,
+                                      const AbstractType& type);
   static void ResolveRedirectingFactoryTarget(
       const Class& cls,
       const Function& factory,
@@ -134,6 +134,9 @@
                                             GrowableArray<intptr_t>* visited);
   static void FinalizeTypeParameters(const Class& cls,
                                      PendingTypes* pending_types = NULL);
+  static intptr_t ExpandAndFinalizeTypeArguments(const Class& cls,
+                                                 const AbstractType& type,
+                                                 PendingTypes* pending_types);
   static void FinalizeTypeArguments(const Class& cls,
                                     const TypeArguments& arguments,
                                     intptr_t num_uninitialized_arguments,
@@ -141,16 +144,16 @@
                                     PendingTypes* pending_types,
                                     TrailPtr trail);
   static void CheckRecursiveType(const Class& cls,
-                                 const Type& type,
+                                 const AbstractType& type,
                                  PendingTypes* pending_types);
-  static void CheckTypeBounds(const Class& cls, const Type& type);
+  static void CheckTypeBounds(const Class& cls, const AbstractType& type);
   static void CheckTypeArgumentBounds(const Class& cls,
                                       const TypeArguments& arguments,
                                       Error* bound_error);
   static void ResolveUpperBounds(const Class& cls);
   static void FinalizeUpperBounds(const Class& cls);
-  static void ResolveAndFinalizeSignature(const Class& cls,
-                                          const Function& function);
+  static void ResolveSignature(const Class& cls, const Function& function);
+  static void FinalizeSignature(const Class& cls, const Function& function);
   static void ResolveAndFinalizeMemberTypes(const Class& cls);
   static void PrintClassInformation(const Class& cls);
   static void CollectInterfaces(
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index 828ecac..2c87c9c 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -14,7 +14,7 @@
   const String& class_name = String::Handle(Symbols::New(name));
   const Script& script = Script::Handle();
   const Class& cls =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   cls.set_interfaces(Object::empty_array());
   cls.SetFunctions(Object::empty_array());
   cls.SetFields(Object::empty_array());
@@ -96,12 +96,12 @@
   const UnresolvedClass& unresolved = UnresolvedClass::Handle(
       UnresolvedClass::New(LibraryPrefix::Handle(),
                            superclass_name,
-                           Scanner::kNoSourcePos));
+                           Token::kNoSourcePos));
   const TypeArguments& type_arguments = TypeArguments::Handle();
   rhb.set_super_type(Type::Handle(
       Type::New(Object::Handle(unresolved.raw()),
                 type_arguments,
-                Scanner::kNoSourcePos)));
+                Token::kNoSourcePos)));
   EXPECT(ClassFinalizer::ProcessPendingClasses());
 }
 
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index adc7853..ac4cb24 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/code_descriptors.h"
+#include "vm/compiler.h"
 
 namespace dart {
 
@@ -15,25 +16,47 @@
          (kind == RawPcDescriptors::kOther) ||
          (deopt_id != Thread::kNoDeoptId));
 
-  intptr_t merged_kind_try =
-      RawPcDescriptors::MergedKindTry::Encode(kind, try_index);
+  // When precompiling, we only use pc descriptors for exceptions.
+  if (Compiler::allow_recompilation() || try_index != -1) {
+    intptr_t merged_kind_try =
+        RawPcDescriptors::MergedKindTry::Encode(kind, try_index);
 
-  PcDescriptors::EncodeInteger(&encoded_data_, merged_kind_try);
-  PcDescriptors::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
-  PcDescriptors::EncodeInteger(&encoded_data_, deopt_id - prev_deopt_id);
-  PcDescriptors::EncodeInteger(&encoded_data_, token_pos - prev_token_pos);
+    PcDescriptors::EncodeInteger(&encoded_data_, merged_kind_try);
+    PcDescriptors::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
+    PcDescriptors::EncodeInteger(&encoded_data_, deopt_id - prev_deopt_id);
+    PcDescriptors::EncodeInteger(&encoded_data_, token_pos - prev_token_pos);
 
-  prev_pc_offset = pc_offset;
-  prev_deopt_id = deopt_id;
-  prev_token_pos = token_pos;
+    prev_pc_offset = pc_offset;
+    prev_deopt_id = deopt_id;
+    prev_token_pos = token_pos;
+  }
 }
 
 
 RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) {
+  if (encoded_data_.length() == 0) {
+    return Object::empty_descriptors().raw();
+  }
   return PcDescriptors::New(&encoded_data_);
 }
 
 
+
+void CodeSourceMapBuilder::AddEntry(intptr_t pc_offset,
+                                    intptr_t token_pos) {
+  CodeSourceMap::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
+  CodeSourceMap::EncodeInteger(&encoded_data_, token_pos - prev_token_pos);
+
+  prev_pc_offset = pc_offset;
+  prev_token_pos = token_pos;
+}
+
+
+RawCodeSourceMap* CodeSourceMapBuilder::Finalize() {
+  return CodeSourceMap::New(&encoded_data_);
+}
+
+
 void StackmapTableBuilder::AddEntry(intptr_t pc_offset,
                                     BitmapBuilder* bitmap,
                                     intptr_t register_bit_count) {
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index e24e186..11e3437 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -42,6 +42,29 @@
 };
 
 
+class CodeSourceMapBuilder : public ZoneAllocated {
+ public:
+  explicit CodeSourceMapBuilder(intptr_t initial_capacity = 64)
+    : encoded_data_(initial_capacity),
+      prev_pc_offset(0),
+      prev_token_pos(0) {}
+
+  ~CodeSourceMapBuilder() { }
+
+  void AddEntry(intptr_t pc_offset, intptr_t token_pos);
+
+  RawCodeSourceMap* Finalize();
+
+ private:
+  GrowableArray<uint8_t> encoded_data_;
+
+  intptr_t prev_pc_offset;
+  intptr_t prev_token_pos;
+
+  DISALLOW_COPY_AND_ASSIGN(CodeSourceMapBuilder);
+};
+
+
 class StackmapTableBuilder : public ZoneAllocated {
  public:
   StackmapTableBuilder()
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 2586a97..30cedd4 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -18,7 +18,7 @@
 
 namespace dart {
 
-static const intptr_t kPos = Scanner::kNoSourcePos;
+static const intptr_t kPos = Token::kNoSourcePos;
 
 
 CODEGEN_TEST_GENERATE(StackmapCodegen, test) {
@@ -268,4 +268,100 @@
   EXPECT(!result.IsError());
 }
 
+
+TEST_CASE(DescriptorList_TokenPositions) {
+  DescriptorList* descriptors = new DescriptorList(64);
+  ASSERT(descriptors != NULL);
+  const intptr_t token_positions[] = {
+    kMinInt32,
+    5,
+    13,
+    13,
+    13,
+    13,
+    31,
+    23,
+    23,
+    23,
+    33,
+    33,
+    5,
+    5,
+    Token::kMinSourcePos,
+    Token::kMaxSourcePos,
+  };
+  const intptr_t num_token_positions =
+      sizeof(token_positions) / sizeof(token_positions[0]);
+
+  for (intptr_t i = 0; i < num_token_positions; i++) {
+    descriptors->AddDescriptor(RawPcDescriptors::kRuntimeCall, 0, 0,
+                               token_positions[i], 0);
+  }
+
+  const PcDescriptors& finalized_descriptors =
+      PcDescriptors::Handle(descriptors->FinalizePcDescriptors(0));
+
+  ASSERT(!finalized_descriptors.IsNull());
+  PcDescriptors::Iterator it(finalized_descriptors,
+                             RawPcDescriptors::kRuntimeCall);
+
+  intptr_t i = 0;
+  while (it.MoveNext()) {
+    if (token_positions[i] != it.TokenPos()) {
+      OS::Print("[%" Pd "]: Expected: %" Pd " != %" Pd "\n",
+                i, token_positions[i], it.TokenPos());
+    }
+    EXPECT(token_positions[i] == it.TokenPos());
+    i++;
+  }
+}
+
+
+TEST_CASE(CodeSourceMap_TokenPositions) {
+  const intptr_t token_positions[] = {
+    kMinInt32,
+    5,
+    13,
+    13,
+    13,
+    13,
+    31,
+    23,
+    23,
+    23,
+    33,
+    33,
+    5,
+    5,
+    Token::kMinSourcePos,
+    Token::kMaxSourcePos,
+  };
+  const intptr_t num_token_positions =
+      sizeof(token_positions) / sizeof(token_positions[0]);
+
+  CodeSourceMapBuilder* builder = new CodeSourceMapBuilder();
+  ASSERT(builder != NULL);
+
+  for (intptr_t i = 0; i < num_token_positions; i++) {
+    builder->AddEntry(i, token_positions[i]);
+  }
+
+  const CodeSourceMap& code_Source_map =
+      CodeSourceMap::Handle(builder->Finalize());
+
+  ASSERT(!code_Source_map.IsNull());
+  CodeSourceMap::Iterator it(code_Source_map);
+
+  uintptr_t i = 0;
+  while (it.MoveNext()) {
+    EXPECT(it.PcOffset() == i);
+    if (token_positions[i] != it.TokenPos()) {
+      OS::Print("[%" Pd "]: Expected: %" Pd " != %" Pd "\n",
+                i, token_positions[i], it.TokenPos());
+    }
+    EXPECT(token_positions[i] == it.TokenPos());
+    i++;
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index d7c92d7..d0cdd74e 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -204,7 +204,7 @@
   ASSERT(!type.IsNull() && !type.IsInstantiated());
   ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
   Error& bound_error = Error::Handle();
-  type = type.InstantiateFrom(instantiator, &bound_error);
+  type = type.InstantiateFrom(instantiator, &bound_error, NULL, Heap::kOld);
   if (!bound_error.IsNull()) {
     // Throw a dynamic type error.
     const intptr_t location = GetCallerLocation();
@@ -300,7 +300,7 @@
   StackFrame* caller_frame = iterator.NextFrame();
   ASSERT(caller_frame != NULL);
 
-  const Type& instance_type = Type::Handle(instance.GetType());
+  const AbstractType& instance_type = AbstractType::Handle(instance.GetType());
   ASSERT(instance_type.IsInstantiated());
   if (type.IsInstantiated()) {
     OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n",
@@ -334,10 +334,10 @@
 
 
 // This updates the type test cache, an array containing 4-value elements
-// (instance class, instance type arguments, instantiator type arguments and
-// test_result). It can be applied to classes with type arguments in which
-// case it contains just the result of the class subtype test, not including
-// the evaluation of type arguments.
+// (instance class (or function if the instance is a closure), instance type
+// arguments, instantiator type arguments and test_result). It can be applied to
+// classes with type arguments in which case it contains just the result of the
+// class subtype test, not including the evaluation of type arguments.
 // This operation is currently very slow (lookup of code is not efficient yet).
 static void UpdateTypeTestCache(
     const Instance& instance,
@@ -360,11 +360,16 @@
     }
     return;
   }
-  TypeArguments& instance_type_arguments =
-      TypeArguments::Handle();
   const Class& instance_class = Class::Handle(instance.clazz());
-
-  if (instance_class.NumTypeArguments() > 0) {
+  Object& instance_class_id_or_function = Object::Handle();
+  if (instance_class.IsClosureClass()) {
+    instance_class_id_or_function = Closure::Cast(instance).function();
+  } else {
+    instance_class_id_or_function = Smi::New(instance_class.id());
+  }
+  TypeArguments& instance_type_arguments = TypeArguments::Handle();
+  if (instance_class.IsClosureClass() ||
+      (instance_class.NumTypeArguments() > 0)) {
     instance_type_arguments = instance.GetTypeArguments();
   }
 
@@ -377,20 +382,19 @@
          instance_type_arguments.IsCanonical());
   ASSERT(instantiator_type_arguments.IsNull() ||
          instantiator_type_arguments.IsCanonical());
-  intptr_t last_instance_class_id = -1;
-  TypeArguments& last_instance_type_arguments =
-      TypeArguments::Handle();
-  TypeArguments& last_instantiator_type_arguments =
-      TypeArguments::Handle();
+  Object& last_instance_class_id_or_function = Object::Handle();
+  TypeArguments& last_instance_type_arguments = TypeArguments::Handle();
+  TypeArguments& last_instantiator_type_arguments = TypeArguments::Handle();
   Bool& last_result = Bool::Handle();
   for (intptr_t i = 0; i < len; ++i) {
     new_cache.GetCheck(
         i,
-        &last_instance_class_id,
+        &last_instance_class_id_or_function,
         &last_instance_type_arguments,
         &last_instantiator_type_arguments,
         &last_result);
-    if ((last_instance_class_id == instance_class.id()) &&
+    if ((last_instance_class_id_or_function.raw() ==
+         instance_class_id_or_function.raw()) &&
         (last_instance_type_arguments.raw() == instance_type_arguments.raw()) &&
         (last_instantiator_type_arguments.raw() ==
          instantiator_type_arguments.raw())) {
@@ -402,7 +406,7 @@
     }
   }
 #endif
-  new_cache.AddCheck(instance_class.id(),
+  new_cache.AddCheck(instance_class_id_or_function,
                      instance_type_arguments,
                      instantiator_type_arguments,
                      result);
@@ -415,13 +419,13 @@
       ASSERT(bound_error.IsNull());  // Malbounded types are not optimized.
     }
     OS::PrintErr("  Updated test cache %p ix: %" Pd " with "
-        "(cid: %" Pd ", type-args: %p, instantiator: %p, result: %s)\n"
+        "(cid-or-fun: %p, type-args: %p, instantiator: %p, result: %s)\n"
         "    instance  [class: (%p '%s' cid: %" Pd "),    type-args: %p %s]\n"
         "    test-type [class: (%p '%s' cid: %" Pd "), in-type-args: %p %s]\n",
         new_cache.raw(),
         len,
 
-        instance_class.id(),
+        instance_class_id_or_function.raw(),
         instance_type_arguments.raw(),
         instantiator_type_arguments.raw(),
         result.ToCString(),
@@ -745,15 +749,8 @@
   if (getter.IsNull() || getter.IsMethodExtractor()) {
     return false;
   }
-  const Class& cache_class = Class::Handle(receiver_class.IsSignatureClass()
-      ? receiver_class.SuperClass()
-      : receiver_class.raw());
-  ASSERT(
-      !receiver_class.IsSignatureClass() ||
-      (receiver_class.SuperClass() == Type::Handle(
-       Isolate::Current()->object_store()->function_impl_type()).type_class()));
   const Function& target_function =
-      Function::Handle(cache_class.GetInvocationDispatcher(
+      Function::Handle(receiver_class.GetInvocationDispatcher(
           target_name,
           arguments_descriptor,
           RawFunction::kInvokeFieldDispatcher,
@@ -1223,15 +1220,14 @@
 // Arg1: arguments descriptor array.
 // Arg2: arguments array.
 DEFINE_RUNTIME_ENTRY(InvokeClosureNoSuchMethod, 3) {
-  const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
+  const Closure& receiver = Closure::CheckedHandle(arguments.ArgAt(0));
   const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(1));
   const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(2));
 
   // For closure the function name is always 'call'. Replace it with the
   // name of the closurized function so that exception contains more
   // relevant information.
-  ASSERT(receiver.IsClosure());
-  const Function& function = Function::Handle(Closure::function(receiver));
+  const Function& function = Function::Handle(receiver.function());
   const String& original_function_name =
       String::Handle(function.QualifiedUserVisibleName());
   const Object& result = Object::Handle(
diff --git a/runtime/vm/code_patcher_arm64_test.cc b/runtime/vm/code_patcher_arm64_test.cc
index bb7008a..bd569fc 100644
--- a/runtime/vm/code_patcher_arm64_test.cc
+++ b/runtime/vm/code_patcher_arm64_test.cc
@@ -24,7 +24,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const String& function_name = String::Handle(Symbols::New("callerFunction"));
   const Function& function = Function::Handle(
       Function::New(function_name, RawFunction::kRegularFunction,
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index f9a3f42..f7d741f 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -24,7 +24,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const String& function_name = String::Handle(Symbols::New("callerFunction"));
   const Function& function = Function::Handle(
       Function::New(function_name, RawFunction::kRegularFunction,
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index a9c62f4..a8184bf 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -24,7 +24,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const String& function_name = String::Handle(Symbols::New("callerFunction"));
   const Function& function = Function::Handle(
       Function::New(function_name, RawFunction::kRegularFunction,
diff --git a/runtime/vm/code_patcher_mips_test.cc b/runtime/vm/code_patcher_mips_test.cc
index 78e698b..676a1b0 100644
--- a/runtime/vm/code_patcher_mips_test.cc
+++ b/runtime/vm/code_patcher_mips_test.cc
@@ -24,7 +24,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const String& function_name = String::Handle(Symbols::New("callerFunction"));
   const Function& function = Function::Handle(
       Function::New(function_name, RawFunction::kRegularFunction,
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index ca98231..7d1f31d 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -24,7 +24,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const String& function_name = String::Handle(Symbols::New("callerFunction"));
   const Function& function = Function::Handle(
       Function::New(function_name, RawFunction::kRegularFunction,
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 70d1ac6..7479506 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -80,7 +80,7 @@
 bool Compiler::always_optimize_ = false;
 bool Compiler::allow_recompilation_ = true;
 
-#ifndef DART_PRECOMPILED
+#ifndef DART_PRECOMPILED_RUNTIME
 
 // TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove
 // separate helpers functions & `optimizing` args.
@@ -282,14 +282,13 @@
   if (cls.is_marked_for_parsing()) {
     return Error::null();
   }
-  // If the class is a signature class there is no need to try and
+  // If the class is a typedef class there is no need to try and
   // compile it. Just finalize it directly.
-  if (cls.IsSignatureClass()) {
+  if (cls.IsTypedefClass()) {
 #if defined(DEBUG)
-    const Type& type = Type::Handle(
-        Isolate::Current()->object_store()->function_impl_type());
-    const Class& type_cls = Class::Handle(type.type_class());
-    ASSERT(type_cls.is_finalized());
+    const Class& closure_cls = Class::Handle(
+        Isolate::Current()->object_store()->closure_class());
+    ASSERT(closure_cls.is_finalized());
 #endif
     LongJumpScope jump;
     if (setjmp(*jump.Set()) == 0) {
@@ -1341,8 +1340,7 @@
     CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id);
     const bool success = helper.Compile(pipeline);
     if (!success) {
-      if (optimized) {
-        ASSERT(!Compiler::always_optimize());  // Optimized is the only code.
+      if (optimized && !Compiler::always_optimize()) {
         // Optimizer bailed out. Disable optimizations and never try again.
         if (trace_compiler) {
           THR_Print("--> disabling optimizations for '%s'\n",
@@ -1359,6 +1357,8 @@
         // We got an error during compilation.
         error = isolate->object_store()->sticky_error();
         isolate->object_store()->clear_sticky_error();
+        ASSERT(error.IsLanguageError() &&
+               LanguageError::Cast(error).kind() != Report::kBailout);
         return error.raw();
       }
     }
@@ -1941,7 +1941,7 @@
 }
 
 
-#else  // DART_PRECOMPILED
+#else  // DART_PRECOMPILED_RUNTIME
 
 
 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
@@ -2046,6 +2046,6 @@
   UNREACHABLE();
 }
 
-#endif  // DART_PRECOMPILED
+#endif  // DART_PRECOMPILED_RUNTIME
 
 }  // namespace dart
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index 491468a..edaea94 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -56,12 +56,16 @@
 
 namespace dart {
 
-// TODO(zra): Add a target for ARMv6.
 #if defined(TARGET_ARCH_ARM_5TE)
 DEFINE_FLAG(bool, use_vfp, false, "Use vfp instructions if supported");
 DEFINE_FLAG(bool, use_neon, false, "Use neon instructions if supported");
 DEFINE_FLAG(bool, use_integer_division, false,
             "Use integer division instruction if supported");
+#elif defined(TARGET_ARCH_ARM_6)
+DEFINE_FLAG(bool, use_vfp, true, "Use vfp instructions if supported");
+DEFINE_FLAG(bool, use_neon, false, "Use neon instructions if supported");
+DEFINE_FLAG(bool, use_integer_division, false,
+            "Use integer division instruction if supported");
 #else
 DEFINE_FLAG(bool, use_vfp, true, "Use vfp instructions if supported");
 DEFINE_FLAG(bool, use_neon, true, "Use neon instructions if supported");
@@ -242,6 +246,8 @@
 
 #if defined(TARGET_ARCH_ARM_5TE)
   arm_version_ = ARMv5TE;
+#elif defined(TARGET_ARCH_ARM_6)
+  arm_version_ = ARMv6;
 #else
   arm_version_ = ARMv7;
 #endif
diff --git a/runtime/vm/cpuinfo.h b/runtime/vm/cpuinfo.h
index 3ccf2d4..cd1247e 100644
--- a/runtime/vm/cpuinfo.h
+++ b/runtime/vm/cpuinfo.h
@@ -61,7 +61,7 @@
     if (HasField(FieldName(kCpuInfoHardware))) {
       return ExtractField(kCpuInfoHardware);
     } else {
-      return "";
+      return strdup("Unknown");
     }
   }
 
diff --git a/runtime/vm/cpuinfo_linux.cc b/runtime/vm/cpuinfo_linux.cc
index 0341530..e58bac1 100644
--- a/runtime/vm/cpuinfo_linux.cc
+++ b/runtime/vm/cpuinfo_linux.cc
@@ -28,14 +28,20 @@
   fields_[kCpuInfoFeatures] = "flags";
   method_ = kCpuInfoCpuId;
   CpuId::InitOnce();
-#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
-  // TODO(zra): Verify that these field names are correct for arm64.
+#elif defined(HOST_ARCH_ARM)
   fields_[kCpuInfoProcessor] = "Processor";
   fields_[kCpuInfoModel] = "model name";
   fields_[kCpuInfoHardware] = "Hardware";
   fields_[kCpuInfoFeatures] = "Features";
   method_ = kCpuInfoSystem;
   ProcCpuInfo::InitOnce();
+#elif defined(HOST_ARCH_ARM64)
+  fields_[kCpuInfoProcessor] = "Processor";
+  fields_[kCpuInfoModel] = "CPU implementer";
+  fields_[kCpuInfoHardware] = "CPU implementer";
+  fields_[kCpuInfoFeatures] = "Features";
+  method_ = kCpuInfoSystem;
+  ProcCpuInfo::InitOnce();
 #elif defined(HOST_ARCH_MIPS)
   fields_[kCpuInfoProcessor] = "system type";
   fields_[kCpuInfoModel] = "cpu model";
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 796aaca..d316138 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -77,7 +77,6 @@
   }
 }
 
-#if 0
 #define API_TIMELINE_DURATION                                                  \
   TimelineDurationScope tds(Thread::Current(),                                 \
                             Timeline::GetVMApiStream(),                        \
@@ -87,10 +86,7 @@
   TimelineBeginEndScope tbes(Thread::Current(),                                \
                              Timeline::GetVMApiStream(),                       \
                              CURRENT_FUNC)
-#else
-#define API_TIMELINE_DURATION ASSERT(true)
-#define API_TIMELINE_BEGIN_END ASSERT(true)
-#endif
+
 
 #if defined(DEBUG)
 // An object visitor which will iterate over all the function objects in the
@@ -111,7 +107,7 @@
       // Verify that the result type of a function is canonical or a
       // TypeParameter.
       typeHandle_ ^= funcHandle_.result_type();
-      ASSERT(typeHandle_.IsNull() ||
+      ASSERT(typeHandle_.IsMalformed() ||
              !typeHandle_.IsResolved() ||
              typeHandle_.IsTypeParameter() ||
              typeHandle_.IsCanonical());
@@ -120,8 +116,9 @@
       const intptr_t num_parameters = funcHandle_.NumParameters();
       for (intptr_t i = 0; i < num_parameters; i++) {
         typeHandle_ = funcHandle_.ParameterTypeAt(i);
-        ASSERT(typeHandle_.IsTypeParameter() ||
+        ASSERT(typeHandle_.IsMalformed() ||
                !typeHandle_.IsResolved() ||
+               typeHandle_.IsTypeParameter() ||
                typeHandle_.IsCanonical());
       }
     }
@@ -1858,14 +1855,7 @@
 
 
 DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
-  // We can't use a fast class index check here because there are many
-  // different signature classes for closures.
-  Thread* thread = Thread::Current();
-  CHECK_ISOLATE(thread->isolate());
-  ReusableObjectHandleScope reused_obj_handle(thread);
-  const Instance& closure_obj =
-      Api::UnwrapInstanceHandle(reused_obj_handle, object);
-  return (!closure_obj.IsNull() && closure_obj.IsClosure());
+  return Api::ClassId(object) == kClosureCid;
 }
 
 
@@ -1917,7 +1907,8 @@
   if (!obj.IsInstance()) {
     RETURN_TYPE_ERROR(Z, instance, Instance);
   }
-  const Type& type = Type::Handle(Instance::Cast(obj).GetType());
+  const AbstractType& type =
+      AbstractType::Handle(Instance::Cast(obj).GetType());
   return Api::NewHandle(T, type.Canonicalize());
 }
 
@@ -3888,7 +3879,7 @@
 
   // Construct name of the constructor to invoke.
   const String& constructor_name = Api::UnwrapStringHandle(Z, name);
-  const Type& type_obj = Type::Handle(Z, instance.GetType());
+  const AbstractType& type_obj = AbstractType::Handle(Z, instance.GetType());
   const Class& cls = Class::Handle(Z, type_obj.type_class());
   const String& class_name = String::Handle(Z, cls.Name());
   const Array& strings = Array::Handle(Z, Array::New(3));
@@ -5135,7 +5126,7 @@
 
   // Construct the type object, canonicalize it and return.
   Type& instantiated_type = Type::Handle(
-      Type::New(cls, type_args_obj, Scanner::kNoSourcePos));
+      Type::New(cls, type_args_obj, Token::kNoSourcePos));
   instantiated_type ^= ClassFinalizer::FinalizeType(
       cls, instantiated_type, ClassFinalizer::kCanonicalize);
   return Api::NewHandle(T, instantiated_type.raw());
@@ -5882,7 +5873,7 @@
 }
 
 
-#if defined(DART_PRECOMPILED)
+#if defined(DART_PRECOMPILED_RUNTIME)
 
 DART_EXPORT Dart_Handle Dart_Precompile(
     Dart_QualifiedFunctionName entry_points[],
@@ -5903,7 +5894,7 @@
   return 0;
 }
 
-#else  // DART_PRECOMPILED
+#else  // DART_PRECOMPILED_RUNTIME
 
 DART_EXPORT Dart_Handle Dart_Precompile(
     Dart_QualifiedFunctionName entry_points[],
@@ -5977,7 +5968,7 @@
 
   return Api::Success();
 }
-#endif  // DART_PRECOMPILED
+#endif  // DART_PRECOMPILED_RUNTIME
 
 
 DART_EXPORT bool Dart_IsRunningPrecompiledCode() {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a2cf1d3..8a40a7a 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -6762,9 +6762,9 @@
 TEST_CASE(SetNativeResolver) {
   const char* kScriptChars =
       "class Test {"
-      "  static foo() native \"SomeNativeFunction\";"
-      "  static bar() native \"SomeNativeFunction2\";"
-      "  static baz() native \"SomeNativeFunction3\";"
+      "  static foo() native \"SomeNativeFunction\";\n"
+      "  static bar() native \"SomeNativeFunction2\";\n"
+      "  static baz() native \"SomeNativeFunction3\";\n"
       "}";
   Dart_Handle error = Dart_NewApiError("incoming error");
   Dart_Handle result;
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index abb3e5d..3a53dcc 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -192,7 +192,12 @@
         ASSERT(getter_result.IsNull() || getter_result.IsInstance());
 
         arguments.SetAt(0, getter_result);
-        return InvokeClosure(arguments, arguments_descriptor);
+        // This otherwise unnecessary handle is used to prevent clang from
+        // doing tail call elimination, which would make the stack overflow
+        // check above ineffective.
+        Object& result = Object::Handle(InvokeClosure(arguments,
+                                                      arguments_descriptor));
+        return result.raw();
       }
       cls = cls.SuperClass();
     }
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index c533e3b..1b3d84a 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -84,7 +84,7 @@
       line_number_(-1),
       column_number_(-1) {
   ASSERT(!script.IsNull());
-  ASSERT(token_pos_ >= 0);
+  ASSERT(Token::IsReal(token_pos_));
 }
 
 // Create a latent breakpoint at given url and line number.
@@ -93,8 +93,8 @@
                                        intptr_t requested_column_number)
     : script_(Script::null()),
       url_(url.raw()),
-      token_pos_(Scanner::kNoSourcePos),
-      end_token_pos_(Scanner::kNoSourcePos),
+      token_pos_(Token::kNoSourcePos),
+      end_token_pos_(Token::kNoSourcePos),
       is_resolved_(false),
       next_(NULL),
       conditions_(NULL),
@@ -239,7 +239,7 @@
       code_(Code::ZoneHandle(code.raw())),
       function_(Function::ZoneHandle(code.function())),
       token_pos_initialized_(false),
-      token_pos_(Scanner::kNoSourcePos),
+      token_pos_(Token::kNoSourcePos),
       try_index_(-1),
       line_number_(-1),
       column_number_(-1),
@@ -566,7 +566,7 @@
 intptr_t ActivationFrame::TokenPos() {
   if (!token_pos_initialized_) {
     token_pos_initialized_ = true;
-    token_pos_ = Scanner::kNoSourcePos;
+    token_pos_ = Token::kNoSourcePos;
     GetPcDescriptors();
     PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
     uword pc_offset = pc_ - code().EntryPoint();
@@ -592,9 +592,10 @@
 
 intptr_t ActivationFrame::LineNumber() {
   // Compute line number lazily since it causes scanning of the script.
-  if ((line_number_ < 0) && (TokenPos() >= 0)) {
+  if ((line_number_ < 0) && Token::IsReal(TokenPos())) {
+    const intptr_t token_pos = TokenPos();
     const Script& script = Script::Handle(SourceScript());
-    script.GetTokenLocation(TokenPos(), &line_number_, NULL);
+    script.GetTokenLocation(token_pos, &line_number_, NULL);
   }
   return line_number_;
 }
@@ -602,10 +603,11 @@
 
 intptr_t ActivationFrame::ColumnNumber() {
   // Compute column number lazily since it causes scanning of the script.
-  if ((column_number_ < 0) && (TokenPos() >= 0)) {
+  if ((column_number_ < 0) && Token::IsReal(TokenPos())) {
+    const intptr_t token_pos = TokenPos();
     const Script& script = Script::Handle(SourceScript());
     if (script.HasSource()) {
-      script.GetTokenLocation(TokenPos(), &line_number_, &column_number_);
+      script.GetTokenLocation(token_pos, &line_number_, &column_number_);
     } else {
       column_number_ = -1;
     }
@@ -654,7 +656,7 @@
     ASSERT(!pc_desc_.IsNull());
     intptr_t innermost_begin_pos = 0;
     intptr_t activation_token_pos = TokenPos();
-    ASSERT(activation_token_pos >= 0);
+    ASSERT(Token::IsReal(activation_token_pos));
     GetVarDescriptors();
     intptr_t var_desc_len = var_descriptors_.Length();
     for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
@@ -767,7 +769,7 @@
   GetVarDescriptors();
 
   intptr_t activation_token_pos = TokenPos();
-  if (activation_token_pos < 0) {
+  if (!Token::IsDebugPause(activation_token_pos)) {
     // We don't have a token position for this frame, so can't determine
     // which variables are visible.
     vars_initialized_ = true;
@@ -1256,6 +1258,7 @@
       obj_cache_(NULL),
       stack_trace_(NULL),
       stepping_fp_(0),
+      skip_next_step_(false),
       exc_pause_info_(kNoPauseOnExceptions) {
 }
 
@@ -1626,7 +1629,6 @@
   // interested in exception events.
   if (ignore_breakpoints_ ||
       IsPaused() ||
-      (!HasDebugEventHandler()) ||
       (exc_pause_info_ == kNoPauseOnExceptions)) {
     return;
   }
@@ -1675,8 +1677,8 @@
 // and:
 //   - has the lowest token position number which satisfies the above.
 //
-// When we consider a column number, we look for the closed token
-// which intersects the desired column.  For example:
+// When we consider a column number, we look for the token which
+// intersects the desired column.  For example:
 //
 //          1         2         3
 // 12345678901234567890         0
@@ -1740,7 +1742,7 @@
   PcDescriptors::Iterator iter(desc, kSafepointKind);
   while (iter.MoveNext()) {
     const intptr_t pos = iter.TokenPos();
-    if ((pos < 0) ||
+    if ((!Token::IsReal(pos)) ||
         (pos < requested_token_pos) ||
         (pos > last_token_pos)) {
       // Token is not in the target range.
@@ -1786,7 +1788,7 @@
     PcDescriptors::Iterator iter(desc, kSafepointKind);
     while (iter.MoveNext()) {
       const intptr_t pos = iter.TokenPos();
-      if ((pos < 0) ||
+      if ((!Token::IsReal(pos)) ||
           (pos < begin_pos) ||
           (pos > end_of_line_pos)) {
         // Token is not on same line as best fit.
@@ -1821,13 +1823,13 @@
     return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(),
                                 -1 /* no column */);
   }
-  return -1;
+  return Token::kNoSourcePos;
 }
 
 
 void Debugger::MakeCodeBreakpointAt(const Function& func,
                                     BreakpointLocation* loc) {
-  ASSERT(loc->token_pos_ >= 0);
+  ASSERT(Token::IsReal(loc->token_pos_));
   ASSERT((loc != NULL) && loc->IsResolved());
   ASSERT(!func.HasOptimizedCode());
   Code& code = Code::Handle(func.unoptimized_code());
@@ -2144,7 +2146,7 @@
   if (!closure.IsClosure()) {
     return NULL;
   }
-  const Function& func = Function::Handle(Closure::function(closure));
+  const Function& func = Function::Handle(Closure::Cast(closure).function());
   const Script& script = Script::Handle(func.script());
   BreakpointLocation* bpt_location = SetBreakpoint(script,
                                                    func.token_pos(),
@@ -2242,14 +2244,14 @@
   script ^= scripts.At(0);
   intptr_t first_token_idx, last_token_idx;
   script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
-  if (first_token_idx < 0) {
+  if (!Token::IsReal(first_token_idx)) {
     // Script does not contain the given line number.
     if (FLAG_verbose_debug) {
       OS::Print("Script '%s' does not contain line number %" Pd "\n",
                 script_url.ToCString(), line_number);
     }
     return NULL;
-  } else if (last_token_idx < 0) {
+  } else if (!Token::IsReal(last_token_idx)) {
     // Line does not contain any tokens.
     if (FLAG_verbose_debug) {
       OS::Print("No executable code at line %" Pd " in '%s'\n",
@@ -2531,7 +2533,8 @@
 }
 
 
-void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) {
+void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace,
+                                     bool skip_next_step) {
   stepping_fp_ = 0;
   if (resume_action_ == kSingleStep) {
     // When single stepping, we need to deoptimize because we might be
@@ -2541,11 +2544,19 @@
     // to call an optimized function.
     DeoptimizeWorld();
     isolate_->set_single_step(true);
+    skip_next_step_ = skip_next_step;
+    if (FLAG_verbose_debug) {
+      OS::Print("HandleSteppingRequest- kSingleStep\n");
+    }
   } else if (resume_action_ == kStepOver) {
     DeoptimizeWorld();
     isolate_->set_single_step(true);
+    skip_next_step_ = skip_next_step;
     ASSERT(stack_trace->Length() > 0);
     stepping_fp_ = stack_trace->FrameAt(0)->fp();
+    if (FLAG_verbose_debug) {
+      OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
+    }
   } else if (resume_action_ == kStepOut) {
     DeoptimizeWorld();
     isolate_->set_single_step(true);
@@ -2557,6 +2568,9 @@
         break;
       }
     }
+    if (FLAG_verbose_debug) {
+      OS::Print("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
+    }
   }
 }
 
@@ -2614,6 +2628,10 @@
   if (IsPaused()) {
     return Error::null();
   }
+  if (skip_next_step_) {
+    skip_next_step_ = false;
+    return Error::null();
+  }
 
   // Check whether we are in a Dart function that the user is
   // interested in. If we saved the frame pointer of a stack frame
@@ -2627,7 +2645,7 @@
     // There is an "interesting frame" set. Only pause at appropriate
     // locations in this frame.
     if (stepping_fp_ > frame->fp()) {
-      // We are in a callee of the frame we're interested in.
+      // We are i n a callee of the frame we're interested in.
       // Ignore this stepping break.
       return Error::null();
     } else if (frame->fp() > stepping_fp_) {
@@ -2641,15 +2659,14 @@
   if (!frame->IsDebuggable()) {
     return Error::null();
   }
-  if (frame->TokenPos() < 0) {
+  if (!Token::IsDebugPause(frame->TokenPos())) {
     return Error::null();
   }
 
-  // Don't pause for a single step if there is a breakpoint set
-  // at this location.
-  if (HasActiveBreakpoint(frame->pc())) {
-    return Error::null();
-  }
+  // If there is an active breakpoint at this pc, then we should have
+  // already bailed out of this function in the skip_next_step_ test
+  // above.
+  ASSERT(!HasActiveBreakpoint(frame->pc()));
 
   if (FLAG_verbose_debug) {
     OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n",
@@ -2748,7 +2765,9 @@
   ASSERT(stack_trace_ == NULL);
   stack_trace_ = stack_trace;
   SignalPausedEvent(top_frame, bpt_hit);
-  HandleSteppingRequest(stack_trace_);
+  // When we single step from a user breakpoint, our next stepping
+  // point will be at the exact same pc.  Skip it.
+  HandleSteppingRequest(stack_trace_, true /* skip next step */);
   stack_trace_ = NULL;
   if (cbpt->IsInternal()) {
     RemoveInternalBreakpoints();
@@ -2886,7 +2905,7 @@
         intptr_t bp_pos =
             ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
                                  loc->requested_column_number());
-        if (bp_pos < 0) {
+        if (!Token::IsDebugPause(bp_pos)) {
           if (FLAG_verbose_debug) {
             OS::Print("Failed resolving breakpoint for function '%s'\n",
                       String::Handle(func.name()).ToCString());
@@ -2974,8 +2993,8 @@
         ASSERT(line_number >= 0);
         intptr_t first_token_pos, last_token_pos;
         script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
-        if ((first_token_pos < 0) ||
-            (last_token_pos < 0)) {
+        if (!Token::IsDebugPause(first_token_pos) ||
+            !Token::IsDebugPause(last_token_pos)) {
           // Script does not contain the given line number or there are no
           // tokens on the line. Drop the breakpoint silently.
           Breakpoint* bpt = matched_loc->breakpoints();
@@ -3111,7 +3130,7 @@
             pause_event_->breakpoint() == curr_bpt) {
           pause_event_->set_breakpoint(NULL);
         }
-        return;
+        break;
       }
 
       prev_bpt = curr_bpt;
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index acb69ec..5696e96 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -651,7 +651,8 @@
   // interrupts, etc.
   void Pause(DebuggerEvent* event);
 
-  void HandleSteppingRequest(DebuggerStackTrace* stack_trace);
+  void HandleSteppingRequest(DebuggerStackTrace* stack_trace,
+                             bool skip_next_step = false);
 
   Isolate* isolate_;
   Dart_Port isolate_id_;  // A unique ID for the isolate in the debugger.
@@ -690,6 +691,11 @@
   // lower on the stack.
   uword stepping_fp_;
 
+  // If we step while at a breakpoint, we would hit the same pc twice.
+  // We use this field to let us skip the next single-step after a
+  // breakpoint.
+  bool skip_next_step_;
+
   Dart_ExceptionPauseInfo exc_pause_info_;
 
   static EventHandler* event_handler_;
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 7e1ec45..5241d34 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -652,7 +652,7 @@
 
   // Construct the super type object, canonicalize it and return.
   Type& instantiated_type = Type::Handle(
-      Type::New(super_cls, super_type_args_array, Scanner::kNoSourcePos));
+      Type::New(super_cls, super_type_args_array, Token::kNoSourcePos));
   ASSERT(!instantiated_type.IsNull());
   instantiated_type.SetIsFinalized();
   return Api::NewHandle(T, instantiated_type.Canonicalize());
@@ -671,7 +671,7 @@
   if (!instance.IsClosure()) {
     return Api::NewError("%s: parameter 0 is not a closure", CURRENT_FUNC);
   }
-  const Function& func = Function::Handle(Closure::function(instance));
+  const Function& func = Function::Handle(Closure::Cast(instance).function());
   ASSERT(!func.IsNull());
   if (name != NULL) {
     *name = Api::NewHandle(T, func.QualifiedUserVisibleName());
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index 71a734a..d3f89c7 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -304,6 +304,48 @@
         }
       }
     }
+  } else if (cls.id() == kClosureCid) {
+    // TODO(regis): It would be better to programmatically add these fields to
+    // the VM Closure class. Declaring them in the Dart class _Closure does not
+    // work, because the class is prefinalized and CalculateFieldOffsets is
+    // therefore not called. Resetting the finalization state may be an option.
+    const Closure& closure = Closure::Cast(*object_);
+
+    Smi& offset = Smi::Handle();
+    Object& value = Object::Handle();
+
+    for (intptr_t i = 0; i < field_count_; i++) {
+      offset ^= GetFieldOffset(i);
+      if (offset.Value() == Closure::type_arguments_offset()) {
+        TypeArguments& arguments = TypeArguments::Handle();
+        arguments ^= GetValue(i);
+        closure.SetTypeArguments(arguments);
+        if (FLAG_trace_deoptimization_verbose) {
+          OS::PrintErr("    closure@type_arguments (offset %" Pd ") <- %s\n",
+                       offset.Value(),
+                       value.ToCString());
+        }
+      } else if (offset.Value() == Closure::function_offset()) {
+        Function& function = Function::Handle();
+        function ^= GetValue(i);
+        closure.set_function(function);
+        if (FLAG_trace_deoptimization_verbose) {
+          OS::PrintErr("    closure@function (offset %" Pd ") <- %s\n",
+                       offset.Value(),
+                       value.ToCString());
+        }
+      } else {
+        ASSERT(offset.Value() == Closure::context_offset());
+        Context& context = Context::Handle();
+        context ^= GetValue(i);
+        closure.set_context(context);
+        if (FLAG_trace_deoptimization_verbose) {
+          OS::PrintErr("    closure@context (offset %" Pd ") <- %s\n",
+                       offset.Value(),
+                       value.ToCString());
+        }
+      }
+    }
   } else {
     const Instance& obj = Instance::Cast(*object_);
 
@@ -324,8 +366,7 @@
                        value.ToCString());
         }
       } else {
-        ASSERT(cls.IsSignatureClass() ||
-               (offset.Value() == cls.type_arguments_field_offset()));
+        ASSERT(offset.Value() == cls.type_arguments_field_offset());
         obj.SetFieldAtOffset(offset.Value(), value);
         if (FLAG_trace_deoptimization_verbose) {
           OS::PrintErr("    null Field @ offset(%" Pd ") <- %s\n",
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index fed89bb..ee62949 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -48,6 +48,9 @@
 // Quick access to the locally defined zone() method.
 #define Z (zone())
 
+// Quick synthetic token position.
+#define ST(token_pos) Token::ToSynthetic(token_pos)
+
 // TODO(srdjan): Allow compiler to add constants as they are encountered in
 // the compilation.
 const double kCommonDoubleConstants[] =
@@ -829,20 +832,26 @@
 
 
 Definition* EffectGraphVisitor::BuildStoreTemp(const LocalVariable& local,
-                                               Value* value) {
+                                               Value* value,
+                                               intptr_t token_pos) {
   ASSERT(!local.is_captured());
-  return new(Z) StoreLocalInstr(local, value);
+  ASSERT(!Token::IsClassifying(token_pos));
+  return new(Z) StoreLocalInstr(local, value, ST(token_pos));
 }
 
 
-Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value) {
+Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value,
+                                                   intptr_t token_pos) {
   return BuildStoreTemp(*owner()->parsed_function().expression_temp_var(),
-                        value);
+                        value,
+                        token_pos);
 }
 
 
-Definition* EffectGraphVisitor::BuildLoadExprTemp() {
-  return BuildLoadLocal(*owner()->parsed_function().expression_temp_var());
+Definition* EffectGraphVisitor::BuildLoadExprTemp(intptr_t token_pos) {
+  ASSERT(!Token::IsClassifying(token_pos));
+  return BuildLoadLocal(*owner()->parsed_function().expression_temp_var(),
+                        token_pos);
 }
 
 
@@ -850,7 +859,7 @@
                                                 Value* value,
                                                 intptr_t token_pos) {
   if (local.is_captured()) {
-    LocalVariable* tmp_var = EnterTempLocalScope(value);
+    LocalVariable* tmp_var = EnterTempLocalScope(value, token_pos);
     intptr_t delta =
         owner()->context_level() - local.owner()->context_level();
     ASSERT(delta >= 0);
@@ -860,7 +869,7 @@
           context, Context::parent_offset(), Type::ZoneHandle(Z, Type::null()),
           token_pos));
     }
-    Value* tmp_val = Bind(new(Z) LoadLocalInstr(*tmp_var));
+    Value* tmp_val = Bind(new(Z) LoadLocalInstr(*tmp_var, token_pos));
     StoreInstanceFieldInstr* store =
         new(Z) StoreInstanceFieldInstr(Context::variable_offset(local.index()),
                                        context,
@@ -868,7 +877,7 @@
                                        kEmitStoreBarrier,
                                        token_pos);
     Do(store);
-    return ExitTempLocalScope(tmp_var);
+    return ExitTempLocalScope(tmp_var, token_pos);
   } else {
     return new(Z) StoreLocalInstr(local, value, token_pos);
   }
@@ -903,6 +912,7 @@
 void EffectGraphVisitor::BuildSaveContext(
     const LocalVariable& variable,
     intptr_t token_pos) {
+  ASSERT(Token::IsSynthetic(token_pos) || Token::IsNoSource(token_pos));
   Value* context = Bind(BuildCurrentContext(token_pos));
   Do(BuildStoreLocal(variable, context, token_pos));
 }
@@ -1122,7 +1132,7 @@
   // statements for which there is no associated source position.
   const Function& function = owner()->function();
   if (FLAG_support_debugger &&
-      (node->token_pos() >= 0) && !function.is_native()) {
+      Token::IsDebugPause(node->token_pos()) && !function.is_native()) {
     AddInstruction(new(Z) DebugStepCheckInstr(node->token_pos(),
                                               RawPcDescriptors::kRuntimeCall));
   }
@@ -1177,7 +1187,7 @@
   if (function.IsAsyncClosure() &&
       (node->return_type() == ReturnNode::kRegular)) {
     // Temporary store the computed return value.
-    Do(BuildStoreExprTemp(return_value));
+    Do(BuildStoreExprTemp(return_value, node->token_pos()));
 
     LocalVariable* rcv_var =
         node->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
@@ -1186,7 +1196,7 @@
         new(Z) ZoneGrowableArray<PushArgumentInstr*>(2);
     Value* rcv_value = Bind(BuildLoadLocal(*rcv_var, node->token_pos()));
     arguments->Add(PushArgument(rcv_value));
-    Value* returned_value = Bind(BuildLoadExprTemp());
+    Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos()));
     arguments->Add(PushArgument(returned_value));
     InstanceCallInstr* call = new(Z) InstanceCallInstr(
         node->token_pos(),
@@ -1199,7 +1209,7 @@
     Do(call);
 
     // Rebind the return value for the actual return call to be null.
-    return_value = BuildNullValue();
+    return_value = BuildNullValue(node->token_pos());
   }
 
   intptr_t current_context_level = owner()->context_level();
@@ -1425,22 +1435,22 @@
                                                  right_value,
                                                  constant_true,
                                                  false));  // No number check.
-    for_right.Do(BuildStoreExprTemp(compare));
+    for_right.Do(BuildStoreExprTemp(compare, node->token_pos()));
 
     if (node->kind() == Token::kAND) {
       ValueGraphVisitor for_false(owner());
       Value* constant_false =
           for_false.Bind(new(Z) ConstantInstr(Bool::False()));
-      for_false.Do(BuildStoreExprTemp(constant_false));
+      for_false.Do(BuildStoreExprTemp(constant_false, node->token_pos()));
       Join(for_test, for_right, for_false);
     } else {
       ASSERT(node->kind() == Token::kOR);
       ValueGraphVisitor for_true(owner());
       Value* constant_true = for_true.Bind(new(Z) ConstantInstr(Bool::True()));
-      for_true.Do(BuildStoreExprTemp(constant_true));
+      for_true.Do(BuildStoreExprTemp(constant_true, node->token_pos()));
       Join(for_test, for_true, for_right);
     }
-    ReturnDefinition(BuildLoadExprTemp());
+    ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
     return;
   }
 
@@ -1502,9 +1512,9 @@
   const Class& instantiator_class = Class::Handle(
       Z, owner()->function().Owner());
   // Since called only when type tested against is not instantiated.
-  ASSERT(instantiator_class.NumTypeParameters() > 0);
+  ASSERT(instantiator_class.IsGeneric());
   Value* instantiator_type_arguments = NULL;
-  Value* instantiator = BuildInstantiator(instantiator_class);
+  Value* instantiator = BuildInstantiator(token_pos);
   if (instantiator == NULL) {
     // No instantiator when inside factory.
     instantiator_type_arguments =
@@ -1527,8 +1537,8 @@
   const Class& instantiator_class = Class::Handle(
       Z, owner()->function().Owner());
   // Since called only when type tested against is not instantiated.
-  ASSERT(instantiator_class.NumTypeParameters() > 0);
-  instantiator = BuildInstantiator(instantiator_class);
+  ASSERT(instantiator_class.IsGeneric());
+  instantiator = BuildInstantiator(token_pos);
   if (instantiator == NULL) {
     // No instantiator when inside factory.
     instantiator_type_arguments =
@@ -1541,8 +1551,9 @@
 }
 
 
-Value* EffectGraphVisitor::BuildNullValue() {
-  return Bind(new(Z) ConstantInstr(Object::ZoneHandle(Z, Object::null())));
+Value* EffectGraphVisitor::BuildNullValue(intptr_t token_pos) {
+  return Bind(new(Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()),
+                                   token_pos));
 }
 
 
@@ -1555,7 +1566,7 @@
   // Build the type check computation.
   Value* instantiator_type_arguments = NULL;
   if (dst_type.IsInstantiated()) {
-    instantiator_type_arguments = BuildNullValue();
+    instantiator_type_arguments = BuildNullValue(token_pos);
   } else {
     BuildTypecheckArguments(token_pos, &instantiator_type_arguments);
   }
@@ -1666,7 +1677,7 @@
   PushArgumentInstr* push_left = PushArgument(for_left_value.value());
   PushArgumentInstr* push_type_args = NULL;
   if (type.IsInstantiated()) {
-    push_type_args = PushArgument(BuildNullValue());
+    push_type_args = PushArgument(BuildNullValue(node->token_pos()));
   } else {
     BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
   }
@@ -1718,7 +1729,7 @@
   PushArgumentInstr* push_left = PushArgument(for_value.value());
   PushArgumentInstr* push_type_args = NULL;
   if (type.IsInstantiated()) {
-    push_type_args = PushArgument(BuildNullValue());
+    push_type_args = PushArgument(BuildNullValue(node->token_pos()));
   } else {
     BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
   }
@@ -1917,15 +1928,17 @@
   ValueGraphVisitor for_true(owner());
   node->true_expr()->Visit(&for_true);
   ASSERT(for_true.is_open());
-  for_true.Do(BuildStoreExprTemp(for_true.value()));
+  for_true.Do(BuildStoreExprTemp(for_true.value(),
+                                 node->true_expr()->token_pos()));
 
   ValueGraphVisitor for_false(owner());
   node->false_expr()->Visit(&for_false);
   ASSERT(for_false.is_open());
-  for_false.Do(BuildStoreExprTemp(for_false.value()));
+  for_false.Do(BuildStoreExprTemp(for_false.value(),
+                                  node->false_expr()->token_pos()));
 
   Join(for_test, for_true, for_false);
-  ReturnDefinition(BuildLoadExprTemp());
+  ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
 }
 
 
@@ -2273,6 +2286,8 @@
   // We need to create a new await state which involves:
   // * Increase the jump counter. Sanity check against the list of targets.
   // * Save the current context for resuming.
+  ASSERT(Token::IsSynthetic(node->token_pos()) ||
+         Token::IsNoSource(node->token_pos()));
   ASSERT(node->async_scope() != NULL);
   ASSERT(node->await_scope() != NULL);
   LocalVariable* jump_var = node->async_scope()->LookupVariable(
@@ -2288,8 +2303,8 @@
   ASSERT(jump_count == owner()->await_joins()->length());
   // Store the counter in :await_jump_var.
   Value* jump_val = Bind(new(Z) ConstantInstr(
-      Smi::ZoneHandle(Z, Smi::New(jump_count))));
-  Do(BuildStoreLocal(*jump_var, jump_val));
+      Smi::ZoneHandle(Z, Smi::New(jump_count)), node->token_pos()));
+  Do(BuildStoreLocal(*jump_var, jump_val, node->token_pos()));
   // Save the current context for resuming.
   BuildSaveContext(*ctx_var, node->token_pos());
 }
@@ -2304,7 +2319,8 @@
 }
 
 
-LocalVariable* EffectGraphVisitor::EnterTempLocalScope(Value* value) {
+LocalVariable* EffectGraphVisitor::EnterTempLocalScope(
+    Value* value, intptr_t token_pos) {
   Do(new(Z) PushTempInstr(value));
   owner()->AllocateTemp();
 
@@ -2313,7 +2329,7 @@
   char name[64];
   OS::SNPrint(name, 64, ":tmp_local%" Pd, index);
   LocalVariable*  var =
-      new(Z) LocalVariable(Scanner::kNoSourcePos,
+      new(Z) LocalVariable(Token::kNoSourcePos,
                            String::ZoneHandle(Z, Symbols::New(name)),
                            *value->Type()->ToAbstractType());
   var->set_index(index);
@@ -2321,8 +2337,9 @@
 }
 
 
-Definition* EffectGraphVisitor::ExitTempLocalScope(LocalVariable* var) {
-  Value* tmp = Bind(new(Z) LoadLocalInstr(*var));
+Definition* EffectGraphVisitor::ExitTempLocalScope(
+    LocalVariable* var, intptr_t token_pos) {
+  Value* tmp = Bind(new(Z) LoadLocalInstr(*var, token_pos));
   owner()->DeallocateTemps(1);
   ASSERT(GetCurrentTempLocalIndex() == var->index());
   return new(Z) DropTempsInstr(1, tmp);
@@ -2400,13 +2417,14 @@
                                                      num_elements);
   Value* array_val = Bind(create);
 
-  { LocalVariable* tmp_var = EnterTempLocalScope(array_val);
+  { LocalVariable* tmp_var = EnterTempLocalScope(array_val, node->token_pos());
     const intptr_t class_id = kArrayCid;
     const intptr_t deopt_id = Thread::kNoDeoptId;
     for (int i = 0; i < node->length(); ++i) {
-      Value* array = Bind(new(Z) LoadLocalInstr(*tmp_var));
+      Value* array = Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos()));
       Value* index =
-          Bind(new(Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i))));
+          Bind(new(Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i)),
+                                    node->token_pos()));
       ValueGraphVisitor for_value(owner());
       node->ElementAt(i)->Visit(&for_value);
       Append(for_value);
@@ -2421,7 +2439,7 @@
           index_scale, class_id, deopt_id, node->token_pos());
       Do(store);
     }
-    ReturnDefinition(ExitTempLocalScope(tmp_var));
+    ReturnDefinition(ExitTempLocalScope(tmp_var, node->token_pos()));
   }
 }
 
@@ -2500,36 +2518,45 @@
       isolate()->AddClosureFunction(function);
     }
   }
-  ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new(Z) ZoneGrowableArray<PushArgumentInstr*>(1);
   ASSERT(function.context_scope() != ContextScope::null());
 
   // The function type of a closure may have type arguments. In that case,
   // pass the type arguments of the instantiator.
-  const Class& cls = Class::ZoneHandle(Z, function.signature_class());
-  ASSERT(!cls.IsNull());
-  const bool requires_type_arguments = cls.NumTypeArguments() > 0;
-  Value* type_arguments = NULL;
-  if (requires_type_arguments) {
-    ASSERT(cls.type_arguments_field_offset() ==
-           Closure::type_arguments_offset());
-    ASSERT(cls.instance_size() == Closure::InstanceSize());
-    const Class& instantiator_class = Class::Handle(
-        Z, owner()->function().Owner());
-    type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
-                                                    instantiator_class,
-                                                    NULL);
-    arguments->Add(PushArgument(type_arguments));
-  }
+  const Class& closure_class =
+      Class::ZoneHandle(Z, isolate()->object_store()->closure_class());
+  ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
+      new(Z) ZoneGrowableArray<PushArgumentInstr*>(0);
   AllocateObjectInstr* alloc = new(Z) AllocateObjectInstr(node->token_pos(),
-                                                          cls,
-                                                          arguments);
+                                                          closure_class,
+                                                          no_arguments);
   alloc->set_closure_function(function);
 
   Value* closure_val = Bind(alloc);
-  { LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val);
+  { LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val,
+                                                         node->token_pos());
+    // Store type arguments if scope class is generic.
+    const FunctionType& function_type =
+        FunctionType::ZoneHandle(Z, function.SignatureType());
+    const Class& scope_cls = Class::ZoneHandle(Z, function_type.scope_class());
+    if (scope_cls.IsGeneric()) {
+      ASSERT(function.Owner() == scope_cls.raw());
+      Value* closure_tmp_val = Bind(new(Z) LoadLocalInstr(*closure_tmp_var,
+                                                          node->token_pos()));
+      const Class& instantiator_class = Class::Handle(
+          Z, owner()->function().Owner());
+      Value* type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
+                                                             instantiator_class,
+                                                             NULL);
+      Do(new(Z) StoreInstanceFieldInstr(Closure::type_arguments_offset(),
+                                        closure_tmp_val,
+                                        type_arguments,
+                                        kEmitStoreBarrier,
+                                        node->token_pos()));
+    }
+
     // Store function.
-    Value* closure_tmp_val = Bind(new(Z) LoadLocalInstr(*closure_tmp_var));
+    Value* closure_tmp_val =
+        Bind(new(Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
     Value* func_val =
         Bind(new(Z) ConstantInstr(Function::ZoneHandle(Z, function.raw())));
     Do(new(Z) StoreInstanceFieldInstr(Closure::function_offset(),
@@ -2543,9 +2570,11 @@
       Value* allocated_context =
           Bind(new(Z) AllocateContextInstr(node->token_pos(),
                                            kNumContextVariables));
-      { LocalVariable* context_tmp_var = EnterTempLocalScope(allocated_context);
+      { LocalVariable* context_tmp_var =
+            EnterTempLocalScope(allocated_context, node->token_pos());
         // Store receiver in context.
-        Value* context_tmp_val = Bind(new(Z) LoadLocalInstr(*context_tmp_var));
+        Value* context_tmp_val =
+            Bind(new(Z) LoadLocalInstr(*context_tmp_var, node->token_pos()));
         ValueGraphVisitor for_receiver(owner());
         node->receiver()->Visit(&for_receiver);
         Append(for_receiver);
@@ -2556,14 +2585,16 @@
                                           kEmitStoreBarrier,
                                           node->token_pos()));
         // Store new context in closure.
-        closure_tmp_val = Bind(new(Z) LoadLocalInstr(*closure_tmp_var));
-        context_tmp_val = Bind(new(Z) LoadLocalInstr(*context_tmp_var));
+        closure_tmp_val =
+            Bind(new(Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
+        context_tmp_val =
+            Bind(new(Z) LoadLocalInstr(*context_tmp_var, node->token_pos()));
         Do(new(Z) StoreInstanceFieldInstr(Closure::context_offset(),
                                           closure_tmp_val,
                                           context_tmp_val,
                                           kEmitStoreBarrier,
                                           node->token_pos()));
-        Do(ExitTempLocalScope(context_tmp_var));
+        Do(ExitTempLocalScope(context_tmp_var, node->token_pos()));
       }
     } else {
       // Store current context in closure.
@@ -2576,7 +2607,7 @@
                                         kEmitStoreBarrier,
                                         node->token_pos()));
     }
-    ReturnDefinition(ExitTempLocalScope(closure_tmp_var));
+    ReturnDefinition(ExitTempLocalScope(closure_tmp_var, node->token_pos()));
   }
 }
 
@@ -2595,34 +2626,34 @@
 
 
 void EffectGraphVisitor::BuildInstanceCallConditional(InstanceCallNode* node) {
+  const intptr_t token_pos = node->token_pos();
   LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
-  LoadLocalNode* load_temp =
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+  LoadLocalNode* load_temp = new(Z) LoadLocalNode(token_pos, temp_var);
 
   LiteralNode* null_constant =
-      new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+      new(Z) LiteralNode(ST(token_pos), Object::null_instance());
   ComparisonNode* check_is_null =
-      new(Z) ComparisonNode(Scanner::kNoSourcePos,
+      new(Z) ComparisonNode(ST(token_pos),
                             Token::kEQ,
                             load_temp,
                             null_constant);
-  TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+  TestGraphVisitor for_test(owner(), ST(token_pos));
   check_is_null->Visit(&for_test);
 
   EffectGraphVisitor for_true(owner());
   EffectGraphVisitor for_false(owner());
 
   StoreLocalNode* store_null =
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, null_constant);
+      new(Z) StoreLocalNode(ST(token_pos), temp_var, null_constant);
   store_null->Visit(&for_true);
 
   InstanceCallNode* call =
-      new(Z) InstanceCallNode(node->token_pos(),
+      new(Z) InstanceCallNode(token_pos,
                               load_temp,
                               node->function_name(),
                               node->arguments());
   StoreLocalNode* store_result =
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, call);
+      new(Z) StoreLocalNode(ST(token_pos), temp_var, call);
   store_result->Visit(&for_false);
 
   Join(for_test, for_true, for_false);
@@ -2634,9 +2665,9 @@
     ValueGraphVisitor for_receiver(owner());
     node->receiver()->Visit(&for_receiver);
     Append(for_receiver);
-    Do(BuildStoreExprTemp(for_receiver.value()));
+    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
     BuildInstanceCallConditional(node);
-    ReturnDefinition(BuildLoadExprTemp());
+    ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
   } else {
     EffectGraphVisitor::VisitInstanceCallNode(node);
   }
@@ -2648,7 +2679,7 @@
   node->receiver()->Visit(&for_receiver);
   Append(for_receiver);
   if (node->is_conditional()) {
-    Do(BuildStoreExprTemp(for_receiver.value()));
+    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
     BuildInstanceCallConditional(node);
   } else {
     PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
@@ -2730,16 +2761,17 @@
   node->closure()->Visit(&for_closure);
   Append(for_closure);
 
-  LocalVariable* tmp_var = EnterTempLocalScope(for_closure.value());
+  LocalVariable* tmp_var =
+      EnterTempLocalScope(for_closure.value(), node->token_pos());
 
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
       new(Z) ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length());
-  Value* closure_val = Bind(new(Z) LoadLocalInstr(*tmp_var));
+  Value* closure_val = Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos()));
   PushArgumentInstr* push_closure = PushArgument(closure_val);
   arguments->Add(push_closure);
   BuildPushArguments(*node->arguments(), arguments);
 
-  closure_val = Bind(new(Z) LoadLocalInstr(*tmp_var));
+  closure_val = Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos()));
   LoadFieldInstr* function_load = new(Z) LoadFieldInstr(
       closure_val,
       Closure::function_offset(),
@@ -2752,11 +2784,11 @@
       new(Z) ClosureCallInstr(function_val, node, arguments);
   if (result_needed) {
     Value* result = Bind(closure_call);
-    Do(new(Z) StoreLocalInstr(*tmp_var, result));
+    Do(new(Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos())));
   } else {
     Do(closure_call);
   }
-  ReturnDefinition(ExitTempLocalScope(tmp_var));
+  ReturnDefinition(ExitTempLocalScope(tmp_var, node->token_pos()));
 }
 
 
@@ -2886,8 +2918,7 @@
 }
 
 
-Value* EffectGraphVisitor::BuildInstantiator(const Class& instantiator_class) {
-  ASSERT(instantiator_class.NumTypeParameters() > 0);
+Value* EffectGraphVisitor::BuildInstantiator(intptr_t token_pos) {
   Function& outer_function = Function::Handle(Z, owner()->function().raw());
   while (outer_function.IsLocalFunction()) {
     outer_function = outer_function.parent_function();
@@ -2898,7 +2929,7 @@
 
   LocalVariable* instantiator = owner()->parsed_function().instantiator();
   ASSERT(instantiator != NULL);
-  Value* result = Bind(BuildLoadLocal(*instantiator));
+  Value* result = Bind(BuildLoadLocal(*instantiator, token_pos));
   return result;
 }
 
@@ -2909,7 +2940,7 @@
     intptr_t token_pos,
     const Class& instantiator_class,
     Value* instantiator) {
-  if (instantiator_class.NumTypeParameters() == 0) {
+  if (!instantiator_class.IsGeneric()) {
     // The type arguments are compile time constants.
     TypeArguments& type_arguments =
         TypeArguments::ZoneHandle(Z, TypeArguments::null());
@@ -2934,10 +2965,10 @@
     LocalVariable* instantiator_var =
         owner()->parsed_function().instantiator();
     ASSERT(instantiator_var != NULL);
-    return Bind(BuildLoadLocal(*instantiator_var));
+    return Bind(BuildLoadLocal(*instantiator_var, token_pos));
   }
   if (instantiator == NULL) {
-    instantiator = BuildInstantiator(instantiator_class);
+    instantiator = BuildInstantiator(token_pos);
   }
   // The instantiator is the receiver of the caller, which is not a factory.
   // The receiver cannot be null; extract its TypeArguments object.
@@ -2951,7 +2982,7 @@
       instantiator,
       type_arguments_field_offset,
       Type::ZoneHandle(Z, Type::null()),  // Not an instance, no type.
-      Scanner::kNoSourcePos));
+      token_pos));
 }
 
 
@@ -2995,11 +3026,12 @@
   //   tn       <- LoadLocal(temp)
 
   Value* allocate = BuildObjectAllocation(node);
-  { LocalVariable* tmp_var = EnterTempLocalScope(allocate);
-    Value* allocated_tmp = Bind(new(Z) LoadLocalInstr(*tmp_var));
+  { LocalVariable* tmp_var = EnterTempLocalScope(allocate, node->token_pos());
+    Value* allocated_tmp =
+        Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos()));
     PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp);
     BuildConstructorCall(node, push_allocated_value);
-    ReturnDefinition(ExitTempLocalScope(tmp_var));
+    ReturnDefinition(ExitTempLocalScope(tmp_var, node->token_pos()));
   }
 }
 
@@ -3007,33 +3039,32 @@
 
 void EffectGraphVisitor::BuildInstanceGetterConditional(
     InstanceGetterNode* node) {
+  const intptr_t token_pos = node->token_pos();
   LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
-  LoadLocalNode* load_temp =
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+  LoadLocalNode* load_temp = new(Z) LoadLocalNode(token_pos, temp_var);
 
   LiteralNode* null_constant =
-      new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+      new(Z) LiteralNode(ST(token_pos), Object::null_instance());
   ComparisonNode* check_is_null =
-      new(Z) ComparisonNode(Scanner::kNoSourcePos,
+      new(Z) ComparisonNode(ST(token_pos),
                             Token::kEQ,
                             load_temp,
                             null_constant);
-  TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+  TestGraphVisitor for_test(owner(), ST(token_pos));
   check_is_null->Visit(&for_test);
 
   EffectGraphVisitor for_true(owner());
   EffectGraphVisitor for_false(owner());
 
   StoreLocalNode* store_null =
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, null_constant);
+      new(Z) StoreLocalNode(ST(token_pos), temp_var, null_constant);
   store_null->Visit(&for_true);
 
-  InstanceGetterNode* getter =
-      new(Z) InstanceGetterNode(node->token_pos(),
-                                load_temp,
-                                node->field_name());
+  InstanceGetterNode* getter = new(Z) InstanceGetterNode(token_pos,
+                                                         load_temp,
+                                                         node->field_name());
   StoreLocalNode* store_getter =
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, temp_var, getter);
+      new(Z) StoreLocalNode(ST(token_pos), temp_var, getter);
   store_getter->Visit(&for_false);
 
   Join(for_test, for_true, for_false);
@@ -3045,9 +3076,9 @@
     ValueGraphVisitor for_receiver(owner());
     node->receiver()->Visit(&for_receiver);
     Append(for_receiver);
-    Do(BuildStoreExprTemp(for_receiver.value()));
+    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
     BuildInstanceGetterConditional(node);
-    ReturnDefinition(BuildLoadExprTemp());
+    ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
   } else {
     EffectGraphVisitor::VisitInstanceGetterNode(node);
   }
@@ -3059,7 +3090,7 @@
   node->receiver()->Visit(&for_receiver);
   Append(for_receiver);
   if (node->is_conditional()) {
-    Do(BuildStoreExprTemp(for_receiver.value()));
+    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
     BuildInstanceGetterConditional(node);
   } else {
     PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
@@ -3095,7 +3126,7 @@
 
   Value* value = NULL;
   if (result_is_needed) {
-    value = Bind(BuildStoreExprTemp(for_value.value()));
+    value = Bind(BuildStoreExprTemp(for_value.value(), node->token_pos()));
   } else {
     value = for_value.value();
   }
@@ -3104,30 +3135,31 @@
 
 
 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
+  const intptr_t token_pos = node->token_pos();
   if (node->is_conditional()) {
     ValueGraphVisitor for_receiver(owner());
     node->receiver()->Visit(&for_receiver);
     Append(for_receiver);
-    Do(BuildStoreExprTemp(for_receiver.value()));
+    Do(BuildStoreExprTemp(for_receiver.value(), token_pos));
 
     LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
     LoadLocalNode* load_temp =
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+        new(Z) LoadLocalNode(ST(token_pos), temp_var);
     LiteralNode* null_constant =
-        new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+        new(Z) LiteralNode(ST(token_pos), Object::null_instance());
     ComparisonNode* check_is_null =
-        new(Z) ComparisonNode(Scanner::kNoSourcePos,
+        new(Z) ComparisonNode(ST(token_pos),
                               Token::kEQ,
                               load_temp,
                               null_constant);
-    TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+    TestGraphVisitor for_test(owner(), ST(token_pos));
     check_is_null->Visit(&for_test);
 
     EffectGraphVisitor for_true(owner());
     EffectGraphVisitor for_false(owner());
 
     InstanceSetterNode* setter =
-        new(Z) InstanceSetterNode(node->token_pos(),
+        new(Z) InstanceSetterNode(token_pos,
                                   load_temp,
                                   node->field_name(),
                                   node->value());
@@ -3141,7 +3173,7 @@
   const String& name =
       String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
   const intptr_t kNumArgsChecked = 1;  // Do not check value type.
-  InstanceCallInstr* call = new(Z) InstanceCallInstr(node->token_pos(),
+  InstanceCallInstr* call = new(Z) InstanceCallInstr(token_pos,
                                                      name,
                                                      Token::kSET,
                                                      arguments,
@@ -3153,40 +3185,41 @@
 
 
 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
+  const intptr_t token_pos = node->token_pos();
   if (node->is_conditional()) {
     ValueGraphVisitor for_receiver(owner());
     node->receiver()->Visit(&for_receiver);
     Append(for_receiver);
-    Do(BuildStoreExprTemp(for_receiver.value()));
+    Do(BuildStoreExprTemp(for_receiver.value(), token_pos));
 
     LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
     LoadLocalNode* load_temp =
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, temp_var);
+        new(Z) LoadLocalNode(ST(token_pos), temp_var);
     LiteralNode* null_constant =
-        new(Z) LiteralNode(Scanner::kNoSourcePos, Object::null_instance());
+        new(Z) LiteralNode(ST(token_pos), Object::null_instance());
     ComparisonNode* check_is_null =
-        new(Z) ComparisonNode(Scanner::kNoSourcePos,
+        new(Z) ComparisonNode(ST(token_pos),
                               Token::kEQ,
                               load_temp,
                               null_constant);
-    TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+    TestGraphVisitor for_test(owner(), ST(token_pos));
     check_is_null->Visit(&for_test);
 
     ValueGraphVisitor for_true(owner());
     null_constant->Visit(&for_true);
-    for_true.Do(BuildStoreExprTemp(for_true.value()));
+    for_true.Do(BuildStoreExprTemp(for_true.value(), token_pos));
 
     ValueGraphVisitor for_false(owner());
     InstanceSetterNode* setter =
-        new(Z) InstanceSetterNode(node->token_pos(),
+        new(Z) InstanceSetterNode(token_pos,
                                   load_temp,
                                   node->field_name(),
                                   node->value());
     setter->Visit(&for_false);
-    for_false.Do(BuildStoreExprTemp(for_false.value()));
+    for_false.Do(BuildStoreExprTemp(for_false.value(), token_pos));
 
     Join(for_test, for_true, for_false);
-    ReturnDefinition(BuildLoadExprTemp());
+    ReturnDefinition(BuildLoadExprTemp(token_pos));
     return;
   }
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
@@ -3195,14 +3228,14 @@
   const String& name =
       String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
   const intptr_t kNumArgsChecked = 1;  // Do not check value type.
-  Do(new(Z) InstanceCallInstr(node->token_pos(),
+  Do(new(Z) InstanceCallInstr(token_pos,
                               name,
                               Token::kSET,
                               arguments,
                               Object::null_array(),
                               kNumArgsChecked,
                               owner()->ic_data_array()));
-  ReturnDefinition(BuildLoadExprTemp());
+  ReturnDefinition(BuildLoadExprTemp(token_pos));
 }
 
 
@@ -3284,6 +3317,7 @@
       String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
       new(Z) ZoneGrowableArray<PushArgumentInstr*>(1);
+  const intptr_t token_pos = node->token_pos();
   // A super setter is an instance setter whose setter function is
   // resolved at compile time (in the caller instance getter's super class).
   // Unlike a static getter, a super getter has a receiver parameter.
@@ -3294,7 +3328,7 @@
     if (is_super_setter) {
       ASSERT(node->receiver() != NULL);
       // Resolve and call noSuchMethod.
-      ArgumentListNode* arguments = new(Z) ArgumentListNode(node->token_pos());
+      ArgumentListNode* arguments = new(Z) ArgumentListNode(token_pos);
       arguments->Add(node->receiver());
       arguments->Add(node->value());
       call = BuildStaticNoSuchMethodCall(
@@ -3306,10 +3340,10 @@
           true);  // Super invocation.
     } else {
       // Throw a NoSuchMethodError.
-      ArgumentListNode* arguments = new(Z) ArgumentListNode(node->token_pos());
+      ArgumentListNode* arguments = new(Z) ArgumentListNode(token_pos);
       arguments->Add(node->value());
       call = BuildThrowNoSuchMethodError(
-          node->token_pos(),
+          token_pos,
           node->cls(),
           setter_name,
           arguments,  // Argument is the value passed to the setter.
@@ -3332,13 +3366,13 @@
     Append(for_value);
     Value* value = NULL;
     if (result_is_needed) {
-      value = Bind(BuildStoreExprTemp(for_value.value()));
+      value = Bind(BuildStoreExprTemp(for_value.value(), token_pos));
     } else {
       value = for_value.value();
     }
     arguments->Add(PushArgument(value));
 
-    call = new(Z) StaticCallInstr(node->token_pos(),
+    call = new(Z) StaticCallInstr(token_pos,
                                   setter_function,
                                   Object::null_array(),  // No names.
                                   arguments,
@@ -3346,7 +3380,7 @@
   }
   if (result_is_needed) {
     Do(call);
-    ReturnDefinition(BuildLoadExprTemp());
+    ReturnDefinition(BuildLoadExprTemp(token_pos));
   } else {
     ReturnDefinition(call);
   }
@@ -3382,10 +3416,11 @@
 }
 
 
-LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar(LocalScope* scope) {
+LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar(
+    LocalScope* scope, intptr_t token_pos) {
   LocalVariable* receiver_var = scope->LookupVariable(Symbols::This(),
                                                       true);  // Test only.
-  return new(Z) LoadLocalInstr(*receiver_var);
+  return new(Z) LoadLocalInstr(*receiver_var, token_pos);
 }
 
 
@@ -3395,7 +3430,7 @@
     intptr_t offset,
     const Type& type,
     intptr_t class_id) {
-  Value* receiver = Bind(BuildLoadThisVar(node->scope()));
+  Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos()));
   LoadFieldInstr* load = new(Z) LoadFieldInstr(receiver,
                                                offset,
                                                type,
@@ -3410,10 +3445,10 @@
     NativeBodyNode* node,
     intptr_t offset,
     StoreBarrierType emit_store_barrier) {
-  Value* receiver = Bind(BuildLoadThisVar(node->scope()));
+  Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos()));
   LocalVariable* value_var =
       node->scope()->LookupVariable(Symbols::Value(), true);
-  Value* value = Bind(new(Z) LoadLocalInstr(*value_var));
+  Value* value = Bind(new(Z) LoadLocalInstr(*value_var, node->token_pos()));
   StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
       offset,
       receiver,
@@ -3427,19 +3462,20 @@
 
 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
   const Function& function = owner()->function();
+  const intptr_t token_pos = node->token_pos();
   if (!function.IsClosureFunction()) {
     MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
     switch (kind) {
       case MethodRecognizer::kObjectEquals: {
-        Value* receiver = Bind(BuildLoadThisVar(node->scope()));
+        Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos));
         LocalVariable* other_var =
             node->scope()->LookupVariable(Symbols::Other(),
                                           true);  // Test only.
-        Value* other = Bind(new(Z) LoadLocalInstr(*other_var));
+        Value* other = Bind(new(Z) LoadLocalInstr(*other_var, token_pos));
         // Receiver is not a number because numbers override equality.
         const bool kNoNumberCheck = false;
         StrictCompareInstr* compare =
-            new(Z) StrictCompareInstr(node->token_pos(),
+            new(Z) StrictCompareInstr(token_pos,
                                       Token::kEQ_STRICT,
                                       receiver,
                                       other,
@@ -3463,11 +3499,11 @@
             Smi::ZoneHandle(Z, Smi::New(0))));
         Value* load_val = Bind(load);
         StrictCompareInstr* compare =
-            new(Z) StrictCompareInstr(node->token_pos(),
-                                   Token::kEQ_STRICT,
-                                   load_val,
-                                   zero_val,
-                                   false);  // No number check.
+            new(Z) StrictCompareInstr(token_pos,
+                                      Token::kEQ_STRICT,
+                                      load_val,
+                                      zero_val,
+                                      false);  // No number check.
         return ReturnDefinition(compare);
       }
       case MethodRecognizer::kGrowableArrayLength:
@@ -3483,12 +3519,12 @@
       case MethodRecognizer::kClassIDgetID: {
         LocalVariable* value_var =
             node->scope()->LookupVariable(Symbols::Value(), true);
-        Value* value = Bind(new(Z) LoadLocalInstr(*value_var));
+        Value* value = Bind(new(Z) LoadLocalInstr(*value_var, token_pos));
         LoadClassIdInstr* load = new(Z) LoadClassIdInstr(value);
         return ReturnDefinition(load);
       }
       case MethodRecognizer::kGrowableArrayCapacity: {
-        Value* receiver = Bind(BuildLoadThisVar(node->scope()));
+        Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos));
         LoadFieldInstr* data_load = new(Z) LoadFieldInstr(
             receiver,
             Array::data_offset(),
@@ -3509,12 +3545,14 @@
         LocalVariable* type_args_parameter =
             node->scope()->LookupVariable(Symbols::TypeArgumentsParameter(),
                                           true);
-        Value* element_type = Bind(new(Z) LoadLocalInstr(*type_args_parameter));
+        Value* element_type =
+            Bind(new(Z) LoadLocalInstr(*type_args_parameter, token_pos));
         LocalVariable* length_parameter =
             node->scope()->LookupVariable(Symbols::Length(), true);
-        Value* length = Bind(new(Z) LoadLocalInstr(*length_parameter));
+        Value* length =
+            Bind(new(Z) LoadLocalInstr(*length_parameter, token_pos));
         CreateArrayInstr* create_array =
-            new CreateArrayInstr(node->token_pos(), element_type, length);
+            new CreateArrayInstr(token_pos, element_type, length);
         return ReturnDefinition(create_array);
       }
       case MethodRecognizer::kBigint_getDigits: {
@@ -3627,7 +3665,7 @@
             !node->value()->AsLoadLocalNode()->local().IsInternal()) ||
         node->value()->IsClosureNode()) &&
         !node->local().IsInternal() &&
-        (node->token_pos() >= 0)) {
+        Token::IsDebugPause(node->token_pos())) {
       AddInstruction(new(Z) DebugStepCheckInstr(
           node->token_pos(), RawPcDescriptors::kRuntimeCall));
     }
@@ -3673,6 +3711,7 @@
 
 void EffectGraphVisitor::VisitStoreInstanceFieldNode(
     StoreInstanceFieldNode* node) {
+  const intptr_t token_pos = node->token_pos();
   ValueGraphVisitor for_instance(owner());
   node->instance()->Visit(&for_instance);
   Append(for_instance);
@@ -3691,26 +3730,26 @@
   }
 
   if (FLAG_use_field_guards) {
-    store_value = Bind(BuildStoreExprTemp(store_value));
+    store_value = Bind(BuildStoreExprTemp(store_value, token_pos));
     GuardFieldClassInstr* guard_field_class =
         new(Z) GuardFieldClassInstr(store_value,
-                                 node->field(),
-                                 thread()->GetNextDeoptId());
+                                    node->field(),
+                                    thread()->GetNextDeoptId());
     AddInstruction(guard_field_class);
-    store_value = Bind(BuildLoadExprTemp());
+    store_value = Bind(BuildLoadExprTemp(token_pos));
     GuardFieldLengthInstr* guard_field_length =
         new(Z) GuardFieldLengthInstr(store_value,
                                      node->field(),
                                      thread()->GetNextDeoptId());
     AddInstruction(guard_field_length);
-    store_value = Bind(BuildLoadExprTemp());
+    store_value = Bind(BuildLoadExprTemp(token_pos));
   }
   StoreInstanceFieldInstr* store =
       new(Z) StoreInstanceFieldInstr(node->field(),
                                      for_instance.value(),
                                      store_value,
                                      kEmitStoreBarrier,
-                                     node->token_pos());
+                                     token_pos);
   // Maybe initializing unboxed store.
   store->set_is_potential_unboxed_initialization(true);
   ReturnDefinition(store);
@@ -3743,7 +3782,7 @@
   Append(for_value);
   Value* store_value = NULL;
   if (result_is_needed) {
-    store_value = Bind(BuildStoreExprTemp(for_value.value()));
+    store_value = Bind(BuildStoreExprTemp(for_value.value(), token_pos));
   } else {
     store_value = for_value.value();
   }
@@ -3752,7 +3791,7 @@
 
   if (result_is_needed) {
     Do(store);
-    return BuildLoadExprTemp();
+    return BuildLoadExprTemp(token_pos);
   } else {
     return store;
   }
@@ -3835,6 +3874,7 @@
     StoreIndexedNode* node,
     bool result_is_needed) {
   Function* super_function = NULL;
+  const intptr_t token_pos = node->token_pos();
   if (node->IsSuperStore()) {
     // Resolve the store indexed operator in the super class.
     super_function = &Function::ZoneHandle(
@@ -3843,7 +3883,7 @@
     if (super_function->IsNull()) {
       // Could not resolve super operator. Generate call noSuchMethod() of the
       // super class instead.
-      ArgumentListNode* arguments = new(Z) ArgumentListNode(node->token_pos());
+      ArgumentListNode* arguments = new(Z) ArgumentListNode(token_pos);
       arguments->Add(node->array());
       arguments->Add(node->index_expr());
       arguments->Add(node->value());
@@ -3857,7 +3897,7 @@
       if (result_is_needed) {
         Do(call);
         // BuildStaticNoSuchMethodCall stores the value in expression_temp.
-        return BuildLoadExprTemp();
+        return BuildLoadExprTemp(token_pos);
       } else {
         return call;
       }
@@ -3881,7 +3921,7 @@
   Append(for_value);
   Value* value = NULL;
   if (result_is_needed) {
-    value = Bind(BuildStoreExprTemp(for_value.value()));
+    value = Bind(BuildStoreExprTemp(for_value.value(), token_pos));
   } else {
     value = for_value.value();
   }
@@ -3891,14 +3931,14 @@
     // Generate static call to super operator []=.
 
     StaticCallInstr* store =
-        new(Z) StaticCallInstr(node->token_pos(),
+        new(Z) StaticCallInstr(token_pos,
                                *super_function,
                                Object::null_array(),
                                arguments,
                                owner()->ic_data_array());
     if (result_is_needed) {
       Do(store);
-      return BuildLoadExprTemp();
+      return BuildLoadExprTemp(token_pos);
     } else {
       return store;
     }
@@ -3908,7 +3948,7 @@
     const String& name =
         String::ZoneHandle(Z, Symbols::New(Token::Str(Token::kASSIGN_INDEX)));
     InstanceCallInstr* store =
-        new(Z) InstanceCallInstr(node->token_pos(),
+        new(Z) InstanceCallInstr(token_pos,
                                  name,
                                  Token::kASSIGN_INDEX,
                                  arguments,
@@ -3917,7 +3957,7 @@
                                  owner()->ic_data_array());
     if (result_is_needed) {
       Do(store);
-      return BuildLoadExprTemp();
+      return BuildLoadExprTemp(token_pos);
     } else {
       return store;
     }
@@ -4008,7 +4048,8 @@
     Value* allocated_context =
         Bind(new(Z) AllocateContextInstr(node->token_pos(),
                                          num_context_variables));
-    { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
+    { LocalVariable* tmp_var =
+          EnterTempLocalScope(allocated_context, node->token_pos());
       if (!is_top_level_sequence || HasContextScope()) {
         ASSERT(is_top_level_sequence ||
                (nested_block.ContextLevel() ==
@@ -4023,7 +4064,7 @@
                                           node->token_pos()));
       }
       Do(BuildStoreContext(
-          Bind(ExitTempLocalScope(tmp_var)),
+          Bind(ExitTempLocalScope(tmp_var, node->token_pos())),
           node->token_pos()));
     }
 
@@ -4041,7 +4082,7 @@
           // Create a temporary local describing the original position.
           const String& temp_name = Symbols::TempParam();
           LocalVariable* temp_local = new(Z) LocalVariable(
-              Scanner::kNoSourcePos,  // Token index.
+              Token::kNoSourcePos,  // Token index.
               temp_name,
               Object::dynamic_type());  // Type.
           temp_local->set_index(param_frame_index);
@@ -4053,14 +4094,16 @@
           temp_local->set_is_captured_parameter(true);
 
           // Copy parameter from local frame to current context.
-          Value* load = Bind(BuildLoadLocal(*temp_local));
-          Do(BuildStoreLocal(parameter, load));
+          Value* load = Bind(BuildLoadLocal(*temp_local, node->token_pos()));
+          Do(BuildStoreLocal(parameter, load, ST(node->token_pos())));
           // Write NULL to the source location to detect buggy accesses and
           // allow GC of passed value if it gets overwritten by a new value in
           // the function.
           Value* null_constant = Bind(new(Z) ConstantInstr(
               Object::ZoneHandle(Z, Object::null())));
-          Do(BuildStoreLocal(*temp_local, null_constant));
+          Do(BuildStoreLocal(*temp_local,
+                             null_constant,
+                             ST(node->token_pos())));
         }
       }
     }
@@ -4074,15 +4117,15 @@
     // basic block. Place this check at the last parameter to ensure parameters
     // are in scope in the debugger at method entry.
     const int num_params = function.NumParameters();
-    intptr_t check_pos = Scanner::kNoSourcePos;
+    intptr_t check_pos = Token::kNoSourcePos;
     if (num_params > 0) {
       const LocalVariable& parameter = *scope->VariableAt(num_params - 1);
       check_pos = parameter.token_pos();
     }
-    if (check_pos < 0) {
+    if (!Token::IsDebugPause(check_pos)) {
       // No parameters or synthetic parameters.
       check_pos = node->token_pos();
-      ASSERT(check_pos >= 0);
+      ASSERT(Token::IsDebugPause(check_pos));
     }
     AddInstruction(new(Z) DebugStepCheckInstr(check_pos,
                                               RawPcDescriptors::kRuntimeCall));
@@ -4122,7 +4165,8 @@
                             NULL,
                             parameter.type(),
                             parameter.name())) {
-        Value* parameter_value = Bind(BuildLoadLocal(parameter));
+        Value* parameter_value =
+            Bind(BuildLoadLocal(parameter, parameter.token_pos()));
         Do(BuildAssertAssignable(parameter.token_pos(),
                                  parameter_value,
                                  parameter.type(),
@@ -4181,7 +4225,7 @@
     exit_ = NULL;
 
     LoadLocalNode* load_jump_count =
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, jump_var);
+        new(Z) LoadLocalNode(node->token_pos(), jump_var);
     ComparisonNode* check_jump_count;
     const intptr_t num_await_states = owner()->await_joins()->length();
 
@@ -4189,12 +4233,12 @@
         Symbols::AwaitContextVar(), false);
     for (intptr_t i = 0; i < num_await_states; i++) {
       check_jump_count = new(Z) ComparisonNode(
-          Scanner::kNoSourcePos,
+          ST(node->token_pos()),
           Token::kEQ,
           load_jump_count,
           new(Z) LiteralNode(
-              Scanner::kNoSourcePos, Smi::ZoneHandle(Z, Smi::New(i))));
-      TestGraphVisitor for_test(owner(), Scanner::kNoSourcePos);
+              ST(node->token_pos()), Smi::ZoneHandle(Z, Smi::New(i))));
+      TestGraphVisitor for_test(owner(), ST(node->token_pos()));
       check_jump_count->Visit(&for_test);
       EffectGraphVisitor for_true(owner());
       EffectGraphVisitor for_false(owner());
@@ -4206,7 +4250,7 @@
 
       // Restore the saved continuation context, i.e. the context that was
       // saved into :await_ctx_var before the closure suspended.
-      for_true.BuildRestoreContext(*old_context, Scanner::kNoSourcePos);
+      for_true.BuildRestoreContext(*old_context, ST(node->token_pos()));
 
       // Goto saved join.
       for_true.Goto((*owner()->await_joins())[i]);
@@ -4264,7 +4308,7 @@
   owner()->set_try_index(try_handler_index);
 
   // Preserve current context into local variable ':saved_try_context_var'.
-  BuildSaveContext(node->context_var(), node->token_pos());
+  BuildSaveContext(node->context_var(), ST(node->token_pos()));
 
   EffectGraphVisitor for_try(owner());
   node->try_block()->Visit(&for_try);
@@ -4341,11 +4385,11 @@
     node->rethrow_clause()->Visit(&for_finally);
     if (for_finally.is_open()) {
       // Rethrow the exception.  Manually build the graph for rethrow.
-      Value* exception = for_finally.Bind(
-          for_finally.BuildLoadLocal(catch_block->rethrow_exception_var()));
+      Value* exception = for_finally.Bind(for_finally.BuildLoadLocal(
+          catch_block->rethrow_exception_var(), finally_block->token_pos()));
       for_finally.PushArgument(exception);
-      Value* stacktrace = for_finally.Bind(
-          for_finally.BuildLoadLocal(catch_block->rethrow_stacktrace_var()));
+      Value* stacktrace = for_finally.Bind(for_finally.BuildLoadLocal(
+          catch_block->rethrow_stacktrace_var(), finally_block->token_pos()));
       for_finally.PushArgument(stacktrace);
       for_finally.AddInstruction(
           new(Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index));
@@ -4420,7 +4464,7 @@
   ZoneGrowableArray<PushArgumentInstr*>* arguments =
       new(Z) ZoneGrowableArray<PushArgumentInstr*>();
   // Object receiver, actually a class literal of the unresolved method's owner.
-  Type& type = Type::ZoneHandle(
+  AbstractType& type = Type::ZoneHandle(
       Z,
       Type::New(function_class,
                 TypeArguments::Handle(Z, TypeArguments::null()),
@@ -4621,6 +4665,7 @@
   Report::MessageF(Report::kBailout,
                    Script::Handle(function.script()),
                    function.token_pos(),
+                   Report::AtLocation,
                    "FlowGraphBuilder Bailout: %s %s",
                    String::Handle(function.name()).ToCString(),
                    reason);
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 94c9444..2c2d14d 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -303,16 +303,18 @@
   void AddReturnExit(intptr_t token_pos, Value* value);
 
  protected:
-  Definition* BuildStoreTemp(const LocalVariable& local, Value* value);
-  Definition* BuildStoreExprTemp(Value* value);
-  Definition* BuildLoadExprTemp();
+  Definition* BuildStoreTemp(const LocalVariable& local,
+                             Value* value,
+                             intptr_t token_pos);
+  Definition* BuildStoreExprTemp(Value* value, intptr_t token_pos);
+  Definition* BuildLoadExprTemp(intptr_t token_pos);
 
   Definition* BuildStoreLocal(const LocalVariable& local,
                               Value* value,
-                              intptr_t token_pos = Scanner::kNoSourcePos);
+                              intptr_t token_pos);
   Definition* BuildLoadLocal(const LocalVariable& local,
-                             intptr_t token_pos = Scanner::kNoSourcePos);
-  LoadLocalInstr* BuildLoadThisVar(LocalScope* scope);
+                             intptr_t token_pos);
+  LoadLocalInstr* BuildLoadThisVar(LocalScope* scope, intptr_t token_pos);
   LoadFieldInstr* BuildNativeGetter(
       NativeBodyNode* node,
       MethodRecognizer::Kind kind,
@@ -341,7 +343,7 @@
       PushArgumentInstr** push_instantiator_type_arguments);
   void BuildTypecheckArguments(intptr_t token_pos,
                                Value** instantiator_type_arguments);
-  Value* BuildInstantiator(const Class& instantiator_class);
+  Value* BuildInstantiator(intptr_t token_pos);
   Value* BuildInstantiatorTypeArguments(intptr_t token_pos,
                                         const Class& instantiator_class,
                                         Value* instantiator);
@@ -428,7 +430,7 @@
 
   void BuildClosureCall(ClosureCallNode* node, bool result_needed);
 
-  Value* BuildNullValue();
+  Value* BuildNullValue(intptr_t token_pos);
 
   // Returns true if the run-time type check can be eliminated.
   bool CanSkipTypeCheck(intptr_t token_pos,
@@ -438,8 +440,8 @@
 
   // Helpers for allocating and deallocating temporary locals on top of the
   // expression stack.
-  LocalVariable* EnterTempLocalScope(Value* value);
-  Definition* ExitTempLocalScope(LocalVariable* var);
+  LocalVariable* EnterTempLocalScope(Value* value, intptr_t token_pos);
+  Definition* ExitTempLocalScope(LocalVariable* var, intptr_t token_pos);
 
   void BuildLetTempExpressions(LetNode* node);
 
diff --git a/runtime/vm/flow_graph_builder_test.cc b/runtime/vm/flow_graph_builder_test.cc
index 91a13b2..2213d0b 100644
--- a/runtime/vm/flow_graph_builder_test.cc
+++ b/runtime/vm/flow_graph_builder_test.cc
@@ -95,6 +95,26 @@
     DUMP_ASSERT(count > 0);
   }
 
+  // Expect to find an instance call at |line| and |column|.
+  void InstanceCallAt(const char* needle,
+                      intptr_t line,
+                      intptr_t column = -1) {
+    ZoneGrowableArray<Instruction*>* instructions =
+        FindInstructionsAt(line, column);
+    intptr_t count = 0;
+    for (intptr_t i = 0; i < instructions->length(); i++) {
+      Instruction* instr = instructions->At(i);
+      EXPECT(instr != NULL);
+      if (instr->IsInstanceCall()) {
+        const char* haystack = instr->ToCString();
+        if (strstr(haystack, needle) != NULL) {
+          count++;
+        }
+      }
+    }
+    DUMP_ASSERT(count > 0);
+  }
+
   // Expect to find at least one static call at |line| and |column|. The
   // static call will have |needle| in its |ToCString| representation.
   void StaticCallAt(const char* needle,
@@ -146,9 +166,26 @@
     }
   }
 
+  // Fails if any of the IR nodes has a token position of Token::kNoSourcePos.
+  void EnsureSourcePositions() {
+    for (intptr_t i = 0; i < blocks_->length(); i++) {
+      BlockEntryInstr* entry = (*blocks_)[i];
+      DUMP_ASSERT(entry->token_pos() != Token::kNoSourcePos);
+      for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
+        Instruction* instr = it.Current();
+        DUMP_ASSERT(instr->token_pos() != Token::kNoSourcePos);
+      }
+    }
+  }
+
  private:
   void DumpInstruction(Instruction* instr) {
-    const intptr_t token_pos = instr->token_pos();
+    intptr_t token_pos = instr->token_pos();
+    bool synthetic = false;
+    if (Token::IsSynthetic(token_pos)) {
+      synthetic = true;
+      token_pos = Token::FromSynthetic(token_pos);
+    }
     if (token_pos < 0) {
       const char* token_pos_string =
           ClassifyingTokenPositions::ToCString(token_pos);
@@ -161,10 +198,17 @@
                                   &token_line,
                                   &token_column,
                                   NULL);
-    THR_Print("       %02d:%02d -- %s\n",
-              static_cast<int>(token_line),
-              static_cast<int>(token_column),
-              instr->ToCString());
+    if (synthetic) {
+      THR_Print("      *%02d:%02d -- %s\n",
+                static_cast<int>(token_line),
+                static_cast<int>(token_column),
+                instr->ToCString());
+    } else {
+      THR_Print("       %02d:%02d -- %s\n",
+                static_cast<int>(token_line),
+                static_cast<int>(token_column),
+                instr->ToCString());
+    }
   }
 
   Instruction* FindFirstInstructionAt(intptr_t line, intptr_t column) {
@@ -185,6 +229,9 @@
       for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
         Instruction* instr = it.Current();
         intptr_t token_pos = instr->token_pos();
+        if (Token::IsSynthetic(token_pos)) {
+          token_pos = Token::FromSynthetic(token_pos);
+        }
         if (token_pos < 0) {
           continue;
         }
@@ -267,6 +314,8 @@
   spt.InstanceCallAt(4, 13, Token::kADD);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 5, 3);
   spt.FuzzyInstructionMatchAt("Return", 5, 3);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -294,6 +343,8 @@
   spt.FuzzyInstructionMatchAt("LoadStaticField", 7, 10);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 7, 3);
   spt.FuzzyInstructionMatchAt("Return", 7, 3);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -323,6 +374,8 @@
   spt.FuzzyInstructionMatchAt("LoadStaticField", 7, 10);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 7, 3);
   spt.FuzzyInstructionMatchAt("Return", 7, 3);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -370,6 +423,8 @@
   spt.FuzzyInstructionMatchAt("LoadStaticField", 10, 10);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 10, 3);
   spt.FuzzyInstructionMatchAt("Return", 10, 3);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -408,6 +463,8 @@
   spt.FuzzyInstructionMatchAt("LoadStaticField", 10, 10);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 10, 3);
   spt.FuzzyInstructionMatchAt("Return", 10, 3);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -445,6 +502,8 @@
   spt.FuzzyInstructionMatchAt("Constant(#null)", 6, 1);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 6, 1);
   spt.FuzzyInstructionMatchAt("Return", 6, 1);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -487,6 +546,8 @@
   spt.FuzzyInstructionMatchAt("Constant(#null)", 6, 1);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 6, 1);
   spt.FuzzyInstructionMatchAt("Return", 6, 1);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -535,6 +596,8 @@
   spt.FuzzyInstructionMatchAt("LoadLocal(z", 9, 10);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 9, 3);
   spt.FuzzyInstructionMatchAt("Return", 9, 3);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -563,6 +626,8 @@
   spt.FuzzyInstructionMatchAt("LoadStaticField", 7, 12);
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 7, 5);
   spt.FuzzyInstructionMatchAt("Return", 7, 5);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -607,6 +672,8 @@
   spt.FuzzyInstructionMatchAt("Constant(#5", 7, 21);             // '5'
   spt.FuzzyInstructionMatchAt("DebugStepCheck", 7, 14);
   spt.FuzzyInstructionMatchAt("Return", 7, 14);
+
+  spt.EnsureSourcePositions();
 }
 
 
@@ -657,6 +724,82 @@
 
   spt.FuzzyInstructionMatchAt("Constant(#99", 10, 12);                 // '9'
   spt.FuzzyInstructionMatchAt("Return", 10, 5);                        // 'r'
+
+  spt.EnsureSourcePositions();
+}
+
+
+TEST_CASE(SourcePosition_InstanceFields) {
+  const char* kScript =
+      "class A {\n"
+      "  var x;\n"
+      "  var y;\n"
+      "}\n"
+      "main() {\n"
+      "  var z = new A();\n"
+      "  z.x = 99;\n"
+      "  z.y = z.x;\n"
+      "  return z.y;\n"
+      "}\n";
+
+  SourcePositionTest spt(thread, kScript);
+  spt.BuildGraphFor("main");
+  spt.FuzzyInstructionMatchAt("AllocateObject(A)", 6, 15);       // 'A'
+  spt.FuzzyInstructionMatchAt("StaticCall", 6, 15);              // 'A'
+  spt.FuzzyInstructionMatchAt("StoreLocal(z", 6, 9);             // '='
+  spt.InstanceCallAt("set:x", 7, 5);                             // 'x'
+  spt.InstanceCallAt("get:x", 8, 11);                            // 'x'
+  spt.InstanceCallAt("set:y", 8, 5);                             // 'y'
+
+  spt.InstanceCallAt("get:y", 9, 12);                            // 'y'
+  spt.FuzzyInstructionMatchAt("DebugStepCheck", 9, 3);
+  spt.FuzzyInstructionMatchAt("Return", 9, 3);
+
+  spt.EnsureSourcePositions();
+}
+
+
+TEST_CASE(SourcePosition_Async) {
+  const char* kScript =
+      "import 'dart:async';\n"
+      "var x = 5;\n"
+      "var y = 5;\n"
+      "foo(Future f1, Future f2) async {\n"
+      "  await f1;\n"
+      "  await f2;\n"
+      "  return 55;\n"
+      "}\n"
+      "main() {\n"
+      "  foo(new Future.value(33));\n"
+      "}\n";
+
+  SourcePositionTest spt(thread, kScript);
+  spt.BuildGraphFor("foo");
+  spt.EnsureSourcePositions();
+  spt.Dump();
+}
+
+
+static bool SyntheticRoundTripTest(intptr_t token_pos) {
+  return Token::FromSynthetic(Token::ToSynthetic(token_pos)) == token_pos;
+}
+
+
+UNIT_TEST_CASE(SourcePosition_SyntheticTokens) {
+  EXPECT(Token::kNoSourcePos == -1);
+  EXPECT(Token::kMinSourcePos == 0);
+  EXPECT(Token::kMaxSourcePos > 0);
+
+  EXPECT(!Token::IsSynthetic(0));
+  EXPECT(Token::IsSynthetic(Token::ToSynthetic(0)));
+  EXPECT(Token::IsSynthetic(Token::ToSynthetic(9)));
+  EXPECT(!Token::IsSynthetic(Token::FromSynthetic(-1)));
+  EXPECT(!Token::IsSynthetic(ClassifyingTokenPositions::kPrivate));
+  EXPECT(!Token::IsSynthetic(ClassifyingTokenPositions::kLast));
+
+  EXPECT(SyntheticRoundTripTest(0));
+  EXPECT(SyntheticRoundTripTest(Token::kMaxSourcePos));
+  EXPECT(SyntheticRoundTripTest(Token::kMinSourcePos));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 1f02942..eabcbf1 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -627,6 +627,7 @@
   Report::MessageF(Report::kBailout,
                    Script::Handle(function.script()),
                    function.token_pos(),
+                   Report::AtLocation,
                    "FlowGraphCompiler Bailout: %s %s",
                    String::Handle(function.name()).ToCString(),
                    reason);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index abd8b65..429631f 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -273,7 +273,7 @@
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-  ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
+  ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0));
   const Register kInstanceReg = R0;
   Error& bound_error = Error::Handle(zone());
   const Type& int_type = Type::Handle(zone(), Type::IntType());
@@ -286,15 +286,15 @@
   } else {
     __ b(is_not_instance_lbl, EQ);
   }
-  const intptr_t num_type_args = type_class.NumTypeArguments();
-  const intptr_t num_type_params = type_class.NumTypeParameters();
-  const intptr_t from_index = num_type_args - num_type_params;
-  const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(zone(), type.arguments());
-  const bool is_raw_type = type_arguments.IsNull() ||
-      type_arguments.IsRaw(from_index, num_type_params);
-  // Signature class is an instantiated parameterized type.
-  if (!type_class.IsSignatureClass()) {
+  // A function type test requires checking the function signature.
+  if (!type.IsFunctionType()) {
+    const intptr_t num_type_args = type_class.NumTypeArguments();
+    const intptr_t num_type_params = type_class.NumTypeParameters();
+    const intptr_t from_index = num_type_args - num_type_params;
+    const TypeArguments& type_arguments =
+        TypeArguments::ZoneHandle(zone(), type.arguments());
+    const bool is_raw_type = type_arguments.IsNull() ||
+        type_arguments.IsRaw(from_index, num_type_params);
     if (is_raw_type) {
       const Register kClassIdReg = R2;
       // dynamic type argument, check only classes.
@@ -362,6 +362,10 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
+  if (type.IsFunctionType()) {
+    // Fallthrough.
+    return true;
+  }
   const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
@@ -392,12 +396,10 @@
     __ b(is_not_instance_lbl);
     return false;
   }
-  if (type.IsFunctionType()) {
+  if (type.IsDartFunctionType()) {
     // Check if instance is a closure.
-    __ LoadClassById(R3, kClassIdReg);
-    __ ldr(R3, FieldAddress(R3, Class::signature_function_offset()));
-    __ CompareObject(R3, Object::null_object());
-    __ b(is_instance_lbl, NE);
+    __ CompareImmediate(kClassIdReg, kClosureCid);
+    __ b(is_instance_lbl, EQ);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -505,7 +507,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType()) {
+  if (type.IsType() || type.IsFunctionType()) {
     const Register kInstanceReg = R0;
     const Register kTypeArgumentsReg = R1;
     __ tst(kInstanceReg, Operand(kSmiTagMask));  // Is instance Smi?
@@ -547,10 +549,10 @@
   }
   if (type.IsInstantiated()) {
     const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-    // A class equality check is only applicable with a dst type of a
-    // non-parameterized class, non-signature class, or with a raw dst type of
+    // A class equality check is only applicable with a dst type (not a
+    // function type) of a non-parameterized class or with a raw dst type of
     // a parameterized class.
-    if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
+    if (type.IsFunctionType() || (type_class.NumTypeArguments() > 0)) {
       return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
                                                        type,
                                                        is_instance_lbl,
@@ -673,7 +675,7 @@
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
                                                  LocationSummary* locs) {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   ASSERT(!dst_type.IsNull());
   ASSERT(dst_type.IsFinalized());
   // Assignable check is skipped in FlowGraphBuilder, not here.
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 359c89c..977010a 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -265,7 +265,7 @@
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-  ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
+  ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0));
   const Register kInstanceReg = R0;
   Error& bound_error = Error::Handle(zone());
   const Type& int_type = Type::Handle(zone(), Type::IntType());
@@ -278,15 +278,15 @@
   } else {
     __ b(is_not_instance_lbl, EQ);
   }
-  const intptr_t num_type_args = type_class.NumTypeArguments();
-  const intptr_t num_type_params = type_class.NumTypeParameters();
-  const intptr_t from_index = num_type_args - num_type_params;
-  const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(zone(), type.arguments());
-  const bool is_raw_type = type_arguments.IsNull() ||
-      type_arguments.IsRaw(from_index, num_type_params);
-  // Signature class is an instantiated parameterized type.
-  if (!type_class.IsSignatureClass()) {
+  // A function type test requires checking the function signature.
+  if (!type.IsFunctionType()) {
+    const intptr_t num_type_args = type_class.NumTypeArguments();
+    const intptr_t num_type_params = type_class.NumTypeParameters();
+    const intptr_t from_index = num_type_args - num_type_params;
+    const TypeArguments& type_arguments =
+        TypeArguments::ZoneHandle(zone(), type.arguments());
+    const bool is_raw_type = type_arguments.IsNull() ||
+        type_arguments.IsRaw(from_index, num_type_params);
     if (is_raw_type) {
       const Register kClassIdReg = R2;
       // dynamic type argument, check only classes.
@@ -354,6 +354,10 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
+  if (type.IsFunctionType()) {
+    // Fallthrough.
+    return true;
+  }
   const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
@@ -384,12 +388,10 @@
     __ b(is_not_instance_lbl);
     return false;
   }
-  if (type.IsFunctionType()) {
+  if (type.IsDartFunctionType()) {
     // Check if instance is a closure.
-    __ LoadClassById(R3, kClassIdReg);
-    __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset());
-    __ CompareObject(R3, Object::null_object());
-    __ b(is_instance_lbl, NE);
+    __ CompareImmediate(kClassIdReg, kClosureCid);
+    __ b(is_instance_lbl, EQ);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -497,7 +499,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType()) {
+  if (type.IsType() || type.IsFunctionType()) {
     const Register kInstanceReg = R0;
     const Register kTypeArgumentsReg = R1;
     __ tsti(kInstanceReg, Immediate(kSmiTagMask));  // Is instance Smi?
@@ -539,10 +541,10 @@
   }
   if (type.IsInstantiated()) {
     const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-    // A class equality check is only applicable with a dst type of a
-    // non-parameterized class, non-signature class, or with a raw dst type of
+    // A class equality check is only applicable with a dst type (not a
+    // function type) of a non-parameterized class or with a raw dst type of
     // a parameterized class.
-    if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
+    if (type.IsFunctionType() || (type_class.NumTypeArguments() > 0)) {
       return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
                                                        type,
                                                        is_instance_lbl,
@@ -665,7 +667,7 @@
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
                                                  LocationSummary* locs) {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   ASSERT(!dst_type.IsNull());
   ASSERT(dst_type.IsFinalized());
   // Assignable check is skipped in FlowGraphBuilder, not here.
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index b2272fe9..3a2ee04 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -277,7 +277,7 @@
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-  ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
+  ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0));
   const Register kInstanceReg = EAX;
   Error& bound_error = Error::Handle(zone());
   const Type& int_type = Type::Handle(zone(), Type::IntType());
@@ -290,15 +290,15 @@
   } else {
     __ j(ZERO, is_not_instance_lbl);
   }
-  const intptr_t num_type_args = type_class.NumTypeArguments();
-  const intptr_t num_type_params = type_class.NumTypeParameters();
-  const intptr_t from_index = num_type_args - num_type_params;
-  const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(zone(), type.arguments());
-  const bool is_raw_type = type_arguments.IsNull() ||
-      type_arguments.IsRaw(from_index, num_type_params);
-  // Signature class is an instantiated parameterized type.
-  if (!type_class.IsSignatureClass()) {
+  // A function type test requires checking the function signature.
+  if (!type.IsFunctionType()) {
+    const intptr_t num_type_args = type_class.NumTypeArguments();
+    const intptr_t num_type_params = type_class.NumTypeParameters();
+    const intptr_t from_index = num_type_args - num_type_params;
+    const TypeArguments& type_arguments =
+        TypeArguments::ZoneHandle(zone(), type.arguments());
+    const bool is_raw_type = type_arguments.IsNull() ||
+        type_arguments.IsRaw(from_index, num_type_params);
     if (is_raw_type) {
       const Register kClassIdReg = ECX;
       // dynamic type argument, check only classes.
@@ -365,6 +365,10 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
+  if (type.IsFunctionType()) {
+    // Fallthrough.
+    return true;
+  }
   const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
@@ -395,14 +399,10 @@
     __ jmp(is_not_instance_lbl);
     return false;
   }
-  if (type.IsFunctionType()) {
+  if (type.IsDartFunctionType()) {
     // Check if instance is a closure.
-    const Immediate& raw_null =
-        Immediate(reinterpret_cast<intptr_t>(Object::null()));
-    __ LoadClassById(EDI, kClassIdReg);
-    __ movl(EDI, FieldAddress(EDI, Class::signature_function_offset()));
-    __ cmpl(EDI, raw_null);
-    __ j(NOT_EQUAL, is_instance_lbl);
+    __ cmpl(kClassIdReg, Immediate(kClosureCid));
+    __ j(EQUAL, is_instance_lbl);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -513,7 +513,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType()) {
+  if (type.IsType() || type.IsFunctionType()) {
     const Register kInstanceReg = EAX;
     const Register kTypeArgumentsReg = EDX;
     __ testl(kInstanceReg, Immediate(kSmiTagMask));  // Is instance Smi?
@@ -555,10 +555,10 @@
   }
   if (type.IsInstantiated()) {
     const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-    // A class equality check is only applicable with a dst type of a
-    // non-parameterized class, non-signature class, or with a raw dst type of
+    // A class equality check is only applicable with a dst type (not a
+    // function type) of a non-parameterized class or with a raw dst type of
     // a parameterized class.
-    if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
+    if (type.IsFunctionType() || (type_class.NumTypeArguments() > 0)) {
       return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
                                                        type,
                                                        is_instance_lbl,
@@ -684,7 +684,7 @@
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
                                                  LocationSummary* locs) {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   ASSERT(!dst_type.IsNull());
   ASSERT(dst_type.IsFinalized());
   // Assignable check is skipped in FlowGraphBuilder, not here.
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index f98bb67..a6fef0b 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -265,7 +265,7 @@
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-  ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
+  ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0));
   const Register kInstanceReg = A0;
   Error& bound_error = Error::Handle(zone());
   const Type& int_type = Type::Handle(zone(), Type::IntType());
@@ -278,15 +278,15 @@
   } else {
     __ beq(CMPRES1, ZR, is_not_instance_lbl);
   }
-  const intptr_t num_type_args = type_class.NumTypeArguments();
-  const intptr_t num_type_params = type_class.NumTypeParameters();
-  const intptr_t from_index = num_type_args - num_type_params;
-  const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(zone(), type.arguments());
-  const bool is_raw_type = type_arguments.IsNull() ||
-      type_arguments.IsRaw(from_index, num_type_params);
-  // Signature class is an instantiated parameterized type.
-  if (!type_class.IsSignatureClass()) {
+  // A function type test requires checking the function signature.
+  if (!type.IsFunctionType()) {
+    const intptr_t num_type_args = type_class.NumTypeArguments();
+    const intptr_t num_type_params = type_class.NumTypeParameters();
+    const intptr_t from_index = num_type_args - num_type_params;
+    const TypeArguments& type_arguments =
+        TypeArguments::ZoneHandle(zone(), type.arguments());
+    const bool is_raw_type = type_arguments.IsNull() ||
+        type_arguments.IsRaw(from_index, num_type_params);
     if (is_raw_type) {
       const Register kClassIdReg = T0;
       // dynamic type argument, check only classes.
@@ -353,6 +353,10 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
+  if (type.IsFunctionType()) {
+    // Fallthrough.
+    return true;
+  }
   const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
@@ -382,11 +386,9 @@
     __ b(is_not_instance_lbl);
     return false;
   }
-  if (type.IsFunctionType()) {
+  if (type.IsDartFunctionType()) {
     // Check if instance is a closure.
-    __ LoadClassById(T1, kClassIdReg);
-    __ lw(T1, FieldAddress(T1, Class::signature_function_offset()));
-    __ BranchNotEqual(T1, Object::null_object(), is_instance_lbl);
+    __ BranchEqual(kClassIdReg, Immediate(kClosureCid), is_instance_lbl);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -493,7 +495,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType()) {
+  if (type.IsType() || type.IsFunctionType()) {
     const Register kInstanceReg = A0;
     const Register kTypeArgumentsReg = A1;
     __ andi(CMPRES1, kInstanceReg, Immediate(kSmiTagMask));
@@ -535,10 +537,10 @@
   }
   if (type.IsInstantiated()) {
     const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-    // A class equality check is only applicable with a dst type of a
-    // non-parameterized class, non-signature class, or with a raw dst type of
+    // A class equality check is only applicable with a dst type (not a
+    // function type) of a non-parameterized class or with a raw dst type of
     // a parameterized class.
-    if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
+    if (type.IsFunctionType() || (type_class.NumTypeArguments() > 0)) {
       return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
                                                        type,
                                                        is_instance_lbl,
@@ -667,7 +669,7 @@
                                                  const String& dst_name,
                                                  LocationSummary* locs) {
   __ Comment("AssertAssignable");
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   ASSERT(!dst_type.IsNull());
   ASSERT(dst_type.IsFinalized());
   // Assignable check is skipped in FlowGraphBuilder, not here.
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index e54b1eb..4662afb 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -274,7 +274,7 @@
   __ Comment("InstantiatedTypeWithArgumentsTest");
   ASSERT(type.IsInstantiated());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-  ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
+  ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0));
   const Register kInstanceReg = RAX;
   Error& bound_error = Error::Handle(zone());
   const Type& int_type = Type::Handle(zone(), Type::IntType());
@@ -287,15 +287,15 @@
   } else {
     __ j(ZERO, is_not_instance_lbl);
   }
-  const intptr_t num_type_args = type_class.NumTypeArguments();
-  const intptr_t num_type_params = type_class.NumTypeParameters();
-  const intptr_t from_index = num_type_args - num_type_params;
-  const TypeArguments& type_arguments =
-      TypeArguments::ZoneHandle(zone(), type.arguments());
-  const bool is_raw_type = type_arguments.IsNull() ||
-      type_arguments.IsRaw(from_index, num_type_params);
-  // Signature class is an instantiated parameterized type.
-  if (!type_class.IsSignatureClass()) {
+  // A function type test requires checking the function signature.
+  if (!type.IsFunctionType()) {
+    const intptr_t num_type_args = type_class.NumTypeArguments();
+    const intptr_t num_type_params = type_class.NumTypeParameters();
+    const intptr_t from_index = num_type_args - num_type_params;
+    const TypeArguments& type_arguments =
+        TypeArguments::ZoneHandle(zone(), type.arguments());
+    const bool is_raw_type = type_arguments.IsNull() ||
+        type_arguments.IsRaw(from_index, num_type_params);
     if (is_raw_type) {
       const Register kClassIdReg = R10;
       // dynamic type argument, check only classes.
@@ -362,6 +362,10 @@
     Label* is_not_instance_lbl) {
   __ Comment("InstantiatedTypeNoArgumentsTest");
   ASSERT(type.IsInstantiated());
+  if (type.IsFunctionType()) {
+    // Fallthrough.
+    return true;
+  }
   const Class& type_class = Class::Handle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() == 0);
 
@@ -392,12 +396,10 @@
     __ jmp(is_not_instance_lbl);
     return false;
   }
-  if (type.IsFunctionType()) {
+  if (type.IsDartFunctionType()) {
     // Check if instance is a closure.
-    __ LoadClassById(R13, kClassIdReg);
-    __ movq(R13, FieldAddress(R13, Class::signature_function_offset()));
-    __ CompareObject(R13, Object::null_object());
-    __ j(NOT_EQUAL, is_instance_lbl);
+    __ cmpq(kClassIdReg, Immediate(kClosureCid));
+    __ j(EQUAL, is_instance_lbl);
   }
   // Custom checking for numbers (Smi, Mint, Bigint and Double).
   // Note that instance is not Smi (checked above).
@@ -507,7 +509,7 @@
     __ Bind(&fall_through);
     return type_test_cache.raw();
   }
-  if (type.IsType()) {
+  if (type.IsType() || type.IsFunctionType()) {
     const Register kInstanceReg = RAX;
     const Register kTypeArgumentsReg = RDX;
     __ testq(kInstanceReg, Immediate(kSmiTagMask));  // Is instance Smi?
@@ -549,10 +551,10 @@
   }
   if (type.IsInstantiated()) {
     const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
-    // A class equality check is only applicable with a dst type of a
-    // non-parameterized class, non-signature class, or with a raw dst type of
+    // A class equality check is only applicable with a dst type (not a
+    // function type) of a non-parameterized class or with a raw dst type of
     // a parameterized class.
-    if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
+    if (type.IsFunctionType() || (type_class.NumTypeArguments() > 0)) {
       return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
                                                        type,
                                                        is_instance_lbl,
@@ -676,7 +678,7 @@
                                                  const AbstractType& dst_type,
                                                  const String& dst_name,
                                                  LocationSummary* locs) {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   ASSERT(!dst_type.IsNull());
   ASSERT(dst_type.IsFinalized());
   // Assignable check is skipped in FlowGraphBuilder, not here.
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index bc5d7bc..1b39f97 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -687,213 +687,236 @@
     // Save and clear deopt id.
     const intptr_t prev_deopt_id = thread()->deopt_id();
     thread()->set_deopt_id(0);
-    // Install bailout jump.
-    LongJumpScope jump;
-    if (setjmp(*jump.Set()) == 0) {
-      // Parse the callee function.
-      bool in_cache;
-      ParsedFunction* parsed_function;
-      {
-        CSTAT_TIMER_SCOPE(thread(), graphinliner_parse_timer);
-        parsed_function = GetParsedFunction(function, &in_cache);
-      }
+    Error& error = Error::Handle();
+    {
+      // Install bailout jump.
+      LongJumpScope jump;
+      if (setjmp(*jump.Set()) == 0) {
+        // Parse the callee function.
+        bool in_cache;
+        ParsedFunction* parsed_function;
+        {
+          CSTAT_TIMER_SCOPE(thread(), graphinliner_parse_timer);
+          parsed_function = GetParsedFunction(function, &in_cache);
+        }
 
-      // Load IC data for the callee.
-      ZoneGrowableArray<const ICData*>* ic_data_array =
-            new(Z) ZoneGrowableArray<const ICData*>();
-      const bool clone_descriptors = Compiler::IsBackgroundCompilation();
-      function.RestoreICDataMap(ic_data_array, clone_descriptors);
+        // Load IC data for the callee.
+        ZoneGrowableArray<const ICData*>* ic_data_array =
+              new(Z) ZoneGrowableArray<const ICData*>();
+        const bool clone_descriptors = Compiler::IsBackgroundCompilation();
+        function.RestoreICDataMap(ic_data_array, clone_descriptors);
 
-      // Build the callee graph.
-      InlineExitCollector* exit_collector =
-          new(Z) InlineExitCollector(caller_graph_, call);
-      FlowGraphBuilder builder(*parsed_function,
-                               *ic_data_array,
-                               exit_collector,
-                               Compiler::kNoOSRDeoptId);
-      builder.SetInitialBlockId(caller_graph_->max_block_id());
-      FlowGraph* callee_graph;
-      {
-        CSTAT_TIMER_SCOPE(thread(), graphinliner_build_timer);
-        callee_graph = builder.BuildGraph();
-      }
+        // Build the callee graph.
+        InlineExitCollector* exit_collector =
+            new(Z) InlineExitCollector(caller_graph_, call);
+        FlowGraphBuilder builder(*parsed_function,
+                                 *ic_data_array,
+                                 exit_collector,
+                                 Compiler::kNoOSRDeoptId);
+        builder.SetInitialBlockId(caller_graph_->max_block_id());
+        FlowGraph* callee_graph;
+        {
+          CSTAT_TIMER_SCOPE(thread(), graphinliner_build_timer);
+          callee_graph = builder.BuildGraph();
+        }
 
-      // The parameter stubs are a copy of the actual arguments providing
-      // concrete information about the values, for example constant values,
-      // without linking between the caller and callee graphs.
-      // TODO(zerny): Put more information in the stubs, eg, type information.
-      ZoneGrowableArray<Definition*>* param_stubs =
-          new(Z) ZoneGrowableArray<Definition*>(
-              function.NumParameters());
+        // The parameter stubs are a copy of the actual arguments providing
+        // concrete information about the values, for example constant values,
+        // without linking between the caller and callee graphs.
+        // TODO(zerny): Put more information in the stubs, eg, type information.
+        ZoneGrowableArray<Definition*>* param_stubs =
+            new(Z) ZoneGrowableArray<Definition*>(
+                function.NumParameters());
 
-      // Create a parameter stub for each fixed positional parameter.
-      for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
-        param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph));
-      }
+        // Create a parameter stub for each fixed positional parameter.
+        for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
+          param_stubs->Add(CreateParameterStub(i, (*arguments)[i],
+                                               callee_graph));
+        }
 
-      // If the callee has optional parameters, rebuild the argument and stub
-      // arrays so that actual arguments are in one-to-one with the formal
-      // parameters.
-      if (function.HasOptionalParameters()) {
-        TRACE_INLINING(THR_Print("     adjusting for optional parameters\n"));
-        if (!AdjustForOptionalParameters(*parsed_function,
-                                         argument_names,
-                                         arguments,
-                                         param_stubs,
-                                         callee_graph)) {
-          function.set_is_inlinable(false);
-          TRACE_INLINING(THR_Print("     Bailout: optional arg mismatch\n"));
-          PRINT_INLINING_TREE("Optional arg mismatch",
+        // If the callee has optional parameters, rebuild the argument and stub
+        // arrays so that actual arguments are in one-to-one with the formal
+        // parameters.
+        if (function.HasOptionalParameters()) {
+          TRACE_INLINING(THR_Print("     adjusting for optional parameters\n"));
+          if (!AdjustForOptionalParameters(*parsed_function,
+                                           argument_names,
+                                           arguments,
+                                           param_stubs,
+                                           callee_graph)) {
+            function.set_is_inlinable(false);
+            TRACE_INLINING(THR_Print("     Bailout: optional arg mismatch\n"));
+            PRINT_INLINING_TREE("Optional arg mismatch",
+                &call_data->caller, &function, call_data->call);
+            return false;
+          }
+        }
+
+        // After treating optional parameters the actual/formal count must
+        // match.
+        ASSERT(arguments->length() == function.NumParameters());
+        ASSERT(param_stubs->length() == callee_graph->parameter_count());
+
+        // Update try-index of the callee graph.
+        BlockEntryInstr* call_block = call_data->call->GetBlock();
+        if (call_block->InsideTryBlock()) {
+          intptr_t try_index = call_block->try_index();
+          for (BlockIterator it = callee_graph->reverse_postorder_iterator();
+               !it.Done(); it.Advance()) {
+            BlockEntryInstr* block = it.Current();
+            block->set_try_index(try_index);
+          }
+        }
+
+        BlockScheduler block_scheduler(callee_graph);
+        block_scheduler.AssignEdgeWeights();
+
+        {
+          CSTAT_TIMER_SCOPE(thread(), graphinliner_ssa_timer);
+          // Compute SSA on the callee graph, catching bailouts.
+          callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
+                                   param_stubs);
+          DEBUG_ASSERT(callee_graph->VerifyUseLists());
+        }
+
+        {
+          CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer);
+          // TODO(fschneider): Improve suppression of speculative inlining.
+          // Deopt-ids overlap between caller and callee.
+          FlowGraphOptimizer optimizer(callee_graph,
+                                       inliner_->use_speculative_inlining_,
+                                       inliner_->inlining_black_list_);
+          if (Compiler::always_optimize()) {
+            optimizer.PopulateWithICData();
+
+            optimizer.ApplyClassIds();
+            DEBUG_ASSERT(callee_graph->VerifyUseLists());
+
+            FlowGraphTypePropagator::Propagate(callee_graph);
+            DEBUG_ASSERT(callee_graph->VerifyUseLists());
+          }
+          optimizer.ApplyICData();
+          DEBUG_ASSERT(callee_graph->VerifyUseLists());
+
+          // Optimize (a << b) & c patterns, merge instructions. Must occur
+          // before 'SelectRepresentations' which inserts conversion nodes.
+          optimizer.TryOptimizePatterns();
+          DEBUG_ASSERT(callee_graph->VerifyUseLists());
+        }
+
+        if (FLAG_trace_inlining &&
+            (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
+          THR_Print("Callee graph for inlining %s\n",
+                    function.ToFullyQualifiedCString());
+          FlowGraphPrinter printer(*callee_graph);
+          printer.PrintBlocks();
+        }
+
+        // Collect information about the call site and caller graph.
+        // TODO(zerny): Do this after CP and dead code elimination.
+        intptr_t constants_count = 0;
+        for (intptr_t i = 0; i < param_stubs->length(); ++i) {
+          if ((*param_stubs)[i]->IsConstant()) ++constants_count;
+        }
+
+        FlowGraphInliner::CollectGraphInfo(callee_graph);
+        const intptr_t size = function.optimized_instruction_count();
+        const intptr_t call_site_count = function.optimized_call_site_count();
+
+        function.set_optimized_instruction_count(size);
+        function.set_optimized_call_site_count(call_site_count);
+
+        // Use heuristics do decide if this call should be inlined.
+        if (!ShouldWeInline(function, size, call_site_count, constants_count)) {
+          // If size is larger than all thresholds, don't consider it again.
+          if ((size > FLAG_inlining_size_threshold) &&
+              (call_site_count > FLAG_inlining_callee_call_sites_threshold) &&
+              (size > FLAG_inlining_constant_arguments_min_size_threshold) &&
+              (size > FLAG_inlining_constant_arguments_max_size_threshold)) {
+            function.set_is_inlinable(false);
+          }
+          thread()->set_deopt_id(prev_deopt_id);
+          TRACE_INLINING(THR_Print("     Bailout: heuristics with "
+                                   "code size:  %" Pd ", "
+                                   "call sites: %" Pd ", "
+                                   "const args: %" Pd "\n",
+                                   size,
+                                   call_site_count,
+                                   constants_count));
+          PRINT_INLINING_TREE("Heuristic fail",
               &call_data->caller, &function, call_data->call);
           return false;
         }
-      }
 
-      // After treating optional parameters the actual/formal count must match.
-      ASSERT(arguments->length() == function.NumParameters());
-      ASSERT(param_stubs->length() == callee_graph->parameter_count());
+        // Inline dispatcher methods regardless of the current depth.
+        const intptr_t depth =
+            (function.IsInvokeFieldDispatcher() ||
+             function.IsNoSuchMethodDispatcher()) ? 0 : inlining_depth_;
+        collected_call_sites_->FindCallSites(callee_graph, depth,
+                                             &inlined_info_);
 
-      // Update try-index of the callee graph.
-      BlockEntryInstr* call_block = call_data->call->GetBlock();
-      if (call_block->InsideTryBlock()) {
-        intptr_t try_index = call_block->try_index();
-        for (BlockIterator it = callee_graph->reverse_postorder_iterator();
-             !it.Done(); it.Advance()) {
-          BlockEntryInstr* block = it.Current();
-          block->set_try_index(try_index);
+        // Add the function to the cache.
+        if (!in_cache) {
+          function_cache_.Add(parsed_function);
         }
-      }
 
-      BlockScheduler block_scheduler(callee_graph);
-      block_scheduler.AssignEdgeWeights();
-
-      {
-        CSTAT_TIMER_SCOPE(thread(), graphinliner_ssa_timer);
-        // Compute SSA on the callee graph, catching bailouts.
-        callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
-                                 param_stubs);
-        DEBUG_ASSERT(callee_graph->VerifyUseLists());
-      }
-
-      {
-        CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer);
-        // TODO(fschneider): Improve suppression of speculative inlining.
-        // Deopt-ids overlap between caller and callee.
-        FlowGraphOptimizer optimizer(callee_graph,
-                                     inliner_->use_speculative_inlining_,
-                                     inliner_->inlining_black_list_);
-        if (Compiler::always_optimize()) {
-          optimizer.PopulateWithICData();
-
-          optimizer.ApplyClassIds();
-          DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-          FlowGraphTypePropagator::Propagate(callee_graph);
-          DEBUG_ASSERT(callee_graph->VerifyUseLists());
-        }
-        optimizer.ApplyICData();
-        DEBUG_ASSERT(callee_graph->VerifyUseLists());
-
-        // Optimize (a << b) & c patterns, merge instructions. Must occur before
-        // 'SelectRepresentations' which inserts conversion nodes.
-        optimizer.TryOptimizePatterns();
-        DEBUG_ASSERT(callee_graph->VerifyUseLists());
-      }
-
-      if (FLAG_trace_inlining &&
-          (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
-        THR_Print("Callee graph for inlining %s\n",
-                  function.ToFullyQualifiedCString());
-        FlowGraphPrinter printer(*callee_graph);
-        printer.PrintBlocks();
-      }
-
-      // Collect information about the call site and caller graph.
-      // TODO(zerny): Do this after CP and dead code elimination.
-      intptr_t constants_count = 0;
-      for (intptr_t i = 0; i < param_stubs->length(); ++i) {
-        if ((*param_stubs)[i]->IsConstant()) ++constants_count;
-      }
-
-      FlowGraphInliner::CollectGraphInfo(callee_graph);
-      const intptr_t size = function.optimized_instruction_count();
-      const intptr_t call_site_count = function.optimized_call_site_count();
-
-      function.set_optimized_instruction_count(size);
-      function.set_optimized_call_site_count(call_site_count);
-
-      // Use heuristics do decide if this call should be inlined.
-      if (!ShouldWeInline(function, size, call_site_count, constants_count)) {
-        // If size is larger than all thresholds, don't consider it again.
-        if ((size > FLAG_inlining_size_threshold) &&
-            (call_site_count > FLAG_inlining_callee_call_sites_threshold) &&
-            (size > FLAG_inlining_constant_arguments_min_size_threshold) &&
-            (size > FLAG_inlining_constant_arguments_max_size_threshold)) {
-          function.set_is_inlinable(false);
+        // Build succeeded so we restore the bailout jump.
+        inlined_ = true;
+        inlined_size_ += size;
+        if (is_recursive_call) {
+          inlined_recursive_call_ = true;
         }
         thread()->set_deopt_id(prev_deopt_id);
-        TRACE_INLINING(THR_Print("     Bailout: heuristics with "
-                                 "code size:  %" Pd ", "
-                                 "call sites: %" Pd ", "
-                                 "const args: %" Pd "\n",
-                                 size,
-                                 call_site_count,
-                                 constants_count));
-        PRINT_INLINING_TREE("Heuristic fail",
-            &call_data->caller, &function, call_data->call);
-        return false;
+
+        call_data->callee_graph = callee_graph;
+        call_data->parameter_stubs = param_stubs;
+        call_data->exit_collector = exit_collector;
+
+        // When inlined, we add the guarded fields of the callee to the caller's
+        // list of guarded fields.
+        for (intptr_t i = 0;
+             i < callee_graph->guarded_fields()->length();
+             ++i) {
+          FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(),
+                                        (*callee_graph->guarded_fields())[i]);
+        }
+        // When inlined, we add the deferred prefixes of the callee to the
+        // caller's list of deferred prefixes.
+        caller_graph()->AddToDeferredPrefixes(
+            callee_graph->deferred_prefixes());
+
+        FlowGraphInliner::SetInliningId(callee_graph,
+            inliner_->NextInlineId(callee_graph->function(),
+                                   call_data->caller_inlining_id_));
+        TRACE_INLINING(THR_Print("     Success\n"));
+        PRINT_INLINING_TREE(NULL,
+            &call_data->caller, &function, call);
+        return true;
+      } else {
+        error = isolate()->object_store()->sticky_error();
+        isolate()->object_store()->clear_sticky_error();
+        ASSERT(error.IsLanguageError());
+
+        if (LanguageError::Cast(error).kind() == Report::kBailout) {
+          thread()->set_deopt_id(prev_deopt_id);
+          TRACE_INLINING(THR_Print("     Bailout: %s\n",
+                                   error.ToErrorCString()));
+          PRINT_INLINING_TREE("Bailout",
+              &call_data->caller, &function, call);
+          return false;
+        } else {
+          // Fall through to exit long jump scope.
+        }
       }
-
-      // Inline dispatcher methods regardless of the current depth.
-      const intptr_t depth =
-          (function.IsInvokeFieldDispatcher() ||
-           function.IsNoSuchMethodDispatcher()) ? 0 : inlining_depth_;
-      collected_call_sites_->FindCallSites(callee_graph, depth, &inlined_info_);
-
-      // Add the function to the cache.
-      if (!in_cache) {
-        function_cache_.Add(parsed_function);
-      }
-
-      // Build succeeded so we restore the bailout jump.
-      inlined_ = true;
-      inlined_size_ += size;
-      if (is_recursive_call) {
-        inlined_recursive_call_ = true;
-      }
-      thread()->set_deopt_id(prev_deopt_id);
-
-      call_data->callee_graph = callee_graph;
-      call_data->parameter_stubs = param_stubs;
-      call_data->exit_collector = exit_collector;
-
-      // When inlined, we add the guarded fields of the callee to the caller's
-      // list of guarded fields.
-      for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) {
-        FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(),
-                                      (*callee_graph->guarded_fields())[i]);
-      }
-      // When inlined, we add the deferred prefixes of the callee to the
-      // caller's list of deferred prefixes.
-      caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes());
-
-      FlowGraphInliner::SetInliningId(callee_graph,
-          inliner_->NextInlineId(callee_graph->function(),
-                                 call_data->caller_inlining_id_));
-      TRACE_INLINING(THR_Print("     Success\n"));
-      PRINT_INLINING_TREE(NULL,
-          &call_data->caller, &function, call);
-      return true;
-    } else {
-      Error& error = Error::Handle();
-      error = isolate()->object_store()->sticky_error();
-      isolate()->object_store()->clear_sticky_error();
-      thread()->set_deopt_id(prev_deopt_id);
-      TRACE_INLINING(THR_Print("     Bailout: %s\n", error.ToErrorCString()));
-      PRINT_INLINING_TREE("Bailout",
-          &call_data->caller, &function, call);
-      return false;
     }
+
+    // Propagate a compile-time error. Only in precompilation do we attempt to
+    // inline functions that have never been compiled before; when JITing we
+    // should only see compile-time errors in unoptimized compilation.
+    ASSERT(Compiler::always_optimize());
+    Thread::Current()->long_jump_base()->Jump(1, error);
+    UNREACHABLE();
+    return false;
   }
 
   void PrintInlinedInfo(const Function& top) {
@@ -1105,14 +1128,13 @@
           call->ArgumentAt(0)->OriginalDefinition()->AsAllocateObject();
       if ((alloc != NULL) && !alloc->closure_function().IsNull()) {
         target ^= alloc->closure_function().raw();
-        ASSERT(target.signature_class() == alloc->cls().raw());
+        ASSERT(alloc->cls().IsClosureClass());
       }
       ConstantInstr* constant =
           call->ArgumentAt(0)->OriginalDefinition()->AsConstant();
       if ((constant != NULL) &&
-          constant->value().IsInstance() &&
-          Instance::Cast(constant->value()).IsClosure()) {
-        target ^= Closure::function(Instance::Cast(constant->value()));
+          constant->value().IsClosure()) {
+        target ^= Closure::Cast(constant->value()).function();
       }
 
       if (target.IsNull()) {
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index c36bf53..ecc3350 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -225,14 +225,6 @@
       // finalized yet.
       return false;
     }
-    // Do not run the optimization below if in background compilation since
-    // resolution of method extractor functions may create new signature
-    // classes.
-    // TODO(regis): Remove test for background compilation once signature
-    // classes are not generated any longer.
-    if (!thread()->IsMutatorThread()) {
-      return false;
-    }
     const Array& args_desc_array = Array::Handle(Z,
         ArgumentsDescriptor::New(call->ArgumentCount(),
                                  call->argument_names()));
@@ -284,12 +276,7 @@
   }
 
   // Check if getter or setter in function's class and class is currently leaf.
-  // Do not run the optimization below if in background compilation since
-  // resolution of getter functions may create new signature classes.
-  // TODO(regis): Remove test for background compilation once signature classes
-  // are not generated any longer.
-  if (thread()->IsMutatorThread() &&
-      FLAG_guess_icdata_cid &&
+  if (FLAG_guess_icdata_cid &&
       ((call->token_kind() == Token::kGET) ||
           (call->token_kind() == Token::kSET))) {
     const Class& owner_class = Class::Handle(Z, function().Owner());
@@ -3904,7 +3891,8 @@
     ZoneGrowableArray<intptr_t>* results) const {
   ASSERT(results->is_empty());
   ASSERT(ic_data.NumArgsTested() == 1);  // Unary checks only.
-  if (!type.IsInstantiated() || type.IsMalformedOrMalbounded()) {
+  if (type.IsFunctionType() || type.IsDartFunctionType() ||
+      !type.IsInstantiated() || type.IsMalformedOrMalbounded()) {
     return Bool::null();
   }
   const Class& type_class = Class::Handle(Z, type.type_class());
@@ -3959,9 +3947,9 @@
   ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
   // Requires CHA.
   if (!type.IsInstantiated()) return false;
+  // Function types have different type checking rules.
+  if (type.IsFunctionType()) return false;
   const Class& type_class = Class::Handle(type.type_class());
-  // Signature classes have different type checking rules.
-  if (type_class.IsSignatureClass()) return false;
   // Could be an interface check?
   if (CHA::IsImplemented(type_class)) return false;
   // Check if there are subclasses.
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 7ea528a..85371e0 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -489,15 +489,15 @@
       cid_ = kDynamicCid;
     } else if (type_->IsVoidType()) {
       cid_ = kNullCid;
+    } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) {
+      cid_ = kClosureCid;
     } else if (type_->HasResolvedTypeClass()) {
       const Class& type_class = Class::Handle(type_->type_class());
       Thread* thread = Thread::Current();
       CHA* cha = thread->cha();
-      // Don't infer a cid from an abstract type for signature classes since
-      // there can be multiple compatible classes with different cids.
-      if (!type_class.IsSignatureClass() &&
-          !CHA::IsImplemented(type_class) &&
-          !CHA::HasSubclasses(type_class)) {
+      // Don't infer a cid from an abstract type since there can be multiple
+      // compatible classes with different cids.
+      if (!CHA::IsImplemented(type_class) && !CHA::HasSubclasses(type_class)) {
         if (type_class.IsPrivate()) {
           // Type of a private class cannot change through later loaded libs.
           cid_ = type_class.id();
@@ -978,10 +978,11 @@
 
 CompileType AllocateObjectInstr::ComputeType() const {
   if (!closure_function().IsNull()) {
-    ASSERT(cls().raw() == closure_function().signature_class());
+    ASSERT(cls().id() == kClosureCid);
     return CompileType(CompileType::kNonNullable,
-                       cls().id(),
-                       &Type::ZoneHandle(cls().SignatureType()));
+                       kClosureCid,
+                       &FunctionType::ZoneHandle(
+                           closure_function().SignatureType()));
   }
   // TODO(vegorov): Incorporate type arguments into the returned type.
   return CompileType::FromCid(cls().id());
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index f5eef18..9b1e89c 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -27,6 +27,11 @@
 const intptr_t kSmiMax = (static_cast<intptr_t>(1) << kSmiBits) - 1;
 const intptr_t kSmiMin =  -(static_cast<intptr_t>(1) << kSmiBits);
 
+// Hard coded from above but for 32-bit architectures.
+const intptr_t kSmiBits32 = kBitsPerInt32 - 2;
+const intptr_t kSmiMax32 = (static_cast<intptr_t>(1) << kSmiBits32) - 1;
+const intptr_t kSmiMin32 =  -(static_cast<intptr_t>(1) << kSmiBits32);
+
 #define kPosInfinity bit_cast<double>(DART_UINT64_C(0x7ff0000000000000))
 #define kNegInfinity bit_cast<double>(DART_UINT64_C(0xfff0000000000000))
 
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index 592cf07..2334bbc 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -435,6 +435,13 @@
     return table.Release().raw();
   }
 
+  template<typename Table>
+  static RawArray* New(const Array& array) {
+    Table table(array.raw());
+    table.Initialize();
+    return table.Release().raw();
+  }
+
   // Clears 'to' and inserts all elements from 'from', in iteration order.
   // The tables must have the same user payload size.
   template<typename From, typename To>
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 15635bc..12663f3 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -2734,7 +2734,7 @@
   if (!compiler->is_optimizing()) {
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -2760,7 +2760,7 @@
     // code that matches backwards from the end of the pattern.
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -3689,6 +3689,7 @@
     Report::MessageF(Report::kError,
                      Script::Handle(function().script()),
                      function().token_pos(),
+                     Report::AtLocation,
                      "native function '%s' (%" Pd " arguments) cannot be found",
                      native_name().ToCString(),
                      function().NumParameters());
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 0a40848..60e25a9 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -38,47 +38,6 @@
 class RangeBoundary;
 class UnboxIntegerInstr;
 
-// These token positions are used to classify instructions that can't be
-// directly tied to an actual source position.
-#define CLASSIFYING_TOKEN_POSITIONS(V)                                         \
-    V(Private, -2)                                                             \
-    V(Box, -3)                                                                 \
-    V(ParallelMove, -4)                                                        \
-    V(TempMove, -5)                                                            \
-    V(Constant, -6)                                                            \
-    V(PushArgument, -7)                                                        \
-    V(ControlFlow, -8)                                                         \
-    V(Context, -9)
-
-// COMPILE_ASSERT that all CLASSIFYING_TOKEN_POSITIONS are less than
-// Scanner::kNoSourcePos.
-#define SANITY_CHECK_VALUES(name, value)                                       \
-  COMPILE_ASSERT(value < Scanner::kNoSourcePos);
-  CLASSIFYING_TOKEN_POSITIONS(SANITY_CHECK_VALUES);
-#undef SANITY_CHECK_VALUES
-
-class ClassifyingTokenPositions : public AllStatic {
- public:
-#define DEFINE_VALUES(name, value)                                             \
-  static const intptr_t k##name = value;
-  CLASSIFYING_TOKEN_POSITIONS(DEFINE_VALUES);
-#undef DEFINE_VALUES
-
-  static const char* ToCString(intptr_t token_pos) {
-    ASSERT(token_pos < 0);
-    switch (token_pos) {
-      case Scanner::kNoSourcePos: return "NoSource";
-#define DEFINE_CASE(name, value)                                               \
-      case value: return #name;
-      CLASSIFYING_TOKEN_POSITIONS(DEFINE_CASE);
-#undef DEFINE_CASE
-      default:
-        UNIMPLEMENTED();
-        return NULL;
-    }
-  }
-};
-
 // CompileType describes type of the value produced by the definition.
 //
 // It captures the following properties:
@@ -668,7 +627,7 @@
   const ICData* GetICData(
       const ZoneGrowableArray<const ICData*>& ic_data_array) const;
 
-  virtual intptr_t token_pos() const { return Scanner::kNoSourcePos; }
+  virtual intptr_t token_pos() const { return Token::kNoSourcePos; }
 
   virtual intptr_t InputCount() const = 0;
   virtual Value* InputAt(intptr_t i) const = 0;
@@ -3312,7 +3271,7 @@
 class LoadLocalInstr : public TemplateDefinition<0, NoThrow> {
  public:
   LoadLocalInstr(const LocalVariable& local,
-                 intptr_t token_pos = Scanner::kNoSourcePos)
+                 intptr_t token_pos)
       : local_(local), is_last_(false), token_pos_(token_pos) { }
 
   DECLARE_INSTRUCTION(LoadLocal)
@@ -3428,7 +3387,7 @@
  public:
   StoreLocalInstr(const LocalVariable& local,
                   Value* value,
-                  intptr_t token_pos = Scanner::kNoSourcePos)
+                  intptr_t token_pos)
       : local_(local), is_dead_(false), is_last_(false), token_pos_(token_pos) {
     SetInputAt(0, value);
   }
@@ -3757,7 +3716,7 @@
  public:
   StoreStaticFieldInstr(const Field& field,
                         Value* value,
-                        intptr_t token_pos = Scanner::kNoSourcePos)
+                        intptr_t token_pos)
       : field_(field),
         token_pos_(token_pos) {
     ASSERT(field.IsZoneHandle());
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 9120195..c585771 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -1834,7 +1834,7 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+    compiler->GenerateCall(Token::kNoSourcePos,  // No token position.
                            stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
@@ -6651,7 +6651,7 @@
     // may be inserted before this instruction.
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -6854,7 +6854,7 @@
   const Register result = locs()->out(0).reg();
   __ PushObject(Object::null_object());
   __ Push(typed_data);
-  compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
+  compiler->GenerateRuntimeCall(Token::kNoSourcePos,  // No token position.
                                 deopt_id(),
                                 kGrowRegExpStackRuntimeEntry,
                                 1,
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index 05ce132..18d82cd 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -1686,7 +1686,7 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+    compiler->GenerateCall(Token::kNoSourcePos,  // No token position.
                            stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
@@ -5414,7 +5414,7 @@
     // may be inserted before this instruction.
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -5616,7 +5616,7 @@
   const Register result = locs()->out(0).reg();
   __ PushObject(Object::null_object());
   __ Push(typed_data);
-  compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
+  compiler->GenerateRuntimeCall(Token::kNoSourcePos,  // No token position.
                                 deopt_id(),
                                 kGrowRegExpStackRuntimeEntry,
                                 1,
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 0c2f782..3ceb83c 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -1675,7 +1675,7 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+    compiler->GenerateCall(Token::kNoSourcePos,  // No token position.
                            stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
@@ -6551,7 +6551,7 @@
     // may be inserted before this instruction.
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -6862,7 +6862,7 @@
   const Register result = locs()->out(0).reg();
   __ PushObject(Object::null_object());
   __ pushl(typed_data);
-  compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
+  compiler->GenerateRuntimeCall(Token::kNoSourcePos,  // No token position.
                                 deopt_id(),
                                 kGrowRegExpStackRuntimeEntry,
                                 1,
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index e403445..ebdd48b 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -1859,7 +1859,7 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+    compiler->GenerateCall(Token::kNoSourcePos,  // No token position.
                            stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
@@ -5389,7 +5389,7 @@
     // may be inserted before this instruction.
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -5591,7 +5591,7 @@
   __ LoadObject(TMP, Object::null_object());
   __ sw(TMP, Address(SP, 1 * kWordSize));
   __ sw(typed_data, Address(SP, 0 * kWordSize));
-  compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
+  compiler->GenerateRuntimeCall(Token::kNoSourcePos,  // No token position.
                                 deopt_id(),
                                 kGrowRegExpStackRuntimeEntry,
                                 1,
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 7ca52de..8c164fc 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -1685,7 +1685,7 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateCall(Scanner::kNoSourcePos,  // No token position.
+    compiler->GenerateCall(Token::kNoSourcePos,  // No token position.
                            stub_entry,
                            RawPcDescriptors::kOther,
                            locs);
@@ -6192,7 +6192,7 @@
     // may be inserted before this instruction.
     compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt,
                                    GetDeoptId(),
-                                   Scanner::kNoSourcePos);
+                                   Token::kNoSourcePos);
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -6444,7 +6444,7 @@
   const Register result = locs()->out(0).reg();
   __ PushObject(Object::null_object());
   __ pushq(typed_data);
-  compiler->GenerateRuntimeCall(Scanner::kNoSourcePos,  // No token position.
+  compiler->GenerateRuntimeCall(Token::kNoSourcePos,  // No token position.
                                 deopt_id(),
                                 kGrowRegExpStackRuntimeEntry,
                                 1,
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index c3356b3..748c8c4 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -68,19 +68,19 @@
   ASSERT(!func.IsNull());                                                      \
   func.set_is_intrinsic(true);
 
-  // Set up all core lib functions that can be intrisified.
+  // Set up all core lib functions that can be intrinsified.
   lib = Library::CoreLibrary();
   ASSERT(!lib.IsNull());
   CORE_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
   CORE_INTEGER_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
   GRAPH_CORE_INTRINSICS_LIST(SETUP_FUNCTION);
 
-  // Set up all math lib functions that can be intrisified.
+  // Set up all math lib functions that can be intrinsified.
   lib = Library::MathLibrary();
   ASSERT(!lib.IsNull());
   MATH_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
 
-  // Set up all dart:typed_data lib functions that can be intrisified.
+  // Set up all dart:typed_data lib functions that can be intrinsified.
   lib = Library::TypedDataLibrary();
   ASSERT(!lib.IsNull());
   TYPED_DATA_LIB_INTRINSIC_LIST(SETUP_FUNCTION);
@@ -304,7 +304,7 @@
       new LoadFieldInstr(new Value(array),
                          length_offset,
                          Type::ZoneHandle(Type::SmiType()),
-                         Scanner::kNoSourcePos));
+                         Token::kNoSourcePos));
   builder->AddInstruction(
       new CheckArrayBoundInstr(new Value(length),
                                new Value(index),
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index bb3121f..1b49169 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -1537,12 +1537,10 @@
   Label fall_through;
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
+  __ CompareImmediate(R1, kClosureCid);
+  __ b(&fall_through, EQ);  // Instance is a closure.
   __ LoadClassById(R2, R1);
-
   // R2: class of instance (R0).
-  __ ldr(R3, FieldAddress(R2, Class::signature_function_offset()));
-  __ CompareObject(R3, Object::null_object());
-  __ b(&fall_through, NE);
 
   __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset()));
   __ CompareImmediate(R3, 0);
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index 265d5d4..3c28ec1 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -1614,11 +1614,10 @@
   Label fall_through;
   __ ldr(R0, Address(SP, 0 * kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
+  __ CompareImmediate(R1, kClosureCid);
+  __ b(&fall_through, EQ);  // Instance is a closure.
   __ LoadClassById(R2, R1);
   // R2: class of instance (R0).
-  __ ldr(R3, FieldAddress(R2, Class::signature_function_offset()));
-  __ CompareObject(R3, Object::null_object());
-  __ b(&fall_through, NE);
 
   __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword);
   __ CompareImmediate(R3, 0);
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 61620c8..9f4c622 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -1680,19 +1680,16 @@
   Label fall_through;
   __ movl(EAX, Address(ESP, + 1 * kWordSize));
   __ LoadClassIdMayBeSmi(EDI, EAX);
+  __ cmpl(EDI, Immediate(kClosureCid));
+  __ j(EQUAL, &fall_through, Assembler::kNearJump);  // Instance is a closure.
   __ LoadClassById(EBX, EDI);
   // EBX: class of instance (EAX).
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
-  __ movl(EDI, FieldAddress(EBX, Class::signature_function_offset()));
-  __ cmpl(EDI, raw_null);
-  __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
 
   __ movzxw(EDI, FieldAddress(EBX, Class::num_type_arguments_offset()));
   __ cmpl(EDI, Immediate(0));
   __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
   __ movl(EAX, FieldAddress(EBX, Class::canonical_types_offset()));
-  __ cmpl(EAX, raw_null);
+  __ CompareObject(EAX, Object::null_object());
   __ j(EQUAL, &fall_through, Assembler::kNearJump);  // Not yet set.
   __ ret();
 
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 2be1114..1e289cc 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -1646,12 +1646,10 @@
   Label fall_through;
   __ lw(T0, Address(SP, 0 * kWordSize));
   __ LoadClassIdMayBeSmi(T1, T0);
+  __ BranchEqual(T1, Immediate(kClosureCid), &fall_through);
   __ LoadClassById(T2, T1);
   // T2: class of instance (T0).
 
-  __ lw(T1, FieldAddress(T2, Class::signature_function_offset()));
-  __ BranchNotEqual(T1, Object::null_object(), &fall_through);
-
   __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset()));
   __ BranchNotEqual(T1, Immediate(0), &fall_through);
 
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index e3f2ca4..d9eb08b 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -1536,11 +1536,11 @@
   __ LoadClassIdMayBeSmi(RCX, RAX);
 
   // RCX: untagged cid of instance (RAX).
+  __ cmpq(RCX, Immediate(kClosureCid));
+  __ j(EQUAL, &fall_through, Assembler::kNearJump);  // Instance is a closure.
+
   __ LoadClassById(RDI, RCX);
   // RDI: class of instance (RAX).
-  __ movq(RCX, FieldAddress(RDI, Class::signature_function_offset()));
-  __ CompareObject(RCX, Object::null_object());
-  __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
 
   __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset()));
   __ cmpq(RCX, Immediate(0));
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 5c764df..a62ac0e 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -58,6 +58,9 @@
             "Pause isolates before starting.");
 DEFINE_FLAG(bool, pause_isolates_on_exit, false,
             "Pause isolates exiting.");
+DEFINE_FLAG(bool, pause_isolates_on_unhandled_exceptions, false,
+            "Pause isolates on unhandled exceptions.");
+
 DEFINE_FLAG(bool, break_at_isolate_spawn, false,
             "Insert a one-time breakpoint at the entrypoint for all spawned "
             "isolates");
@@ -1070,6 +1073,9 @@
   if (!ServiceIsolate::IsServiceIsolate(this)) {
     message_handler()->set_pause_on_start(FLAG_pause_isolates_on_start);
     message_handler()->set_pause_on_exit(FLAG_pause_isolates_on_exit);
+    if (FLAG_pause_isolates_on_unhandled_exceptions) {
+      debugger()->SetExceptionPauseInfo(kPauseOnUnhandledExceptions);
+    }
   }
   IsolateSpawnState* state = spawn_state();
   if (state != NULL) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 8e84d00..56cf82e 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -718,6 +718,7 @@
   RawCode* ic_miss_code_;
   ClassTable class_table_;
   bool single_step_;
+  bool skip_step_;  // skip the next single step.
 
   ThreadRegistry* thread_registry_;
   Dart_MessageNotifyCallback message_notify_callback_;
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index d576beb..b7f6589 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -13,7 +13,8 @@
 
 DEFINE_FLAG(charp, isolate_log_filter, NULL,
             "Log isolates whose name include the filter. "
-            "Default: service isolate log messages are suppressed.");
+            "Default: service isolate log messages are suppressed "
+            "(specify 'vm-service' to log them).");
 
 Log::Log(LogPrinter printer)
     : printer_(printer),
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 7f4bbec..6f2d172 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -72,6 +72,7 @@
                                      false,  // Not native.
                                      cls,
                                      0));  // No token position.
+  function.set_result_type(Type::Handle(Type::DynamicType()));
   function.set_is_debuggable(false);
   function.set_is_visible(false);
   function.AttachCode(code);
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 54f40b4..195b2c6 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -203,9 +203,9 @@
     // TODO(johnmccutchan): Move port -> handler map out of Dart and into the
     // VM, that way we can lookup the handler without invoking Dart code.
     msg_handler = DartLibraryCalls::LookupHandler(current->dest_port());
-    if (msg_handler.IsInstance() && Instance::Cast(msg_handler).IsClosure()) {
+    if (msg_handler.IsClosure()) {
       // Grab function from closure.
-      msg_handler = Closure::function(Instance::Cast(msg_handler));
+      msg_handler = Closure::Cast(msg_handler).function();
     }
     if (msg_handler.IsFunction()) {
       const Function& function = Function::Cast(msg_handler);
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index 4d0a348..ddc649b 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -334,18 +334,8 @@
   String& name = String::Handle(Z);
   while (it.HasNext()) {
     cls = it.GetNextClass();
-    if (cls.IsSignatureClass()) {
-      if (!cls.IsCanonicalSignatureClass()) {
-        // This is a typedef.  Add it to the list of class names.
-        name = cls.UserVisibleName();
-        names.Add(name);
-      } else {
-        // Skip canonical signature classes.  These are not named.
-      }
-    } else {
-      name = cls.UserVisibleName();
-      names.Add(name);
-    }
+    name = cls.UserVisibleName();
+    names.Add(name);
   }
   return Api::NewHandle(T, Array::MakeArray(names));
 }
@@ -362,7 +352,7 @@
 
   ASSERT(ClassFinalizer::AllClassesFinalized());
 
-  RawFunction* rf = Closure::function(closure_obj);
+  RawFunction* rf = Closure::Cast(closure_obj).function();
   return Api::NewHandle(T, rf);
 }
 
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 3fb2f74..0655a69 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -107,7 +107,7 @@
       // Retrieve the receiver from the context.
       const Object& closure = Object::Handle(ArgAt(0));
       const Context& context =
-          Context::Handle(Closure::context(Instance::Cast(closure)));
+          Context::Handle(Closure::Cast(closure).context());
       return context.At(0);
     }
     return ArgAt(NumHiddenArgs(function_bits));
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 730d560..df6fde0 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -141,6 +141,8 @@
 RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::code_source_map_class_ =
+    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::stackmap_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::var_descriptors_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
@@ -613,6 +615,9 @@
   cls = Class::New<PcDescriptors>();
   pc_descriptors_class_ = cls.raw();
 
+  cls = Class::New<CodeSourceMap>();
+  code_source_map_class_ = cls.raw();
+
   cls = Class::New<Stackmap>();
   stackmap_class_ = cls.raw();
 
@@ -945,6 +950,7 @@
   SET_CLASS_NAME(code, Code);
   SET_CLASS_NAME(instructions, Instructions);
   SET_CLASS_NAME(object_pool, ObjectPool);
+  SET_CLASS_NAME(code_source_map, CodeSourceMap);
   SET_CLASS_NAME(pc_descriptors, PcDescriptors);
   SET_CLASS_NAME(stackmap, Stackmap);
   SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
@@ -1122,6 +1128,8 @@
 
   // Setup type class early in the process.
   const Class& type_cls = Class::Handle(zone, Class::New<Type>());
+  const Class& function_type_cls = Class::Handle(zone,
+                                                 Class::New<FunctionType>());
   const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
   const Class& type_parameter_cls = Class::Handle(zone,
                                                   Class::New<TypeParameter>());
@@ -1176,7 +1184,7 @@
   // could expect. Use with caution.
   type ^= Type::New(Object::Handle(zone, cls.raw()),
                     TypeArguments::Handle(zone),
-                    Scanner::kNoSourcePos);
+                    Token::kNoSourcePos);
   type.SetIsFinalized();
   type ^= type.Canonicalize();
   object_store->set_array_type(type);
@@ -1284,6 +1292,9 @@
   RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
   pending_classes.Add(type_cls);
 
+  RegisterPrivateClass(function_type_cls, Symbols::FunctionType(), core_lib);
+  pending_classes.Add(function_type_cls);
+
   RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
   pending_classes.Add(type_ref_cls);
 
@@ -1321,15 +1332,14 @@
   RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
   pending_classes.Add(cls);
 
-  // Abstract super class for all signature classes.
-  cls = Class::New<Instance>(kIllegalCid);
-  cls.set_num_type_arguments(0);
+  // Class that represents the Dart class _Closure and C++ class Closure.
+  cls = Class::New<Closure>();
+  cls.set_type_arguments_field_offset(Closure::type_arguments_offset());
+  cls.set_num_type_arguments(0);  // Although a closure has type_arguments_.
   cls.set_num_own_type_arguments(0);
-  cls.set_is_prefinalized();
-  RegisterPrivateClass(cls, Symbols::FunctionImpl(), core_lib);
+  RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
   pending_classes.Add(cls);
-  type = Type::NewNonParameterizedType(cls);
-  object_store->set_function_impl_type(type);
+  object_store->set_closure_class(cls);
 
   cls = Class::New<WeakProperty>();
   object_store->set_weak_property_class(cls);
@@ -1606,6 +1616,7 @@
 
   cls = Class::New<LibraryPrefix>();
   cls = Class::New<Type>();
+  cls = Class::New<FunctionType>();
   cls = Class::New<TypeRef>();
   cls = Class::New<TypeParameter>();
   cls = Class::New<BoundedType>();
@@ -1660,6 +1671,9 @@
   cls = Class::New<Double>();
   object_store->set_double_class(cls);
 
+  cls = Class::New<Closure>();
+  object_store->set_closure_class(cls);
+
   cls = Class::New<Bigint>();
   object_store->set_bigint_class(cls);
 
@@ -1953,41 +1967,11 @@
 }
 
 
-RawType* Class::SignatureType() const {
-  ASSERT(IsSignatureClass());
-  Zone* zone = Thread::Current()->zone();
-  const Function& function = Function::Handle(zone, signature_function());
-  ASSERT(!function.IsNull());
-  if (function.signature_class() != raw()) {
-    // This class is a function type alias. Return the canonical signature type.
-    const Class& canonical_signature_class =
-        Class::Handle(zone, function.signature_class());
-    return canonical_signature_class.SignatureType();
-  }
-  const Type& signature_type = Type::Handle(zone, CanonicalType());
-  if (!signature_type.IsNull()) {
-    return signature_type.raw();
-  }
-  // A signature class extends class Instance and is parameterized in the same
-  // way as the owner class of its non-static signature function.
-  // It is not type parameterized if its signature function is static.
-  // See Class::NewSignatureClass() for the setup of its type parameters.
-  // During type finalization, the type arguments of the super class of the
-  // owner class of its signature function will be prepended to the type
-  // argument vector. Therefore, we only need to set the type arguments
-  // matching the type parameters here.
-  const TypeArguments& signature_type_arguments =
-      TypeArguments::Handle(zone, type_parameters());
-  // Return the still unfinalized signature type.
-  return Type::New(*this, signature_type_arguments, token_pos());
-}
-
-
 RawAbstractType* Class::RareType() const {
   const Type& type = Type::Handle(Type::New(
       *this,
       Object::null_type_arguments(),
-      Scanner::kNoSourcePos));
+      Token::kNoSourcePos));
   return ClassFinalizer::FinalizeType(*this,
                                       type,
                                       ClassFinalizer::kCanonicalize);
@@ -1999,7 +1983,7 @@
   const Type& type = Type::Handle(Type::New(
       *this,
       args,
-      Scanner::kNoSourcePos));
+      Token::kNoSourcePos));
   return ClassFinalizer::FinalizeType(*this,
                                       type,
                                       ClassFinalizer::kCanonicalize);
@@ -2037,7 +2021,7 @@
   result.set_num_type_arguments(0);
   result.set_num_own_type_arguments(0);
   result.set_num_native_fields(0);
-  result.set_token_pos(Scanner::kNoSourcePos);
+  result.set_token_pos(Token::kNoSourcePos);
   result.InitEmptyFields();
   Isolate::Current()->RegisterClass(result);
   return result.raw();
@@ -2049,6 +2033,7 @@
   Report::MessageF(Report::kError,
                    Script::Handle(cls.script()),
                    cls.token_pos(),
+                   Report::AtLocation,
                    "too many type parameters declared in class '%s' or in its "
                    "super classes",
                    String::Handle(cls.Name()).ToCString());
@@ -2180,6 +2165,8 @@
       set.Insert(func);
     }
     StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
+  } else {
+    StorePointer(&raw_ptr()->functions_hash_table_, Array::null());
   }
 }
 
@@ -2457,14 +2444,6 @@
   cls = raw();
   intptr_t num_type_args = 0;
   do {
-    if (cls.IsSignatureClass()) {
-      Function& signature_fun = Function::Handle(zone);
-      signature_fun ^= cls.signature_function();
-      if (!signature_fun.is_static() &&
-          !signature_fun.HasInstantiatedSignature()) {
-        cls = signature_fun.Owner();
-      }
-    }
     // Calling NumOwnTypeArguments() on a mixin application class will setup the
     // type parameters if not already done.
     num_type_args += cls.NumOwnTypeArguments();
@@ -2474,8 +2453,12 @@
       break;
     }
     sup_type = cls.super_type();
-    ClassFinalizer::ResolveTypeClass(cls, sup_type);
+    // A BoundedType, TypeRef, or FunctionType can appear as type argument of
+    // sup_type, but not as sup_type itself.
+    ASSERT(sup_type.IsType());
+    sup_type = ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
     cls = sup_type.type_class();
+    ASSERT(!cls.IsTypedefClass());
   } while (true);
   set_num_type_arguments(num_type_args);
   return num_type_args;
@@ -2527,6 +2510,7 @@
 
 
 void Class::CalculateFieldOffsets() const {
+  ASSERT(id() != kClosureCid);  // Class _Closure is prefinalized.
   Array& flds = Array::Handle(fields());
   const Class& super = Class::Handle(SuperClass());
   intptr_t offset = 0;
@@ -2694,7 +2678,7 @@
                   false,  // Not external.
                   false,  // Not native.
                   owner,
-                  0));    // token_pos
+                  ClassifyingTokenPositions::kMethodExtractor));  // token_pos
 
   // Initialize signature: receiver is a single fixed parameter.
   const intptr_t kNumParameters = 1;
@@ -2740,9 +2724,7 @@
 
 void Class::Finalize() const {
   ASSERT(Thread::Current()->IsMutatorThread());
-  // Even if all regular classes are prefinalized (precompilation), signature
-  // classes may be added later when we encounter local functions.
-  ASSERT(IsSignatureClass() || !Isolate::Current()->all_classes_finalized());
+  ASSERT(!Isolate::Current()->all_classes_finalized());
   ASSERT(!is_finalized());
   // Prefinalized classes have a VM internal representation and no Dart fields.
   // Their instance size  is precomputed and field offsets are known.
@@ -2898,6 +2880,7 @@
           *error,  // No previous error.
           Script::Handle(patch.script()),
           func.token_pos(),
+          Report::AtLocation,
           Report::kError,
           Heap::kNew,
           "signature mismatch: '%s'", member_name.ToCString());
@@ -2943,6 +2926,7 @@
           *error,  // No previous error.
           Script::Handle(patch.script()),
           field.token_pos(),
+          Report::AtLocation,
           Report::kError,
           Heap::kNew,
           "duplicate field: %s", member_name.ToCString());
@@ -3107,7 +3091,7 @@
   result.set_num_type_arguments(kUnknownNumTypeArguments);
   result.set_num_own_type_arguments(kUnknownNumTypeArguments);
   result.set_num_native_fields(0);
-  result.set_token_pos(Scanner::kNoSourcePos);
+  result.set_token_pos(Token::kNoSourcePos);
   result.InitEmptyFields();
   Isolate::Current()->RegisterClass(result);
   return result.raw();
@@ -3125,79 +3109,12 @@
 }
 
 
-RawClass* Class::NewSignatureClass(const String& name,
-                                   const Function& signature_function,
-                                   const Script& script,
-                                   intptr_t token_pos) {
-  const Class& result = Class::Handle(New(name, script, token_pos));
-  // Instances of a signature class can only be closures.
-  result.set_instance_size(Closure::InstanceSize());
-  result.set_next_field_offset(Closure::NextFieldOffset());
-  // Signature classes extend the _FunctionImpl class.
-  result.set_super_type(Type::Handle(
-      Isolate::Current()->object_store()->function_impl_type()));
-  result.set_is_synthesized_class();
-  result.set_type_arguments_field_offset(Closure::type_arguments_offset());
-  if (!signature_function.IsNull()) {
-    result.PatchSignatureFunction(signature_function);
-  }
-  return result.raw();
-}
-
-
-void Class::PatchSignatureFunction(const Function& signature_function) const {
-  ASSERT(!signature_function.IsNull());
-  set_signature_function(signature_function);
-  const Class& owner_class = Class::Handle(signature_function.Owner());
-  ASSERT(!owner_class.IsNull());
-  // A signature class extends class Instance and is either not parameterized or
-  // parameterized with exactly the same list of type parameters as the owner
-  // class of its function.
-  // In case of a function type alias, the function owner is the alias class,
-  // which is also the signature class. The signature class is therefore
-  // parameterized according to the alias class declaration, even if the
-  // function type is not generic.
-  // Otherwise, if the function is static or if its signature type is
-  // non-generic, i.e. it does not depend on any type parameter of the owner
-  // class, then the signature class is not parameterized, although the owner
-  // class may be.
-  if (owner_class.raw() == raw()) {
-    // This signature class is an alias, which cannot be the canonical
-    // signature class for this signature function.
-    ASSERT(!IsCanonicalSignatureClass());
-    // Do not modify the declared type parameters of the alias, even if unused.
-  } else {
-    // Copy the type parameters only for an instance function type that is not
-    // instantiated, i.e. that depends on the type parameters of the owner
-    // class.
-    // TODO(regis): Verify that it is not a problem for the copied type
-    // parameters to refer to the owner class rather than to the signature
-    // class. In other words, uninstantiated function types should only get
-    // instantiated by the owner class as instantiator and never by the
-    // signature class itself.
-    TypeArguments& type_parameters = TypeArguments::Handle();
-    if (!signature_function.is_static() &&
-        (owner_class.NumTypeParameters() > 0) &&
-        !signature_function.HasInstantiatedSignature()) {
-      type_parameters = owner_class.type_parameters();
-    }
-    set_type_parameters(type_parameters);
-    if (signature_function.signature_class() == Object::null()) {
-      // Make this signature class the canonical signature class.
-      signature_function.set_signature_class(*this);
-      ASSERT(IsCanonicalSignatureClass());
-    }
-  }
-  set_is_prefinalized();
-}
-
-
 RawClass* Class::NewNativeWrapper(const Library& library,
                                   const String& name,
                                   int field_count) {
   Class& cls = Class::Handle(library.LookupClass(name));
   if (cls.IsNull()) {
-    cls = New(name, Script::Handle(), Scanner::kNoSourcePos);
+    cls = New(name, Script::Handle(), Token::kNoSourcePos);
     cls.SetFields(Object::empty_array());
     cls.SetFunctions(Object::empty_array());
     // Set super class to Object.
@@ -3289,12 +3206,8 @@
 
 
 RawString* Class::GeneratePrettyName() const {
-  if (!IsCanonicalSignatureClass()) {
-    const String& name = String::Handle(Name());
-    return String::IdentifierPrettyName(name);
-  } else {
-    return Name();
-  }
+  const String& name = String::Handle(Name());
+  return String::IdentifierPrettyName(name);
 }
 
 
@@ -3343,6 +3256,8 @@
       return Symbols::Instructions().raw();
     case kObjectPoolCid:
       return Symbols::ObjectPool().raw();
+    case kCodeSourceMapCid:
+      return Symbols::CodeSourceMap().raw();
     case kPcDescriptorsCid:
       return Symbols::PcDescriptors().raw();
     case kStackmapCid:
@@ -3432,12 +3347,8 @@
     case kExternalTypedDataFloat64ArrayCid:
       return Symbols::Float64List().raw();
     default:
-      if (!IsCanonicalSignatureClass()) {
-        const String& name = String::Handle(Name());
-        return String::IdentifierPrettyName(name);
-      } else {
-        return Name();
-      }
+      const String& name = String::Handle(Name());
+      return String::IdentifierPrettyName(name);
   }
   UNREACHABLE();
 }
@@ -3449,14 +3360,14 @@
 
 
 void Class::set_token_pos(intptr_t token_pos) const {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
 
 intptr_t Class::ComputeEndTokenPos() const {
   // Return the begin token for synthetic classes.
-  if (IsSignatureClass() || IsMixinApplication() || IsTopLevel()) {
+  if (IsMixinApplication() || IsTopLevel()) {
     return token_pos();
   }
   const Script& scr = Script::Handle(script());
@@ -3639,7 +3550,7 @@
 
 
 RawType* Class::CanonicalType() const {
-  if (!IsGeneric()) {
+  if (!IsGeneric() && !IsClosureClass()) {
     return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
   }
   Array& types = Array::Handle();
@@ -3653,7 +3564,7 @@
 
 void Class::SetCanonicalType(const Type& type) const {
   ASSERT(type.IsCanonical());
-  if (!IsGeneric()) {
+  if (!IsGeneric() && !IsClosureClass()) {
     ASSERT((canonical_types() == Object::null()) ||
            (canonical_types() == type.raw()));  // Set during own finalization.
     set_canonical_types(type);
@@ -3667,7 +3578,7 @@
 }
 
 
-intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
+intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const {
   Thread* thread = Thread::Current();
   if (EnsureIsFinalized(thread) != Error::null()) {
     return -1;
@@ -3697,8 +3608,8 @@
 }
 
 
-RawType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
-  Type& type = Type::Handle();
+RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
+  AbstractType& type = AbstractType::Handle();
   if (idx == 0) {
     type = CanonicalType();
     if (!type.IsNull()) {
@@ -3745,12 +3656,6 @@
 }
 
 
-bool Class::IsCanonicalSignatureClass() const {
-  const Function& function = Function::Handle(signature_function());
-  return (!function.IsNull() && (function.signature_class() == raw()));
-}
-
-
 // If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T.
 // If test_kind == kIsMoreSpecificThan, checks if S is more specific than T.
 // Type S is specified by this class parameterized with 'type_arguments', and
@@ -3823,25 +3728,8 @@
                                      bound_error,
                                      space);
     }
-    const bool other_is_function_class = other.IsFunctionClass();
-    if (other.IsSignatureClass() || other_is_function_class) {
-      const Function& other_fun = Function::Handle(zone,
-                                                   other.signature_function());
-      if (thsi.IsSignatureClass()) {
-        if (other_is_function_class) {
-          return true;
-        }
-        // Check for two function types.
-        const Function& fun =
-            Function::Handle(zone, thsi.signature_function());
-        return fun.TypeTest(test_kind,
-                            type_arguments,
-                            other_fun,
-                            other_type_arguments,
-                            bound_error,
-                            space);
-      }
-      // Check if type S has a call() method of function type T.
+    if (other.IsFunctionClass()) {
+      // Check if type S has a call() method.
       Function& function =
           Function::Handle(zone, thsi.LookupDynamicFunction(Symbols::Call()));
       if (function.IsNull()) {
@@ -3853,15 +3741,7 @@
         }
       }
       if (!function.IsNull()) {
-        if (other_is_function_class ||
-            function.TypeTest(test_kind,
-                              type_arguments,
-                              other_fun,
-                              other_type_arguments,
-                              bound_error,
-                              space)) {
-              return true;
-            }
+        return true;
       }
     }
     // Check for 'direct super type' specified in the implements clause
@@ -4385,7 +4265,7 @@
 
 
 void UnresolvedClass::set_token_pos(intptr_t token_pos) const {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
@@ -4901,7 +4781,8 @@
   }
   // Cache lookup failed. Instantiate the type arguments.
   TypeArguments& result = TypeArguments::Handle();
-  result = InstantiateFrom(instantiator_type_arguments, bound_error);
+  result = InstantiateFrom(
+      instantiator_type_arguments, bound_error, NULL, Heap::kOld);
   if ((bound_error != NULL) && !bound_error->IsNull()) {
     return result.raw();
   }
@@ -5493,33 +5374,67 @@
 }
 
 
-RawClass* Function::signature_class() const {
+RawFunctionType* Function::SignatureType() const {
+  FunctionType& type = FunctionType::Handle();
+  const Object& obj = Object::Handle(raw_ptr()->data_);
   if (IsSignatureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data_);
-    ASSERT(obj.IsNull() || obj.IsClass());
-    return (obj.IsNull()) ? Class::null() : Class::Cast(obj).raw();
-  }
-  if (IsClosureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data_);
+    ASSERT(obj.IsNull() || obj.IsFunctionType());
+    type = obj.IsNull() ? FunctionType::null() : FunctionType::Cast(obj).raw();
+  } else {
+    ASSERT(IsClosureFunction());
     ASSERT(!obj.IsNull());
-    return ClosureData::Cast(obj).signature_class();
+    type = ClosureData::Cast(obj).signature_type();
   }
-  return Class::null();
+  if (type.IsNull()) {
+    // A function type is parameterized in the same way as the owner class of
+    // its non-static signature function.
+    // It is not type parameterized if its signature function is static.
+    // During type finalization, the type arguments of the super class of the
+    // owner class of its signature function will be prepended to the type
+    // argument vector. Therefore, we only need to set the type arguments
+    // matching the type parameters here.
+    // In case of a function type alias, the function owner is the alias class,
+    // i.e. the typedef. The signature type is therefore parameterized according
+    // to the alias class declaration, even if the function type is not generic.
+    // Otherwise, if the function is static or if its signature type is
+    // non-generic, i.e. it does not depend on any type parameter of the owner
+    // class, then the signature type is not parameterized, although the owner
+    // class may be. In this case, the scope class of the function type is reset
+    // to _Closure class as well as the owner of the signature function.
+    Class& scope_class = Class::Handle(Owner());
+    if (!scope_class.IsTypedefClass() &&
+        (is_static() ||
+         !scope_class.IsGeneric() ||
+         HasInstantiatedSignature())) {
+      scope_class = Isolate::Current()->object_store()->closure_class();
+      if (IsSignatureFunction()) {
+        set_owner(scope_class);
+        set_token_pos(Token::kNoSourcePos);
+      }
+    }
+    const TypeArguments& signature_type_arguments =
+        TypeArguments::Handle(scope_class.type_parameters());
+    // Return the still unfinalized signature type.
+    type = FunctionType::New(scope_class,
+                             signature_type_arguments,
+                             *this,
+                             token_pos());
+
+    SetSignatureType(type);
+  }
+  return type.raw();
 }
 
 
-void Function::set_signature_class(const Class& value) const {
+void Function::SetSignatureType(const FunctionType& value) const {
   if (IsSignatureFunction()) {
     set_data(value);
-    return;
-  }
-  if (IsClosureFunction()) {
+  } else {
+    ASSERT(IsClosureFunction());
     const Object& obj = Object::Handle(raw_ptr()->data_);
     ASSERT(!obj.IsNull());
-    ClosureData::Cast(obj).set_signature_class(value);
-    return;
+    ClosureData::Cast(obj).set_signature_type(value);
   }
-  UNREACHABLE();
 }
 
 
@@ -5640,7 +5555,7 @@
 
 // This field is heavily overloaded:
 //   eval function:           Script expression source
-//   signature function:      Class signature class
+//   signature function:      Function type
 //   method extractor:        Function extracted closure function
 //   noSuchMethod dispatcher: Array arguments descriptor
 //   invoke-field dispatcher: Array arguments descriptor
@@ -5787,7 +5702,7 @@
 
 
 void Function::set_token_pos(intptr_t token_pos) const {
-  ASSERT(token_pos >= 0);
+  ASSERT(!Token::IsClassifying(token_pos) || IsMethodExtractor());
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
@@ -6169,6 +6084,7 @@
         *bound_error,  // A bound error if non null.
         Script::Handle(other.script()),
         other.token_pos(),
+        Report::AtLocation,
         Report::kError,
         Heap::kNew,
         "signature type '%s' of function '%s' is not a subtype of signature "
@@ -6505,6 +6421,25 @@
 }
 
 
+RawFunction* Function::NewSignatureFunction(const Class& owner,
+                                            intptr_t token_pos) {
+  const Function& result = Function::Handle(Function::New(
+      Symbols::AnonymousSignature(),
+      RawFunction::kSignatureFunction,
+      /* is_static = */ false,
+      /* is_const = */ false,
+      /* is_abstract = */ false,
+      /* is_external = */ false,
+      /* is_native = */ false,
+      owner,  // Same as function type scope class.
+      token_pos));
+  result.set_is_reflectable(false);
+  result.set_is_visible(false);
+  result.set_is_debuggable(false);
+  return result.raw();
+}
+
+
 RawFunction* Function::NewEvalFunction(const Class& owner,
                                        const Script& script,
                                        bool is_static) {
@@ -6583,35 +6518,12 @@
     param_name = ParameterNameAt(has_receiver - kClosure + i);
     closure_function.SetParameterNameAt(i, param_name);
   }
-
-  // Lookup or create a new signature class for the closure function in the
-  // library of the owner class.
-  const Class& owner_class = Class::Handle(Owner());
-  ASSERT(!owner_class.IsNull() && (Owner() == closure_function.Owner()));
-  const Library& library = Library::Handle(owner_class.library());
-  ASSERT(!library.IsNull());
-  const String& signature = String::Handle(closure_function.Signature());
-  Class& signature_class = Class::ZoneHandle(
-      library.LookupLocalClass(signature));
-  if (signature_class.IsNull()) {
-    const Script& script = Script::Handle(this->script());
-    signature_class = Class::NewSignatureClass(signature,
-                                               closure_function,
-                                               script,
-                                               closure_function.token_pos());
-    library.AddClass(signature_class);
-  } else {
-    closure_function.set_signature_class(signature_class);
-  }
-  // Finalize types in signature class here, so that the
-  // signature type is not computed twice.
-  ClassFinalizer::FinalizeTypesInClass(signature_class);
-  const Type& signature_type = Type::Handle(signature_class.SignatureType());
+  const FunctionType& signature_type =
+      FunctionType::Handle(closure_function.SignatureType());
   if (!signature_type.IsFinalized()) {
     ClassFinalizer::FinalizeType(
-        signature_class, signature_type, ClassFinalizer::kCanonicalize);
+        Class::Handle(Owner()), signature_type, ClassFinalizer::kCanonicalize);
   }
-  ASSERT(closure_function.signature_class() == signature_class.raw());
   set_implicit_closure_function(closure_function);
   ASSERT(closure_function.IsImplicitClosureFunction());
   return closure_function.raw();
@@ -6716,9 +6628,6 @@
         Context::Handle(zone, object_store->empty_context());
     Instance& closure =
         Instance::Handle(zone, Closure::New(*this, context, Heap::kOld));
-    const char* error_str = NULL;
-    closure ^= closure.CheckAndCanonicalize(&error_str);
-    ASSERT(!closure.IsNull());
     set_implicit_static_closure(closure);
   }
   return implicit_static_closure();
@@ -6727,11 +6636,12 @@
 
 RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const {
   ASSERT(IsImplicitClosureFunction());
-  const Class& cls = Class::Handle(signature_class());
+  const FunctionType& signature_type = FunctionType::Handle(SignatureType());
+  const Class& cls = Class::Handle(signature_type.type_class());
   const Context& context = Context::Handle(Context::New(1));
   context.SetAt(0, receiver);
   const Instance& result = Instance::Handle(Closure::New(*this, context));
-  if (cls.NumTypeArguments() > 0) {
+  if (cls.IsGeneric()) {
     const TypeArguments& type_arguments =
         TypeArguments::Handle(receiver.GetTypeArguments());
     result.SetTypeArguments(type_arguments);
@@ -6748,18 +6658,17 @@
   GrowableHandlePtrArray<const String> pieces(zone, 4);
   String& name = String::Handle(zone);
   if (!instantiate && !is_static() && (name_visibility == kInternalName)) {
-    // Prefix the signature with its signature class and type parameters, if any
+    // Prefix the signature with its scope class and type parameters, if any
     // (e.g. "Map<K, V>(K) => bool"). In case of a function type alias, the
-    // signature class name is the alias name.
+    // scope class name is the alias name.
     // The signature of static functions cannot be type parameterized.
-    const Class& function_class = Class::Handle(zone, Owner());
-    ASSERT(!function_class.IsNull());
-    const TypeArguments& type_parameters = TypeArguments::Handle(
-        zone, function_class.type_parameters());
-    if (!type_parameters.IsNull()) {
-      const String& function_class_name =
-          String::Handle(zone, function_class.Name());
-      pieces.Add(function_class_name);
+    const Class& scope_class = Class::Handle(zone, Owner());
+    ASSERT(!scope_class.IsNull());
+    if (scope_class.IsGeneric()) {
+      const TypeArguments& type_parameters = TypeArguments::Handle(
+          zone, scope_class.type_parameters());
+      const String& scope_class_name = String::Handle(zone, scope_class.Name());
+      pieces.Add(scope_class_name);
       const intptr_t num_type_parameters = type_parameters.Length();
       pieces.Add(Symbols::LAngleBracket());
       TypeParameter& type_parameter = TypeParameter::Handle(zone);
@@ -7271,8 +7180,8 @@
 }
 
 
-void ClosureData::set_signature_class(const Class& value) const {
-  StorePointer(&raw_ptr()->signature_class_, value.raw());
+void ClosureData::set_signature_type(const FunctionType& value) const {
+  StorePointer(&raw_ptr()->signature_type_, value.raw());
 }
 
 
@@ -8547,7 +8456,10 @@
       cur_token_kind_(Token::kILLEGAL),
       cur_token_obj_index_(-1),
       stream_type_(stream_type) {
-  SetCurrentPosition(token_pos);
+  ASSERT(token_pos != Token::kNoSourcePos);
+  if (token_pos >= 0) {
+    SetCurrentPosition(token_pos);
+  }
 }
 
 
@@ -9239,7 +9151,8 @@
   const String& url = String::Handle(lib.url());
   Report::MessageF(Report::kError,
                    Script::Handle(lib.LookupScript(url)),
-                   Scanner::kNoSourcePos,
+                   Token::kNoSourcePos,
+                   Report::AtLocation,
                    "too many imports in library '%s'",
                    url.ToCString());
   UNREACHABLE();
@@ -10155,9 +10068,17 @@
 }
 
 
-void Library::InitResolvedNamesCache(intptr_t size) const {
-  const Array& cache = Array::Handle(HashTables::New<ResolvedNamesMap>(size));
-  StorePointer(&raw_ptr()->resolved_names_, cache.raw());
+void Library::InitResolvedNamesCache(intptr_t size,
+                                     SnapshotReader* reader) const {
+  if (reader == NULL) {
+    StorePointer(&raw_ptr()->resolved_names_,
+                 HashTables::New<ResolvedNamesMap>(size));
+  } else {
+    intptr_t len = ResolvedNamesMap::ArrayLengthForNumOccupied(size);
+    *reader->ArrayHandle() ^= reader->NewArray(len);
+    StorePointer(&raw_ptr()->resolved_names_,
+                 HashTables::New<ResolvedNamesMap>(*reader->ArrayHandle()));
+  }
 }
 
 
@@ -10512,8 +10433,7 @@
     Class& klass = Class::Handle();
     while (class_iter.HasNext()) {
       klass = class_iter.GetNextClass();
-      if (!klass.IsCanonicalSignatureClass() &&
-          !klass.IsMixinApplication()) {
+      if (!klass.IsMixinApplication()) {
         jsarr.AddValue(klass);
       }
     }
@@ -11246,15 +11166,15 @@
 }
 
 
-// Encode integer in SLEB128 format.
-void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data,
-                                  intptr_t value) {
+// Encode integer |value| in SLEB128 format and store into |data|.
+static void EncodeSLEB128(GrowableArray<uint8_t>* data,
+                          intptr_t value) {
   bool is_last_part = false;
   while (!is_last_part) {
-    intptr_t part = value & 0x7f;
+    uint8_t part = value & 0x7f;
     value >>= 7;
     if ((value == 0 && (part & 0x40) == 0) ||
-        (value == -1 && (part & 0x40) != 0)) {
+        (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
       is_last_part = true;
     } else {
       part |= 0x80;
@@ -11264,24 +11184,39 @@
 }
 
 
+// Decode integer in SLEB128 format from |data| and update |byte_index|.
+static intptr_t DecodeSLEB128(const uint8_t* data,
+                              const intptr_t data_length,
+                              intptr_t* byte_index) {
+  ASSERT(*byte_index < data_length);
+  uword shift = 0;
+  intptr_t value = 0;
+  uint8_t part = 0;
+  do {
+    part = data[(*byte_index)++];
+    value |= static_cast<intptr_t>(part & 0x7f) << shift;
+    shift += 7;
+  } while ((part & 0x80) != 0);
+
+  if ((shift < (sizeof(value) * 8)) && ((part & 0x40) != 0)) {
+    value |= static_cast<intptr_t>(-1) << shift;
+  }
+  return value;
+}
+
+
+// Encode integer in SLEB128 format.
+void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data,
+                                  intptr_t value) {
+  return EncodeSLEB128(data, value);
+}
+
+
 // Decode SLEB128 encoded integer. Update byte_index to the next integer.
 intptr_t PcDescriptors::DecodeInteger(intptr_t* byte_index) const {
   NoSafepointScope no_safepoint;
   const uint8_t* data = raw_ptr()->data();
-  ASSERT(*byte_index < Length());
-  uword shift = 0;
-  intptr_t value = 0;
-  intptr_t part = 0;
-  do {
-    part = data[(*byte_index)++];
-    value |= (part & 0x7f) << shift;
-    shift += 7;
-  } while ((part & 0x80) != 0);
-
-  if (shift < sizeof(value) * 8 && (part & 0x40) != 0) {
-    value |= -(1 << shift);
-  }
-  return value;
+  return DecodeSLEB128(data, Length(), byte_index);
 }
 
 
@@ -11583,6 +11518,114 @@
 }
 
 
+intptr_t CodeSourceMap::Length() const {
+  return raw_ptr()->length_;
+}
+
+
+void CodeSourceMap::SetLength(intptr_t value) const {
+  StoreNonPointer(&raw_ptr()->length_, value);
+}
+
+
+void CodeSourceMap::CopyData(GrowableArray<uint8_t>* delta_encoded_data) {
+  NoSafepointScope no_safepoint;
+  uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]);
+  for (intptr_t i = 0; i < delta_encoded_data->length(); ++i) {
+    data[i] = (*delta_encoded_data)[i];
+  }
+}
+
+
+RawCodeSourceMap* CodeSourceMap::New(GrowableArray<uint8_t>* data) {
+  ASSERT(Object::code_source_map_class() != Class::null());
+  Thread* thread = Thread::Current();
+  CodeSourceMap& result = CodeSourceMap::Handle(thread->zone());
+  {
+    uword size = CodeSourceMap::InstanceSize(data->length());
+    RawObject* raw = Object::Allocate(CodeSourceMap::kClassId,
+                                      size,
+                                      Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.SetLength(data->length());
+    result.CopyData(data);
+  }
+  return result.raw();
+}
+
+
+RawCodeSourceMap* CodeSourceMap::New(intptr_t length) {
+  ASSERT(Object::code_source_map_class() != Class::null());
+  Thread* thread = Thread::Current();
+  CodeSourceMap& result = CodeSourceMap::Handle(thread->zone());
+  {
+    uword size = CodeSourceMap::InstanceSize(length);
+    RawObject* raw = Object::Allocate(CodeSourceMap::kClassId,
+                                      size,
+                                      Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+    result.SetLength(length);
+  }
+  return result.raw();
+}
+
+
+void CodeSourceMap::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Object::PrintJSONImpl(stream, ref);
+}
+
+
+const char* CodeSourceMap::ToCString() const {
+  // "*" in a printf format specifier tells it to read the field width from
+  // the printf argument list.
+#define FORMAT "%#-*" Px "\t%" Pd "\n"
+  if (Length() == 0) {
+    return "empty CodeSourceMap\n";
+  }
+  // 4 bits per hex digit.
+  const int addr_width = kBitsPerWord / 4;
+  // First compute the buffer size required.
+  intptr_t len = 1;  // Trailing '\0'.
+  {
+    Iterator iter(*this);
+    while (iter.MoveNext()) {
+      len += OS::SNPrint(NULL, 0, FORMAT, addr_width,
+                         iter.PcOffset(),
+                         iter.TokenPos());
+    }
+  }
+  // Allocate the buffer.
+  char* buffer = Thread::Current()->zone()->Alloc<char>(len);
+  // Layout the fields in the buffer.
+  intptr_t index = 0;
+  Iterator iter(*this);
+  while (iter.MoveNext()) {
+    index += OS::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
+                         iter.PcOffset(),
+                         iter.TokenPos());
+  }
+  return buffer;
+#undef FORMAT
+}
+
+
+// Encode integer in SLEB128 format.
+void CodeSourceMap::EncodeInteger(GrowableArray<uint8_t>* data,
+                                  intptr_t value) {
+  return EncodeSLEB128(data, value);
+}
+
+
+// Decode SLEB128 encoded integer. Update byte_index to the next integer.
+intptr_t CodeSourceMap::DecodeInteger(intptr_t* byte_index) const {
+  NoSafepointScope no_safepoint;
+  const uint8_t* data = raw_ptr()->data();
+  return DecodeSLEB128(data, Length(), byte_index);
+}
+
+
 bool Stackmap::GetBit(intptr_t bit_index) const {
   ASSERT(InRange(bit_index));
   int byte_index = bit_index >> kBitsPerByteLog2;
@@ -14379,7 +14422,7 @@
 
 
 void SubtypeTestCache::AddCheck(
-    intptr_t instance_class_id,
+    const Object& instance_class_id_or_function,
     const TypeArguments& instance_type_arguments,
     const TypeArguments& instantiator_type_arguments,
     const Bool& test_result) const {
@@ -14389,24 +14432,24 @@
   data = Array::Grow(data, new_len);
   set_cache(data);
   intptr_t data_pos = old_num * kTestEntryLength;
-  data.SetAt(data_pos + kInstanceClassId,
-      Smi::Handle(Smi::New(instance_class_id)));
+  data.SetAt(data_pos + kInstanceClassIdOrFunction,
+             instance_class_id_or_function);
   data.SetAt(data_pos + kInstanceTypeArguments, instance_type_arguments);
   data.SetAt(data_pos + kInstantiatorTypeArguments,
-      instantiator_type_arguments);
+             instantiator_type_arguments);
   data.SetAt(data_pos + kTestResult, test_result);
 }
 
 
 void SubtypeTestCache::GetCheck(intptr_t ix,
-                                intptr_t* instance_class_id,
+                                Object* instance_class_id_or_function,
                                 TypeArguments* instance_type_arguments,
                                 TypeArguments* instantiator_type_arguments,
                                 Bool* test_result) const {
   Array& data = Array::Handle(cache());
   intptr_t data_pos = ix * kTestEntryLength;
-  *instance_class_id =
-      Smi::Value(Smi::RawCast(data.At(data_pos + kInstanceClassId)));
+  *instance_class_id_or_function =
+      data.At(data_pos + kInstanceClassIdOrFunction);
   *instance_type_arguments ^= data.At(data_pos + kInstanceTypeArguments);
   *instantiator_type_arguments ^=
       data.At(data_pos + kInstantiatorTypeArguments);
@@ -14503,6 +14546,7 @@
 RawLanguageError* LanguageError::NewFormattedV(const Error& prev_error,
                                                const Script& script,
                                                intptr_t token_pos,
+                                               bool report_after_token,
                                                Report::Kind kind,
                                                Heap::Space space,
                                                const char* format,
@@ -14519,6 +14563,7 @@
   result.set_previous_error(prev_error);
   result.set_script(script);
   result.set_token_pos(token_pos);
+  result.set_report_after_token(report_after_token);
   result.set_kind(kind);
   result.set_message(String::Handle(
       String::NewFormattedV(format, args, space)));
@@ -14529,13 +14574,15 @@
 RawLanguageError* LanguageError::NewFormatted(const Error& prev_error,
                                               const Script& script,
                                               intptr_t token_pos,
+                                              bool report_after_token,
                                               Report::Kind kind,
                                               Heap::Space space,
                                               const char* format, ...) {
   va_list args;
   va_start(args, format);
   RawLanguageError* result = LanguageError::NewFormattedV(
-      prev_error, script, token_pos, kind, space, format, args);
+      prev_error, script, token_pos, report_after_token,
+      kind, space, format, args);
   NoSafepointScope no_safepoint;
   va_end(args);
   return result;
@@ -14571,11 +14618,16 @@
 
 
 void LanguageError::set_token_pos(intptr_t token_pos) const {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
 
+void LanguageError::set_report_after_token(bool value) {
+  StoreNonPointer(&raw_ptr()->report_after_token_, value);
+}
+
+
 void LanguageError::set_kind(uint8_t value) const {
   StoreNonPointer(&raw_ptr()->kind_, value);
 }
@@ -14599,6 +14651,7 @@
       Report::PrependSnippet(kind(),
                              Script::Handle(script()),
                              token_pos(),
+                             report_after_token(),
                              String::Handle(message())));
   // Prepend previous error message.
   const Error& prev_error = Error::Handle(previous_error());
@@ -14955,11 +15008,32 @@
 }
 
 
-RawType* Instance::GetType() const {
+RawAbstractType* Instance::GetType() const {
   if (IsNull()) {
     return Type::NullType();
   }
   const Class& cls = Class::Handle(clazz());
+  if (cls.IsClosureClass()) {
+    const Function& signature =
+        Function::Handle(Closure::Cast(*this).function());
+    FunctionType& type = FunctionType::Handle(signature.SignatureType());
+    if (type.scope_class() == cls.raw()) {
+      // Type is not parameterized.
+      if (!type.IsCanonical()) {
+        type ^= type.Canonicalize();
+        signature.SetSignatureType(type);
+      }
+      return type.raw();
+    }
+    const Class& scope_cls = Class::Handle(type.scope_class());
+    ASSERT(scope_cls.NumTypeArguments() > 0);
+    TypeArguments& type_arguments = TypeArguments::Handle(GetTypeArguments());
+    type = FunctionType::New(
+        scope_cls, type_arguments, signature, Token::kNoSourcePos);
+    type.SetIsFinalized();
+    type ^= type.Canonicalize();
+    return type.raw();
+  }
   Type& type = Type::Handle();
   if (!cls.IsGeneric()) {
     type = cls.CanonicalType();
@@ -14969,7 +15043,7 @@
     if (cls.NumTypeArguments() > 0) {
       type_arguments = GetTypeArguments();
     }
-    type = Type::New(cls, type_arguments, Scanner::kNoSourcePos);
+    type = Type::New(cls, type_arguments, Token::kNoSourcePos);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
   }
@@ -15008,6 +15082,47 @@
   }
   Zone* zone = Thread::Current()->zone();
   const Class& cls = Class::Handle(zone, clazz());
+  if (cls.IsClosureClass()) {
+    if (other.IsObjectType() || other.IsDartFunctionType()) {
+      return true;
+    }
+    Function& other_signature = Function::Handle(zone);
+    TypeArguments& other_type_arguments = TypeArguments::Handle(zone);
+    // Note that we may encounter a bound error in checked mode.
+    if (!other.IsInstantiated()) {
+      const AbstractType& instantiated_other = AbstractType::Handle(
+          zone, other.InstantiateFrom(other_instantiator, bound_error));
+      if ((bound_error != NULL) && !bound_error->IsNull()) {
+        ASSERT(Isolate::Current()->flags().type_checks());
+        return false;
+      }
+      if (instantiated_other.IsDynamicType() ||
+          instantiated_other.IsObjectType() ||
+          instantiated_other.IsDartFunctionType()) {
+        return true;
+      }
+      if (!instantiated_other.IsFunctionType()) {
+        return false;
+      }
+      other_signature = FunctionType::Cast(instantiated_other).signature();
+      other_type_arguments = instantiated_other.arguments();
+    } else {
+      if (!other.IsFunctionType()) {
+        return false;
+      }
+      other_signature = FunctionType::Cast(other).signature();
+      other_type_arguments = other.arguments();
+    }
+    const Function& signature =
+        Function::Handle(zone, Closure::Cast(*this).function());
+    const TypeArguments& type_arguments =
+        TypeArguments::Handle(zone, GetTypeArguments());
+    return signature.IsSubtypeOf(type_arguments,
+                                 other_signature,
+                                 other_type_arguments,
+                                 bound_error,
+                                 Heap::kOld);
+  }
   TypeArguments& type_arguments = TypeArguments::Handle(zone);
   if (cls.NumTypeArguments() > 0) {
     type_arguments = GetTypeArguments();
@@ -15025,20 +15140,54 @@
   }
   Class& other_class = Class::Handle(zone);
   TypeArguments& other_type_arguments = TypeArguments::Handle(zone);
+  AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
   // Note that we may encounter a bound error in checked mode.
   if (!other.IsInstantiated()) {
-    const AbstractType& instantiated_other = AbstractType::Handle(
-        zone, other.InstantiateFrom(other_instantiator, bound_error));
+    instantiated_other = other.InstantiateFrom(other_instantiator, bound_error);
     if ((bound_error != NULL) && !bound_error->IsNull()) {
       ASSERT(Isolate::Current()->flags().type_checks());
       return false;
     }
-    other_class = instantiated_other.type_class();
-    other_type_arguments = instantiated_other.arguments();
-  } else {
-    other_class = other.type_class();
-    other_type_arguments = other.arguments();
+    if (instantiated_other.IsTypeRef()) {
+      instantiated_other = TypeRef::Cast(instantiated_other).type();
+    }
+    if (instantiated_other.IsDynamicType()) {
+      return true;
+    }
   }
+  other_type_arguments = instantiated_other.arguments();
+  const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
+  if (other_is_dart_function || instantiated_other.IsFunctionType()) {
+    // Check if this instance understands a call() method of a compatible type.
+    Function& call =
+        Function::Handle(zone, cls.LookupDynamicFunction(Symbols::Call()));
+    if (call.IsNull()) {
+      // Walk up the super_class chain.
+      Class& super_cls = Class::Handle(zone, cls.SuperClass());
+      while (!super_cls.IsNull() && call.IsNull()) {
+        call = super_cls.LookupDynamicFunction(Symbols::Call());
+        super_cls = super_cls.SuperClass();
+      }
+    }
+    if (!call.IsNull()) {
+      if (other_is_dart_function) {
+        return true;
+      }
+      const Function& other_signature = Function::Handle(
+          zone, FunctionType::Cast(instantiated_other).signature());
+      if (call.IsSubtypeOf(type_arguments,
+                           other_signature,
+                           other_type_arguments,
+                           bound_error,
+                           Heap::kOld)) {
+        return true;
+      }
+    }
+  }
+  if (!instantiated_other.IsType()) {
+    return false;
+  }
+  other_class = instantiated_other.type_class();
   return cls.IsSubtypeOf(type_arguments, other_class, other_type_arguments,
                          bound_error, Heap::kOld);
 }
@@ -15104,17 +15253,11 @@
 }
 
 
-bool Instance::IsClosure() const {
-  const Class& cls = Class::Handle(clazz());
-  return cls.IsSignatureClass();
-}
-
-
 bool Instance::IsCallable(Function* function) const {
   Class& cls = Class::Handle(clazz());
-  if (cls.IsSignatureClass()) {
+  if (cls.IsClosureClass()) {
     if (function != NULL) {
-      *function = Closure::function(*this);
+      *function = Closure::Cast(*this).function();
     }
     return true;
   }
@@ -15219,7 +15362,7 @@
     return "Instance";
   } else {
     if (IsClosure()) {
-      return Closure::ToCString(*this);
+      return Closure::Cast(*this).ToCString();
     }
     const Class& cls = Class::Handle(clazz());
     TypeArguments& type_arguments = TypeArguments::Handle();
@@ -15228,7 +15371,7 @@
       type_arguments = GetTypeArguments();
     }
     const Type& type =
-        Type::Handle(Type::New(cls, type_arguments, Scanner::kNoSourcePos));
+        Type::Handle(Type::New(cls, type_arguments, Token::kNoSourcePos));
     const String& type_name = String::Handle(type.UserVisibleName());
     return OS::SCreate(Thread::Current()->zone(),
         "Instance of '%s'", type_name.ToCString());
@@ -15304,9 +15447,9 @@
   jsobj.AddServiceId(*this);
   if (IsClosure()) {
     jsobj.AddProperty("closureFunction",
-                      Function::Handle(Closure::function(*this)));
+                      Function::Handle(Closure::Cast(*this).function()));
     jsobj.AddProperty("closureContext",
-                      Context::Handle(Closure::context(*this)));
+                      Context::Handle(Closure::Cast(*this).context()));
   }
   if (ref) {
     return;
@@ -15328,6 +15471,12 @@
 }
 
 
+void AbstractType::SetIsResolved() const {
+  // AbstractType is an abstract class.
+  UNREACHABLE();
+}
+
+
 bool AbstractType::HasResolvedTypeClass() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -15356,6 +15505,11 @@
 }
 
 
+void AbstractType::set_arguments(const TypeArguments& value) const {
+  // AbstractType is an abstract class.
+  UNREACHABLE();
+}
+
 intptr_t AbstractType::token_pos() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -15377,6 +15531,12 @@
 }
 
 
+void AbstractType::SetIsFinalized() const {
+  // AbstractType is an abstract class.
+  UNREACHABLE();
+}
+
+
 bool AbstractType::IsBeingFinalized() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -15384,6 +15544,12 @@
 }
 
 
+void AbstractType::SetIsBeingFinalized() const {
+  // AbstractType is an abstract class.
+  UNREACHABLE();
+}
+
+
 bool AbstractType::IsMalformed() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -15538,8 +15704,29 @@
   String& class_name = String::Handle(zone);
   intptr_t first_type_param_index;
   intptr_t num_type_params;  // Number of type parameters to print.
-  if (HasResolvedTypeClass()) {
-    const Class& cls = Class::Handle(zone, type_class());
+  Class& cls = Class::Handle(zone);
+  if (IsFunctionType()) {
+    cls = type_class();
+    if (!cls.IsTypedefClass()) {
+      const Function& signature_function = Function::Handle(
+          zone, FunctionType::Cast(*this).signature());
+      if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
+        return signature_function.UserVisibleSignature();
+      }
+      return signature_function.InstantiatedSignatureFrom(args,
+                                                          name_visibility);
+    }
+    class_name = cls.Name();  // Typedef name.
+    // We may be reporting an error about a malformed function type. In that
+    // case, avoid instantiating the signature, since it may cause divergence.
+    if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
+      return class_name.raw();
+    }
+    // Print the name of a typedef as a regular, possibly parameterized, class.
+  } else if (HasResolvedTypeClass()) {
+    cls = type_class();
+  }
+  if (!cls.IsNull()) {
     if (IsResolved() || !cls.IsMixinApplication()) {
       // Do not print the full vector, but only the declared type parameters.
       num_type_params = cls.NumTypeParameters();
@@ -15577,29 +15764,8 @@
         first_type_param_index = num_args - num_type_params;
       }
     }
-    if (cls.IsSignatureClass()) {
-      // We may be reporting an error about a malformed function type. In that
-      // case, avoid instantiating the signature, since it may cause divergence.
-      if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
-        return class_name.raw();
-      }
-      // To avoid divergence, print the name of a typedef (non-canonical
-      // signature class) as a regular, possibly parameterized, class.
-      if (cls.IsCanonicalSignatureClass()) {
-        const Function& signature_function = Function::Handle(
-            zone, cls.signature_function());
-        // Signature classes have no super type, however, they take as many
-        // type arguments as the owner class of their signature function (if it
-        // is non static and generic, see Class::NumTypeArguments()). Therefore,
-        // first_type_param_index may be greater than 0 here.
-        return signature_function.InstantiatedSignatureFrom(args,
-                                                            name_visibility);
-      }
-    }
   } else {
-    const UnresolvedClass& cls =
-        UnresolvedClass::Handle(zone, unresolved_class());
-    class_name = cls.Name();
+    class_name = UnresolvedClass::Handle(zone, unresolved_class()).Name();
     num_type_params = num_args;
     first_type_param_index = 0;
   }
@@ -15691,7 +15857,7 @@
 }
 
 
-bool AbstractType::IsFunctionType() const {
+bool AbstractType::IsDartFunctionType() const {
   return HasResolvedTypeClass() &&
       (type_class() == Type::Handle(Type::Function()).type_class());
 }
@@ -15729,6 +15895,9 @@
     }
     return false;
   }
+  if (other.IsObjectType() || other.IsDynamicType()) {
+    return true;
+  }
   if (IsBoundedType() || other.IsBoundedType()) {
     if (Equals(other)) {
       return true;
@@ -15740,6 +15909,7 @@
     }
     return false;  // TODO(regis): We should return "maybe after instantiation".
   }
+  Zone* zone = Thread::Current()->zone();
   // Type parameters cannot be handled by Class::TypeTest().
   // When comparing two uninstantiated function types, one returning type
   // parameter K, the other returning type parameter V, we cannot assume that K
@@ -15748,7 +15918,7 @@
   // The same rule applies when checking the upper bound of a still
   // uninstantiated type at compile time. Returning false will defer the test
   // to run time.
-  // There are however some cases can be decided at compile time.
+  // There are however some cases that can be decided at compile time.
   // For example, with class A<K, V extends K>, new A<T, T> called from within
   // a class B<T> will never require a run time bound check, even if T is
   // uninstantiated at compile time.
@@ -15760,7 +15930,7 @@
         return true;
       }
     }
-    const AbstractType& bound = AbstractType::Handle(type_param.bound());
+    const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
     // We may be checking bounds at finalization time and can encounter
     // a still unfinalized bound. Finalizing the bound here may lead to cycles.
     if (!bound.IsFinalized()) {
@@ -15774,13 +15944,59 @@
   if (other.IsTypeParameter()) {
     return false;  // TODO(regis): We should return "maybe after instantiation".
   }
-  const Class& cls = Class::Handle(type_class());
-  return cls.TypeTest(test_kind,
-                      TypeArguments::Handle(arguments()),
-                      Class::Handle(other.type_class()),
-                      TypeArguments::Handle(other.arguments()),
-                      bound_error,
-                      space);
+  const Class& type_cls = Class::Handle(zone, type_class());
+  // Function types cannot be handled by Class::TypeTest().
+  const bool other_is_dart_function_type = other.IsDartFunctionType();
+  if (other_is_dart_function_type || other.IsFunctionType()) {
+    if (IsFunctionType()) {
+      if (other_is_dart_function_type) {
+        return true;
+      }
+      const Function& other_fun =
+          Function::Handle(zone, FunctionType::Cast(other).signature());
+      // Check for two function types.
+      const Function& fun =
+          Function::Handle(zone, FunctionType::Cast(*this).signature());
+      return fun.TypeTest(test_kind,
+                          TypeArguments::Handle(zone, arguments()),
+                          other_fun,
+                          TypeArguments::Handle(zone, other.arguments()),
+                          bound_error,
+                          space);
+    }
+    // Check if type S has a call() method of function type T.
+    Function& function =
+        Function::Handle(zone, type_cls.LookupDynamicFunction(Symbols::Call()));
+    if (function.IsNull()) {
+      // Walk up the super_class chain.
+      Class& cls = Class::Handle(zone, type_cls.SuperClass());
+      while (!cls.IsNull() && function.IsNull()) {
+        function = cls.LookupDynamicFunction(Symbols::Call());
+        cls = cls.SuperClass();
+      }
+    }
+    if (!function.IsNull()) {
+      if (other_is_dart_function_type ||
+          function.TypeTest(test_kind,
+                            TypeArguments::Handle(zone, arguments()),
+                            Function::Handle(
+                                zone, FunctionType::Cast(other).signature()),
+                            TypeArguments::Handle(zone, other.arguments()),
+                            bound_error,
+                            space)) {
+        return true;
+      }
+    }
+  }
+  if (IsFunctionType()) {
+    return false;
+  }
+  return type_cls.TypeTest(test_kind,
+                           TypeArguments::Handle(zone, arguments()),
+                           Class::Handle(zone, other.type_class()),
+                           TypeArguments::Handle(zone, other.arguments()),
+                           bound_error,
+                           space);
 }
 
 
@@ -15890,7 +16106,7 @@
     const TypeArguments& no_type_arguments = TypeArguments::Handle();
     type ^= Type::New(Object::Handle(type_class.raw()),
                       no_type_arguments,
-                      Scanner::kNoSourcePos);
+                      Token::kNoSourcePos);
     type.SetIsFinalized();
     type ^= type.Canonicalize();
   }
@@ -15910,14 +16126,7 @@
 }
 
 
-void Type::ResetIsFinalized() const {
-  ASSERT(IsFinalized());
-  set_type_state(RawType::kBeingFinalized);
-  SetIsFinalized();
-}
-
-
-void Type::set_is_being_finalized() const {
+void Type::SetIsBeingFinalized() const {
   ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
   set_type_state(RawType::kBeingFinalized);
 }
@@ -15962,8 +16171,10 @@
 }
 
 
-void Type::set_is_resolved() const {
+void Type::SetIsResolved() const {
   ASSERT(!IsResolved());
+  // A Typedef is a FunctionType, not a type.
+  ASSERT(!Class::Handle(type_class()).IsTypedefClass());
   set_type_state(RawType::kResolved);
 }
 
@@ -16001,11 +16212,6 @@
 }
 
 
-RawTypeArguments* Type::arguments() const {
-  return raw_ptr()->arguments_;
-}
-
-
 bool Type::IsInstantiated(TrailPtr trail) const {
   if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) {
     return true;
@@ -16021,7 +16227,6 @@
   intptr_t len = num_type_args;  // Check the full vector of type args.
   ASSERT(num_type_args > 0);
   // This type is not instantiated if it refers to type parameters.
-  // This IsInstantiated() call may be invoked on an unresolved signature type.
   // Although this type may still be unresolved, the type parameters it may
   // refer to are resolved by definition. We can therefore return the correct
   // result even for an unresolved type. We just need to look at all type
@@ -16068,7 +16273,8 @@
 
   // This uninstantiated type is not modified, as it can be instantiated
   // with different instantiators. Allocate a new instantiated version of it.
-  instantiated_type = Type::New(cls, TypeArguments::Handle(zone), token_pos());
+  instantiated_type =
+      Type::New(cls, TypeArguments::Handle(zone), token_pos(), space);
   TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
   ASSERT(type_arguments.Length() == cls.NumTypeArguments());
   if (type_arguments.IsRecursive()) {
@@ -16082,7 +16288,7 @@
   if (IsFinalized()) {
     instantiated_type.SetIsFinalized();
   } else {
-    instantiated_type.set_is_resolved();
+    instantiated_type.SetIsResolved();
   }
   // Canonicalization is not part of instantiation.
   return instantiated_type.raw();
@@ -16184,9 +16390,9 @@
   ASSERT(!IsBeingFinalized());  // Cloning must occur prior to finalization.
   TypeArguments& type_args = TypeArguments::Handle(arguments());
   type_args = type_args.CloneUnfinalized();
-  const Class& type_cls = Class::Handle(type_class());
-  const Type& clone = Type::Handle(Type::New(type_cls, type_args, token_pos()));
-  clone.set_is_resolved();
+  const Type& clone = Type::Handle(
+      Type::New(Class::Handle(type_class()), type_args, token_pos()));
+  clone.SetIsResolved();
   return clone.raw();
 }
 
@@ -16228,13 +16434,14 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
-  Type& type = Type::Handle(zone);
+  AbstractType& type = Type::Handle(zone);
   const Class& cls = Class::Handle(zone, type_class());
+  ASSERT(!cls.IsTypedefClass());  // This type should be a FunctionType.
   if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
     return Object::dynamic_type().raw();
   }
   // Fast canonical lookup/registry for simple types.
-  if (!cls.IsGeneric()) {
+  if (!cls.IsGeneric() && !cls.IsClosureClass()) {
     type = cls.CanonicalType();
     if (type.IsNull()) {
       ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
@@ -16319,36 +16526,6 @@
     canonical_types = new_canonical_types.raw();
   }
   canonical_types.SetAt(index, *this);
-  if ((index == 1) && cls.IsCanonicalSignatureClass()) {
-    canonical_types.SetAt(0, *this);  // Also set canonical signature type at 0.
-#ifdef DEBUG
-    // Verify that the first canonical type is the signature type by checking
-    // that the type argument vector of the canonical type ends with the
-    // uninstantiated type parameters of the signature class. Note that these
-    // type parameters may be bounded if the super class of the owner class
-    // declares bounds.
-    // The signature type is finalized during class finalization, before the
-    // optimizer may canonicalize instantiated function types of the same
-    // signature class.
-    // Although the signature class extends class Instance, the type arguments
-    // of the super class of the owner class of its signature function will be
-    // prepended to the type argument vector during class finalization.
-    const TypeArguments& type_params =
-        TypeArguments::Handle(zone, cls.type_parameters());
-    const intptr_t num_type_params = cls.NumTypeParameters();
-    const intptr_t num_type_args = cls.NumTypeArguments();
-    AbstractType& type_arg = AbstractType::Handle(zone);
-    TypeParameter& type_param = TypeParameter::Handle(zone);
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_arg = type_args.TypeAt(num_type_args - num_type_params + i);
-      while (type_arg.IsBoundedType()) {
-        type_arg = BoundedType::Cast(type_arg).type();
-      }
-      type_param ^= type_params.TypeAt(i);
-      ASSERT(type_arg.Equals(type_param));
-    }
-#endif
-  }
   ASSERT(IsOld());
   ASSERT(type_args.IsNull() || type_args.IsOld());
   SetCanonical();
@@ -16399,7 +16576,7 @@
 
 
 void Type::set_token_pos(intptr_t token_pos) const {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
@@ -16465,6 +16642,552 @@
 }
 
 
+void FunctionType::SetIsFinalized() const {
+  ASSERT(!IsFinalized());
+  if (IsInstantiated()) {
+    set_type_state(RawFunctionType::kFinalizedInstantiated);
+  } else {
+    set_type_state(RawFunctionType::kFinalizedUninstantiated);
+  }
+}
+
+
+void FunctionType::ResetIsFinalized() const {
+  ASSERT(IsFinalized());
+  set_type_state(RawFunctionType::kBeingFinalized);
+  SetIsFinalized();
+}
+
+
+void FunctionType::SetIsBeingFinalized() const {
+  ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
+  set_type_state(RawFunctionType::kBeingFinalized);
+}
+
+
+bool FunctionType::IsMalformed() const {
+  if (raw_ptr()->error_ == LanguageError::null()) {
+    return false;
+  }
+  const LanguageError& type_error = LanguageError::Handle(error());
+  return type_error.kind() == Report::kMalformedType;
+}
+
+
+bool FunctionType::IsMalbounded() const {
+  if (!Isolate::Current()->flags().type_checks()) {
+    return false;
+  }
+  if (raw_ptr()->error_ == LanguageError::null()) {
+    return false;
+  }
+  const LanguageError& type_error = LanguageError::Handle(error());
+  return type_error.kind() == Report::kMalboundedType;
+}
+
+
+bool FunctionType::IsMalformedOrMalbounded() const {
+  if (raw_ptr()->error_ == LanguageError::null()) {
+    return false;
+  }
+  const LanguageError& type_error = LanguageError::Handle(error());
+  if (type_error.kind() == Report::kMalformedType) {
+    return true;
+  }
+  ASSERT(type_error.kind() == Report::kMalboundedType);
+  return Isolate::Current()->flags().type_checks();
+}
+
+
+void FunctionType::set_error(const LanguageError& value) const {
+  StorePointer(&raw_ptr()->error_, value.raw());
+}
+
+
+void FunctionType::SetIsResolved() const {
+  ASSERT(!IsResolved());
+  set_type_state(RawFunctionType::kResolved);
+}
+
+
+bool FunctionType::IsInstantiated(TrailPtr trail) const {
+  if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) {
+    return true;
+  }
+  if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated) {
+    return false;
+  }
+  if (arguments() == TypeArguments::null()) {
+    return true;
+  }
+  const Class& scope_cls = Class::Handle(scope_class());
+  if (!scope_cls.IsGeneric()) {
+    ASSERT(scope_cls.IsClosureClass() || scope_cls.IsTypedefClass());
+    ASSERT(arguments() == TypeArguments::null());
+    return true;
+  }
+  const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
+  const intptr_t num_type_args = scope_cls.NumTypeArguments();
+  const intptr_t num_type_params = scope_cls.NumTypeParameters();
+  // The vector may be longer than necessary. An empty vector is handled above.
+  ASSERT(type_arguments.Length() >= num_type_args);
+  return
+      (num_type_params == 0) ||
+      type_arguments.IsSubvectorInstantiated(num_type_args - num_type_params,
+                                             num_type_params);
+}
+
+
+RawAbstractType* FunctionType::InstantiateFrom(
+    const TypeArguments& instantiator_type_arguments,
+    Error* bound_error,
+    TrailPtr trail,
+    Heap::Space space) const {
+  Zone* zone = Thread::Current()->zone();
+  ASSERT(IsFinalized() || IsBeingFinalized());
+  ASSERT(!IsInstantiated());
+  ASSERT(!IsMalformed());  // FunctionType cannot be malformed.
+  // Instantiating this type with its own type arguments as instantiator can
+  // occur during finalization and bounds checking. Return the type unchanged.
+  if (arguments() == instantiator_type_arguments.raw()) {
+    return raw();
+  }
+  // If this type is recursive, we may already be instantiating it.
+  FunctionType& instantiated_type = FunctionType::Handle(zone);
+  instantiated_type ^= OnlyBuddyInTrail(trail);
+  if (!instantiated_type.IsNull()) {
+    ASSERT(IsRecursive());
+    return instantiated_type.raw();
+  }
+  // Note that the scope class has to be resolved at this time, but not
+  // necessarily finalized yet. We may be checking bounds at compile time or
+  // finalizing the type argument vector of a recursive type.
+  const Class& cls = Class::Handle(zone, scope_class());
+
+  // This uninstantiated type is not modified, as it can be instantiated
+  // with different instantiators. Allocate a new instantiated version of it.
+  instantiated_type =
+      FunctionType::New(cls,
+                        TypeArguments::Handle(zone),
+                        Function::Handle(zone, signature()),
+                        token_pos(),
+                        space);
+  TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
+  ASSERT(type_arguments.Length() == cls.NumTypeArguments());
+  if (type_arguments.IsRecursive()) {
+    AddOnlyBuddyToTrail(&trail, instantiated_type);
+  }
+  type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
+                                                  bound_error,
+                                                  trail,
+                                                  space);
+  instantiated_type.set_arguments(type_arguments);
+  if (IsFinalized()) {
+    instantiated_type.SetIsFinalized();
+  } else {
+    instantiated_type.SetIsResolved();
+  }
+  // Canonicalization is not part of instantiation.
+  return instantiated_type.raw();
+}
+
+
+bool FunctionType::IsEquivalent(const Instance& other, TrailPtr trail) const {
+  ASSERT(!IsNull());
+  if (raw() == other.raw()) {
+    return true;
+  }
+  if (!other.IsFunctionType()) {
+    return false;
+  }
+  const FunctionType& other_type = FunctionType::Cast(other);
+  ASSERT(IsResolved() && other_type.IsResolved());
+  if (IsMalformed() || other_type.IsMalformed()) {
+    return false;
+  }
+  if (scope_class() != other_type.scope_class()) {
+    return false;
+  }
+  if ((arguments() == other_type.arguments()) &&
+      (signature() == other_type.signature())) {
+    return true;
+  }
+  if (!IsFinalized() || !other_type.IsFinalized()) {
+    return false;
+  }
+
+  // We do not instantiate the types of the signature. This happens on demand
+  // at runtime during a type test.
+  // Therefore, equal function types must have equal type arguments.
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+  const TypeArguments& other_type_args = TypeArguments::Handle(
+      zone, other_type.arguments());
+  if (!type_args.Equals(other_type_args)) {
+    return false;
+  }
+
+  // Type arguments are equal.
+  // Equal function types must have equal signature types and equal optional
+  // named arguments.
+  if (signature() == other_type.signature()) {
+    return true;
+  }
+  const Function& sig_fun = Function::Handle(zone, signature());
+  const Function& other_sig_fun = Function::Handle(
+      zone, other_type.signature());
+
+  // Compare number of function parameters.
+  const intptr_t num_fixed_params = sig_fun.num_fixed_parameters();
+  const intptr_t other_num_fixed_params = other_sig_fun.num_fixed_parameters();
+  if (num_fixed_params != other_num_fixed_params) {
+    return false;
+  }
+  const intptr_t num_opt_pos_params = sig_fun.NumOptionalPositionalParameters();
+  const intptr_t other_num_opt_pos_params =
+      other_sig_fun.NumOptionalPositionalParameters();
+  if (num_opt_pos_params != other_num_opt_pos_params) {
+    return false;
+  }
+  const intptr_t num_opt_named_params = sig_fun.NumOptionalNamedParameters();
+  const intptr_t other_num_opt_named_params =
+      other_sig_fun.NumOptionalNamedParameters();
+  if (num_opt_named_params != other_num_opt_named_params) {
+    return false;
+  }
+  const intptr_t num_ignored_params = sig_fun.NumImplicitParameters();
+  const intptr_t other_num_ignored_params =
+      other_sig_fun.NumImplicitParameters();
+  if (num_ignored_params != other_num_ignored_params) {
+    return false;
+  }
+  AbstractType& param_type = Type::Handle(zone);
+  AbstractType& other_param_type = Type::Handle(zone);
+  // Check the result type.
+  param_type = sig_fun.result_type();
+  other_param_type = other_sig_fun.result_type();
+  if (!param_type.Equals(other_param_type)) {
+    return false;
+  }
+  // Check the types of all parameters.
+  const intptr_t num_params = sig_fun.NumParameters();
+  ASSERT(other_sig_fun.NumParameters() == num_params);
+  for (intptr_t i = 0; i < num_params; i++) {
+    param_type = sig_fun.ParameterTypeAt(i);
+    other_param_type = other_sig_fun.ParameterTypeAt(i);
+    if (!param_type.Equals(other_param_type)) {
+      return false;
+    }
+  }
+  // Check the names and types of optional named parameters.
+  if (num_opt_named_params == 0) {
+    return true;
+  }
+  for (intptr_t i = num_fixed_params; i < num_params; i++) {
+    if (sig_fun.ParameterNameAt(i) != other_sig_fun.ParameterNameAt(i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+bool FunctionType::IsRecursive() const {
+  return TypeArguments::Handle(arguments()).IsRecursive();
+}
+
+
+RawAbstractType* FunctionType::CloneUnfinalized() const {
+  ASSERT(IsResolved());
+  if (IsFinalized()) {
+    return raw();
+  }
+  ASSERT(!IsMalformed());  // Malformed types are finalized.
+  ASSERT(!IsBeingFinalized());  // Cloning must occur prior to finalization.
+  TypeArguments& type_args = TypeArguments::Handle(arguments());
+  type_args = type_args.CloneUnfinalized();
+  const FunctionType& clone = FunctionType::Handle(
+      FunctionType::New(Class::Handle(scope_class()),
+                        type_args,
+                        Function::Handle(signature()),
+                        token_pos()));
+  clone.SetIsResolved();
+  return clone.raw();
+}
+
+
+RawAbstractType* FunctionType::CloneUninstantiated(const Class& new_owner,
+                                                   TrailPtr trail) const {
+  ASSERT(IsFinalized());
+  ASSERT(!IsMalformed());
+  if (IsInstantiated()) {
+    return raw();
+  }
+  // We may recursively encounter a type already being cloned, because we clone
+  // the upper bounds of its uninstantiated type arguments in the same pass.
+  FunctionType& clone = FunctionType::Handle();
+  clone ^= OnlyBuddyInTrail(trail);
+  if (!clone.IsNull()) {
+    return clone.raw();
+  }
+  clone = FunctionType::New(Class::Handle(scope_class()),
+                            TypeArguments::Handle(),
+                            Function::Handle(signature()),
+                            token_pos());
+  TypeArguments& type_args = TypeArguments::Handle(arguments());
+  // Upper bounds of uninstantiated type arguments may form a cycle.
+  if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
+    AddOnlyBuddyToTrail(&trail, clone);
+  }
+  type_args = type_args.CloneUninstantiated(new_owner, trail);
+  clone.set_arguments(type_args);
+  clone.SetIsFinalized();
+  return clone.raw();
+}
+
+
+RawAbstractType* FunctionType::Canonicalize(TrailPtr trail) const {
+  ASSERT(IsFinalized());
+  if (IsCanonical() || IsMalformed()) {
+    ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
+    return this->raw();
+  }
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  AbstractType& type = Type::Handle(zone);
+  const Class& scope_cls = Class::Handle(zone, type_class());
+  Array& canonical_types = Array::Handle(zone);
+  canonical_types ^= scope_cls.canonical_types();
+  if (canonical_types.IsNull()) {
+    canonical_types = empty_array().raw();
+  }
+  intptr_t length = canonical_types.Length();
+  // Linear search to see whether this type is already present in the
+  // list of canonicalized types.
+  // TODO(asiva): Try to re-factor this lookup code to make sharing
+  // easy between the 4 versions of this loop.
+  intptr_t index = 1;  // Slot 0 is reserved for CanonicalType().
+  while (index < length) {
+    type ^= canonical_types.At(index);
+    if (type.IsNull()) {
+      break;
+    }
+    ASSERT(type.IsFinalized());
+    if (this->Equals(type)) {
+      ASSERT(type.IsCanonical());
+      return type.raw();
+    }
+    index++;
+  }
+  // The type was not found in the table. It is not canonical yet.
+
+  // Canonicalize the type arguments.
+  TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+  // In case the type is first canonicalized at runtime, its type argument
+  // vector may be longer than necessary. This is not an issue.
+  ASSERT(type_args.IsNull() ||
+         (type_args.Length() >= scope_cls.NumTypeArguments()));
+  type_args = type_args.Canonicalize(trail);
+  set_arguments(type_args);
+
+  // Replace the actual function by a signature function.
+  const Function& fun = Function::Handle(zone, signature());
+  if (!fun.IsSignatureFunction()) {
+    Function& sig_fun =
+        Function::Handle(zone,
+                         Function::NewSignatureFunction(scope_cls,
+                                                        Token::kNoSourcePos));
+    type = fun.result_type();
+    type = type.Canonicalize(trail);
+    sig_fun.set_result_type(type);
+    const intptr_t num_params = fun.NumParameters();
+    sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
+    sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
+                                     fun.HasOptionalPositionalParameters());
+    sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
+                                                         Heap::kOld)));
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = fun.ParameterTypeAt(i);
+      type = type.Canonicalize(trail);
+      sig_fun.SetParameterTypeAt(i, type);
+    }
+    sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+    set_signature(sig_fun);
+  }
+
+  // Canonicalizing the type arguments and the signature may have changed the
+  // index, may have grown the table, or may even have canonicalized this type.
+  canonical_types ^= scope_cls.canonical_types();
+  if (canonical_types.IsNull()) {
+    canonical_types = empty_array().raw();
+  }
+  length = canonical_types.Length();
+  while (index < length) {
+    type ^= canonical_types.At(index);
+    if (type.IsNull()) {
+      break;
+    }
+    ASSERT(type.IsFinalized());
+    if (this->Equals(type)) {
+      ASSERT(type.IsCanonical());
+      return type.raw();
+    }
+    index++;
+  }
+
+  // The type needs to be added to the list. Grow the list if it is full.
+  if (index >= length) {
+    ASSERT((index == length) || ((index == 1) && (length == 0)));
+    const intptr_t new_length = (length > 64) ?
+        (length + 64) :
+        ((length == 0) ? 2 : (length * 2));
+    const Array& new_canonical_types = Array::Handle(
+        zone, Array::Grow(canonical_types, new_length, Heap::kOld));
+    scope_cls.set_canonical_types(new_canonical_types);
+    canonical_types = new_canonical_types.raw();
+  }
+  canonical_types.SetAt(index, *this);
+  ASSERT(IsOld());
+  ASSERT(type_args.IsNull() || type_args.IsOld());
+  SetCanonical();
+  return this->raw();
+}
+
+
+intptr_t FunctionType::Hash() const {
+  ASSERT(IsFinalized());
+  uint32_t result = 1;
+  if (IsMalformed()) return result;
+  result = CombineHashes(result, Class::Handle(scope_class()).id());
+  result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
+  const Function& sig_fun = Function::Handle(signature());
+  AbstractType& type = AbstractType::Handle(sig_fun.result_type());
+  result = CombineHashes(result, type.Hash());
+  result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
+  const intptr_t num_params = sig_fun.NumParameters();
+  for (intptr_t i = 0; i < num_params; i++) {
+    type = sig_fun.ParameterTypeAt(i);
+    result = CombineHashes(result, type.Hash());
+  }
+  if (sig_fun.NumOptionalNamedParameters() > 0) {
+    String& param_name = String::Handle();
+    for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
+      param_name = sig_fun.ParameterNameAt(i);
+      result = CombineHashes(result, param_name.Hash());
+    }
+  }
+  return FinalizeHash(result);
+}
+
+
+void FunctionType::set_scope_class(const Class& value) const {
+  ASSERT(!value.IsNull());
+  StorePointer(&raw_ptr()->scope_class_, value.raw());
+}
+
+
+void FunctionType::set_arguments(const TypeArguments& value) const {
+  StorePointer(&raw_ptr()->arguments_, value.raw());
+}
+
+
+void FunctionType::set_signature(const Function& value) const {
+  StorePointer(&raw_ptr()->signature_, value.raw());
+}
+
+
+RawFunctionType* FunctionType::New(Heap::Space space) {
+  RawObject* raw = Object::Allocate(FunctionType::kClassId,
+                                    FunctionType::InstanceSize(),
+                                    space);
+  return reinterpret_cast<RawFunctionType*>(raw);
+}
+
+
+RawFunctionType* FunctionType::New(const Class& clazz,
+                                   const TypeArguments& arguments,
+                                   const Function& signature,
+                                   intptr_t token_pos,
+                                   Heap::Space space) {
+  const FunctionType& result = FunctionType::Handle(FunctionType::New(space));
+  result.set_scope_class(clazz);
+  result.set_arguments(arguments);
+  result.set_signature(signature);
+  result.set_token_pos(token_pos);
+  result.StoreNonPointer(&result.raw_ptr()->type_state_,
+                         RawFunctionType::kAllocated);
+  return result.raw();
+}
+
+
+void FunctionType::set_token_pos(intptr_t token_pos) const {
+  ASSERT(!Token::IsClassifying(token_pos));
+  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
+}
+
+
+void FunctionType::set_type_state(int8_t state) const {
+  ASSERT((state >= RawFunctionType::kAllocated) &&
+         (state <= RawFunctionType::kFinalizedUninstantiated));
+  StoreNonPointer(&raw_ptr()->type_state_, state);
+}
+
+
+const char* FunctionType::ToCString() const {
+  const char* unresolved = IsResolved() ? "" : "Unresolved ";
+  const Class& scope_cls = Class::Handle(scope_class());
+  const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
+  const Function& signature_function = Function::Handle(signature());
+  const String& signature_string = String::Handle(
+      signature_function.InstantiatedSignatureFrom(type_arguments,
+                                                   kInternalName));
+  if (scope_cls.IsClosureClass()) {
+    ASSERT(arguments() == TypeArguments::null());
+    return OS::SCreate(
+        Thread::Current()->zone(),
+        "%sFunctionType: %s", unresolved, signature_string.ToCString());
+  }
+  const char* class_name = String::Handle(scope_cls.Name()).ToCString();
+  const char* args_cstr =
+      type_arguments.IsNull() ? "null" : type_arguments.ToCString();
+  return OS::SCreate(
+      Thread::Current()->zone(),
+      "%s FunctionType: %s (scope_cls: %s, args: %s)",
+      unresolved,
+      signature_string.ToCString(),
+      class_name,
+      args_cstr);
+}
+
+
+void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  JSONObject jsobj(stream);
+  PrintSharedInstanceJSON(&jsobj, ref);
+  jsobj.AddProperty("kind", "FunctionType");
+  if (IsCanonical()) {
+    const Class& scope_cls = Class::Handle(scope_class());
+    intptr_t id = scope_cls.FindCanonicalTypeIndex(*this);
+    ASSERT(id >= 0);
+    intptr_t cid = scope_cls.id();
+    jsobj.AddFixedServiceId("classes/%" Pd "/types/%" Pd "", cid, id);
+    jsobj.AddProperty("scopeClass", scope_cls);
+  } else {
+    jsobj.AddServiceId(*this);
+  }
+  const String& user_name = String::Handle(PrettyName());
+  const String& vm_name = String::Handle(Name());
+  AddNameProperties(&jsobj, user_name, vm_name);
+  if (ref) {
+    return;
+  }
+  const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
+  if (!typeArgs.IsNull()) {
+    jsobj.AddProperty("typeArguments", typeArgs);
+  }
+}
+
+
 bool TypeRef::IsInstantiated(TrailPtr trail) const {
   if (TestAndAddToTrail(&trail)) {
     return true;
@@ -16528,7 +17251,7 @@
 
 
 void TypeRef::set_type(const AbstractType& value) const {
-  ASSERT(value.HasResolvedTypeClass());
+  ASSERT(value.IsFunctionType() || value.HasResolvedTypeClass());
   ASSERT(!value.IsTypeRef());
   StorePointer(&raw_ptr()->type_, value.raw());
 }
@@ -16640,7 +17363,7 @@
 }
 
 
-void TypeParameter::set_is_finalized() const {
+void TypeParameter::SetIsFinalized() const {
   ASSERT(!IsFinalized());
   set_type_state(RawTypeParameter::kFinalizedUninstantiated);
 }
@@ -16747,6 +17470,7 @@
           *bound_error,
           script,
           token_pos(),
+          Report::AtLocation,
           Report::kMalboundedType,
           Heap::kNew,
           "type parameter '%s' of class '%s' must extend bound '%s', "
@@ -16789,7 +17513,7 @@
                          String::Handle(name()),
                          upper_bound,
                          token_pos()));
-  clone.set_is_finalized();
+  clone.SetIsFinalized();
   return clone.raw();
 }
 
@@ -16830,7 +17554,7 @@
 
 
 void TypeParameter::set_token_pos(intptr_t token_pos) const {
-  ASSERT(Scanner::ValidSourcePosition(token_pos));
+  ASSERT(!Token::IsClassifying(token_pos));
   StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
 }
 
@@ -21466,8 +22190,8 @@
 }
 
 
-const char* Closure::ToCString(const Instance& closure) {
-  const Function& fun = Function::Handle(Closure::function(closure));
+const char* Closure::ToCString() const {
+  const Function& fun = Function::Handle(function());
   const bool is_implicit_closure = fun.IsImplicitClosureFunction();
   const char* fun_sig = String::Handle(fun.UserVisibleSignature()).ToCString();
   const char* from = is_implicit_closure ? " from " : "";
@@ -21477,23 +22201,36 @@
 }
 
 
-RawInstance* Closure::New(const Function& function,
-                          const Context& context,
-                          Heap::Space space) {
-  const Class& cls = Class::Handle(function.signature_class());
-  ASSERT(cls.instance_size() == Closure::InstanceSize());
-  Instance& result = Instance::Handle();
+void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Instance::PrintJSONImpl(stream, ref);
+}
+
+
+RawClosure* Closure::New(const Function& function,
+                         const Context& context,
+                         Heap::Space space) {
+  Closure& result = Closure::Handle();
   {
-    RawObject* raw = Object::Allocate(cls.id(), Closure::InstanceSize(), space);
+    RawObject* raw = Object::Allocate(Closure::kClassId,
+                                      Closure::InstanceSize(),
+                                      space);
     NoSafepointScope no_safepoint;
     result ^= raw;
+    result.StorePointer(&result.raw_ptr()->function_, function.raw());
+    result.StorePointer(&result.raw_ptr()->context_, context.raw());
   }
-  Closure::set_function(result, function);
-  Closure::set_context(result, context);
   return result.raw();
 }
 
 
+RawClosure* Closure::New() {
+  RawObject* raw = Object::Allocate(Closure::kClassId,
+                                    Closure::InstanceSize(),
+                                    Heap::kOld);
+  return reinterpret_cast<RawClosure*>(raw);
+}
+
+
 intptr_t Stacktrace::Length() const {
   const Array& code_array = Array::Handle(raw_ptr()->code_array_);
   return code_array.Length();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index d67b06a..5ce318c 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -507,6 +507,7 @@
   static RawClass* instructions_class() { return instructions_class_; }
   static RawClass* object_pool_class() { return object_pool_class_; }
   static RawClass* pc_descriptors_class() { return pc_descriptors_class_; }
+  static RawClass* code_source_map_class() { return code_source_map_class_; }
   static RawClass* stackmap_class() { return stackmap_class_; }
   static RawClass* var_descriptors_class() { return var_descriptors_class_; }
   static RawClass* exception_handlers_class() {
@@ -768,6 +769,7 @@
   static RawClass* instructions_class_;  // Class of the Instructions vm object.
   static RawClass* object_pool_class_;  // Class of the ObjectPool vm object.
   static RawClass* pc_descriptors_class_;  // Class of PcDescriptors vm object.
+  static RawClass* code_source_map_class_;  // Class of CodeSourceMap vm object.
   static RawClass* stackmap_class_;  // Class of Stackmap vm object.
   static RawClass* var_descriptors_class_;  // Class of LocalVarDescriptors.
   static RawClass* exception_handlers_class_;  // Class of ExceptionHandlers.
@@ -941,26 +943,11 @@
 
   intptr_t ComputeEndTokenPos() const;
 
-  // This class represents the signature class of a closure function if
-  // signature_function() is not null.
-  // The associated function may be a closure function (with code) or a
-  // signature function (without code) solely describing the result type and
-  // parameter types of the signature.
+  // This class represents a typedef if the signature function is not null.
   RawFunction* signature_function() const {
     return raw_ptr()->signature_function_;
   }
-  static intptr_t signature_function_offset() {
-    return OFFSET_OF(RawClass, signature_function_);
-  }
-
-  // Return the signature type of this signature class.
-  // For example, if this class represents a signature of the form
-  // 'F<T, R>(T, [b: B, c: C]) => R', then its signature type is a parameterized
-  // type with this class as the type class and type parameters 'T' and 'R'
-  // as its type argument vector.
-  // SignatureType is used as the type of formal parameters representing a
-  // function.
-  RawType* SignatureType() const;
+  void set_signature_function(const Function& value) const;
 
   // Return the Type with type parameters declared by this class filled in with
   // dynamic and type parameters declared in superclasses filled in as declared
@@ -1004,6 +991,7 @@
   // not overlapping with the type arguments of the super class of this class.
   intptr_t NumOwnTypeArguments() const;
 
+  // Return true if this class declares type parameters.
   bool IsGeneric() const;
 
   // If this class is parameterized, each instance has a type_arguments field.
@@ -1094,22 +1082,23 @@
   // Check if this class represents the 'Function' class.
   bool IsFunctionClass() const;
 
-  // Check if this class represents a signature class.
-  bool IsSignatureClass() const {
+  // Check if this class represents the 'Closure' class.
+  bool IsClosureClass() const  { return id() == kClosureCid; }
+  static bool IsClosureClass(RawClass* cls) {
+    NoSafepointScope no_safepoint;
+    return cls->ptr()->id_ == kClosureCid;
+  }
+
+  // Check if this class represents a typedef class.
+  bool IsTypedefClass() const {
     return signature_function() != Object::null();
   }
-  static bool IsSignatureClass(RawClass* cls) {
-    return cls->ptr()->signature_function_ != Object::null();
-  }
+
   static bool IsInFullSnapshot(RawClass* cls) {
     NoSafepointScope no_safepoint;
     return cls->ptr()->library_->ptr()->is_in_fullsnapshot_;
   }
 
-  // Check if this class represents a canonical signature class, i.e. not an
-  // alias as defined in a typedef.
-  bool IsCanonicalSignatureClass() const;
-
   // Check the subtype relationship.
   bool IsSubtypeOf(const TypeArguments& type_arguments,
                    const Class& other,
@@ -1184,8 +1173,8 @@
 
   void InsertCanonicalConstant(intptr_t index, const Instance& constant) const;
 
-  intptr_t FindCanonicalTypeIndex(const Type& needle) const;
-  RawType* CanonicalTypeFromIndex(intptr_t idx) const;
+  intptr_t FindCanonicalTypeIndex(const AbstractType& needle) const;
+  RawAbstractType* CanonicalTypeFromIndex(intptr_t idx) const;
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawClass));
@@ -1334,21 +1323,6 @@
   // Allocate the raw ExternalTypedData classes.
   static RawClass* NewExternalTypedDataClass(intptr_t class_id);
 
-  // Allocate a class representing a function signature described by
-  // signature_function, which must be a closure function or a signature
-  // function.
-  // The class may be type parameterized unless the signature_function is in a
-  // static scope. In that case, the type parameters are copied from the owner
-  // class of signature_function.
-  // A null signature function may be passed in and patched later. See below.
-  static RawClass* NewSignatureClass(const String& name,
-                                     const Function& signature_function,
-                                     const Script& script,
-                                     intptr_t token_pos);
-
-  // Patch the signature function of a signature class allocated without it.
-  void PatchSignatureFunction(const Function& signature_function) const;
-
   // Register code that has used CHA for optimization.
   // TODO(srdjan): Also register kind of CHA optimization (e.g.: leaf class,
   // leaf method, ...).
@@ -1409,8 +1383,6 @@
   void set_user_name(const String& value) const;
   RawString* GeneratePrettyName() const;
   RawString* GenerateUserVisibleName() const;
-  void set_signature_function(const Function& value) const;
-  void set_signature_type(const AbstractType& value) const;
   void set_state_bits(intptr_t bits) const;
 
   void set_constants(const Array& value) const;
@@ -1483,6 +1455,7 @@
   friend class Instance;
   friend class Object;
   friend class Type;
+  friend class FunctionType;
   friend class Intrinsifier;
   friend class Precompiler;
 };
@@ -2108,6 +2081,17 @@
 
   RawString* GetSource() const;
 
+  // Return the type of this function's signature. It may not be canonical yet.
+  // For example, if this function has a signature of the form
+  // '(T, [b: B, c: C]) => R', where 'T' and 'R' are type parameters of the
+  // owner class of this function, then its signature type is a parameterized
+  // FunctionType with uninstantiated type arguments 'T' and 'R' as elements of
+  // its type argument vector.
+  RawFunctionType* SignatureType() const;
+
+  // Update the signature type (with a canonical version).
+  void SetSignatureType(const FunctionType& value) const;
+
   // Build a string of the form 'C<T, R>(T, {b: B, c: C}) => R' representing the
   // internal signature of the given function. In this example, T and R are
   // type parameters of class C, the owner of the function.
@@ -2124,9 +2108,10 @@
 
   // Build a string of the form '(T, {b: B, c: C}) => R' representing the
   // user visible signature of the given function. In this example, T and R are
-  // type parameters of class C, the owner of the function.
+  // type parameters of class C, the owner of the function, also called the
+  // scope class of the function type.
   // Implicit parameters are hidden, as well as the prefix denoting the
-  // signature class and its type parameters.
+  // scope class and its type parameters.
   RawString* UserVisibleSignature() const {
     const bool instantiate = false;
     return BuildSignature(
@@ -2219,10 +2204,6 @@
   // Enclosing function of this local function.
   RawFunction* parent_function() const;
 
-  // Signature class of this closure function or signature function.
-  RawClass* signature_class() const;
-  void set_signature_class(const Class& value) const;
-
   void set_extracted_method_closure(const Function& function) const;
   RawFunction* extracted_method_closure() const;
 
@@ -2494,6 +2475,14 @@
                     space);
   }
 
+  // Check the subtype or 'more specific' relationship.
+  bool TypeTest(TypeTestKind test_kind,
+                const TypeArguments& type_arguments,
+                const Function& other,
+                const TypeArguments& other_type_arguments,
+                Error* bound_error,
+                Heap::Space space) const;
+
   // Returns true if this function represents an explicit getter function.
   bool IsGetterFunction() const {
     return kind() == RawFunction::kGetterFunction;
@@ -2557,6 +2546,11 @@
   bool IsSignatureFunction() const {
     return kind() == RawFunction::kSignatureFunction;
   }
+  static bool IsSignatureFunction(RawFunction* function) {
+    NoSafepointScope no_safepoint;
+    return KindBits::decode(function->ptr()->kind_tag_) ==
+        RawFunction::kSignatureFunction;
+  }
 
   bool IsAsyncFunction() const {
     return modifier() == RawFunction::kAsync;
@@ -2612,14 +2606,16 @@
                           const Object& owner,
                           intptr_t token_pos);
 
-  // Allocates a new Function object representing a closure function, as well as
-  // a new associated Class object representing the signature class of the
-  // function.
-  // The function and the class share the same given name.
+  // Allocates a new Function object representing a closure function.
   static RawFunction* NewClosureFunction(const String& name,
                                          const Function& parent,
                                          intptr_t token_pos);
 
+  // Allocates a new Function object representing a signature function.
+  // The owner is the scope class of the function type.
+  static RawFunction* NewSignatureFunction(const Class& owner,
+                                           intptr_t token_pos);
+
   static RawFunction* NewEvalFunction(const Class& owner,
                                       const Script& script,
                                       bool is_static);
@@ -2775,14 +2771,6 @@
                             NameVisibility name_visibility,
                             const TypeArguments& instantiator) const;
 
-  // Check the subtype or 'more specific' relationship.
-  bool TypeTest(TypeTestKind test_kind,
-                const TypeArguments& type_arguments,
-                const Function& other,
-                const TypeArguments& other_type_arguments,
-                Error* bound_error,
-                Heap::Space space) const;
-
   // Checks the type of the formal parameter at the given position for
   // subtyping or 'more specific' relationship between the type of this function
   // and the type of the other function.
@@ -2819,9 +2807,9 @@
   RawFunction* parent_function() const { return raw_ptr()->parent_function_; }
   void set_parent_function(const Function& value) const;
 
-  // Signature class of this closure function or signature function.
-  RawClass* signature_class() const { return raw_ptr()->signature_class_; }
-  void set_signature_class(const Class& value) const;
+  // Signature type of this closure function.
+  RawFunctionType* signature_type() const { return raw_ptr()->signature_type_; }
+  void set_signature_type(const FunctionType& value) const;
 
   RawInstance* implicit_static_closure() const {
     return raw_ptr()->closure_;
@@ -3601,7 +3589,8 @@
   void InitClassDictionary() const;
 
   RawArray* resolved_names() const { return raw_ptr()->resolved_names_; }
-  void InitResolvedNamesCache(intptr_t size) const;
+  void InitResolvedNamesCache(intptr_t size,
+                              SnapshotReader* reader = NULL) const;
   void GrowResolvedNamesCache() const;
   bool LookupResolvedNamesCache(const String& name, Object* obj) const;
   void AddToResolvedNamesCache(const String& name, const Object& obj) const;
@@ -3986,6 +3975,77 @@
 };
 
 
+class CodeSourceMap : public Object {
+ public:
+  static const intptr_t kBytesPerElement = 1;
+  static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
+
+  static intptr_t InstanceSize() {
+    ASSERT(sizeof(RawCodeSourceMap) ==
+           OFFSET_OF_RETURNED_VALUE(RawCodeSourceMap, data));
+    return 0;
+  }
+  static intptr_t InstanceSize(intptr_t len) {
+    ASSERT(0 <= len && len <= kMaxElements);
+    return RoundedAllocationSize(sizeof(RawCodeSourceMap) + len);
+  }
+
+  static RawCodeSourceMap* New(GrowableArray<uint8_t>* delta_encoded_data);
+
+  void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
+
+  // Encode integer in SLEB128 format.
+  static void EncodeInteger(GrowableArray<uint8_t>* data, intptr_t value);
+
+  // Decode SLEB128 encoded integer. Update byte_index to the next integer.
+  intptr_t DecodeInteger(intptr_t* byte_index) const;
+
+  class Iterator : ValueObject {
+   public:
+    explicit Iterator(const CodeSourceMap& code_source_map)
+        : code_source_map_(code_source_map),
+          byte_index_(0),
+          cur_pc_offset_(0),
+          cur_token_pos_(0) {
+    }
+
+    bool MoveNext() {
+      // Moves to the next record.
+      while (byte_index_ < code_source_map_.Length()) {
+        cur_pc_offset_ += code_source_map_.DecodeInteger(&byte_index_);
+        cur_token_pos_ += code_source_map_.DecodeInteger(&byte_index_);
+
+        return true;
+      }
+      return false;
+    }
+
+    uword PcOffset() const { return cur_pc_offset_; }
+    intptr_t TokenPos() const { return cur_token_pos_; }
+
+   private:
+    friend class CodeSourceMap;
+
+    const CodeSourceMap& code_source_map_;
+    intptr_t byte_index_;
+
+    intptr_t cur_pc_offset_;
+    intptr_t cur_token_pos_;
+  };
+
+ private:
+  static RawCodeSourceMap* New(intptr_t length);
+
+  intptr_t Length() const;
+  void SetLength(intptr_t value) const;
+  void CopyData(GrowableArray<uint8_t>* data);
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(CodeSourceMap, Object);
+  friend class Class;
+  friend class Object;
+};
+
+
 class Stackmap : public Object {
  public:
   static const intptr_t kNoMaximum = -1;
@@ -4216,6 +4276,15 @@
     StorePointer(&raw_ptr()->pc_descriptors_, descriptors.raw());
   }
 
+  RawCodeSourceMap* code_source_map() const {
+    return raw_ptr()->code_source_map_;
+  }
+
+  void set_code_source_map(const CodeSourceMap& code_source_map) const {
+    ASSERT(code_source_map.IsOld());
+    StorePointer(&raw_ptr()->code_source_map_, code_source_map.raw());
+  }
+
   // Array of DeoptInfo objects.
   RawArray* deopt_info_array() const {
     return raw_ptr()->deopt_info_array_;
@@ -4726,7 +4795,7 @@
 class SubtypeTestCache : public Object {
  public:
   enum Entries {
-    kInstanceClassId = 0,
+    kInstanceClassIdOrFunction = 0,
     kInstanceTypeArguments = 1,
     kInstantiatorTypeArguments = 2,
     kTestResult = 3,
@@ -4734,12 +4803,12 @@
   };
 
   intptr_t NumberOfChecks() const;
-  void AddCheck(intptr_t class_id,
+  void AddCheck(const Object& instance_class_id_or_function,
                 const TypeArguments& instance_type_arguments,
                 const TypeArguments& instantiator_type_arguments,
                 const Bool& test_result) const;
   void GetCheck(intptr_t ix,
-                intptr_t* class_id,
+                Object* instance_class_id_or_function,
                 TypeArguments* instance_type_arguments,
                 TypeArguments* instantiator_type_arguments,
                 Bool* test_result) const;
@@ -4817,14 +4886,16 @@
   static RawLanguageError* NewFormatted(const Error& prev_error,
                                         const Script& script,
                                         intptr_t token_pos,
+                                        bool report_after_token,
                                         Report::Kind kind,
                                         Heap::Space space,
                                         const char* format, ...)
-    PRINTF_ATTRIBUTE(6, 7);
+    PRINTF_ATTRIBUTE(7, 8);
 
   static RawLanguageError* NewFormattedV(const Error& prev_error,
                                          const Script& script,
                                          intptr_t token_pos,
+                                         bool report_after_token,
                                          Report::Kind kind,
                                          Heap::Space space,
                                          const char* format, va_list args);
@@ -4847,6 +4918,9 @@
   intptr_t token_pos() const { return raw_ptr()->token_pos_; }
   void set_token_pos(intptr_t value) const;
 
+  bool report_after_token() const { return raw_ptr()->report_after_token_; }
+  void set_report_after_token(bool value);
+
   void set_kind(uint8_t value) const;
 
   RawString* message() const { return raw_ptr()->message_; }
@@ -4957,7 +5031,7 @@
     StorePointer(FieldAddr(field), value.raw());
   }
 
-  RawType* GetType() const;
+  RawAbstractType* GetType() const;
 
   virtual RawTypeArguments* GetTypeArguments() const;
   virtual void SetTypeArguments(const TypeArguments& value) const;
@@ -4984,9 +5058,6 @@
 
   void SetNativeField(int index, intptr_t value) const;
 
-  // Returns true if the instance is a closure object.
-  bool IsClosure() const;
-
   // If the instance is a callable object, i.e. a closure or the instance of a
   // class implementing a 'call' method, return true and set the function
   // (if not NULL) to call.
@@ -5113,17 +5184,21 @@
 class AbstractType : public Instance {
  public:
   virtual bool IsFinalized() const;
+  virtual void SetIsFinalized() const;
   virtual bool IsBeingFinalized() const;
+  virtual void SetIsBeingFinalized() const;
   virtual bool IsMalformed() const;
   virtual bool IsMalbounded() const;
   virtual bool IsMalformedOrMalbounded() const;
   virtual RawLanguageError* error() const;
   virtual void set_error(const LanguageError& value) const;
   virtual bool IsResolved() const;
+  virtual void SetIsResolved() const;
   virtual bool HasResolvedTypeClass() const;
   virtual RawClass* type_class() const;
   virtual RawUnresolvedClass* unresolved_class() const;
   virtual RawTypeArguments* arguments() const;
+  virtual void set_arguments(const TypeArguments& value) const;
   virtual intptr_t token_pos() const;
   virtual bool IsInstantiated(TrailPtr trail = NULL) const;
   virtual bool CanonicalizeEquals(const Instance& other) const {
@@ -5238,8 +5313,8 @@
   // Check if this type represents the 'String' type.
   bool IsStringType() const;
 
-  // Check if this type represents the 'Function' type.
-  bool IsFunctionType() const;
+  // Check if this type represents the Dart 'Function' type.
+  bool IsDartFunctionType() const;
 
   // Check the subtype relationship.
   bool IsSubtypeOf(const AbstractType& other,
@@ -5291,12 +5366,11 @@
         (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) ||
         (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated);
   }
-  void SetIsFinalized() const;
-  void ResetIsFinalized() const;  // Ignore current state and set again.
+  virtual void SetIsFinalized() const;
   virtual bool IsBeingFinalized() const {
     return raw_ptr()->type_state_ == RawType::kBeingFinalized;
   }
-  void set_is_being_finalized() const;
+  virtual void SetIsBeingFinalized() const;
   virtual bool IsMalformed() const;
   virtual bool IsMalbounded() const;
   virtual bool IsMalformedOrMalbounded() const;
@@ -5305,13 +5379,13 @@
   virtual bool IsResolved() const {
     return raw_ptr()->type_state_ >= RawType::kResolved;
   }
-  void set_is_resolved() const;
+  virtual void SetIsResolved() const;
   virtual bool HasResolvedTypeClass() const;  // Own type class resolved.
   virtual RawClass* type_class() const;
   void set_type_class(const Object& value) const;
   virtual RawUnresolvedClass* unresolved_class() const;
-  virtual RawTypeArguments* arguments() const;
-  void set_arguments(const TypeArguments& value) const;
+  virtual RawTypeArguments* arguments() const { return raw_ptr()->arguments_; }
+  virtual void set_arguments(const TypeArguments& value) const;
   virtual intptr_t token_pos() const { return raw_ptr()->token_pos_; }
   virtual bool IsInstantiated(TrailPtr trail = NULL) const;
   virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
@@ -5401,6 +5475,104 @@
 };
 
 
+// TODO(regis): FunctionType is very similar to Type. Instead of a separate
+// class FunctionType, we could consider an object of class Type as representing
+// a function type if it has a non-null function (signature) field.
+// In order to save space, we could reuse the error_ field? A malformed or
+// malbounded function type would lose its function reference, but the error
+// string would contain relevant info.
+
+// A FunctionType describes the signature of a function, i.e. the result type
+// and formal parameter types of the function, as well as the names of optional
+// named formal parameters.
+// If these types refer to type parameters of a class in scope, the function
+// type is generic. A generic function type may be instantiated by a type
+// argument vector.
+// Therefore, a FunctionType consists of a scope class, a type argument vector,
+// and a signature.
+// The scope class is either a generic class (or generic typedef) declaring the
+// type parameters referred to by the signature, or class _Closure in the
+// non-generic case (including the non-generic typedef case).
+// The type arguments specify an instantiation of the generic signature (null in
+// the non-generic case).
+// The signature is a reference to an actual closure function (kClosureFunction)
+// or to a signature function (kSignatureFunction).
+// Since typedefs cannot refer to themselves, directly or indirectly, a
+// FunctionType cannot be recursive. Only individual formal parameter types can.
+class FunctionType : public AbstractType {
+ public:
+  virtual bool IsFinalized() const {
+    return
+        (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) ||
+        (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated);
+  }
+  virtual void SetIsFinalized() const;
+  void ResetIsFinalized() const;  // Ignore current state and set again.
+  virtual bool IsBeingFinalized() const {
+    return raw_ptr()->type_state_ == RawFunctionType::kBeingFinalized;
+  }
+  virtual void SetIsBeingFinalized() const;
+  virtual bool IsMalformed() const;
+  virtual bool IsMalbounded() const;
+  virtual bool IsMalformedOrMalbounded() const;
+  virtual RawLanguageError* error() const { return raw_ptr()->error_; }
+  virtual void set_error(const LanguageError& value) const;
+  virtual bool IsResolved() const {
+    return raw_ptr()->type_state_ >= RawFunctionType::kResolved;
+  }
+  virtual void SetIsResolved() const;
+  // The scope class of a FunctionType is always resolved. It has no actual
+  // type class. Returning false is important for the type testers to work, e.g.
+  // IsDynamicType(), IsBoolType(), etc...
+  virtual bool HasResolvedTypeClass() const { return false; }
+  // Return scope_class from virtual type_class() to factorize finalization
+  // with Type, also a parameterized type.
+  virtual RawClass* type_class() const { return scope_class(); }
+  RawClass* scope_class() const { return raw_ptr()->scope_class_; }
+  void set_scope_class(const Class& value) const;
+  virtual RawTypeArguments* arguments() const { return raw_ptr()->arguments_; }
+  virtual void set_arguments(const TypeArguments& value) const;
+  RawFunction* signature() const { return raw_ptr()->signature_; }
+  virtual intptr_t token_pos() const { return raw_ptr()->token_pos_; }
+  virtual bool IsInstantiated(TrailPtr trail = NULL) const;
+  virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
+  virtual bool IsRecursive() const;
+  virtual RawAbstractType* InstantiateFrom(
+      const TypeArguments& instantiator_type_arguments,
+      Error* malformed_error,
+      TrailPtr trail = NULL,
+      Heap::Space space = Heap::kNew) const;
+  virtual RawAbstractType* CloneUnfinalized() const;
+  virtual RawAbstractType* CloneUninstantiated(
+      const Class& new_owner,
+      TrailPtr trail = NULL) const;
+  virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const;
+
+  virtual intptr_t Hash() const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawFunctionType));
+  }
+
+  static RawFunctionType* New(const Class& scope_class,
+                              const TypeArguments& arguments,
+                              const Function& signature,
+                              intptr_t token_pos,
+                              Heap::Space space = Heap::kOld);
+
+ private:
+  void set_signature(const Function& value) const;
+  void set_token_pos(intptr_t token_pos) const;
+  void set_type_state(int8_t state) const;
+
+  static RawFunctionType* New(Heap::Space space = Heap::kOld);
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(FunctionType, AbstractType);
+  friend class Class;
+  friend class TypeArguments;
+};
+
+
 // A TypeRef is used to break cycles in the representation of recursive types.
 // Its only field is the recursive AbstractType it refers to.
 // Note that the cycle always involves type arguments.
@@ -5422,7 +5594,10 @@
     return AbstractType::Handle(type()).IsMalformedOrMalbounded();
   }
   virtual bool IsResolved() const { return true; }
-  virtual bool HasResolvedTypeClass() const { return true; }
+  virtual bool HasResolvedTypeClass() const {
+    // Returns false if the ref type is a function type.
+    return AbstractType::Handle(type()).HasResolvedTypeClass();
+  }
   RawAbstractType* type() const { return raw_ptr()->type_; }
   void set_type(const AbstractType& value) const;
   virtual RawClass* type_class() const {
@@ -5491,7 +5666,7 @@
     ASSERT(raw_ptr()->type_state_ != RawTypeParameter::kFinalizedInstantiated);
     return raw_ptr()->type_state_ == RawTypeParameter::kFinalizedUninstantiated;
   }
-  void set_is_finalized() const;
+  virtual void SetIsFinalized() const;
   virtual bool IsBeingFinalized() const { return false; }
   virtual bool IsMalformed() const { return false; }
   virtual bool IsMalbounded() const { return false; }
@@ -7667,86 +7842,45 @@
 };
 
 
-class Closure : public AllStatic {
+class Closure : public Instance {
  public:
-  static RawFunction* function(const Instance& closure) {
-    return *FunctionAddr(closure);
+  RawFunction* function() const { return raw_ptr()->function_; }
+  void set_function(const Function& function) const {
+    // TODO(regis): Only used from deferred_objects.cc. Remove once fixed.
+    StorePointer(&raw_ptr()->function_, function.raw());
   }
-  static intptr_t function_offset() {
-    return static_cast<intptr_t>(kFunctionOffset * kWordSize);
-  }
+  static intptr_t function_offset() { return OFFSET_OF(RawClosure, function_); }
 
-  static RawContext* context(const Instance& closure) {
-    return *ContextAddr(closure);
+  RawContext* context() const { return raw_ptr()->context_; }
+  void set_context(const Context& context) const {
+    // TODO(regis): Only used from deferred_objects.cc. Remove once fixed.
+    StorePointer(&raw_ptr()->context_, context.raw());
   }
-  static intptr_t context_offset() {
-    return static_cast<intptr_t>(kContextOffset * kWordSize);
-  }
+  static intptr_t context_offset() { return OFFSET_OF(RawClosure, context_); }
 
-  static RawTypeArguments* GetTypeArguments(const Instance& closure) {
-    return *TypeArgumentsAddr(closure);
-  }
-  static void SetTypeArguments(const Instance& closure,
-                               const TypeArguments& value) {
-    ASSERT(value.IsNull() || value.IsCanonical());
-    closure.StorePointer(TypeArgumentsAddr(closure), value.raw());
-  }
   static intptr_t type_arguments_offset() {
-    return static_cast<intptr_t>(kTypeArgumentsOffset * kWordSize);
+    return OFFSET_OF(RawClosure, type_arguments_);
   }
 
-  static const char* ToCString(const Instance& closure);
-
   static intptr_t InstanceSize() {
-    intptr_t size = sizeof(RawInstance) + (kNumFields * kWordSize);
-    ASSERT(size == Object::RoundedAllocationSize(size));
-    return size;
+    return RoundedAllocationSize(sizeof(RawClosure));
   }
 
-  static RawInstance* New(const Function& function,
-                          const Context& context,
-                          Heap::Space space = Heap::kNew);
+  // Returns true if all elements are OK for canonicalization.
+  virtual bool CheckAndCanonicalizeFields(const char** error_str) const {
+    // None of the fields of a closure are instances.
+    return true;
+  }
+
+  static RawClosure* New(const Function& function,
+                         const Context& context,
+                         Heap::Space space = Heap::kNew);
 
  private:
-  static const int kTypeArgumentsOffset = 1;
-  static const int kFunctionOffset = 2;
-  static const int kContextOffset = 3;
-  static const int kNumFields = 3;
+  static RawClosure* New();
 
-  static RawTypeArguments** TypeArgumentsAddr(const Instance& obj) {
-    ASSERT(obj.IsClosure());
-    return reinterpret_cast<RawTypeArguments**>(
-        reinterpret_cast<intptr_t>(obj.raw_ptr()) + type_arguments_offset());
-  }
-  static RawFunction** FunctionAddr(const Instance& obj) {
-    ASSERT(obj.IsClosure());
-    return reinterpret_cast<RawFunction**>(
-        reinterpret_cast<intptr_t>(obj.raw_ptr()) + function_offset());
-  }
-  static RawContext** ContextAddr(const Instance& obj) {
-    ASSERT(obj.IsClosure());
-    return reinterpret_cast<RawContext**>(
-        reinterpret_cast<intptr_t>(obj.raw_ptr()) + context_offset());
-  }
-  static void set_function(const Instance& closure,
-                           const Function& value) {
-    closure.StorePointer(FunctionAddr(closure), value.raw());
-  }
-  static void set_context(const Instance& closure,
-                          const Context& value) {
-    closure.StorePointer(ContextAddr(closure), value.raw());
-  }
-  static intptr_t NextFieldOffset() {
-    // Indicates this class cannot be extended by dart code.
-    return -kWordSize;
-  }
-  static RawFunction* GetFunction(RawObject* obj) {
-    return *(reinterpret_cast<RawFunction**>(
-        reinterpret_cast<intptr_t>(obj->ptr()) + function_offset()));
-  }
-
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Closure, Instance);
   friend class Class;
-  friend class SnapshotWriter;
 };
 
 
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 624e1fe..c5a6be6 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -20,7 +20,7 @@
     null_class_(Class::null()),
     null_type_(Type::null()),
     function_type_(Type::null()),
-    function_impl_type_(Type::null()),
+    closure_class_(Class::null()),
     number_type_(Type::null()),
     int_type_(Type::null()),
     integer_implementation_class_(Class::null()),
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index db57663..2b68902 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -67,9 +67,9 @@
     function_type_ = value.raw();
   }
 
-  RawType* function_impl_type() const { return function_impl_type_; }
-  void set_function_impl_type(const Type& value) {
-    function_impl_type_ = value.raw();
+  RawClass* closure_class() const { return closure_class_; }
+  void set_closure_class(const Class& value) {
+    closure_class_ = value.raw();
   }
 
   RawType* number_type() const { return number_type_; }
@@ -504,7 +504,7 @@
   RawClass* null_class_;
   RawType* null_type_;
   RawType* function_type_;
-  RawType* function_impl_type_;
+  RawClass* closure_class_;
   RawType* number_type_;
   RawType* int_type_;
   RawClass* integer_implementation_class_;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 422121e..9f31fee 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -29,7 +29,7 @@
 static RawClass* CreateDummyClass(const String& class_name,
                                   const Script& script) {
   const Class& cls = Class::Handle(
-      Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::New(class_name, script, Token::kNoSourcePos));
   cls.set_is_synthesized_class();  // Dummy class for testing.
   return cls.raw();
 }
@@ -2537,17 +2537,17 @@
   const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
   const String& a = String::ZoneHandle(Symbols::New("a"));
   LocalVariable* var_a =
-      new LocalVariable(Scanner::kNoSourcePos, a, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, a, dynamic_type);
   parent_scope->AddVariable(var_a);
 
   const String& b = String::ZoneHandle(Symbols::New("b"));
   LocalVariable* var_b =
-      new LocalVariable(Scanner::kNoSourcePos, b, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, b, dynamic_type);
   local_scope->AddVariable(var_b);
 
   const String& c = String::ZoneHandle(Symbols::New("c"));
   LocalVariable* var_c =
-      new LocalVariable(Scanner::kNoSourcePos, c, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, c, dynamic_type);
   parent_scope->AddVariable(var_c);
 
   bool test_only = false;  // Please, insert alias.
@@ -2630,18 +2630,13 @@
   Function& function = Function::Handle();
   const String& function_name = String::Handle(Symbols::New("foo"));
   function = Function::NewClosureFunction(function_name, parent, 0);
-  const Class& signature_class = Class::Handle(
-      Class::NewSignatureClass(function_name, function, script, 0));
-  const Instance& closure = Instance::Handle(Closure::New(function, context));
+  const Closure& closure = Closure::Handle(Closure::New(function, context));
   const Class& closure_class = Class::Handle(closure.clazz());
-  EXPECT(closure_class.IsSignatureClass());
-  EXPECT(closure_class.IsCanonicalSignatureClass());
-  EXPECT_EQ(closure_class.raw(), signature_class.raw());
-  const Function& signature_function =
-    Function::Handle(signature_class.signature_function());
-  EXPECT_EQ(signature_function.raw(), function.raw());
-  const Context& closure_context = Context::Handle(Closure::context(closure));
-  EXPECT_EQ(closure_context.raw(), closure_context.raw());
+  EXPECT_EQ(closure_class.id(), kClosureCid);
+  const Function& closure_function = Function::Handle(closure.function());
+  EXPECT_EQ(closure_function.raw(), function.raw());
+  const Context& closure_context = Context::Handle(closure.context());
+  EXPECT_EQ(closure_context.raw(), context.raw());
 }
 
 
@@ -3092,16 +3087,18 @@
   SubtypeTestCache& cache = SubtypeTestCache::Handle(SubtypeTestCache::New());
   EXPECT(!cache.IsNull());
   EXPECT_EQ(0, cache.NumberOfChecks());
+  const Object& class_id_or_fun = Object::Handle(Smi::New(empty_class.id()));
   const TypeArguments& targ_0 = TypeArguments::Handle(TypeArguments::New(2));
   const TypeArguments& targ_1 = TypeArguments::Handle(TypeArguments::New(3));
-  cache.AddCheck(empty_class.id(), targ_0, targ_1, Bool::True());
+  cache.AddCheck(class_id_or_fun, targ_0, targ_1, Bool::True());
   EXPECT_EQ(1, cache.NumberOfChecks());
-  intptr_t test_class_id = -1;
+  Object& test_class_id_or_fun = Object::Handle();
   TypeArguments& test_targ_0 = TypeArguments::Handle();
   TypeArguments& test_targ_1 = TypeArguments::Handle();
   Bool& test_result = Bool::Handle();
-  cache.GetCheck(0, &test_class_id, &test_targ_0, &test_targ_1, &test_result);
-  EXPECT_EQ(empty_class.id(), test_class_id);
+  cache.GetCheck(
+      0, &test_class_id_or_fun, &test_targ_0, &test_targ_1, &test_result);
+  EXPECT_EQ(class_id_or_fun.raw(), test_class_id_or_fun.raw());
   EXPECT_EQ(targ_0.raw(), test_targ_0.raw());
   EXPECT_EQ(targ_1.raw(), test_targ_1.raw());
   EXPECT_EQ(Bool::True().raw(), test_result.raw());
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 47cb001..5440dfb 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -5,7 +5,7 @@
 #include "vm/parser.h"
 #include "vm/flags.h"
 
-#ifndef DART_PRECOMPILED
+#ifndef DART_PRECOMPILED_RUNTIME
 
 #include "lib/invocation_mirror.h"
 #include "platform/utils.h"
@@ -66,6 +66,8 @@
 #define I (isolate())
 #define Z (zone())
 
+// Quick synthetic token position.
+#define ST(token_pos) Token::ToSynthetic(token_pos)
 
 #if defined(DEBUG)
 class TraceParser : public ValueObject {
@@ -125,6 +127,27 @@
 };
 
 
+class RecursionChecker : public ValueObject {
+ public:
+  explicit RecursionChecker(Parser* p) : parser_(p) {
+    parser_->recursion_counter_++;
+    // No need to check the stack unless the parser is in an unusually deep
+    // recurive state. Thus, we omit the more expensive stack checks in
+    // the common case.
+    const int kMaxUncheckedDepth = 100;  // Somewhat arbitrary.
+    if (parser_->recursion_counter_ > kMaxUncheckedDepth) {
+      parser_->CheckStack();
+    }
+  }
+  ~RecursionChecker() {
+    parser_->recursion_counter_--;
+  }
+
+ private:
+  Parser* parser_;
+};
+
+
 static RawTypeArguments* NewTypeArguments(
     const GrowableArray<AbstractType*>& objs) {
   const TypeArguments& a =
@@ -239,7 +262,7 @@
 
 struct CatchParamDesc {
   CatchParamDesc()
-      : token_pos(Scanner::kNoSourcePos), type(NULL), name(NULL), var(NULL) { }
+      : token_pos(Token::kNoSourcePos), type(NULL), name(NULL), var(NULL) { }
   intptr_t token_pos;
   const AbstractType* type;
   const String* name;
@@ -347,7 +370,8 @@
       last_used_try_index_(0),
       unregister_pending_function_(false),
       async_temp_scope_(NULL),
-      trace_indent_(0) {
+      trace_indent_(0),
+      recursion_counter_(0) {
   ASSERT(tokens_iterator_.IsValid());
   ASSERT(!library.IsNull());
 }
@@ -381,7 +405,8 @@
       last_used_try_index_(0),
       unregister_pending_function_(false),
       async_temp_scope_(NULL),
-      trace_indent_(0) {
+      trace_indent_(0),
+      recursion_counter_(0) {
   ASSERT(tokens_iterator_.IsValid());
   ASSERT(!current_function().IsNull());
   EnsureExpressionTemp();
@@ -449,6 +474,7 @@
 void Parser::SetPosition(intptr_t position) {
   tokens_iterator_.SetCurrentPosition(position);
   token_kind_ = Token::kILLEGAL;
+  prev_token_pos_ = position;
 }
 
 
@@ -518,7 +544,7 @@
 struct ParamDesc {
   ParamDesc()
       : type(NULL),
-        name_pos(Scanner::kNoSourcePos),
+        name_pos(Token::kNoSourcePos),
         name(NULL),
         default_value(NULL),
         metadata(NULL),
@@ -623,10 +649,10 @@
     has_factory = false;
     has_operator = false;
     has_native = false;
-    metadata_pos = Scanner::kNoSourcePos;
+    metadata_pos = Token::kNoSourcePos;
     operator_token = Token::kILLEGAL;
     type = NULL;
-    name_pos = Scanner::kNoSourcePos;
+    name_pos = Token::kNoSourcePos;
     name = NULL;
     redirect_name = NULL;
     dict_name = NULL;
@@ -970,7 +996,7 @@
       if (!func.IsImplicitConstructor()) {
         parser.SkipFunctionPreamble();
       }
-      node_sequence = parser.ParseFunc(func);
+      node_sequence = parser.ParseFunc(func, false);
       break;
     case RawFunction::kImplicitGetter:
       ASSERT(!func.is_static());
@@ -1311,7 +1337,7 @@
   LoadInstanceFieldNode* load_field =
       new LoadInstanceFieldNode(ident_pos, load_receiver, field);
 
-  ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, load_field);
+  ReturnNode* return_node = new ReturnNode(ST(ident_pos), load_field);
   current_block_->statements->Add(return_node);
   return CloseBlock();
 }
@@ -1355,7 +1381,7 @@
   StoreInstanceFieldNode* store_field =
       new StoreInstanceFieldNode(ident_pos, receiver, field, value);
   current_block_->statements->Add(store_field);
-  current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos));
+  current_block_->statements->Add(new ReturnNode(ST(ident_pos)));
   return CloseBlock();
 }
 
@@ -1483,7 +1509,7 @@
   ParamList params;
 
   const intptr_t ident_pos = func.token_pos();
-  ASSERT(func.token_pos() == 0);
+  ASSERT(func.token_pos() == ClassifyingTokenPositions::kMethodExtractor);
   ASSERT(current_class().raw() == func.Owner());
   params.AddReceiver(ReceiverType(current_class()), ident_pos);
   ASSERT(func.num_fixed_parameters() == 1);  // Receiver.
@@ -1503,7 +1529,7 @@
       load_receiver,
       NULL);
 
-  ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, closure);
+  ReturnNode* return_node = new ReturnNode(ident_pos, closure);
   current_block_->statements->Add(return_node);
   return CloseBlock();
 }
@@ -1624,14 +1650,14 @@
   ArgumentListNode* no_args = new ArgumentListNode(token_pos);
   LoadLocalNode* receiver = new LoadLocalNode(token_pos, scope->VariableAt(0));
 
-  const Class& function_impl = Class::Handle(Type::Handle(
-      Isolate::Current()->object_store()->function_impl_type()).type_class());
+  const Class& closure_cls = Class::Handle(
+      Isolate::Current()->object_store()->closure_class());
 
   const Class& owner = Class::Handle(Z, func.Owner());
   ASSERT(!owner.IsNull());
   const String& name = String::Handle(Z, func.name());
   AstNode* function_object = NULL;
-  if (owner.raw() == function_impl.raw() && name.Equals(Symbols::Call())) {
+  if (owner.raw() == closure_cls.raw() && name.Equals(Symbols::Call())) {
     function_object = receiver;
   } else {
     const String& getter_name = String::ZoneHandle(Z,
@@ -1658,7 +1684,7 @@
   args->set_names(names);
 
   AstNode* result = NULL;
-  if (owner.raw() == function_impl.raw() && name.Equals(Symbols::Call())) {
+  if (owner.raw() == closure_cls.raw() && name.Equals(Symbols::Call())) {
     result = new ClosureCallNode(token_pos, function_object, args);
   } else {
     result = BuildClosureCall(token_pos, function_object, args);
@@ -1735,7 +1761,8 @@
   if (!is_match) {
     const Error& error = Error::Handle(
         LanguageError::NewFormatted(Error::Handle(),
-            script_, opening_pos, Report::kWarning, Heap::kNew,
+            script_, opening_pos, Report::AtLocation,
+            Report::kWarning, Heap::kNew,
             "unbalanced '%s' opens here", Token::Str(opening_token)));
     ReportErrors(error, script_, token_pos,
                  "unbalanced '%s'", Token::Str(token));
@@ -1879,55 +1906,22 @@
       ParseFormalParameterList(no_explicit_default_values, false, &func_params);
 
       // In top-level and mixin functions, the source may be in a different
-      // script than the script of the current class.
-      Object& sig_func_owner = Object::Handle(Z, current_class().raw());
-      if (current_class().script() != script_.raw()) {
-        sig_func_owner = PatchClass::New(current_class(), script_);
-      }
-
-      // The field 'is_static' has no meaning for signature functions.
+      // script than the script of the current class. However, we never reparse
+      // signature functions (except typedef signature functions), therefore
+      // we do not need to keep the correct script via a patch class. Use the
+      // actual current class as owner of the signature function.
       const Function& signature_function = Function::Handle(Z,
-          Function::New(*parameter.name,
-                        RawFunction::kSignatureFunction,
-                        /* is_static = */ false,
-                        /* is_const = */ false,
-                        /* is_abstract = */ false,
-                        /* is_external = */ false,
-                        /* is_native = */ false,
-                        sig_func_owner,
-                        parameter.name_pos));
+          Function::NewSignatureFunction(current_class(),
+                                         Token::kNoSourcePos));
       signature_function.set_result_type(result_type);
-      signature_function.set_is_debuggable(false);
       AddFormalParamsToFunction(&func_params, signature_function);
-      const String& signature =
-          String::Handle(Z, signature_function.Signature());
-      // Lookup the signature class, i.e. the class whose name is the signature.
-      // We only lookup in the current library, but not in its imports, and only
-      // create a new canonical signature class if it does not exist yet.
-      Class& signature_class =
-          Class::ZoneHandle(Z, library_.LookupLocalClass(signature));
-      if (signature_class.IsNull()) {
-        signature_class = Class::NewSignatureClass(signature,
-                                                   signature_function,
-                                                   script_,
-                                                   parameter.name_pos);
-        // Record the function signature class in the current library, unless
-        // we are currently skipping a formal parameter list, in which case
-        // the signature class could remain unfinalized.
-        if (!params->skipped) {
-          library_.AddClass(signature_class);
-        }
-      } else {
-        signature_function.set_signature_class(signature_class);
-      }
-      ASSERT(signature_function.signature_class() == signature_class.raw());
+      FunctionType& signature_type =
+          FunctionType::ZoneHandle(Z, signature_function.SignatureType());
       if (!is_top_level_) {
-        // Finalize types in signature class here, so that the
-        // signature type is not computed twice.
-        ClassFinalizer::FinalizeTypesInClass(signature_class);
+        signature_type ^= ClassFinalizer::FinalizeType(
+            current_class(), signature_type, ClassFinalizer::kCanonicalize);
+        signature_function.SetSignatureType(signature_type);
       }
-      const Type& signature_type =
-          Type::ZoneHandle(Z, signature_class.SignatureType());
       ASSERT(is_top_level_ || signature_type.IsFinalized());
       // A signature type itself cannot be malformed or malbounded, only its
       // signature function's result type or parameter types may be.
@@ -2312,9 +2306,10 @@
     // parameterized class, make sure that the receiver is captured as
     // instantiator.
     if (current_block_->scope->function_level() > 0) {
-      const Class& signature_class = Class::Handle(Z,
-          implicit_closure_function.signature_class());
-      if (signature_class.NumTypeParameters() > 0) {
+      const FunctionType& signature_type = FunctionType::Handle(Z,
+          implicit_closure_function.SignatureType());
+      const Class& scope_class = Class::Handle(Z, signature_type.type_class());
+      if (scope_class.IsGeneric()) {
         CaptureInstantiator();
       }
     }
@@ -2877,7 +2872,7 @@
   OpenFunctionBlock(func);
 
   LocalVariable* receiver = new LocalVariable(
-      Scanner::kNoSourcePos, Symbols::This(), *ReceiverType(current_class()));
+      Token::kNoSourcePos, Symbols::This(), *ReceiverType(current_class()));
   current_block_->scope->InsertParameterAt(0, receiver);
 
   // Parse expressions of instance fields that have an explicit
@@ -2920,20 +2915,20 @@
 
     // Prepare user-defined arguments to be forwarded to super call.
     // The first user-defined argument is at position 1.
-    forwarding_args = new ArgumentListNode(Scanner::kNoSourcePos);
+    forwarding_args = new ArgumentListNode(ST(ctor_pos));
     for (int i = 1; i < func.NumParameters(); i++) {
       LocalVariable* param = new LocalVariable(
-          Scanner::kNoSourcePos,
+          Token::kNoSourcePos,
           String::ZoneHandle(Z, func.ParameterNameAt(i)),
           Object::dynamic_type());
       current_block_->scope->InsertParameterAt(i, param);
-      forwarding_args->Add(new LoadLocalNode(Scanner::kNoSourcePos, param));
+      forwarding_args->Add(new LoadLocalNode(ST(ctor_pos), param));
     }
   }
 
   AstNode* super_call = GenerateSuperConstructorCall(
       current_class(),
-      Scanner::kNoSourcePos,
+      ctor_pos,
       receiver,
       forwarding_args);
   if (super_call != NULL) {
@@ -2942,7 +2937,7 @@
   CheckFieldsInitialized(current_class());
 
   // Empty constructor body.
-  current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos));
+  current_block_->statements->Add(new ReturnNode(ST(ctor_pos)));
   SequenceNode* statements = CloseBlock();
   return statements;
 }
@@ -3142,7 +3137,7 @@
 // Parser is at the opening parenthesis of the formal parameter
 // declaration of the function or constructor.
 // Parse the formal parameters and code.
-SequenceNode* Parser::ParseFunc(const Function& func) {
+SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
   TRACE_PARSER("ParseFunc");
   Function& saved_innermost_function =
       Function::Handle(Z, innermost_function().raw());
@@ -3319,7 +3314,7 @@
 
   BoolScope allow_await(&this->await_is_keyword_,
                         func.IsAsyncOrGenerator() || func.is_generated_body());
-  intptr_t end_token_pos = Scanner::kNoSourcePos;
+  intptr_t end_token_pos = Token::kNoSourcePos;
   if (CurrentToken() == Token::kLBRACE) {
     ConsumeToken();
     if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) {
@@ -3349,6 +3344,9 @@
     ASSERT(expr != NULL);
     current_block_->statements->Add(new ReturnNode(expr_pos, expr));
     end_token_pos = TokenPos();
+    if (check_semicolon) {
+      ExpectSemicolon();
+    }
   } else if (IsSymbol(Symbols::Native())) {
     if (String::Handle(Z, func.name()).Equals(
         Symbols::EqualOperator())) {
@@ -3409,24 +3407,24 @@
 
 void Parser::AddEqualityNullCheck() {
   AstNode* argument =
-      new LoadLocalNode(Scanner::kNoSourcePos,
+      new LoadLocalNode(Token::kNoSourcePos,
                         current_block_->scope->parent()->VariableAt(1));
   LiteralNode* null_operand =
-      new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(Z));
+      new LiteralNode(Token::kNoSourcePos, Instance::ZoneHandle(Z));
   ComparisonNode* check_arg =
-      new ComparisonNode(Scanner::kNoSourcePos,
+      new ComparisonNode(Token::kNoSourcePos,
                          Token::kEQ_STRICT,
                          argument,
                          null_operand);
   ComparisonNode* result =
-      new ComparisonNode(Scanner::kNoSourcePos,
+      new ComparisonNode(Token::kNoSourcePos,
                          Token::kEQ_STRICT,
-                         LoadReceiver(Scanner::kNoSourcePos),
+                         LoadReceiver(Token::kNoSourcePos),
                          null_operand);
-  SequenceNode* arg_is_null = new SequenceNode(Scanner::kNoSourcePos,
+  SequenceNode* arg_is_null = new SequenceNode(Token::kNoSourcePos,
                                                current_block_->scope);
-  arg_is_null->Add(new ReturnNode(Scanner::kNoSourcePos, result));
-  IfNode* if_arg_null = new IfNode(Scanner::kNoSourcePos,
+  arg_is_null->Add(new ReturnNode(Token::kNoSourcePos, result));
+  IfNode* if_arg_null = new IfNode(Token::kNoSourcePos,
                                    check_arg,
                                    arg_is_null,
                                    NULL);
@@ -4114,7 +4112,8 @@
     member.has_var = true;
     // The member type is the 'dynamic' type.
     member.type = &Object::dynamic_type();
-  } else if (CurrentToken() == Token::kFACTORY) {
+  } else if ((CurrentToken() == Token::kFACTORY) &&
+      (LookaheadToken(1) != Token::kLPAREN)) {
     ConsumeToken();
     if (member.has_static) {
       ReportError("factory method cannot be explicitly marked static");
@@ -4380,10 +4379,6 @@
       // Preserve and reuse the original type parameters and bounds since the
       // ones defined in the patch class will not be finalized.
       orig_type_parameters = cls.type_parameters();
-      // A patch class must be given the same name as the class it is patching,
-      // otherwise the generic signature classes it defines will not match the
-      // patched generic signature classes. Therefore, new signature classes
-      // will be introduced and the original ones will not get finalized.
       cls = Class::New(class_name, script_, declaration_pos);
       cls.set_library(library_);
     } else {
@@ -4967,15 +4962,15 @@
                 "'%s' is already defined", alias_name->ToCString());
   }
 
-  // Create the function type alias signature class. It will be linked to its
+  // Create the function type alias scope class. It will be linked to its
   // signature function after it has been parsed. The type parameters, in order
-  // to be properly finalized, need to be associated to this signature class as
+  // to be properly finalized, need to be associated to this scope class as
   // they are parsed.
   const Class& function_type_alias = Class::Handle(Z,
-      Class::NewSignatureClass(*alias_name,
-                               Function::Handle(Z),
-                               script_,
-                               declaration_pos));
+      Class::New(*alias_name, script_, declaration_pos));
+  function_type_alias.set_is_synthesized_class();
+  function_type_alias.set_is_abstract();
+  function_type_alias.set_is_prefinalized();
   library_.AddClass(function_type_alias);
   set_current_class(function_type_alias);
   // Parse the type parameters of the function type.
@@ -5000,52 +4995,21 @@
   const bool no_explicit_default_values = false;
   ParseFormalParameterList(no_explicit_default_values, false, &func_params);
   ExpectSemicolon();
-  // The field 'is_static' has no meaning for signature functions.
-  Function& signature_function = Function::Handle(Z,
-      Function::New(*alias_name,
-                    RawFunction::kSignatureFunction,
-                    /* is_static = */ false,
-                    /* is_const = */ false,
-                    /* is_abstract = */ false,
-                    /* is_external = */ false,
-                    /* is_native = */ false,
-                    function_type_alias,
-                    alias_name_pos));
+  Function& signature_function =
+      Function::Handle(Z, Function::NewSignatureFunction(function_type_alias,
+                                                         alias_name_pos));
   signature_function.set_result_type(result_type);
-  signature_function.set_is_debuggable(false);
   AddFormalParamsToFunction(&func_params, signature_function);
 
-  // Patch the signature function in the signature class.
-  function_type_alias.PatchSignatureFunction(signature_function);
+  // Set the signature function in the function type alias class.
+  function_type_alias.set_signature_function(signature_function);
 
-  const String& signature = String::Handle(Z,
-                                           signature_function.Signature());
   if (FLAG_trace_parser) {
     OS::Print("TopLevel parsing function type alias '%s'\n",
-              signature.ToCString());
+              String::Handle(Z, signature_function.Signature()).ToCString());
   }
-  // Lookup the signature class, i.e. the class whose name is the signature.
-  // We only lookup in the current library, but not in its imports, and only
-  // create a new canonical signature class if it does not exist yet.
-  Class& signature_class =
-      Class::ZoneHandle(Z, library_.LookupLocalClass(signature));
-  if (signature_class.IsNull()) {
-    signature_class = Class::NewSignatureClass(signature,
-                                               signature_function,
-                                               script_,
-                                               alias_name_pos);
-    // Record the function signature class in the current library.
-    library_.AddClass(signature_class);
-  } else {
-    // Forget the just created signature function and use the existing one.
-    signature_function = signature_class.signature_function();
-    function_type_alias.PatchSignatureFunction(signature_function);
-  }
-  ASSERT(signature_function.signature_class() == signature_class.raw());
-
   // The alias should not be marked as finalized yet, since it needs to be
   // checked in the class finalizer for illegal self references.
-  ASSERT(!function_type_alias.IsCanonicalSignatureClass());
   ASSERT(!function_type_alias.is_finalized());
   pending_classes.Add(function_type_alias, Heap::kOld);
   if (FLAG_enable_mirrors && (metadata_pos >= 0)) {
@@ -5073,7 +5037,7 @@
 
 intptr_t Parser::SkipMetadata() {
   if (CurrentToken() != Token::kAT) {
-    return Scanner::kNoSourcePos;
+    return Token::kNoSourcePos;
   }
   intptr_t metadata_pos = TokenPos();
   while (CurrentToken() == Token::kAT) {
@@ -5832,7 +5796,7 @@
     CheckToken(Token::kAS, "'as' expected");
   }
   String& prefix = String::Handle(Z);
-  intptr_t prefix_pos = Scanner::kNoSourcePos;
+  intptr_t prefix_pos = Token::kNoSourcePos;
   if (is_import && (CurrentToken() == Token::kAS)) {
     ConsumeToken();
     prefix_pos = TokenPos();
@@ -6107,6 +6071,18 @@
 }
 
 
+void Parser::CheckStack() {
+  volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
+  volatile uword c_stack_base = OSThread::Current()->stack_base();
+  volatile uword c_stack_limit =
+      c_stack_base - OSThread::GetSpecifiedStackSize();
+  // Note: during early initialization the stack_base() can return 0.
+  if ((c_stack_base > 0) && (c_stack_pos < c_stack_limit)) {
+    ReportError("stack overflow while parsing");
+  }
+}
+
+
 void Parser::ChainNewBlock(LocalScope* outer_scope) {
   Block* block = new(Z) Block(
       current_block_,
@@ -6188,10 +6164,10 @@
   // Add the exception and stack trace parameters to the scope.
   CatchParamDesc exception_param;
   CatchParamDesc stack_trace_param;
-  exception_param.token_pos = Scanner::kNoSourcePos;
+  exception_param.token_pos = Token::kNoSourcePos;
   exception_param.type = &Object::dynamic_type();
   exception_param.name = &Symbols::ExceptionParameter();
-  stack_trace_param.token_pos = Scanner::kNoSourcePos;
+  stack_trace_param.token_pos = Token::kNoSourcePos;
   stack_trace_param.type = &Object::dynamic_type();
   stack_trace_param.name = &Symbols::StackTraceParameter();
 
@@ -6211,9 +6187,9 @@
     // Generate code to load the exception object (:exception_var) into
     // the exception variable specified in this block.
     current_block_->statements->Add(new(Z) StoreLocalNode(
-        Scanner::kNoSourcePos,
+        Token::kNoSourcePos,
         exception_param.var,
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
+        new(Z) LoadLocalNode(Token::kNoSourcePos, exception_var)));
   }
 
   LocalVariable* stack_trace_var =
@@ -6224,9 +6200,9 @@
     // to load the stack trace object (:stack_trace_var) into the stack
     // trace variable specified in this block.
     current_block_->statements->Add(new(Z) StoreLocalNode(
-        Scanner::kNoSourcePos,
+        Token::kNoSourcePos,
         stack_trace_param.var,
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
+        new(Z) LoadLocalNode(Token::kNoSourcePos, stack_trace_var)));
   }
   LocalVariable* saved_exception_var = try_scope->LocalLookupVariable(
       Symbols::SavedExceptionVar());
@@ -6245,15 +6221,15 @@
       current_block_->scope->LookupVariable(Symbols::Controller(), false);
   ASSERT(controller != NULL);
   ArgumentListNode* args =
-      new(Z) ArgumentListNode(Scanner::kNoSourcePos);
-  args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
-  args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
+      new(Z) ArgumentListNode(Token::kNoSourcePos);
+  args->Add(new(Z) LoadLocalNode(Token::kNoSourcePos, exception_param.var));
+  args->Add(new(Z) LoadLocalNode(Token::kNoSourcePos, stack_trace_param.var));
   current_block_->statements->Add(
       new(Z) InstanceCallNode(try_end_pos,
-          new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
+          new(Z) LoadLocalNode(Token::kNoSourcePos, controller),
           Symbols::AddError(),
           args));
-  ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
+  ReturnNode* return_node = new(Z) ReturnNode(Token::kNoSourcePos);
   AddNodeForFinallyInlining(return_node);
   current_block_->statements->Add(return_node);
   AstNode* catch_block = CloseBlock();
@@ -6278,10 +6254,10 @@
   do {
     OpenBlock();
     ArgumentListNode* no_args =
-        new(Z) ArgumentListNode(Scanner::kNoSourcePos);
+        new(Z) ArgumentListNode(Token::kNoSourcePos);
     current_block_->statements->Add(
         new(Z) InstanceCallNode(try_end_pos,
-            new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
+            new(Z) LoadLocalNode(Token::kNoSourcePos, controller),
             Symbols::Close(),
             no_args));
 
@@ -6289,7 +6265,7 @@
     AwaitMarkerNode* await_marker =
         new(Z) AwaitMarkerNode(async_temp_scope_,
                                current_block_->scope,
-                               Scanner::kNoSourcePos);
+                               Token::kNoSourcePos);
     current_block_->statements->Add(await_marker);
     ReturnNode* continuation_ret = new(Z) ReturnNode(try_end_pos);
     continuation_ret->set_return_type(ReturnNode::kContinuationTarget);
@@ -6320,7 +6296,7 @@
   handler_types.Add(Object::dynamic_type());
 
   CatchClauseNode* catch_clause = new(Z) CatchClauseNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       catch_handler_list,
       Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
       context_var,
@@ -6334,7 +6310,7 @@
   const intptr_t try_index = try_statement->try_index();
 
   AstNode* try_catch_node =
-      new(Z) TryCatchNode(Scanner::kNoSourcePos,
+      new(Z) TryCatchNode(Token::kNoSourcePos,
                           body,
                           context_var,
                           catch_clause,
@@ -6359,10 +6335,10 @@
   OpenBlock();  // Catch block.
   CatchParamDesc exception_param;
   CatchParamDesc stack_trace_param;
-  exception_param.token_pos = Scanner::kNoSourcePos;
+  exception_param.token_pos = Token::kNoSourcePos;
   exception_param.type = &Object::dynamic_type();
   exception_param.name = &Symbols::ExceptionParameter();
-  stack_trace_param.token_pos = Scanner::kNoSourcePos;
+  stack_trace_param.token_pos = Token::kNoSourcePos;
   stack_trace_param.type = &Object::dynamic_type();
   stack_trace_param.name = &Symbols::StackTraceParameter();
 
@@ -6380,9 +6356,9 @@
     // the exception variable specified in this block.
     ASSERT(exception_var != NULL);
     current_block_->statements->Add(new(Z) StoreLocalNode(
-        Scanner::kNoSourcePos,
+        Token::kNoSourcePos,
         exception_param.var,
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
+        new(Z) LoadLocalNode(Token::kNoSourcePos, exception_var)));
   }
 
   LocalVariable* stack_trace_var =
@@ -6393,9 +6369,9 @@
     // trace variable specified in this block.
     ASSERT(stack_trace_var != NULL);
     current_block_->statements->Add(new(Z) StoreLocalNode(
-        Scanner::kNoSourcePos,
+        Token::kNoSourcePos,
         stack_trace_param.var,
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
+        new(Z) LoadLocalNode(Token::kNoSourcePos, stack_trace_var)));
   }
   LocalVariable* saved_exception_var = try_scope->LocalLookupVariable(
       Symbols::SavedExceptionVar());
@@ -6413,17 +6389,17 @@
       Symbols::AsyncCompleter(), false);
   ASSERT(async_completer != NULL);
   ArgumentListNode* completer_args =
-      new (Z) ArgumentListNode(Scanner::kNoSourcePos);
+      new (Z) ArgumentListNode(Token::kNoSourcePos);
   completer_args->Add(
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
+      new (Z) LoadLocalNode(Token::kNoSourcePos, exception_param.var));
   completer_args->Add(
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
+      new (Z) LoadLocalNode(Token::kNoSourcePos, stack_trace_param.var));
   current_block_->statements->Add(new (Z) InstanceCallNode(
       TokenPos(),
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_completer),
+      new (Z) LoadLocalNode(Token::kNoSourcePos, async_completer),
       Symbols::CompleterCompleteError(),
       completer_args));
-  ReturnNode* return_node = new (Z) ReturnNode(Scanner::kNoSourcePos);
+  ReturnNode* return_node = new (Z) ReturnNode(Token::kNoSourcePos);
   // Behavior like a continuation return, i.e,. don't call a completer.
   return_node->set_return_type(ReturnNode::kContinuation);
   current_block_->statements->Add(return_node);
@@ -6440,7 +6416,7 @@
   const intptr_t try_index = try_statement->try_index();
 
   CatchClauseNode* catch_clause = new (Z) CatchClauseNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       catch_handler_list,
       Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
       context_var,
@@ -6451,7 +6427,7 @@
       CatchClauseNode::kInvalidTryIndex,
       true);
   AstNode* try_catch_node = new (Z) TryCatchNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       try_block,
       context_var,
       catch_clause,
@@ -6551,19 +6527,12 @@
     // Add the parameters to the newly created closure.
     AddFormalParamsToFunction(&closure_params, body);
 
-    // Create and set the signature class of the closure.
-    const String& sig = String::Handle(Z, body.Signature());
-    Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
-    if (sig_cls.IsNull()) {
-      sig_cls = Class::NewSignatureClass(sig, body, script_, body.token_pos());
-      library_.AddClass(sig_cls);
-    }
-    body.set_signature_class(sig_cls);
-    // Finalize types in signature class here, so that the
-    // signature type is not computed twice.
-    ClassFinalizer::FinalizeTypesInClass(sig_cls);
-    const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
-    ASSERT(sig_type.IsFinalized());
+    // Finalize function type.
+    FunctionType& signature_type =
+        FunctionType::Handle(Z, body.SignatureType());
+    signature_type ^= ClassFinalizer::FinalizeType(
+        current_class(), signature_type, ClassFinalizer::kCanonicalize);
+    body.SetSignatureType(signature_type);
     ASSERT(AbstractType::Handle(Z, body.result_type()).IsResolved());
     ASSERT(body.NumParameters() == closure_params.parameters->length());
   }
@@ -6589,9 +6558,9 @@
   LocalVariable* jump_var =
       current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
   LiteralNode* init_value =
-      new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
+      new(Z) LiteralNode(Token::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
   current_block_->statements->Add(
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));
+      new(Z) StoreLocalNode(Token::kNoSourcePos, jump_var, init_value));
 
   // return new SyncIterable(body_closure);
   const Class& iterable_class =
@@ -6605,17 +6574,17 @@
   const String& closure_name = String::Handle(Z, closure.name());
   ASSERT(closure_name.IsSymbol());
 
-  ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
+  ArgumentListNode* arguments = new(Z) ArgumentListNode(Token::kNoSourcePos);
   ClosureNode* closure_obj = new(Z) ClosureNode(
-      Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
+      Token::kNoSourcePos, closure, NULL, closure_body->scope());
   arguments->Add(closure_obj);
   ConstructorCallNode* new_iterable =
-      new(Z) ConstructorCallNode(Scanner::kNoSourcePos,
+      new(Z) ConstructorCallNode(Token::kNoSourcePos,
           TypeArguments::ZoneHandle(Z),
           iterable_constructor,
           arguments);
   ReturnNode* return_node =
-      new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable);
+      new (Z) ReturnNode(Token::kNoSourcePos, new_iterable);
   current_block_->statements->Add(return_node);
   return CloseBlock();
 }
@@ -6688,20 +6657,12 @@
     // Add the parameters to the newly created closure.
     AddFormalParamsToFunction(&closure_params, closure);
 
-    // Create and set the signature class of the closure.
-    const String& sig = String::Handle(Z, closure.Signature());
-    Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
-    if (sig_cls.IsNull()) {
-      sig_cls =
-          Class::NewSignatureClass(sig, closure, script_, closure.token_pos());
-      library_.AddClass(sig_cls);
-    }
-    closure.set_signature_class(sig_cls);
-    // Finalize types in signature class here, so that the
-    // signature type is not computed twice.
-    ClassFinalizer::FinalizeTypesInClass(sig_cls);
-    const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
-    ASSERT(sig_type.IsFinalized());
+    // Finalize function type.
+    FunctionType& signature_type =
+        FunctionType::Handle(Z, closure.SignatureType());
+    signature_type ^= ClassFinalizer::FinalizeType(
+        current_class(), signature_type, ClassFinalizer::kCanonicalize);
+    closure.SetSignatureType(signature_type);
     ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved());
     ASSERT(closure.NumParameters() == closure_params.parameters->length());
   }
@@ -6717,10 +6678,10 @@
   //   var :await_jump_var;
   //   var :await_ctx_var;
   LocalVariable* await_jump_var = new (Z) LocalVariable(
-      Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), Object::dynamic_type());
+      Token::kNoSourcePos, Symbols::AwaitJumpVar(), Object::dynamic_type());
   current_block_->scope->AddVariable(await_jump_var);
   LocalVariable* await_ctx_var = new (Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       Symbols::AwaitContextVar(),
       Object::dynamic_type());
   current_block_->scope->AddVariable(await_ctx_var);
@@ -6734,20 +6695,20 @@
   //   var :async_catch_error_callback;
   //   var :async_completer;
   LocalVariable* async_op_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos, Symbols::AsyncOperation(), Object::dynamic_type());
+      Token::kNoSourcePos, Symbols::AsyncOperation(), Object::dynamic_type());
   current_block_->scope->AddVariable(async_op_var);
   LocalVariable* async_then_callback_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       Symbols::AsyncThenCallback(),
       Object::dynamic_type());
   current_block_->scope->AddVariable(async_then_callback_var);
   LocalVariable* async_catch_error_callback_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       Symbols::AsyncCatchErrorCallback(),
       Object::dynamic_type());
   current_block_->scope->AddVariable(async_catch_error_callback_var);
   LocalVariable* async_completer = new(Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       Symbols::AsyncCompleter(),
       Object::dynamic_type());
   current_block_->scope->AddVariable(async_completer);
@@ -6766,18 +6727,18 @@
   // These variables are used to store the async generator closure containing
   // the body of the async* function. They are used by the await operator.
   LocalVariable* controller_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos, Symbols::Controller(), Object::dynamic_type());
+      Token::kNoSourcePos, Symbols::Controller(), Object::dynamic_type());
   current_block_->scope->AddVariable(controller_var);
   LocalVariable* async_op_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos, Symbols::AsyncOperation(), Object::dynamic_type());
+      Token::kNoSourcePos, Symbols::AsyncOperation(), Object::dynamic_type());
   current_block_->scope->AddVariable(async_op_var);
   LocalVariable* async_then_callback_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       Symbols::AsyncThenCallback(),
       Object::dynamic_type());
   current_block_->scope->AddVariable(async_then_callback_var);
   LocalVariable* async_catch_error_callback_var = new(Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       Symbols::AsyncCatchErrorCallback(),
       Object::dynamic_type());
   current_block_->scope->AddVariable(async_catch_error_callback_var);
@@ -6823,20 +6784,12 @@
     // Add the parameters to the newly created closure.
     AddFormalParamsToFunction(&closure_params, closure);
 
-    // Create and set the signature class of the closure.
-    const String& sig = String::Handle(Z, closure.Signature());
-    Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
-    if (sig_cls.IsNull()) {
-      sig_cls =
-          Class::NewSignatureClass(sig, closure, script_, closure.token_pos());
-      library_.AddClass(sig_cls);
-    }
-    closure.set_signature_class(sig_cls);
-    // Finalize types in signature class here, so that the
-    // signature type is not computed twice.
-    ClassFinalizer::FinalizeTypesInClass(sig_cls);
-    const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
-    ASSERT(sig_type.IsFinalized());
+    // Finalize function type.
+    FunctionType& signature_type =
+        FunctionType::Handle(Z, closure.SignatureType());
+    signature_type ^= ClassFinalizer::FinalizeType(
+        current_class(), signature_type, ClassFinalizer::kCanonicalize);
+    closure.SetSignatureType(signature_type);
     ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved());
     ASSERT(closure.NumParameters() == closure_params.parameters->length());
   }
@@ -6904,18 +6857,18 @@
   LocalVariable* jump_var =
       current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
   LiteralNode* init_value =
-      new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
+      new(Z) LiteralNode(Token::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
   current_block_->statements->Add(
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));
+      new(Z) StoreLocalNode(Token::kNoSourcePos, jump_var, init_value));
 
   // Add to AST:
   //   :async_op = <closure>;  (containing the original body)
   LocalVariable* async_op_var =
       current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false);
   ClosureNode* closure_obj = new(Z) ClosureNode(
-      Scanner::kNoSourcePos, closure_func, NULL, closure_body->scope());
+      Token::kNoSourcePos, closure_func, NULL, closure_body->scope());
   StoreLocalNode* store_async_op = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_op_var,
       closure_obj);
 
@@ -6927,18 +6880,18 @@
           Symbols::AsyncThenWrapperHelper()));
   ASSERT(!async_then_wrapper_helper.IsNull());
   ArgumentListNode* async_then_wrapper_helper_args = new (Z) ArgumentListNode(
-      Scanner::kNoSourcePos);
+      Token::kNoSourcePos);
   async_then_wrapper_helper_args->Add(
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
+      new (Z) LoadLocalNode(Token::kNoSourcePos, async_op_var));
   StaticCallNode* then_wrapper_call = new (Z) StaticCallNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_then_wrapper_helper,
       async_then_wrapper_helper_args);
   LocalVariable* async_then_callback_var =
       current_block_->scope->LookupVariable(
           Symbols::AsyncThenCallback(), false);
   StoreLocalNode* store_async_then_callback = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_then_callback_var,
       then_wrapper_call);
 
@@ -6951,43 +6904,43 @@
           Symbols::AsyncErrorWrapperHelper()));
   ASSERT(!async_error_wrapper_helper.IsNull());
   ArgumentListNode* async_error_wrapper_helper_args = new (Z) ArgumentListNode(
-      Scanner::kNoSourcePos);
+      Token::kNoSourcePos);
   async_error_wrapper_helper_args->Add(
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
+      new (Z) LoadLocalNode(Token::kNoSourcePos, async_op_var));
   StaticCallNode* error_wrapper_call = new (Z) StaticCallNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_error_wrapper_helper,
       async_error_wrapper_helper_args);
   LocalVariable* async_catch_error_callback_var =
       current_block_->scope->LookupVariable(
           Symbols::AsyncCatchErrorCallback(), false);
   StoreLocalNode* store_async_catch_error_callback = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_catch_error_callback_var,
       error_wrapper_call);
 
   current_block_->statements->Add(store_async_catch_error_callback);
 
   // :controller = new _AsyncStarStreamController(body_closure);
-  ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
-  arguments->Add(new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
+  ArgumentListNode* arguments = new(Z) ArgumentListNode(Token::kNoSourcePos);
+  arguments->Add(new (Z) LoadLocalNode(Token::kNoSourcePos, async_op_var));
   ConstructorCallNode* controller_constructor_call =
-      new(Z) ConstructorCallNode(Scanner::kNoSourcePos,
+      new(Z) ConstructorCallNode(Token::kNoSourcePos,
                                  TypeArguments::ZoneHandle(Z),
                                  controller_constructor,
                                  arguments);
   LocalVariable* controller_var =
      current_block_->scope->LookupVariable(Symbols::Controller(), false);
   StoreLocalNode* store_controller =
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos,
+      new(Z) StoreLocalNode(Token::kNoSourcePos,
                             controller_var,
                             controller_constructor_call);
   current_block_->statements->Add(store_controller);
 
   // return :controller.stream;
-  ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos,
-      new(Z) InstanceGetterNode(Scanner::kNoSourcePos,
-          new(Z) LoadLocalNode(Scanner::kNoSourcePos,
+  ReturnNode* return_node = new(Z) ReturnNode(Token::kNoSourcePos,
+      new(Z) InstanceGetterNode(Token::kNoSourcePos,
+          new(Z) LoadLocalNode(Token::kNoSourcePos,
               controller_var),
               Symbols::Stream()));
   current_block_->statements->Add(return_node);
@@ -7081,17 +7034,18 @@
   LocalVariable* async_completer = current_block_->scope->LookupVariable(
       Symbols::AsyncCompleter(), false);
 
+  const intptr_t token_pos = ST(closure_body->token_pos());
   // Add to AST:
   //   :async_completer = new Completer.sync();
   ArgumentListNode* empty_args =
-      new (Z) ArgumentListNode(Scanner::kNoSourcePos);
+      new (Z) ArgumentListNode(token_pos);
   ConstructorCallNode* completer_constructor_node = new (Z) ConstructorCallNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       TypeArguments::ZoneHandle(Z),
       completer_constructor,
       empty_args);
   StoreLocalNode* store_completer = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       async_completer,
       completer_constructor_node);
   current_block_->statements->Add(store_completer);
@@ -7100,18 +7054,19 @@
   LocalVariable* jump_var =
       current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
   LiteralNode* init_value =
-      new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
+      new(Z) LiteralNode(token_pos,
+                         Smi::ZoneHandle(Smi::New(-1)));
   current_block_->statements->Add(
-      new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));
+      new(Z) StoreLocalNode(token_pos, jump_var, init_value));
 
   // Add to AST:
   //   :async_op = <closure>;  (containing the original body)
   LocalVariable* async_op_var = current_block_->scope->LookupVariable(
       Symbols::AsyncOperation(), false);
   ClosureNode* cn = new(Z) ClosureNode(
-      Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
+      token_pos, closure, NULL, closure_body->scope());
   StoreLocalNode* store_async_op = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       async_op_var,
       cn);
   current_block_->statements->Add(store_async_op);
@@ -7123,18 +7078,18 @@
           Symbols::AsyncThenWrapperHelper()));
   ASSERT(!async_then_wrapper_helper.IsNull());
   ArgumentListNode* async_then_wrapper_helper_args = new (Z) ArgumentListNode(
-      Scanner::kNoSourcePos);
+      token_pos);
   async_then_wrapper_helper_args->Add(
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
+      new (Z) LoadLocalNode(token_pos, async_op_var));
   StaticCallNode* then_wrapper_call = new (Z) StaticCallNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       async_then_wrapper_helper,
       async_then_wrapper_helper_args);
   LocalVariable* async_then_callback_var =
       current_block_->scope->LookupVariable(
           Symbols::AsyncThenCallback(), false);
   StoreLocalNode* store_async_then_callback = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       async_then_callback_var,
       then_wrapper_call);
 
@@ -7147,18 +7102,18 @@
           Symbols::AsyncErrorWrapperHelper()));
   ASSERT(!async_error_wrapper_helper.IsNull());
   ArgumentListNode* async_error_wrapper_helper_args = new (Z) ArgumentListNode(
-      Scanner::kNoSourcePos);
+      token_pos);
   async_error_wrapper_helper_args->Add(
-      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
+      new (Z) LoadLocalNode(token_pos, async_op_var));
   StaticCallNode* error_wrapper_call = new (Z) StaticCallNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       async_error_wrapper_helper,
       async_error_wrapper_helper_args);
   LocalVariable* async_catch_error_callback_var =
       current_block_->scope->LookupVariable(
           Symbols::AsyncCatchErrorCallback(), false);
   StoreLocalNode* store_async_catch_error_callback = new (Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       async_catch_error_callback_var,
       error_wrapper_call);
 
@@ -7166,22 +7121,22 @@
 
   // Add to AST:
   //   new Future.microtask(:async_op);
-  ArgumentListNode* arguments = new (Z) ArgumentListNode(Scanner::kNoSourcePos);
+  ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos);
   arguments->Add(new (Z) LoadLocalNode(
-      Scanner::kNoSourcePos, async_op_var));
+      token_pos, async_op_var));
   ConstructorCallNode* future_node = new (Z) ConstructorCallNode(
-      Scanner::kNoSourcePos, TypeArguments::ZoneHandle(Z), constructor,
+      token_pos, TypeArguments::ZoneHandle(Z), constructor,
       arguments);
   current_block_->statements->Add(future_node);
 
   // Add to AST:
   //   return :async_completer.future;
   ReturnNode* return_node = new (Z) ReturnNode(
-      Scanner::kNoSourcePos,
+      token_pos,
       new (Z) InstanceGetterNode(
-          Scanner::kNoSourcePos,
+          token_pos,
           new (Z) LoadLocalNode(
-              Scanner::kNoSourcePos,
+              token_pos,
               async_completer),
           Symbols::CompleterFuture()));
   current_block_->statements->Add(return_node);
@@ -7231,7 +7186,8 @@
   if (!Utils::IsInt(16, params->num_fixed_parameters) ||
       !Utils::IsInt(16, params->num_optional_parameters)) {
     const Script& script = Script::Handle(Class::Handle(func.Owner()).script());
-    Report::MessageF(Report::kError, script, func.token_pos(),
+    Report::MessageF(Report::kError,
+                     script, func.token_pos(), Report::AtLocation,
                      "too many formal parameters");
   }
   func.set_num_fixed_parameters(params->num_fixed_parameters);
@@ -7513,7 +7469,7 @@
   result_type = Type::DynamicType();
 
   const intptr_t function_pos = TokenPos();
-  intptr_t metadata_pos = Scanner::kNoSourcePos;
+  intptr_t metadata_pos = Token::kNoSourcePos;
   if (is_literal) {
     ASSERT(CurrentToken() == Token::kLPAREN);
     function_name = &Symbols::AnonymousClosure();
@@ -7553,7 +7509,6 @@
   // Note that we cannot share the same closure function between the closurized
   // and non-closurized versions of the same parent function.
   Function& function = Function::ZoneHandle(Z);
-  bool is_new_closure = false;
   // TODO(hausner): There could be two different closures at the given
   // function_pos, one enclosed in a closurized function and one enclosed in the
   // non-closurized version of this same function.
@@ -7562,7 +7517,6 @@
     // The function will be registered in the lookup table by the
     // EffectGraphVisitor::VisitClosureNode when the newly allocated closure
     // function has been properly setup.
-    is_new_closure = true;
     function = Function::NewClosureFunction(*function_name,
                                             innermost_function(),
                                             function_pos);
@@ -7577,17 +7531,19 @@
   // passed as a function argument, or returned as a function result.
 
   LocalVariable* function_variable = NULL;
-  Type& function_type = Type::ZoneHandle(Z);
+  FunctionType& function_type = FunctionType::ZoneHandle(Z);
   if (variable_name != NULL) {
     // Since the function type depends on the signature of the closure function,
     // it cannot be determined before the formal parameter list of the closure
     // function is parsed. Therefore, we set the function type to a new
-    // parameterized type to be patched after the actual type is known.
-    // We temporarily use the class of the Function interface.
-    const Class& unknown_signature_class = Class::Handle(Z,
-        Type::Handle(Z, Type::Function()).type_class());
-    function_type = Type::New(unknown_signature_class,
-                              TypeArguments::Handle(Z), function_pos);
+    // function type to be patched after the actual type is known.
+    // We temporarily use the Closure class as scope class.
+    const Class& unknown_scope_class = Class::Handle(Z,
+        I->object_store()->closure_class());
+    function_type = FunctionType::New(unknown_scope_class,
+                                      TypeArguments::Handle(Z),
+                                      function,
+                                      function_pos);
     function_type.SetIsFinalized();  // No finalization needed.
 
     // Add the function variable to the scope before parsing the function in
@@ -7611,52 +7567,28 @@
   }
 
   // Parse the local function.
-  SequenceNode* statements = Parser::ParseFunc(function);
+  SequenceNode* statements = Parser::ParseFunc(function, !is_literal);
   INC_STAT(thread(), num_functions_parsed, 1);
 
   // Now that the local function has formal parameters, lookup the signature
-  // class in the current library (but not in its imports) and only create a new
-  // canonical signature class if it does not exist yet.
-  const String& signature = String::Handle(Z, function.Signature());
-  Class& signature_class = Class::ZoneHandle(Z);
-  if (!is_new_closure) {
-    signature_class = function.signature_class();
-  }
-  if (signature_class.IsNull()) {
-    signature_class = library_.LookupLocalClass(signature);
-  }
-  if (signature_class.IsNull()) {
-    // If we don't have a signature class yet, this must be a closure we
-    // have not parsed before.
-    ASSERT(is_new_closure);
-    signature_class = Class::NewSignatureClass(signature,
-                                               function,
-                                               script_,
-                                               function.token_pos());
-    // Record the function signature class in the current library.
-    library_.AddClass(signature_class);
-  } else if (is_new_closure) {
-    function.set_signature_class(signature_class);
-  }
-  ASSERT(function.signature_class() == signature_class.raw());
+  FunctionType& signature_type =
+      FunctionType::ZoneHandle(Z, function.SignatureType());
+  signature_type ^= ClassFinalizer::FinalizeType(
+      current_class(), signature_type, ClassFinalizer::kCanonicalize);
+  function.SetSignatureType(signature_type);
 
   // Local functions are registered in the enclosing class, but
   // ignored during class finalization. The enclosing class has
   // already been finalized.
   ASSERT(current_class().is_finalized());
+  ASSERT(signature_type.IsFinalized());
 
   // Make sure that the instantiator is captured.
-  if ((signature_class.NumTypeParameters() > 0) &&
-      (current_block_->scope->function_level() > 0)) {
+  if ((current_block_->scope->function_level() > 0) &&
+      Class::Handle(signature_type.type_class()).IsGeneric()) {
     CaptureInstantiator();
   }
 
-  // Finalize types in signature class here, so that the
-  // signature type is not computed twice.
-  ClassFinalizer::FinalizeTypesInClass(signature_class);
-  const Type& signature_type = Type::Handle(Z, signature_class.SignatureType());
-  ASSERT(signature_type.IsFinalized());
-
   // A signature type itself cannot be malformed or malbounded, only its
   // signature function's result type or parameter types may be.
   ASSERT(!signature_type.IsMalformed());
@@ -7664,9 +7596,11 @@
 
   if (variable_name != NULL) {
     // Patch the function type of the variable now that the signature is known.
-    function_type.set_type_class(signature_class);
+    function_type.set_scope_class(
+        Class::Handle(Z, signature_type.scope_class()));
     function_type.set_arguments(
         TypeArguments::Handle(Z, signature_type.arguments()));
+    ASSERT(function_type.signature() == function.raw());
 
     // The function type was initially marked as instantiated, but it may
     // actually be uninstantiated.
@@ -8052,6 +7986,7 @@
   TRACE_PARSER("ParseStatementSequence");
   const bool dead_code_allowed = true;
   bool abrupt_completing_seen = false;
+  RecursionChecker rc(this);
   while (CurrentToken() != Token::kRBRACE) {
     const intptr_t statement_pos = TokenPos();
     AstNode* statement = ParseStatement();
@@ -8091,6 +8026,7 @@
     ParseStatementSequence();
     ExpectToken(Token::kRBRACE);
   } else {
+    RecursionChecker rc(this);
     AstNode* statement = ParseStatement();
     if (statement != NULL) {
       current_block_->statements->Add(statement);
@@ -8514,11 +8450,11 @@
   const Function& print_fn = Function::ZoneHandle(
       Z, lib.LookupFunctionAllowPrivate(Symbols::print()));
   ASSERT(!print_fn.IsNull());
-  ArgumentListNode* one_arg = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
+  ArgumentListNode* one_arg = new(Z) ArgumentListNode(Token::kNoSourcePos);
   String& msg = String::ZoneHandle(Symbols::NewFormatted("%s", str));
-  one_arg->Add(new(Z) LiteralNode(Scanner::kNoSourcePos, msg));
+  one_arg->Add(new(Z) LiteralNode(Token::kNoSourcePos, msg));
   AstNode* print_call =
-      new(Z) StaticCallNode(Scanner::kNoSourcePos, print_fn, one_arg);
+      new(Z) StaticCallNode(Token::kNoSourcePos, print_fn, one_arg);
   return print_call;
 }
 
@@ -8723,9 +8659,9 @@
 
   if (outer_saved_try_ctx != NULL) {
     catch_block->Add(new (Z) StoreLocalNode(
-        Scanner::kNoSourcePos,
+        Token::kNoSourcePos,
         outer_saved_try_ctx,
-        new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+        new (Z) LoadLocalNode(Token::kNoSourcePos,
                               outer_async_saved_try_ctx)));
   }
 
@@ -8757,17 +8693,17 @@
   do {
     OpenBlock();
     ArgumentListNode* no_args =
-        new(Z) ArgumentListNode(Scanner::kNoSourcePos);
+        new(Z) ArgumentListNode(Token::kNoSourcePos);
     current_block_->statements->Add(
-        new(Z) InstanceCallNode(Scanner::kNoSourcePos,
-            new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_var),
+        new(Z) InstanceCallNode(Token::kNoSourcePos,
+            new(Z) LoadLocalNode(Token::kNoSourcePos, iterator_var),
             Symbols::Cancel(),
             no_args));
     finally_clause = CloseBlock();
     AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
     if (node_to_inline != NULL) {
       InlinedFinallyNode* node =
-          new(Z) InlinedFinallyNode(Scanner::kNoSourcePos,
+          new(Z) InlinedFinallyNode(Token::kNoSourcePos,
                                     finally_clause,
                                     context_var,
                                     outer_try_index);
@@ -8823,7 +8759,7 @@
     ReportError("Loop variable cannot be 'const'");
   }
   const String* loop_var_name = NULL;
-  intptr_t loop_var_pos = Scanner::kNoSourcePos;
+  intptr_t loop_var_pos = Token::kNoSourcePos;
   bool new_loop_var = false;
   AbstractType& loop_var_type =  AbstractType::ZoneHandle(Z);
   if (LookaheadToken(1) == Token::kIN) {
@@ -9124,16 +9060,16 @@
   ASSERT(saved_exception_var != NULL);
   ASSERT(exception_var != NULL);
   statements->Add(new(Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       saved_exception_var,
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
+      new(Z) LoadLocalNode(Token::kNoSourcePos, exception_var)));
 
   ASSERT(saved_stack_trace_var != NULL);
   ASSERT(stack_trace_var != NULL);
   statements->Add(new(Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       saved_stack_trace_var,
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
+      new(Z) LoadLocalNode(Token::kNoSourcePos, stack_trace_var)));
 }
 
 
@@ -9168,9 +9104,9 @@
                                           try_stack_->try_index());
         current_block_->statements->Add(
             new (Z) StoreLocalNode(
-                Scanner::kNoSourcePos,
+                Token::kNoSourcePos,
                 saved_try_ctx,
-                new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+                new (Z) LoadLocalNode(Token::kNoSourcePos,
                                       async_saved_try_ctx)));
       }
     }
@@ -9441,9 +9377,9 @@
                                           try_block->try_index());
         async_code->Add(
             new (Z) StoreLocalNode(
-                Scanner::kNoSourcePos,
+                Token::kNoSourcePos,
                 saved_try_ctx,
-                new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+                new (Z) LoadLocalNode(Token::kNoSourcePos,
                                       async_saved_try_ctx)));
       }
     }
@@ -9470,16 +9406,16 @@
                            Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
                            last_used_try_index_ - 1));
   LocalVariable* async_saved_try_ctx = new (Z) LocalVariable(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_saved_try_ctx_name,
       Object::dynamic_type());
   ASSERT(async_temp_scope_ != NULL);
   async_temp_scope_->AddVariable(async_saved_try_ctx);
   ASSERT(saved_try_context != NULL);
   current_block_->statements->Add(new(Z) StoreLocalNode(
-      Scanner::kNoSourcePos,
+      Token::kNoSourcePos,
       async_saved_try_ctx,
-      new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context)));
+      new(Z) LoadLocalNode(Token::kNoSourcePos, saved_try_context)));
 }
 
 
@@ -9808,9 +9744,9 @@
     ASSERT(iterator_param != NULL);
     // Generate :iterator.current = expr;
     AstNode* iterator =
-        new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param);
+        new(Z) LoadLocalNode(Token::kNoSourcePos, iterator_param);
     AstNode* store_current =
-        new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
+        new(Z) InstanceSetterNode(Token::kNoSourcePos,
                                   iterator,
                                   String::ZoneHandle(Symbols::Current().raw()),
                                   expr);
@@ -9818,7 +9754,7 @@
     if (is_yield_each) {
       // Generate :iterator.isYieldEach = true;
       AstNode* set_is_yield_each =
-          new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
+          new(Z) InstanceSetterNode(Token::kNoSourcePos,
               iterator,
               String::ZoneHandle(Symbols::IsYieldEach().raw()),
               new(Z) LiteralNode(TokenPos(), Bool::True()));
@@ -9827,7 +9763,7 @@
     AwaitMarkerNode* await_marker =
         new(Z) AwaitMarkerNode(async_temp_scope_,
                                current_block_->scope,
-                               Scanner::kNoSourcePos);
+                               Token::kNoSourcePos);
     yield->AddNode(await_marker);
     // Return true to indicate that a value has been generated.
     ReturnNode* return_true = new(Z) ReturnNode(yield_pos,
@@ -9848,15 +9784,15 @@
                            &outer_async_saved_try_ctx);
     if (saved_try_ctx != NULL) {
       yield->AddNode(new (Z) StoreLocalNode(
-          Scanner::kNoSourcePos,
+          Token::kNoSourcePos,
           saved_try_ctx,
-          new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+          new (Z) LoadLocalNode(Token::kNoSourcePos,
                                 async_saved_try_ctx)));
       if (outer_saved_try_ctx != NULL) {
         yield->AddNode(new (Z) StoreLocalNode(
-            Scanner::kNoSourcePos,
+            Token::kNoSourcePos,
             outer_saved_try_ctx,
-            new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+            new (Z) LoadLocalNode(Token::kNoSourcePos,
                                   outer_async_saved_try_ctx)));
       }
     } else {
@@ -9874,7 +9810,7 @@
     add_args->Add(expr);
     AstNode* add_call =
         new(Z) InstanceCallNode(yield_pos,
-            new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var),
+            new(Z) LoadLocalNode(Token::kNoSourcePos, controller_var),
             is_yield_each ? Symbols::AddStream() : Symbols::add(),
             add_args);
 
@@ -9886,18 +9822,18 @@
     // restore saved_try_context
 
     SequenceNode* true_branch =
-        new(Z) SequenceNode(Scanner::kNoSourcePos, NULL);
+        new(Z) SequenceNode(Token::kNoSourcePos, NULL);
     AstNode* return_from_generator = new(Z) ReturnNode(yield_pos);
     true_branch->Add(return_from_generator);
     AddNodeForFinallyInlining(return_from_generator);
     AstNode* if_is_cancelled =
-       new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL);
+       new(Z) IfNode(Token::kNoSourcePos, add_call, true_branch, NULL);
     yield->AddNode(if_is_cancelled);
 
     AwaitMarkerNode* await_marker =
         new(Z) AwaitMarkerNode(async_temp_scope_,
                                current_block_->scope,
-                               Scanner::kNoSourcePos);
+                               Token::kNoSourcePos);
     yield->AddNode(await_marker);
     ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos);
     continuation_return->set_return_type(ReturnNode::kContinuationTarget);
@@ -9916,15 +9852,15 @@
                            &outer_async_saved_try_ctx);
     if (saved_try_ctx != NULL) {
       yield->AddNode(new (Z) StoreLocalNode(
-          Scanner::kNoSourcePos,
+          Token::kNoSourcePos,
           saved_try_ctx,
-          new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+          new (Z) LoadLocalNode(Token::kNoSourcePos,
                                 async_saved_try_ctx)));
       if (outer_saved_try_ctx != NULL) {
         yield->AddNode(new (Z) StoreLocalNode(
-            Scanner::kNoSourcePos,
+            Token::kNoSourcePos,
             outer_saved_try_ctx,
-            new (Z) LoadLocalNode(Scanner::kNoSourcePos,
+            new (Z) LoadLocalNode(Token::kNoSourcePos,
                                   outer_async_saved_try_ctx)));
       }
     } else {
@@ -9938,7 +9874,7 @@
 AstNode* Parser::ParseStatement() {
   TRACE_PARSER("ParseStatement");
   AstNode* statement = NULL;
-  intptr_t label_pos = Scanner::kNoSourcePos;
+  intptr_t label_pos = Token::kNoSourcePos;
   String* label_name = NULL;
   if (IsIdentifier()) {
     if (LookaheadToken(1) == Token::kCOLON) {
@@ -10098,7 +10034,19 @@
 void Parser::ReportError(intptr_t token_pos, const char* format, ...) const {
   va_list args;
   va_start(args, format);
-  Report::MessageV(Report::kError, script_, token_pos, format, args);
+  Report::MessageV(Report::kError,
+                   script_, token_pos, Report::AtLocation, format, args);
+  va_end(args);
+  UNREACHABLE();
+}
+
+
+void Parser::ReportErrorBefore(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  Report::MessageV(Report::kError,
+                   script_, PrevTokenPos(), Report::AfterLocation,
+                   format, args);
   va_end(args);
   UNREACHABLE();
 }
@@ -10107,7 +10055,8 @@
 void Parser::ReportError(const char* format, ...) const {
   va_list args;
   va_start(args, format);
-  Report::MessageV(Report::kError, script_, TokenPos(), format, args);
+  Report::MessageV(Report::kError,
+                   script_, TokenPos(), Report::AtLocation, format, args);
   va_end(args);
   UNREACHABLE();
 }
@@ -10116,7 +10065,8 @@
 void Parser::ReportWarning(intptr_t token_pos, const char* format, ...) const {
   va_list args;
   va_start(args, format);
-  Report::MessageV(Report::kWarning, script_, token_pos, format, args);
+  Report::MessageV(Report::kWarning,
+                   script_, token_pos, Report::AtLocation, format, args);
   va_end(args);
 }
 
@@ -10124,7 +10074,8 @@
 void Parser::ReportWarning(const char* format, ...) const {
   va_list args;
   va_start(args, format);
-  Report::MessageV(Report::kWarning, script_, TokenPos(), format, args);
+  Report::MessageV(Report::kWarning,
+                   script_, TokenPos(), Report::AtLocation, format, args);
   va_end(args);
 }
 
@@ -10150,7 +10101,7 @@
 
 void Parser::ExpectSemicolon() {
   if (CurrentToken() != Token::kSEMICOLON) {
-    ReportError("semicolon expected");
+    ReportErrorBefore("semicolon expected");
   }
   ConsumeToken();
 }
@@ -10282,8 +10233,8 @@
       func->is_external() && !func->is_static()) {
     arguments->Add(LoadReceiver(func->token_pos()));
   } else {
-    Type& type = Type::ZoneHandle(Z,
-        Type::New(cls, TypeArguments::Handle(Z), call_pos, Heap::kOld));
+    AbstractType& type = AbstractType::ZoneHandle(Z);
+    type ^= Type::New(cls, TypeArguments::Handle(Z), call_pos, Heap::kOld);
     type ^= ClassFinalizer::FinalizeType(
         current_class(), type, ClassFinalizer::kCanonicalize);
     arguments->Add(new(Z) LiteralNode(call_pos, type));
@@ -10510,9 +10461,22 @@
   }
   if (binary_op == Token::kIFNULL) {
     // Handle a ?? b.
+    if ((lhs->EvalConstExpr() != NULL) && (rhs->EvalConstExpr() != NULL)) {
+      Instance& expr_value = Instance::ZoneHandle(Z);
+      if (!GetCachedConstant(op_pos, &expr_value)) {
+        expr_value = EvaluateConstExpr(lhs->token_pos(), lhs).raw();
+        if (expr_value.IsNull()) {
+          expr_value = EvaluateConstExpr(rhs->token_pos(), rhs).raw();
+        }
+        CacheConstantValue(op_pos, expr_value);
+      }
+      return new(Z) LiteralNode(op_pos, expr_value);
+    }
+
     LetNode* result = new(Z) LetNode(op_pos);
     LocalVariable* left_temp = result->AddInitializer(lhs);
-    const intptr_t no_pos = Scanner::kNoSourcePos;
+    left_temp->set_is_final();
+    const intptr_t no_pos = Token::kNoSourcePos;
     LiteralNode* null_operand =
         new(Z) LiteralNode(no_pos, Object::null_instance());
     LoadLocalNode* load_left_temp = new(Z) LoadLocalNode(no_pos, left_temp);
@@ -10814,6 +10778,8 @@
       Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
   const intptr_t expr_pos = TokenPos();
 
+  RecursionChecker rc(this);
+
   if (CurrentToken() == Token::kTHROW) {
     if (require_compiletime_const) {
       ReportError("'throw expr' is not a valid compile-time constant");
@@ -11861,16 +11827,15 @@
 
 const AbstractType* Parser::ReceiverType(const Class& cls) {
   ASSERT(!cls.IsNull());
+  ASSERT(!cls.IsTypedefClass());
+  // Note that if cls is _Closure, the returned type will be _Closure,
+  // and not the signature type.
   Type& type = Type::ZoneHandle(Z, cls.CanonicalType());
   if (!type.IsNull()) {
     return &type;
   }
-  if (cls.IsSignatureClass()) {
-    type = cls.SignatureType();
-  } else {
-    type = Type::New(cls,
-        TypeArguments::Handle(Z, cls.type_parameters()), cls.token_pos());
-  }
+  type = Type::New(cls,
+      TypeArguments::Handle(Z, cls.type_parameters()), cls.token_pos());
   if (cls.is_type_finalized()) {
     type ^= ClassFinalizer::FinalizeType(
         cls, type, ClassFinalizer::kCanonicalizeWellFormed);
@@ -11887,7 +11852,7 @@
       !current_function().IsInFactoryScope()) {
     return false;
   }
-  return current_class().NumTypeParameters() > 0;
+  return current_class().IsGeneric();
 }
 
 // We cache computed compile-time constants in a map so we can look them
@@ -12447,7 +12412,7 @@
     bool consume_unresolved_prefix) {
   LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
   return ParseType(finalization, allow_deferred_type,
-                         consume_unresolved_prefix, &prefix);
+                   consume_unresolved_prefix, &prefix);
 }
 
 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
@@ -13132,19 +13097,12 @@
   closure.set_result_type(Object::dynamic_type());
   AddFormalParamsToFunction(&params, closure);
 
-  // Create and set the signature class of the closure.
-  const String& sig = String::Handle(Z, closure.Signature());
-  Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
-  if (sig_cls.IsNull()) {
-    sig_cls = Class::NewSignatureClass(sig, closure, script_, token_pos);
-    library_.AddClass(sig_cls);
-  }
-  closure.set_signature_class(sig_cls);
-  // Finalize types in signature class here, so that the
-  // signature type is not computed twice.
-  ClassFinalizer::FinalizeTypesInClass(sig_cls);
-  const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
-  ASSERT(sig_type.IsFinalized());
+  // Finalize function type.
+  FunctionType& signature_type =
+      FunctionType::Handle(Z, closure.SignatureType());
+  signature_type ^= ClassFinalizer::FinalizeType(
+      current_class(), signature_type, ClassFinalizer::kCanonicalize);
+  closure.SetSignatureType(signature_type);
   // Finalization would be premature when top-level parsing.
   ASSERT(!is_top_level_);
   return closure.raw();
@@ -14318,7 +14276,7 @@
 }  // namespace dart
 
 
-#else  // DART_PRECOMPILED
+#else  // DART_PRECOMPILED_RUNTIME
 
 
 namespace dart {
@@ -14402,4 +14360,4 @@
 
 }  // namespace dart
 
-#endif  // DART_PRECOMPILED
+#endif  // DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 1be0f50..9d9e503 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -36,6 +36,7 @@
 struct ParamList;
 struct QualIdent;
 class TopLevel;
+class RecursionChecker;
 
 // The class ParsedFunction holds the result of parsing a function.
 class ParsedFunction : public ZoneAllocated {
@@ -294,6 +295,7 @@
   }
 
   intptr_t TokenPos() const { return tokens_iterator_.CurrentPosition(); }
+  intptr_t PrevTokenPos() const { return prev_token_pos_; }
 
   Token::Kind CurrentToken() {
     if (token_kind_ == Token::kILLEGAL) {
@@ -316,6 +318,7 @@
 
   void ConsumeToken() {
     // Reset cache and advance the token.
+    prev_token_pos_ = tokens_iterator_.CurrentPosition();
     token_kind_ = Token::kILLEGAL;
     tokens_iterator_.Advance();
     INC_STAT(thread(), num_tokens_consumed, 1);
@@ -363,6 +366,9 @@
                                          const Function& constructor,
                                          const TypeArguments& type_arguments);
 
+  // Report error if parsed code is too deeply nested; avoid stack overflow.
+  void CheckStack();
+
   // Report already formatted error.
   static void ReportError(const Error& error);
 
@@ -374,6 +380,8 @@
   // Report error message at location of current token in current script.
   void ReportError(const char* msg, ...) const PRINTF_ATTRIBUTE(2, 3);
 
+  void ReportErrorBefore(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
+
   // Report error message at given location in current script.
   void ReportError(intptr_t token_pos,
                    const char* msg, ...) const PRINTF_ATTRIBUTE(3, 4);
@@ -533,7 +541,7 @@
   void AddFormalParamsToScope(const ParamList* params, LocalScope* scope);
 
   SequenceNode* ParseConstructor(const Function& func);
-  SequenceNode* ParseFunc(const Function& func);
+  SequenceNode* ParseFunc(const Function& func, bool check_semicolon);
 
   void ParseNativeFunctionBlock(const ParamList* params, const Function& func);
 
@@ -833,6 +841,7 @@
   Script& script_;
   TokenStream::Iterator tokens_iterator_;
   Token::Kind token_kind_;  // Cached token kind for current token.
+  intptr_t prev_token_pos_;
   Block* current_block_;
 
   // is_top_level_ is true if parsing the "top level" of a compilation unit,
@@ -889,6 +898,9 @@
   // Indentation of parser trace.
   intptr_t trace_indent_;
 
+  intptr_t recursion_counter_;
+  friend class RecursionChecker;
+
   DISALLOW_COPY_AND_ASSIGN(Parser);
 };
 
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index e7450b7..a5e6f2e 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -270,7 +270,7 @@
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -309,7 +309,7 @@
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -325,7 +325,7 @@
       " 3 StackVar      scope=2   begin=18  end=38  name=c\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -368,7 +368,7 @@
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -384,7 +384,7 @@
       " 3 StackVar      scope=2   begin=30  end=52  name=bb\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -397,7 +397,7 @@
       " 2 StackVar      scope=2   begin=18  end=62  name=aa\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -450,7 +450,7 @@
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -495,7 +495,7 @@
       "   name=:current_context_var\n"
 
       // Closure call saves current context.
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -536,7 +536,7 @@
       " 0 ContextVar    level=0   begin=50  end=62  name=x\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
@@ -551,7 +551,7 @@
       " 4 ContextVar    level=1   begin=22  end=47  name=i\n"
       " 5 StackVar      scope=4   begin=32  end=47  name=d\n"
 
-      "_FunctionImpl.call\n"
+      "_Closure.call\n"
       " 0 StackVar      scope=1   begin=0   end=4   name=this\n"
       " 1 CurrentCtx    scope=0   begin=0   end=0"
       "   name=:current_context_var\n"
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 97f90c3..2131faf 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -63,6 +63,7 @@
     class_count_(0),
     selector_count_(0),
     dropped_function_count_(0),
+    dropped_field_count_(0),
     libraries_(GrowableObjectArray::Handle(Z, I->object_store()->libraries())),
     pending_functions_(
         GrowableObjectArray::Handle(Z, GrowableObjectArray::New())),
@@ -111,6 +112,7 @@
   }
 
   DropUncompiledFunctions();
+  DropFields();
 
   // TODO(rmacnak): DropEmptyClasses();
 
@@ -120,14 +122,18 @@
 
   if (FLAG_trace_precompiler) {
     THR_Print("Precompiled %" Pd " functions, %" Pd " dynamic types,"
-              " %" Pd " dynamic selectors.\n Dropped %" Pd " functions.\n",
+              " %" Pd " dynamic selectors.\n Dropped %" Pd " functions, %" Pd
+              " fields.\n",
               function_count_,
               class_count_,
               selector_count_,
-              dropped_function_count_);
+              dropped_function_count_,
+              dropped_field_count_);
   }
 
   I->set_compilation_allowed(false);
+  I->object_store()->set_compile_time_constants(Array::null_array());
+  I->object_store()->set_unique_dynamic_targets(Array::null_array());
 }
 
 
@@ -154,6 +160,7 @@
   static const intptr_t kExternallyAllocatedCids[] = {
     kBoolCid,
     kNullCid,
+    kClosureCid,
 
     kSmiCid,
     kMintCid,
@@ -201,6 +208,7 @@
     kFloat64x2Cid,
 
     kTypeCid,
+    kFunctionTypeCid,
     kTypeRefCid,
     kTypeParameterCid,
     kBoundedTypeCid,
@@ -224,6 +232,7 @@
   }
 
   Dart_QualifiedFunctionName vm_entry_points[] = {
+    // Functions
     { "dart:async", "::", "_setScheduleImmediateClosure" },
     { "dart:core", "::", "_completeDeferredLoads"},
     { "dart:core", "AbstractClassInstantiationError",
@@ -262,6 +271,9 @@
     { "dart:_vmservice", "::", "_registerIsolate" },
     { "dart:_vmservice", "::", "boot" },
     { "dart:developer", "Metrics", "_printMetrics" },
+    // Fields
+    { "dart:core", "Error", "_stackTrace" },
+    { "dart:math", "_Random", "_state" },
     { NULL, NULL, NULL }  // Must be terminated with NULL entries.
   };
 
@@ -274,6 +286,7 @@
   Library& lib = Library::Handle(Z);
   Class& cls = Class::Handle(Z);
   Function& func = Function::Handle(Z);
+  Field& field = Field::Handle(Z);
   String& library_uri = String::Handle(Z);
   String& class_name = String::Handle(Z);
   String& function_name = String::Handle(Z);
@@ -293,6 +306,7 @@
 
     if (class_name.raw() == Symbols::TopLevel().raw()) {
       func = lib.LookupFunctionAllowPrivate(function_name);
+      field = lib.LookupFieldAllowPrivate(function_name);
     } else {
       cls = lib.LookupClassAllowPrivate(class_name);
       if (cls.IsNull()) {
@@ -306,25 +320,31 @@
 
       ASSERT(!cls.IsNull());
       func = cls.LookupFunctionAllowPrivate(function_name);
+      field = cls.LookupField(function_name);
     }
 
-    if (func.IsNull()) {
+    if (func.IsNull() && field.IsNull()) {
       if (FLAG_trace_precompiler) {
         THR_Print("WARNING: Missing %s %s %s\n",
                   entry_points[i].library_uri,
                   entry_points[i].class_name,
                   entry_points[i].function_name);
       }
-      continue;
     }
 
-    AddFunction(func);
-    if (func.IsGenerativeConstructor()) {
-      // Allocation stubs are referenced from the call site of the constructor,
-      // not in the constructor itself. So compiling the constructor isn't
-      // enough for us to discover the class is instantiated if the class isn't
-      // otherwise instantiated from Dart code and only instantiated from C++.
-      AddInstantiatedClass(cls);
+    if (!func.IsNull()) {
+      AddFunction(func);
+      if (func.IsGenerativeConstructor()) {
+        // Allocation stubs are referenced from the call site of the
+        // constructor, not in the constructor itself. So compiling the
+        // constructor isn't enough for us to discover the class is
+        // instantiated if the class isn't otherwise instantiated from Dart
+        // code and only instantiated from C++.
+        AddInstantiatedClass(cls);
+      }
+    }
+    if (!field.IsNull()) {
+      AddField(field);
     }
   }
 }
@@ -468,7 +488,8 @@
 
   if (instance.IsClosure()) {
     // An implicit static closure.
-    const Function& func = Function::Handle(Z, Closure::function(instance));
+    const Function& func =
+        Function::Handle(Z, Closure::Cast(instance).function());
     ASSERT(func.is_static());
     AddFunction(func);
     return;
@@ -511,10 +532,8 @@
 void Precompiler::AddClosureCall(const ICData& call_site) {
   const Array& arguments_descriptor =
       Array::Handle(Z, call_site.arguments_descriptor());
-  const Type& function_impl =
-      Type::Handle(Z, I->object_store()->function_impl_type());
   const Class& cache_class =
-      Class::Handle(Z, function_impl.type_class());
+      Class::Handle(Z, I->object_store()->closure_class());
   const Function& dispatcher = Function::Handle(Z,
       cache_class.GetInvocationDispatcher(Symbols::Call(),
                                           arguments_descriptor,
@@ -525,6 +544,8 @@
 
 
 void Precompiler::AddField(const Field& field) {
+  fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.raw()));
+
   if (field.is_static()) {
     const Object& value = Object::Handle(Z, field.StaticValue());
     if (value.IsInstance()) {
@@ -906,12 +927,12 @@
         }
       }
 
-      functions = Array::New(retained_functions.Length(), Heap::kOld);
-      for (intptr_t j = 0; j < retained_functions.Length(); j++) {
-        function ^= retained_functions.At(j);
-        functions.SetAt(j, function);
+      if (retained_functions.Length() > 0) {
+        functions = Array::MakeArray(retained_functions);
+        cls.SetFunctions(functions);
+      } else {
+        cls.SetFunctions(Object::empty_array());
       }
-      cls.SetFunctions(functions);
     }
   }
 
@@ -933,6 +954,49 @@
 }
 
 
+void Precompiler::DropFields() {
+  Library& lib = Library::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  Array& fields = Array::Handle(Z);
+  Field& field = Field::Handle(Z);
+  GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z);
+
+  for (intptr_t i = 0; i < libraries_.Length(); i++) {
+    lib ^= libraries_.At(i);
+    ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+    while (it.HasNext()) {
+      cls = it.GetNextClass();
+      if (cls.IsDynamicClass()) {
+        continue;  // class 'dynamic' is in the read-only VM isolate.
+      }
+
+      fields = cls.fields();
+      retained_fields = GrowableObjectArray::New();
+      for (intptr_t j = 0; j < fields.Length(); j++) {
+        field ^= fields.At(j);
+        bool drop = fields_to_retain_.Lookup(&field) == NULL;
+        if (drop) {
+          dropped_field_count_++;
+          if (FLAG_trace_precompiler) {
+            THR_Print("Precompilation dropping %s\n",
+                      field.ToCString());
+          }
+        } else {
+          retained_fields.Add(field);
+        }
+      }
+
+      if (retained_fields.Length() > 0) {
+        fields = Array::MakeArray(retained_fields);
+        cls.SetFields(fields);
+      } else {
+        cls.SetFields(Object::empty_array());
+      }
+    }
+  }
+}
+
+
 void Precompiler::BindStaticCalls() {
   class BindStaticCallsVisitor : public FunctionVisitor {
    public:
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 50f9551..fe7ec2d 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -87,6 +87,29 @@
 typedef DirectChainedHashMap<FunctionKeyValueTrait> FunctionSet;
 
 
+class FieldKeyValueTrait {
+ public:
+  // Typedefs needed for the DirectChainedHashMap template.
+  typedef const Field* Key;
+  typedef const Field* Value;
+  typedef const Field* Pair;
+
+  static Key KeyOf(Pair kv) { return kv; }
+
+  static Value ValueOf(Pair kv) { return kv; }
+
+  static inline intptr_t Hashcode(Key key) {
+    return key->token_pos();
+  }
+
+  static inline bool IsKeyEqual(Pair pair, Key key) {
+    return pair->raw() == key->raw();
+  }
+};
+
+typedef DirectChainedHashMap<FieldKeyValueTrait> FieldSet;
+
+
 class Precompiler : public ValueObject {
  public:
   static RawError* CompileAll(
@@ -125,6 +148,7 @@
   void CheckForNewDynamicFunctions();
 
   void DropUncompiledFunctions();
+  void DropFields();
   void CollectDynamicFunctionNames();
   void BindStaticCalls();
   void DedupStackmaps();
@@ -155,11 +179,13 @@
   intptr_t class_count_;
   intptr_t selector_count_;
   intptr_t dropped_function_count_;
+  intptr_t dropped_field_count_;
 
   const GrowableObjectArray& libraries_;
   const GrowableObjectArray& pending_functions_;
   SymbolSet sent_selectors_;
   FunctionSet enqueued_functions_;
+  FieldSet fields_to_retain_;
   Error& error_;
 };
 
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 63ac759..4c30971 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -853,7 +853,7 @@
 }
 
 
-TEST_CASE(Profiler_ClassAllocation) {
+TEST_CASE(Profiler_ClosureAllocation) {
   DisableNativeProfileScope dnps;
   const char* kScript =
       "var msg1 = 'a';\n"
@@ -875,12 +875,12 @@
   root_library ^= Api::UnwrapHandle(lib);
   Isolate* isolate = thread->isolate();
 
-  const Class& class_class =
-      Class::Handle(Object::class_class());
-  EXPECT(!class_class.IsNull());
-  class_class.SetTraceAllocation(true);
+  const Class& closure_class =
+      Class::Handle(Isolate::Current()->object_store()->closure_class());
+  EXPECT(!closure_class.IsNull());
+  closure_class.SetTraceAllocation(true);
 
-  // Invoke "foo" which during compilation, triggers a closure class allocation.
+  // Invoke "foo" which during compilation, triggers a closure allocation.
   Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
   EXPECT_VALID(result);
 
@@ -888,7 +888,7 @@
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
-    AllocationFilter filter(isolate, class_class.id());
+    AllocationFilter filter(isolate, closure_class.id());
     filter.set_enable_vm_ticks(true);
     profile.Build(thread, &filter, Profile::kNoTags);
     // We should have one allocation sample.
@@ -897,19 +897,14 @@
 
     walker.Reset(Profile::kExclusiveCode);
     EXPECT(walker.Down());
-#if defined(TARGET_OS_WINDOWS)
-    // TODO(johnmccutchan): Hookup native symbol resolver on Windows.
-    EXPECT_SUBSTRING("[Native]", walker.CurrentName());
-#else
-    EXPECT_SUBSTRING("dart::Profiler::SampleAllocation", walker.CurrentName());
-#endif
+    EXPECT_SUBSTRING("foo", walker.CurrentName());
     EXPECT(!walker.Down());
   }
 
-  // Disable allocation tracing for Class.
-  class_class.SetTraceAllocation(false);
+  // Disable allocation tracing for Closure.
+  closure_class.SetTraceAllocation(false);
 
-  // Invoke "bar" which during compilation, triggers a closure class allocation.
+  // Invoke "bar" which during compilation, triggers a closure allocation.
   result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
   EXPECT_VALID(result);
 
@@ -917,7 +912,7 @@
     StackZone zone(thread);
     HANDLESCOPE(thread);
     Profile profile(isolate);
-    AllocationFilter filter(isolate, class_class.id());
+    AllocationFilter filter(isolate, closure_class.id());
     filter.set_enable_vm_ticks(true);
     profile.Build(thread, &filter, Profile::kNoTags);
     // We should still only have one allocation sample.
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index ba53d37..d32b5ab 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -144,6 +144,13 @@
       instance_size = PcDescriptors::InstanceSize(length);
       break;
     }
+    case kCodeSourceMapCid: {
+      const RawCodeSourceMap* raw_code_source_map =
+          reinterpret_cast<const RawCodeSourceMap*>(this);
+      intptr_t length = raw_code_source_map->ptr()->length_;
+      instance_size = CodeSourceMap::InstanceSize(length);
+      break;
+    }
     case kStackmapCid: {
       const RawStackmap* map = reinterpret_cast<const RawStackmap*>(this);
       intptr_t length = map->ptr()->length_;
@@ -336,6 +343,13 @@
 }
 
 
+intptr_t RawFunctionType::VisitFunctionTypePointers(
+    RawFunctionType* raw_obj, ObjectPointerVisitor* visitor) {
+  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+  return FunctionType::InstanceSize();
+}
+
+
 intptr_t RawTypeRef::VisitTypeRefPointers(
     RawTypeRef* raw_obj, ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
@@ -379,6 +393,13 @@
 }
 
 
+intptr_t RawClosure::VisitClosurePointers(
+    RawClosure* raw_obj, ObjectPointerVisitor* visitor) {
+  visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+  return Closure::InstanceSize();
+}
+
+
 intptr_t RawClosureData::VisitClosureDataPointers(
     RawClosureData* raw_obj, ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(raw_obj->from(), raw_obj->to());
@@ -575,6 +596,12 @@
 }
 
 
+intptr_t RawCodeSourceMap::VisitCodeSourceMapPointers(
+    RawCodeSourceMap* raw_obj, ObjectPointerVisitor* visitor) {
+  return CodeSourceMap::InstanceSize(raw_obj->ptr()->length_);
+}
+
+
 intptr_t RawStackmap::VisitStackmapPointers(RawStackmap* raw_obj,
                                             ObjectPointerVisitor* visitor) {
   return Stackmap::InstanceSize(raw_obj->ptr()->length_);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ee5450d..35be68a 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -33,6 +33,7 @@
   V(Instructions)                                                              \
   V(ObjectPool)                                                                \
   V(PcDescriptors)                                                             \
+  V(CodeSourceMap)                                                             \
   V(Stackmap)                                                                  \
   V(LocalVarDescriptors)                                                       \
   V(ExceptionHandlers)                                                         \
@@ -50,10 +51,12 @@
     V(LibraryPrefix)                                                           \
     V(AbstractType)                                                            \
       V(Type)                                                                  \
+      V(FunctionType)                                                          \
       V(TypeRef)                                                               \
       V(TypeParameter)                                                         \
       V(BoundedType)                                                           \
       V(MixinAppType)                                                          \
+    V(Closure)                                                                 \
     V(Number)                                                                  \
       V(Integer)                                                               \
         V(Smi)                                                                 \
@@ -145,9 +148,10 @@
 #define DEFINE_OBJECT_KIND(clazz)                                              \
   kTypedData##clazz##ViewCid,
 CLASS_LIST_TYPED_DATA(DEFINE_OBJECT_KIND)
-  kByteDataViewCid,
 #undef DEFINE_OBJECT_KIND
 
+  kByteDataViewCid,
+
 #define DEFINE_OBJECT_KIND(clazz)                                              \
   kExternalTypedData##clazz##Cid,
 CLASS_LIST_TYPED_DATA(DEFINE_OBJECT_KIND)
@@ -590,8 +594,8 @@
   friend class Array;
   friend class Bigint;
   friend class ByteBuffer;
-  friend class Code;
   friend class Closure;
+  friend class Code;
   friend class Double;
   friend class FreeListElement;
   friend class Function;
@@ -659,7 +663,7 @@
   RawTypeArguments* type_parameters_;  // Array of TypeParameter.
   RawAbstractType* super_type_;
   RawType* mixin_;  // Generic mixin type, e.g. M<T>, not M<int>.
-  RawFunction* signature_function_;  // Associated function for signature class.
+  RawFunction* signature_function_;  // Associated function for typedef class.
   RawArray* constants_;  // Canonicalized values of this class.
   RawObject* canonical_types_;  // An array of canonicalized types of this class
                                 // or the canonical type.
@@ -830,7 +834,7 @@
   }
   RawContextScope* context_scope_;
   RawFunction* parent_function_;  // Enclosing function of this local function.
-  RawClass* signature_class_;
+  RawFunctionType* signature_type_;
   RawInstance* closure_;  // Closure object for static implicit closures.
   RawObject** to() {
     return reinterpret_cast<RawObject**>(&ptr()->closure_);
@@ -1052,6 +1056,7 @@
   RawObject* owner_;  // Function, Null, or a Class.
   RawExceptionHandlers* exception_handlers_;
   RawPcDescriptors* pc_descriptors_;
+  RawCodeSourceMap* code_source_map_;
   RawArray* stackmaps_;
   RawObject** to_snapshot() {
     return reinterpret_cast<RawObject**>(&ptr()->stackmaps_);
@@ -1199,6 +1204,23 @@
 };
 
 
+// CodeSourceMap stores a mapping between code PC ranges and source token
+// positions.
+class RawCodeSourceMap : public RawObject {
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(CodeSourceMap);
+
+  int32_t length_;  // Number of entries.
+
+  // Variable length data follows here.
+  uint8_t* data() { OPEN_ARRAY_START(uint8_t, intptr_t); }
+  const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }
+
+  friend class Object;
+  friend class SnapshotReader;
+};
+
+
 // Stackmap is an immutable representation of the layout of the stack at a
 // PC. The stack map representation consists of a bit map which marks each
 // live object index starting from the base of the frame.
@@ -1471,6 +1493,7 @@
     return reinterpret_cast<RawObject**>(&ptr()->formatted_message_);
   }
   int32_t token_pos_;  // Source position in script_.
+  bool report_after_token_;  // Report message at or after the token.
   int8_t kind_;  // Of type LanguageError::Kind.
 };
 
@@ -1562,6 +1585,25 @@
 };
 
 
+class RawFunctionType : public RawAbstractType {
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
+
+  RawObject** from() {
+    return reinterpret_cast<RawObject**>(&ptr()->scope_class_);
+  }
+  RawClass* scope_class_;
+  RawTypeArguments* arguments_;
+  RawFunction* signature_;
+  RawLanguageError* error_;  // Error object if type is malformed or malbounded.
+  RawObject** to() {
+    return reinterpret_cast<RawObject**>(&ptr()->error_);
+  }
+  int32_t token_pos_;
+  int8_t type_state_;
+};
+
+
 class RawTypeRef : public RawAbstractType {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeRef);
@@ -1624,6 +1666,24 @@
 };
 
 
+class RawClosure : public RawInstance {
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Closure);
+
+  RawObject** from() {
+    return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
+  }
+
+  RawTypeArguments* type_arguments_;
+  RawFunction* function_;
+  RawContext* context_;
+
+  RawObject** to() {
+    return reinterpret_cast<RawObject**>(&ptr()->context_);
+  }
+};
+
+
 class RawNumber : public RawInstance {
   RAW_OBJECT_IMPLEMENTATION(Number);
 };
@@ -2245,6 +2305,7 @@
          (index == kInstructionsCid) ||
          (index == kObjectPoolCid) ||
          (index == kPcDescriptorsCid) ||
+         (index == kCodeSourceMapCid) ||
          (index == kStackmapCid) ||
          (index == kLocalVarDescriptorsCid) ||
          (index == kExceptionHandlersCid) ||
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 87305ba..3a934d5 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -237,7 +237,7 @@
   READ_OBJECT_FIELDS(type, type.raw()->from(), type.raw()->to(), kAsReference);
 
   // Set the canonical bit.
-  if (!defer_canonicalization && RawObject::IsCanonical(tags)) {
+  if (!defer_canonicalization && is_canonical) {
     type.SetCanonical();
   }
 
@@ -275,15 +275,89 @@
   writer->Write<int32_t>(ptr()->token_pos_);
   writer->Write<int8_t>(ptr()->type_state_);
 
-  // Write out all the object pointer fields. Since we will be canonicalizing
-  // the type object when reading it back we should write out all the fields
-  // inline and not as references.
+  // Write out all the object pointer fields.
   ASSERT(ptr()->type_class_ != Object::null());
   SnapshotWriterVisitor visitor(writer, kAsReference);
   visitor.VisitPointers(from(), to());
 }
 
 
+RawFunctionType* FunctionType::ReadFrom(SnapshotReader* reader,
+                                        intptr_t object_id,
+                                        intptr_t tags,
+                                        Snapshot::Kind kind,
+                                        bool as_reference) {
+  ASSERT(reader != NULL);
+
+  // Determine if the scope class of this function type is in the full snapshot.
+  bool scopeclass_is_in_fullsnapshot = reader->Read<bool>();
+
+  // Allocate function type object.
+  FunctionType& function_type =
+      FunctionType::ZoneHandle(reader->zone(), NEW_OBJECT(FunctionType));
+  bool is_canonical = RawObject::IsCanonical(tags);
+  bool defer_canonicalization = is_canonical &&
+      (kind != Snapshot::kFull && scopeclass_is_in_fullsnapshot);
+  reader->AddBackRef(object_id,
+                     &function_type,
+                     kIsDeserialized,
+                     defer_canonicalization);
+
+  // Set all non object fields.
+  function_type.set_token_pos(reader->Read<int32_t>());
+  function_type.set_type_state(reader->Read<int8_t>());
+
+  // Set all the object fields.
+  READ_OBJECT_FIELDS(function_type,
+                     function_type.raw()->from(), function_type.raw()->to(),
+                     kAsReference);
+
+  // Set the canonical bit.
+  if (!defer_canonicalization && is_canonical) {
+    function_type.SetCanonical();
+  }
+
+  return function_type.raw();
+}
+
+
+void RawFunctionType::WriteTo(SnapshotWriter* writer,
+                              intptr_t object_id,
+                              Snapshot::Kind kind,
+                              bool as_reference) {
+  ASSERT(writer != NULL);
+
+  // Only resolved and finalized function types should be written to a snapshot.
+  ASSERT((ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) ||
+         (ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated));
+  ASSERT(ptr()->scope_class_ != Object::null());
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(kFunctionTypeCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+
+  // Write out scopeclass_is_in_fullsnapshot first as this will
+  // help the reader decide on how to canonicalize the type object.
+  intptr_t tags = writer->GetObjectTags(ptr()->scope_class_);
+  bool scopeclass_is_in_fullsnapshot =
+      (ClassIdTag::decode(tags) == kClassCid) &&
+      Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->scope_class_));
+  writer->Write<bool>(scopeclass_is_in_fullsnapshot);
+
+  // Write out all the non object pointer fields.
+  writer->Write<int32_t>(ptr()->token_pos_);
+  writer->Write<int8_t>(ptr()->type_state_);
+
+  // Write out all the object pointer fields.
+  ASSERT(ptr()->scope_class_ != Object::null());
+  SnapshotWriterVisitor visitor(writer, kAsReference);
+  visitor.VisitPointers(from(), to());
+}
+
+
 RawTypeRef* TypeRef::ReadFrom(SnapshotReader* reader,
                               intptr_t object_id,
                               intptr_t tags,
@@ -472,7 +546,7 @@
   }
 
   // Set the canonical bit.
-  if (!defer_canonicalization && RawObject::IsCanonical(tags)) {
+  if (!defer_canonicalization && is_canonical) {
     type_arguments.SetCanonical();
   }
 
@@ -548,6 +622,57 @@
 }
 
 
+RawClosure* Closure::ReadFrom(SnapshotReader* reader,
+                              intptr_t object_id,
+                              intptr_t tags,
+                              Snapshot::Kind kind,
+                              bool as_reference) {
+  ASSERT(reader != NULL);
+  ASSERT(kind == Snapshot::kFull);
+
+  // Allocate closure object.
+  Closure& closure = Closure::ZoneHandle(
+      reader->zone(), NEW_OBJECT(Closure));
+  reader->AddBackRef(object_id, &closure, kIsDeserialized);
+
+  // Set all the object fields.
+  READ_OBJECT_FIELDS(closure,
+                     closure.raw()->from(), closure.raw()->to(),
+                     kAsReference);
+
+  return closure.raw();
+}
+
+
+void RawClosure::WriteTo(SnapshotWriter* writer,
+                         intptr_t object_id,
+                         Snapshot::Kind kind,
+                         bool as_reference) {
+  ASSERT(writer != NULL);
+  if ((kind == Snapshot::kMessage) || (kind == Snapshot::kScript)) {
+    // Check if closure is serializable, throw an exception otherwise.
+    RawFunction* func = writer->IsSerializableClosure(this);
+    if (func != Function::null()) {
+      writer->WriteStaticImplicitClosure(object_id,
+                                         func,
+                                         writer->GetObjectTags(this));
+      return;
+    }
+  }
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+
+  // Write out the class and tags information.
+  writer->WriteIndexedObject(kClosureCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+
+  // Write out all the object pointer fields.
+  SnapshotWriterVisitor visitor(writer, kAsReference);
+  visitor.VisitPointers(from(), to());
+}
+
+
 RawClosureData* ClosureData::ReadFrom(SnapshotReader* reader,
                                       intptr_t object_id,
                                       intptr_t tags,
@@ -599,8 +724,8 @@
   // Parent function.
   writer->WriteObjectImpl(ptr()->parent_function_, kAsInlinedObject);
 
-  // Signature class.
-  writer->WriteObjectImpl(ptr()->signature_class_, kAsInlinedObject);
+  // Signature type.
+  writer->WriteObjectImpl(ptr()->signature_type_, kAsInlinedObject);
 
   // Static closure/Closure allocation stub.
   // We don't write the closure or allocation stub in the snapshot.
@@ -665,12 +790,15 @@
         reader->zone(), NEW_OBJECT(Function));
     reader->AddBackRef(object_id, &func, kIsDeserialized);
 
-    // Set all the non object fields.
-    func.set_token_pos(reader->Read<int32_t>());
-    func.set_end_token_pos(reader->Read<int32_t>());
+    // Set all the non object fields. Read the token positions now but
+    // don't set them until after setting the kind.
+    const int32_t token_pos = reader->Read<int32_t>();
+    const int32_t end_token_pos = reader->Read<uint32_t>();
     func.set_num_fixed_parameters(reader->Read<int16_t>());
     func.set_num_optional_parameters(reader->Read<int16_t>());
     func.set_kind_tag(reader->Read<uint32_t>());
+    func.set_token_pos(token_pos);
+    func.set_end_token_pos(end_token_pos);
     if (reader->snapshot_code()) {
       func.set_usage_counter(0);
       func.set_deoptimization_counter(0);
@@ -720,7 +848,7 @@
   ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
   bool is_in_fullsnapshot = false;
   bool owner_is_class = false;
-  if (kind == Snapshot::kScript) {
+  if ((kind == Snapshot::kScript) && !Function::IsSignatureFunction(this)) {
     intptr_t tags = writer->GetObjectTags(ptr()->owner_);
     intptr_t cid = ClassIdTag::decode(tags);
     owner_is_class = (cid == kClassCid);
@@ -1107,26 +1235,27 @@
     // The native resolver and symbolizer are not serialized.
     library.set_native_entry_resolver(NULL);
     library.set_native_entry_symbol_resolver(NULL);
-    // The cache of loaded scripts is not serialized.
-    library.StorePointer(&library.raw_ptr()->loaded_scripts_, Array::null());
 
     // Set all the object fields.
     // TODO(5411462): Need to assert No GC can happen here, even though
     // allocations may happen.
-    RawObject** toobj = (kind == Snapshot::kFull) ?
-        library.raw()->to() : library.raw()->to_snapshot();
-    intptr_t num_flds = (toobj - library.raw()->from());
+    intptr_t num_flds = (library.raw()->to_snapshot() - library.raw()->from());
     for (intptr_t i = 0; i <= num_flds; i++) {
       (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
       library.StorePointer((library.raw()->from() + i),
                            reader->PassiveObjectHandle()->raw());
     }
+    // Initialize cache of resolved names.
+    const intptr_t kInitialNameCacheSize = 64;
     if (kind != Snapshot::kFull) {
       // The cache of resolved names in library scope is not serialized.
-      const intptr_t kInitialNameCacheSize = 64;
       library.InitResolvedNamesCache(kInitialNameCacheSize);
       library.Register();
+    } else {
+      library.InitResolvedNamesCache(kInitialNameCacheSize, reader);
     }
+    // Initialize cache of loaded scripts.
+    library.StorePointer(&library.raw_ptr()->loaded_scripts_, Array::null());
   }
   return library.raw();
 }
@@ -1165,14 +1294,13 @@
     writer->Write<bool>(ptr()->debuggable_);
     // We do not serialize the native resolver or symbolizer. These need to be
     // explicitly set after deserialization.
-    // We do not write the loaded_scripts_ cache to the snapshot. It gets
-    // set to NULL when reading the library from the snapshot, and will
-    // be rebuilt lazily.
 
+    // We do not write the loaded_scripts_ and resolved_names_ caches to the
+    // snapshot. They get initialized when reading the library from the
+    // snapshot and will be rebuilt lazily.
     // Write out all the object pointer fields.
-    RawObject** toobj = (kind == Snapshot::kFull) ? to() : to_snapshot();
     SnapshotWriterVisitor visitor(writer, kAsReference);
-    visitor.VisitPointers(from(), toobj);
+    visitor.VisitPointers(from(), to_snapshot());
   }
 }
 
@@ -1548,6 +1676,51 @@
 }
 
 
+RawCodeSourceMap* CodeSourceMap::ReadFrom(SnapshotReader* reader,
+                                          intptr_t object_id,
+                                          intptr_t tags,
+                                          Snapshot::Kind kind,
+                                          bool as_reference) {
+  ASSERT(reader->snapshot_code());
+  ASSERT(kind == Snapshot::kFull);
+
+  const int32_t length = reader->Read<int32_t>();
+  CodeSourceMap& result =
+      CodeSourceMap::ZoneHandle(reader->zone(),
+                                NEW_OBJECT_WITH_LEN(CodeSourceMap, length));
+  reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+  if (result.Length() > 0) {
+    NoSafepointScope no_safepoint;
+    intptr_t len = result.Length();
+    uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
+    reader->ReadBytes(data, len);
+  }
+
+  return result.raw();
+}
+
+
+void RawCodeSourceMap::WriteTo(SnapshotWriter* writer,
+                               intptr_t object_id,
+                               Snapshot::Kind kind,
+                               bool as_reference) {
+  ASSERT(writer->snapshot_code());
+  ASSERT(kind == Snapshot::kFull);
+
+  // Write out the serialization header value for this object.
+  writer->WriteInlinedObjectHeader(object_id);
+  writer->WriteIndexedObject(kCodeSourceMapCid);
+  writer->WriteTags(writer->GetObjectTags(this));
+  writer->Write<int32_t>(ptr()->length_);
+  if (ptr()->length_ > 0) {
+    intptr_t len = ptr()->length_;
+    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
+    writer->WriteBytes(data, len);
+  }
+}
+
+
 RawStackmap* Stackmap::ReadFrom(SnapshotReader* reader,
                                 intptr_t object_id,
                                 intptr_t tags,
@@ -2037,6 +2210,7 @@
 
   // Set all non object fields.
   language_error.set_token_pos(reader->Read<int32_t>());
+  language_error.set_report_after_token(reader->Read<bool>());
   language_error.set_kind(reader->Read<uint8_t>());
 
   // Set all the object fields.
@@ -2063,6 +2237,7 @@
 
   // Write out all the non object fields.
   writer->Write<int32_t>(ptr()->token_pos_);
+  writer->Write<bool>(ptr()->report_after_token_);
   writer->Write<uint8_t>(ptr()->kind_);
 
   // Write out all the object pointer fields.
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index a41db46..40043b7 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -36,7 +36,7 @@
 
 
 static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex;
-static const intptr_t kNoSourcePos = Scanner::kNoSourcePos;
+static const intptr_t kNoSourcePos = Token::kNoSourcePos;
 static const intptr_t kMinStackSize = 512;
 
 
@@ -588,13 +588,13 @@
 
 
 LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const {
-  return new(Z) LoadLocalInstr(*local);
+  return new(Z) LoadLocalInstr(*local, kNoSourcePos);
 }
 
 
 void IRRegExpMacroAssembler::StoreLocal(LocalVariable* local,
                                         Value* value) {
-  Do(new(Z) StoreLocalInstr(*local, value));
+  Do(new(Z) StoreLocalInstr(*local, value, kNoSourcePos));
 }
 
 
@@ -621,7 +621,7 @@
     return Bind(new(Z) ConstantInstr(*local.ConstValue()));
   }
   ASSERT(!local.is_captured());
-  return Bind(new(Z) LoadLocalInstr(local));
+  return Bind(new(Z) LoadLocalInstr(local, kNoSourcePos));
 }
 
 
@@ -1924,7 +1924,7 @@
       index_val,
       characters,
       specialization_cid_,
-      Scanner::kNoSourcePos));
+      kNoSourcePos));
 }
 
 
diff --git a/runtime/vm/report.cc b/runtime/vm/report.cc
index d09d2a9..e5ab2ec 100644
--- a/runtime/vm/report.cc
+++ b/runtime/vm/report.cc
@@ -26,6 +26,7 @@
 RawString* Report::PrependSnippet(Kind kind,
                                   const Script& script,
                                   intptr_t token_pos,
+                                  bool report_after_token,
                                   const String& message) {
   const char* message_header;
   switch (kind) {
@@ -41,8 +42,11 @@
   if (!script.IsNull()) {
     const String& script_url = String::Handle(script.url());
     if (token_pos >= 0) {
-      intptr_t line, column;
-      script.GetTokenLocation(token_pos, &line, &column);
+      intptr_t line, column, token_len;
+      script.GetTokenLocation(token_pos, &line, &column, &token_len);
+      if (report_after_token) {
+        column += token_len;
+      }
       // Only report the line position if we have the original source. We still
       // need to get a valid column so that we can report the ^ mark below the
       // snippet.
@@ -120,7 +124,7 @@
                        const Script& script, intptr_t token_pos,
                        const char* format, va_list args) {
   const Error& error = Error::Handle(LanguageError::NewFormattedV(
-      prev_error, script, token_pos,
+      prev_error, script, token_pos, Report::AtLocation,
       kError, Heap::kNew,
       format, args));
   LongJump(error);
@@ -129,15 +133,18 @@
 
 
 void Report::MessageF(Kind kind, const Script& script, intptr_t token_pos,
-                      const char* format, ...) {
+                      bool report_after_token, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  MessageV(kind, script, token_pos, format, args);
+  MessageV(kind, script, token_pos, report_after_token, format, args);
   va_end(args);
 }
 
 
-void Report::MessageV(Kind kind, const Script& script, intptr_t token_pos,
+void Report::MessageV(Kind kind,
+                      const Script& script,
+                      intptr_t token_pos,
+                      bool report_after_token,
                       const char* format, va_list args) {
   if (kind < kError) {
     // Reporting a warning.
@@ -147,7 +154,7 @@
     if (!FLAG_warning_as_error) {
       const String& msg = String::Handle(String::NewFormattedV(format, args));
       const String& snippet_msg = String::Handle(
-          PrependSnippet(kind, script, token_pos, msg));
+          PrependSnippet(kind, script, token_pos, report_after_token, msg));
       OS::Print("%s", snippet_msg.ToCString());
       if (kind == kJSWarning) {
         TraceJSWarning(script, token_pos, msg);
@@ -166,7 +173,7 @@
   // Reporting an error (or a warning as error).
   const Error& error = Error::Handle(
       LanguageError::NewFormattedV(Error::Handle(),  // No previous error.
-                                   script, token_pos,
+                                   script, token_pos, report_after_token,
                                    kind, Heap::kNew,
                                    format, args));
   if (kind == kJSWarning) {
@@ -232,7 +239,7 @@
   const intptr_t token_pos = caller_code.GetTokenIndexOfPC(caller_pc);
   const Function& caller = Function::Handle(zone, caller_code.function());
   const Script& script = Script::Handle(zone, caller.script());
-  MessageF(kJSWarning, script, token_pos, "%s", msg);
+  MessageF(kJSWarning, script, token_pos, Report::AtLocation, "%s", msg);
 }
 
 
diff --git a/runtime/vm/report.h b/runtime/vm/report.h
index 8cc50a1..1a8d22a 100644
--- a/runtime/vm/report.h
+++ b/runtime/vm/report.h
@@ -28,6 +28,9 @@
     kBailout,
   };
 
+  static const bool AtLocation = false;
+  static const bool AfterLocation = true;
+
   // Report an already formatted error via a long jump.
   static void LongJump(const Error& error);
 
@@ -41,8 +44,10 @@
 
   // Report a warning/jswarning/error/bailout message.
   static void MessageF(Kind kind, const Script& script, intptr_t token_pos,
-                       const char* format, ...) PRINTF_ATTRIBUTE(4, 5);
+                       bool report_after_token,
+                       const char* format, ...) PRINTF_ATTRIBUTE(5, 6);
   static void MessageV(Kind kind, const Script& script, intptr_t token_pos,
+                       bool report_after_token,
                        const char* format, va_list args);
 
   // Support to report Javascript compatibility warnings. Note that a
@@ -67,6 +72,7 @@
   static RawString* PrependSnippet(Kind kind,
                                    const Script& script,
                                    intptr_t token_pos,
+                                   bool report_after_token,
                                    const String& message);
 
  private:
diff --git a/runtime/vm/report_test.cc b/runtime/vm/report_test.cc
index 6338f5b..95e469e 100644
--- a/runtime/vm/report_test.cc
+++ b/runtime/vm/report_test.cc
@@ -21,7 +21,8 @@
   {
     const intptr_t token_pos = 0;
     const char* message = "High Voltage";
-    Report::MessageF(Report::kJSWarning, script, token_pos, "%s", message);
+    Report::MessageF(Report::kJSWarning,
+                     script, token_pos, Report::AtLocation, "%s", message);
     {
       JSONStream js;
       trace_buffer->PrintToJSONStream(&js);
@@ -45,7 +46,8 @@
   {
     const intptr_t token_pos = 1;
     const char* message = "Low Voltage";
-    Report::MessageF(Report::kJSWarning, script, token_pos, "%s", message);
+    Report::MessageF(Report::kJSWarning,
+                     script, token_pos, Report::AtLocation, "%s", message);
   }
   EXPECT_EQ(2, trace_buffer->Length());
   EXPECT_SUBSTRING("{\"type\":\"JSCompatibilityWarning\",\"script\":{\"type\":"
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index f177a10..6e0b1bb 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -17,7 +17,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const String& function_name = String::ZoneHandle(Symbols::New(name));
   const Function& function = Function::ZoneHandle(
       Function::New(function_name, RawFunction::kRegularFunction,
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index 7a81040..5b35317 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -44,13 +44,6 @@
     const String* literal;    // Identifier, number or string literal.
   };
 
-  // Dummy token index reflecting an unknown source position.
-  static const intptr_t kNoSourcePos = -1;
-
-  static bool ValidSourcePosition(intptr_t token_pos) {
-    return (token_pos >= 0) || (token_pos == kNoSourcePos);
-  }
-
   typedef ZoneGrowableArray<TokenDescriptor> GrowableTokenStream;
 
   // Initializes scanner to scan string source.
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index 4c52227..9b609c1 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -29,8 +29,8 @@
       loop_level_(loop_level),
       context_level_(LocalScope::kUnitializedContextLevel),
       num_context_variables_(0),
-      begin_token_pos_(Scanner::kNoSourcePos),
-      end_token_pos_(Scanner::kNoSourcePos),
+      begin_token_pos_(Token::kNoSourcePos),
+      end_token_pos_(Token::kNoSourcePos),
       variables_(),
       labels_(),
       referenced_() {
diff --git a/runtime/vm/scopes_test.cc b/runtime/vm/scopes_test.cc
index 3640937..c3ad21d 100644
--- a/runtime/vm/scopes_test.cc
+++ b/runtime/vm/scopes_test.cc
@@ -14,18 +14,18 @@
   const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
   const String& a = String::ZoneHandle(Symbols::New("a"));
   LocalVariable* var_a =
-      new LocalVariable(Scanner::kNoSourcePos, a, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, a, dynamic_type);
   LocalVariable* inner_var_a =
-      new LocalVariable(Scanner::kNoSourcePos, a, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, a, dynamic_type);
   const String& b = String::ZoneHandle(Symbols::New("b"));
   LocalVariable* var_b =
-      new LocalVariable(Scanner::kNoSourcePos, b, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, b, dynamic_type);
   const String& c = String::ZoneHandle(Symbols::New("c"));
   LocalVariable* var_c =
-      new LocalVariable(Scanner::kNoSourcePos, c, dynamic_type);
+      new LocalVariable(Token::kNoSourcePos, c, dynamic_type);
   const String& L = String::ZoneHandle(Symbols::New("L"));
   SourceLabel* label_L =
-      new SourceLabel(Scanner::kNoSourcePos, L, SourceLabel::kFor);
+      new SourceLabel(Token::kNoSourcePos, L, SourceLabel::kFor);
 
   LocalScope* outer_scope = new LocalScope(NULL, 0, 0);
   LocalScope* inner_scope1 = new LocalScope(outer_scope, 0, 0);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 631a4ec..8991390 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2311,13 +2311,15 @@
 }
 
 
-static const char* kCallSitesStr = "CallSites";
+static const char* kCallSitesStr = "_CallSites";
 static const char* kCoverageStr = "Coverage";
+static const char* kPossibleBreakpointsStr = "PossibleBreakpoints";
 
 
 static const char* const report_enum_names[] = {
   kCallSitesStr,
   kCoverageStr,
+  kPossibleBreakpointsStr,
   NULL,
 };
 
@@ -2346,6 +2348,8 @@
       report_set |= SourceReport::kCallSites;
     } else if (strcmp(*reports, kCoverageStr) == 0) {
       report_set |= SourceReport::kCoverage;
+    } else if (strcmp(*reports, kPossibleBreakpointsStr) == 0) {
+      report_set |= SourceReport::kPossibleBreakpoints;
     }
     reports++;
   }
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index a57296f..a1c1d5c 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -28,6 +28,9 @@
 
 namespace dart {
 
+DECLARE_FLAG(bool, use_field_guards);
+
+
 static const int kNumVmIsolateSnapshotReferences = 32 * KB;
 static const int kNumInitialReferencesInFullSnapshot = 160 * KB;
 static const int kNumInitialReferences = 64;
@@ -480,6 +483,8 @@
     AddBackRef(object_id, result, state);
     cls_ ^= ReadObjectImpl(kAsInlinedObject);
     ASSERT(!cls_.IsNull());
+    // Closure instances are handled by Closure::ReadFrom().
+    ASSERT(!cls_.IsClosureClass());
     instance_size = cls_.instance_size();
     ASSERT(instance_size > 0);
     // Allocate the instance and read in all the fields for the object.
@@ -495,8 +500,7 @@
   }
   if (!as_reference) {
     // Read all the individual fields for inlined objects.
-    intptr_t next_field_offset = Class::IsSignatureClass(cls_.raw())
-        ? Closure::InstanceSize() : cls_.next_field_offset();
+    intptr_t next_field_offset = cls_.next_field_offset();
 
     intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
     ASSERT(next_field_offset > 0);
@@ -509,7 +513,8 @@
       pobj_ = ReadObjectImpl(read_as_reference);
       result->SetFieldAtOffset(offset, pobj_);
       if ((offset != type_argument_field_offset) &&
-          (kind_ == Snapshot::kMessage)) {
+          (kind_ == Snapshot::kMessage) &&
+          FLAG_use_field_guards) {
         // TODO(fschneider): Consider hoisting these lookups out of the loop.
         // This would involve creating a handle, since cls_ can't be reused
         // across the call to ReadObjectImpl.
@@ -781,6 +786,17 @@
 }
 
 
+RawCodeSourceMap* SnapshotReader::NewCodeSourceMap(intptr_t len) {
+  ASSERT(kind_ == Snapshot::kFull);
+  ASSERT_NO_SAFEPOINT_SCOPE();
+  RawCodeSourceMap* obj = reinterpret_cast<RawCodeSourceMap*>(
+      AllocateUninitialized(kCodeSourceMapCid,
+                            CodeSourceMap::InstanceSize(len)));
+  obj->ptr()->length_ = len;
+  return obj;
+}
+
+
 RawStackmap* SnapshotReader::NewStackmap(intptr_t len) {
   ASSERT(kind_ == Snapshot::kFull);
   ASSERT_NO_SAFEPOINT_SCOPE();
@@ -921,6 +937,11 @@
 }
 
 
+RawFunctionType* SnapshotReader::NewFunctionType() {
+  ALLOC_NEW_OBJECT(FunctionType);
+}
+
+
 RawTypeRef* SnapshotReader::NewTypeRef() {
   ALLOC_NEW_OBJECT(TypeRef);
 }
@@ -946,6 +967,11 @@
 }
 
 
+RawClosure* SnapshotReader::NewClosure() {
+  ALLOC_NEW_OBJECT(Closure);
+}
+
+
 RawClosureData* SnapshotReader::NewClosureData() {
   ALLOC_NEW_OBJECT(ClosureData);
 }
@@ -1389,16 +1415,20 @@
 
 void SnapshotReader::ProcessDeferredCanonicalizations() {
   Type& typeobj = Type::Handle();
+  FunctionType& funtypeobj = FunctionType::Handle();
   TypeArguments& typeargs = TypeArguments::Handle();
   Object& newobj = Object::Handle();
   for (intptr_t i = 0; i < backward_references_->length(); i++) {
     BackRefNode& backref = (*backward_references_)[i];
     if (backref.defer_canonicalization()) {
       Object* objref = backref.reference();
-      // Object should either be an abstract type or a type argument.
+      // Object should either be a type, a function type, or a type argument.
       if (objref->IsType()) {
         typeobj ^= objref->raw();
         newobj = typeobj.Canonicalize();
+      } else if (objref->IsFunctionType()) {
+        funtypeobj ^= objref->raw();
+        newobj = funtypeobj.Canonicalize();
       } else {
         ASSERT(objref->IsTypeArguments());
         typeargs ^= objref->raw();
@@ -2321,33 +2351,28 @@
 }
 
 
-RawFunction* SnapshotWriter::IsSerializableClosure(RawClass* cls,
-                                                   RawObject* obj) {
-  if (Class::IsSignatureClass(cls)) {
-    // 'obj' is a closure as its class is a signature class, extract
-    // the function object to check if this closure can be sent in an
-    // isolate message.
-    RawFunction* func = Closure::GetFunction(obj);
-    // We only allow closure of top level methods or static functions in a
-    // class to be sent in isolate messages.
-    if (can_send_any_object() &&
-        Function::IsImplicitStaticClosureFunction(func)) {
-      return func;
-    }
-    // Not a closure of a top level method or static function, throw an
-    // exception as we do not allow these objects to be serialized.
-    HANDLESCOPE(thread());
-
-    const Class& clazz = Class::Handle(zone(), cls);
-    const Function& errorFunc = Function::Handle(zone(), func);
-    ASSERT(!errorFunc.IsNull());
-
-    // All other closures are errors.
-    char* chars = OS::SCreate(thread()->zone(),
-        "Illegal argument in isolate message : (object is a closure - %s %s)",
-        clazz.ToCString(), errorFunc.ToCString());
-    SetWriteException(Exceptions::kArgument, chars);
+RawFunction* SnapshotWriter::IsSerializableClosure(RawClosure* closure) {
+  // Extract the function object to check if this closure
+  // can be sent in an isolate message.
+  RawFunction* func = closure->ptr()->function_;
+  // We only allow closure of top level methods or static functions in a
+  // class to be sent in isolate messages.
+  if (can_send_any_object() &&
+      Function::IsImplicitStaticClosureFunction(func)) {
+    return func;
   }
+  // Not a closure of a top level method or static function, throw an
+  // exception as we do not allow these objects to be serialized.
+  HANDLESCOPE(thread());
+
+  const Function& errorFunc = Function::Handle(zone(), func);
+  ASSERT(!errorFunc.IsNull());
+
+  // All other closures are errors.
+  char* chars = OS::SCreate(thread()->zone(),
+      "Illegal argument in isolate message : (object is a closure - %s)",
+      errorFunc.ToCString());
+  SetWriteException(Exceptions::kArgument, chars);
   return Function::null();
 }
 
@@ -2393,20 +2418,12 @@
                                    intptr_t tags,
                                    intptr_t object_id,
                                    bool as_reference) {
+  // Closure instances are handled by RawClosure::WriteTo().
+  ASSERT(!Class::IsClosureClass(cls));
+
   // Check if the instance has native fields and throw an exception if it does.
   CheckForNativeFields(cls);
 
-  if ((kind() == Snapshot::kMessage) || (kind() == Snapshot::kScript)) {
-    // Check if object is a closure that is serializable, if the object is a
-    // closure that is not serializable this will throw an exception.
-    RawFunction* func = IsSerializableClosure(cls, raw);
-    if (func != Function::null()) {
-      forward_list_->SetState(object_id, kIsSerialized);
-      WriteStaticImplicitClosure(object_id, func, tags);
-      return;
-    }
-  }
-
   // Object is regular dart instance.
   if (as_reference) {
     // Write out the serialization header value for this object.
@@ -2419,8 +2436,7 @@
     // Write out the class information for this object.
     WriteObjectImpl(cls, kAsInlinedObject);
   } else {
-    intptr_t next_field_offset = Class::IsSignatureClass(cls) ?
-        Closure::InstanceSize() :
+    intptr_t next_field_offset =
         cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2;
     ASSERT(next_field_offset > 0);
 
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 8570a06..f635618 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -22,6 +22,7 @@
 class Array;
 class Class;
 class ClassTable;
+class Closure;
 class Code;
 class ExternalTypedData;
 class GrowableObjectArray;
@@ -40,7 +41,9 @@
 class RawBoundedType;
 class RawCapability;
 class RawClass;
+class RawClosure;
 class RawClosureData;
+class RawCodeSourceMap;
 class RawContext;
 class RawContextScope;
 class RawDouble;
@@ -49,6 +52,7 @@
 class RawFloat32x4;
 class RawFloat64x2;
 class RawFunction;
+class RawFunctionType;
 class RawGrowableObjectArray;
 class RawICData;
 class RawImmutableArray;
@@ -412,17 +416,20 @@
   RawDouble* NewDouble(double value);
   RawUnresolvedClass* NewUnresolvedClass();
   RawType* NewType();
+  RawFunctionType* NewFunctionType();
   RawTypeRef* NewTypeRef();
   RawTypeParameter* NewTypeParameter();
   RawBoundedType* NewBoundedType();
   RawMixinAppType* NewMixinAppType();
   RawPatchClass* NewPatchClass();
+  RawClosure* NewClosure();
   RawClosureData* NewClosureData();
   RawRedirectionData* NewRedirectionData();
   RawFunction* NewFunction();
   RawCode* NewCode(intptr_t pointer_offsets_length);
   RawObjectPool* NewObjectPool(intptr_t length);
   RawPcDescriptors* NewPcDescriptors(intptr_t length);
+  RawCodeSourceMap* NewCodeSourceMap(intptr_t length);
   RawLocalVarDescriptors* NewLocalVarDescriptors(intptr_t num_entries);
   RawExceptionHandlers* NewExceptionHandlers(intptr_t num_entries);
   RawStackmap* NewStackmap(intptr_t length);
@@ -558,6 +565,7 @@
   friend class Bigint;
   friend class BoundedType;
   friend class Class;
+  friend class Closure;
   friend class ClosureData;
   friend class Code;
   friend class Context;
@@ -588,6 +596,7 @@
   friend class SubtypeTestCache;
   friend class TokenStream;
   friend class Type;
+  friend class FunctionType;
   friend class TypeArguments;
   friend class TypeParameter;
   friend class TypeRef;
@@ -921,14 +930,17 @@
 
   void WriteFunctionId(RawFunction* func, bool owner_is_class);
 
+  RawFunction* IsSerializableClosure(RawClosure* closure);
+
+  void WriteStaticImplicitClosure(intptr_t object_id,
+                                  RawFunction* func,
+                                  intptr_t tags);
+
  protected:
   bool CheckAndWritePredefinedObject(RawObject* raw);
   bool HandleVMIsolateObject(RawObject* raw);
 
   void WriteClassId(RawClass* cls);
-  void WriteStaticImplicitClosure(intptr_t object_id,
-                                  RawFunction* func,
-                                  intptr_t tags);
   void WriteObjectImpl(RawObject* raw, bool as_reference);
   void WriteMarkedObjectImpl(RawObject* raw,
                              intptr_t tags,
@@ -942,7 +954,6 @@
                     RawTypeArguments* type_arguments,
                     RawObject* data[],
                     bool as_reference);
-  RawFunction* IsSerializableClosure(RawClass* cls, RawObject* obj);
   RawClass* GetFunctionOwner(RawFunction* func);
   void CheckForNativeFields(RawClass* cls);
   void SetWriteException(Exceptions::ExceptionType type, const char* msg);
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 8c08726..93400bb 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -206,6 +206,44 @@
   }
 }
 
+void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
+                                                const Function& func,
+                                                const Code& code) {
+  const uint8_t kSafepointKind = (RawPcDescriptors::kIcCall |
+                                  RawPcDescriptors::kUnoptStaticCall |
+                                  RawPcDescriptors::kRuntimeCall);
+  const intptr_t begin_pos = func.token_pos();
+  const intptr_t end_pos = func.end_token_pos();
+
+  const PcDescriptors& descriptors = PcDescriptors::Handle(
+      zone(), code.pc_descriptors());
+
+  intptr_t func_length = (end_pos - begin_pos) + 1;
+  GrowableArray<char> possible(func_length);
+  possible.SetLength(func_length);
+  for (int i = 0; i < func_length; i++) {
+    possible[i] = false;
+  }
+
+  PcDescriptors::Iterator iter(descriptors, kSafepointKind);
+  while (iter.MoveNext()) {
+    const intptr_t token_pos = iter.TokenPos();
+    if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+      // Does not correspond to a valid source position.
+      continue;
+    }
+    intptr_t token_offset = token_pos - begin_pos;
+    possible[token_offset] = true;
+  }
+
+  JSONArray bpts(jsobj, "possibleBreakpoints");
+  for (int i = 0; i < func_length; i++) {
+    if (possible[i]) {
+      bpts.AddValue(begin_pos + i);  // Add the token position.
+    }
+  }
+}
+
 
 void SourceReport::PrintScriptTable(JSONArray* scripts) {
   for (int i = 0; i < script_table_entries_.length(); i++) {
@@ -265,6 +303,9 @@
   if (IsReportRequested(kCoverage)) {
     PrintCoverageData(&range, func, code);
   }
+  if (IsReportRequested(kPossibleBreakpoints)) {
+    PrintPossibleBreakpointsData(&range, func, code);
+  }
 }
 
 
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
index 09c8092..9b03a23 100644
--- a/runtime/vm/source_report.h
+++ b/runtime/vm/source_report.h
@@ -18,8 +18,9 @@
 class SourceReport {
  public:
   enum ReportKind {
-    kCallSites = 0x1,
-    kCoverage  = 0x2,
+    kCallSites           = 0x1,
+    kCoverage            = 0x2,
+    kPossibleBreakpoints = 0x4,
   };
 
   enum CompileMode {
@@ -55,6 +56,8 @@
                           const Function& func, const Code& code);
   void PrintCoverageData(JSONObject* jsobj,
                          const Function& func, const Code& code);
+  void PrintPossibleBreakpointsData(JSONObject* jsobj,
+                                    const Function& func, const Code& code);
   void PrintScriptTable(JSONArray* jsarr);
 
   void VisitFunction(JSONArray* jsarr, const Function& func);
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index 0e1bb79..b213a20 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -458,4 +458,49 @@
       buffer);
 }
 
+
+TEST_CASE(SourceReport_PossibleBreakpoints_Simple) {
+  char buffer[1024];
+  const char* kScript =
+      "helper0() {}\n"
+      "helper1() {}\n"
+      "main() {\n"
+      "  if (true) {\n"
+      "    helper0();\n"
+      "  } else {\n"
+      "    helper1();\n"
+      "  }\n"
+      "}";
+
+  Library& lib = Library::Handle();
+  lib ^= ExecuteScript(kScript);
+  ASSERT(!lib.IsNull());
+  const Script& script = Script::Handle(lib.LookupScript(
+      String::Handle(String::New("test-lib"))));
+
+  SourceReport report(SourceReport::kPossibleBreakpoints);
+  JSONStream js;
+  report.PrintJSON(&js, script);
+  ElideJSONSubstring("classes", js.ToCString(), buffer);
+  ElideJSONSubstring("libraries", buffer, buffer);
+  EXPECT_STREQ(
+      "{\"type\":\"SourceReport\",\"ranges\":["
+
+      // helper0.
+      "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":4,\"compiled\":true,"
+      "\"possibleBreakpoints\":[1,4]},"
+
+      // One range not compiled (helper1).
+      "{\"scriptIndex\":0,\"startPos\":6,\"endPos\":10,\"compiled\":false},"
+
+      // main.
+      "{\"scriptIndex\":0,\"startPos\":12,\"endPos\":39,\"compiled\":true,"
+      "\"possibleBreakpoints\":[13,23,32,39]}],"
+
+      // Only one script in the script table.
+      "\"scripts\":[{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
+      "\"uri\":\"test-lib\",\"_kind\":\"script\"}]}",
+      buffer);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index ad3c995..d4be5b5 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -45,13 +45,13 @@
 
 
 void StubCode::InitOnce() {
-#if !defined(DART_PRECOMPILED)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   // Generate all the stubs.
   Code& code = Code::Handle();
   VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
 #else
   UNREACHABLE();
-#endif  // DART_PRECOMPILED
+#endif  // DART_PRECOMPILED_RUNTIME
 }
 
 
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 711c901..4cf291b 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1804,8 +1804,12 @@
   // R3: instance class id.
   // R4: instance type arguments.
   __ SmiTag(R3);
+  __ CompareImmediate(R3, Smi::RawValue(kClosureCid));
+  __ ldr(R3, FieldAddress(R0, Closure::function_offset()), EQ);
+  // R3: instance class id as Smi or function.
   __ Bind(&loop);
-  __ ldr(R9, Address(R2, kWordSize * SubtypeTestCache::kInstanceClassId));
+  __ ldr(R9,
+         Address(R2, kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
   __ CompareObject(R9, Object::null_object());
   __ b(&not_found, EQ);
   __ cmp(R9, Operand(R3));
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 0585653..5db34dc 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -1865,9 +1865,13 @@
   // R3: instance class id.
   // R4: instance type arguments.
   __ SmiTag(R3);
+  __ CompareImmediate(R3, Smi::RawValue(kClosureCid));
+  __ b(&loop, NE);
+  __ LoadFieldFromOffset(R3, R0, Closure::function_offset());
+  // R3: instance class id as Smi or function.
   __ Bind(&loop);
   __ LoadFromOffset(
-      R5, R2, kWordSize * SubtypeTestCache::kInstanceClassId);
+      R5, R2, kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction);
   __ CompareObject(R5, Object::null_object());
   __ b(&not_found, EQ);
   __ CompareRegisters(R5, R3);
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index eba3949..a64d6f7 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -23,7 +23,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const Library& lib = Library::Handle(Library::New(class_name));
   owner_class.set_library(lib);
   const String& function_name = String::ZoneHandle(Symbols::New(name));
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index 39aa9e6..36d703e 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -23,7 +23,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const Library& lib = Library::Handle(Library::New(class_name));
   owner_class.set_library(lib);
   const String& function_name = String::ZoneHandle(Symbols::New(name));
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index b6302d3..e1e3fff 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1781,8 +1781,14 @@
   // ECX: instance class id.
   // EBX: instance type arguments.
   __ SmiTag(ECX);
+  __ cmpl(ECX, Immediate(Smi::RawValue(kClosureCid)));
+  __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
+  __ movl(ECX, FieldAddress(EAX, Closure::function_offset()));
+  // ECX: instance class id as Smi or function.
   __ Bind(&loop);
-  __ movl(EDI, Address(EDX, kWordSize * SubtypeTestCache::kInstanceClassId));
+  __ movl(EDI,
+          Address(EDX,
+                  kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmpl(EDI, raw_null);
   __ j(EQUAL, &not_found, Assembler::kNearJump);
   __ cmpl(EDI, ECX);
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index 1ab200b..fff4bc7 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -23,7 +23,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const Library& lib = Library::Handle(Library::New(class_name));
   owner_class.set_library(lib);
   const String& function_name = String::ZoneHandle(Symbols::New(name));
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 58af418..bd6567d 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1943,8 +1943,12 @@
   // T2: Entry start.
   // T7: null.
   __ SmiTag(T0);
+  __ BranchNotEqual(T0, Immediate(Smi::RawValue(kClosureCid)), &loop);
+  __ lw(T0, FieldAddress(A0, Closure::function_offset()));
+  // T0: instance class id as Smi or function.
   __ Bind(&loop);
-  __ lw(T3, Address(T2, kWordSize * SubtypeTestCache::kInstanceClassId));
+  __ lw(T3,
+        Address(T2, kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
   __ beq(T3, T7, &not_found);
 
   if (n == 1) {
diff --git a/runtime/vm/stub_code_mips_test.cc b/runtime/vm/stub_code_mips_test.cc
index 512baaf..21e7768 100644
--- a/runtime/vm/stub_code_mips_test.cc
+++ b/runtime/vm/stub_code_mips_test.cc
@@ -23,7 +23,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const Library& lib = Library::Handle(Library::New(class_name));
   owner_class.set_library(lib);
   const String& function_name = String::ZoneHandle(Symbols::New(name));
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 39d8dc9..024fbfa 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1841,8 +1841,14 @@
   // R13: instance type arguments.
   Label loop, found, not_found, next_iteration;
   __ SmiTag(R10);
+  __ cmpq(R10, Immediate(Smi::RawValue(kClosureCid)));
+  __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
+  __ movq(R10, FieldAddress(RAX, Closure::function_offset()));
+  // R10: instance class id as Smi or function.
   __ Bind(&loop);
-  __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId));
+  __ movq(RDI,
+          Address(RDX,
+                  kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmpq(RDI, R9);
   __ j(EQUAL, &not_found, Assembler::kNearJump);
   __ cmpq(RDI, R10);
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index ff020e7..2716433 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -23,7 +23,7 @@
   const String& class_name = String::Handle(Symbols::New("ownerClass"));
   const Script& script = Script::Handle();
   const Class& owner_class =
-      Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+      Class::Handle(Class::New(class_name, script, Token::kNoSourcePos));
   const Library& lib = Library::Handle(Library::New(class_name));
   owner_class.set_library(lib);
   const String& function_name = String::ZoneHandle(Symbols::New(name));
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 1c40fb5..eae0796 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -55,6 +55,7 @@
   V(_EnumNames, "_enum_names")                                                 \
   V(ExprTemp, ":expr_temp")                                                    \
   V(AnonymousClosure, "<anonymous closure>")                                   \
+  V(AnonymousSignature, "<anonymous signature>")                               \
   V(ImplicitClosure, "<implicit closure>")                                     \
   V(ClosureParameter, ":closure")                                              \
   V(TypeArgumentsParameter, ":type_arguments")                                 \
@@ -135,6 +136,7 @@
   V(Dynamic, "dynamic")                                                        \
   V(UnresolvedClass, "UnresolvedClass")                                        \
   V(Type, "_Type")                                                             \
+  V(FunctionType, "_FunctionType")                                             \
   V(TypeRef, "_TypeRef")                                                       \
   V(TypeParameter, "_TypeParameter")                                           \
   V(BoundedType, "_BoundedType")                                               \
@@ -143,7 +145,7 @@
   V(Patch, "patch")                                                            \
   V(PatchClass, "PatchClass")                                                  \
   V(Function, "Function")                                                      \
-  V(FunctionImpl, "_FunctionImpl")                                             \
+  V(_Closure, "_Closure")                                                      \
   V(FunctionResult, "function result")                                         \
   V(FactoryResult, "factory result")                                           \
   V(ClosureData, "ClosureData")                                                \
@@ -159,6 +161,7 @@
   V(Instructions, "Instructions")                                              \
   V(ObjectPool, "ObjectPool")                                                  \
   V(PcDescriptors, "PcDescriptors")                                            \
+  V(CodeSourceMap, "CodeSourceMap")                                            \
   V(Stackmap, "Stackmap")                                                      \
   V(LocalVarDescriptors, "LocalVarDescriptors")                                \
   V(ExceptionHandlers, "ExceptionHandlers")                                    \
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 64c7127..76d4729 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -80,12 +80,10 @@
   } else if (use_ring_recorder) {
     recorder_ = new TimelineEventRingRecorder();
   }
-  vm_stream_ = new TimelineStream();
-  vm_stream_->Init("VM", EnableStreamByDefault("VM"), NULL);
-  vm_api_stream_ = new TimelineStream();
-  vm_api_stream_->Init("API",
-                       EnableStreamByDefault("API"),
-                       &stream_API_enabled_);
+  vm_stream_.Init("VM", EnableStreamByDefault("VM"), NULL);
+  vm_api_stream_.Init("API",
+                      EnableStreamByDefault("API"),
+                      &stream_API_enabled_);
   // Global overrides.
 #define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used)                   \
   stream_##name##_enabled_ = EnableStreamByDefault(#name);
@@ -99,12 +97,15 @@
   if (FLAG_timeline_dir != NULL) {
     recorder_->WriteTo(FLAG_timeline_dir);
   }
+  // Disable global streams.
+  vm_stream_.set_enabled(false);
+  vm_api_stream_.set_enabled(false);
+#define ISOLATE_TIMELINE_STREAM_DISABLE(name, not_used)                   \
+  stream_##name##_enabled_ = false;
+  ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DISABLE)
+#undef ISOLATE_TIMELINE_STREAM_DISABLE
   delete recorder_;
   recorder_ = NULL;
-  delete vm_stream_;
-  vm_stream_ = NULL;
-  delete vm_api_stream_;
-  vm_api_stream_ = NULL;
 }
 
 
@@ -120,14 +121,12 @@
 
 
 TimelineStream* Timeline::GetVMStream() {
-  ASSERT(vm_stream_ != NULL);
-  return vm_stream_;
+  return &vm_stream_;
 }
 
 
 TimelineStream* Timeline::GetVMApiStream() {
-  ASSERT(vm_api_stream_ != NULL);
-  return vm_api_stream_;
+  return &vm_api_stream_;
 }
 
 
@@ -164,8 +163,8 @@
 
 
 TimelineEventRecorder* Timeline::recorder_ = NULL;
-TimelineStream* Timeline::vm_stream_ = NULL;
-TimelineStream* Timeline::vm_api_stream_ = NULL;
+TimelineStream Timeline::vm_stream_;
+TimelineStream Timeline::vm_api_stream_;
 
 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default)          \
   bool Timeline::stream_##name##_enabled_ = enabled_by_default;
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index d0c43e0..168956a 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -69,8 +69,8 @@
 
  private:
   static TimelineEventRecorder* recorder_;
-  static TimelineStream* vm_stream_;
-  static TimelineStream* vm_api_stream_;
+  static TimelineStream vm_stream_;
+  static TimelineStream vm_api_stream_;
 
 #define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used)                   \
   static bool stream_##name##_enabled_;
diff --git a/runtime/vm/token.cc b/runtime/vm/token.cc
index 75872e5..504b6d9 100644
--- a/runtime/vm/token.cc
+++ b/runtime/vm/token.cc
@@ -78,4 +78,21 @@
 }
 
 
+const char* ClassifyingTokenPositions::ToCString(intptr_t token_pos) {
+  ASSERT(token_pos < Token::kMinSourcePos);
+  COMPILE_ASSERT(ClassifyingTokenPositions::kPrivate ==
+                 (Token::kNoSourcePos - 1));
+  COMPILE_ASSERT(kLast < kPrivate);
+  switch (token_pos) {
+    case Token::kNoSourcePos: return "NoSource";
+#define DEFINE_CASE(name, value)                                               \
+    case value: return #name;
+    CLASSIFYING_TOKEN_POSITIONS(DEFINE_CASE);
+#undef DEFINE_CASE
+    default:
+      UNIMPLEMENTED();
+      return NULL;
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index a1018f8..39659d9 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -6,6 +6,7 @@
 #define VM_TOKEN_H_
 
 #include "platform/assert.h"
+#include "vm/allocation.h"
 
 namespace dart {
 
@@ -193,9 +194,55 @@
   KW(kWHILE, "while", 0, kKeyword)                                             \
   KW(kWITH, "with", 0, kKeyword) /* == kLastKeyword */
 
-
 class String;
 
+// The token space is organized as follows:
+//
+// Sentinel values start at -1 and move towards negative infinity:
+// kNoSourcePos                -> -1
+// ClassifyingTokenPositions 1 -> -1 - 1
+// ClassifyingTokenPositions N -> -1 - N
+//
+// Synthetically created AstNodes are given real source positions but encoded
+// as negative numbers from [kSmiMin32, -1 - N]. For example:
+//
+// A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
+// A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
+//
+// All other AstNodes are given real source positions encoded as positive
+// integers.
+//
+// This organization allows for ~1 billion token positions.
+//
+// NOTE: While token positions are passed around as an intptr_t they are encoded
+// into the snapshot as an int32_t.
+
+// These token positions are used to classify instructions that can't be
+// directly tied to an actual source position.
+#define CLASSIFYING_TOKEN_POSITIONS(V)                                         \
+    V(Private, -2)                                                             \
+    V(Box, -3)                                                                 \
+    V(ParallelMove, -4)                                                        \
+    V(TempMove, -5)                                                            \
+    V(Constant, -6)                                                            \
+    V(PushArgument, -7)                                                        \
+    V(ControlFlow, -8)                                                         \
+    V(Context, -9)                                                             \
+    V(MethodExtractor, -10)                                                    \
+    V(Last, -11)   // Always keep this at the end.
+
+
+class ClassifyingTokenPositions : public AllStatic {
+ public:
+#define DEFINE_VALUES(name, value)                                             \
+  static const intptr_t k##name = value;
+  CLASSIFYING_TOKEN_POSITIONS(DEFINE_VALUES);
+#undef DEFINE_VALUES
+
+  static const char* ToCString(intptr_t token_pos);
+};
+
+
 class Token {
  public:
 #define T(t, s, p, a) t,
@@ -212,6 +259,78 @@
     kPseudoKeyword   = 1 << 1,
   };
 
+  // Token position constants.
+  static const intptr_t kNoSourcePos = -1;
+  static const intptr_t kMinSourcePos = 0;
+  static const intptr_t kMaxSourcePos =
+      kSmiMax32 - (-ClassifyingTokenPositions::kLast) - 2;
+
+  // Is |token_pos| a classifying sentinel source position?
+  static bool IsClassifying(intptr_t token_pos) {
+    return (token_pos >= ClassifyingTokenPositions::kPrivate) &&
+           (token_pos <= ClassifyingTokenPositions::kLast);
+  }
+
+  // Is |token_pos| a synthetic source position?
+  static bool IsSynthetic(intptr_t token_pos) {
+    if (token_pos >= kMinSourcePos) {
+      return false;
+    }
+    if (token_pos < ClassifyingTokenPositions::kLast) {
+      return true;
+    }
+    return false;
+  }
+
+  // Is |token_pos| the no source position sentinel?
+  static bool IsNoSource(intptr_t token_pos) {
+    return token_pos == kNoSourcePos;
+  }
+
+  // Is |token_pos| a real source position?
+  static bool IsReal(intptr_t token_pos) {
+    return token_pos >= kMinSourcePos;
+  }
+
+  // Is |token_pos| a source position?
+  static bool IsSourcePosition(intptr_t token_pos) {
+    return IsReal(token_pos) || IsNoSource(token_pos) || IsSynthetic(token_pos);
+  }
+
+  // Is |token_pos| a debug pause source position?
+  static bool IsDebugPause(intptr_t token_pos) {
+    return IsReal(token_pos);
+  }
+
+  // Encode |token_pos| into a synthetic source position.
+  static intptr_t ToSynthetic(intptr_t token_pos) {
+    if (IsClassifying(token_pos) || IsNoSource(token_pos)) {
+      return token_pos;
+    }
+    if (IsSynthetic(token_pos)) {
+      return token_pos;
+    }
+    ASSERT(!IsSynthetic(token_pos));
+    const intptr_t value = (ClassifyingTokenPositions::kLast - 1) - token_pos;
+    ASSERT(IsSynthetic(value));
+    ASSERT(value < ClassifyingTokenPositions::kLast);
+    return value;
+  }
+
+  // Decode |token_pos| from a synthetic source position.
+  static intptr_t FromSynthetic(intptr_t token_pos) {
+    if (IsClassifying(token_pos) || IsNoSource(token_pos)) {
+      return token_pos;
+    }
+    if (!IsSynthetic(token_pos)) {
+      return token_pos;
+    }
+    ASSERT(IsSynthetic(token_pos));
+    const intptr_t value = -token_pos + (ClassifyingTokenPositions::kLast - 1);
+    ASSERT(!IsSynthetic(value));
+    return value;
+  }
+
   static const Kind kFirstKeyword = kABSTRACT;
   static const Kind kLastKeyword = kWITH;
   static const int kNumKeywords = kLastKeyword - kFirstKeyword + 1;
@@ -328,7 +447,6 @@
   static const Attribute attributes_[];
 };
 
-
 }  // namespace dart
 
 #endif  // VM_TOKEN_H_
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index b3df320..c686463 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -96,7 +96,7 @@
         }]],
     },
     {
-      'target_name': 'libdart_vm_precompiled',
+      'target_name': 'libdart_vm_precompiled_runtime',
       'type': 'static_library',
       'toolsets':['host', 'target'],
       'includes': [
@@ -112,7 +112,7 @@
         '..',
       ],
       'defines': [
-        'DART_PRECOMPILED',
+        'DART_PRECOMPILED_RUNTIME',
       ],
       'conditions': [
         ['OS=="linux"', {
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index dfed0df..b5ad1e8 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -106,37 +106,61 @@
 // Patch for Expando implementation.
 @patch
 class Expando<T> {
+  static const String _EXPANDO_PROPERTY_NAME = 'expando\$values';
+
+  // Incremented to make unique keys.
+  static int _keyCount = 0;
+
+  // Stores either a JS WeakMap or a "unique" string key.
+  final Object _jsWeakMapOrKey;
+
   @patch
-  Expando([String name]) : this.name = name;
+  Expando([String name])
+      : this.name = name,
+        _jsWeakMapOrKey = JS('bool', 'typeof WeakMap == "function"')
+            ? JS('=Object|Null', 'new WeakMap()')
+            : _createKey();
 
   @patch
   T operator[](Object object) {
-    var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
-    return (values == null) ? null : Primitives.getProperty(values, _getKey());
+    if (_jsWeakMapOrKey is! String) {
+      _checkType(object);  // WeakMap doesn't check on reading, only writing.
+      return JS('', '#.get(#)', _jsWeakMapOrKey, object);
+    }
+    return _getFromObject(_jsWeakMapOrKey, object);
   }
 
   @patch
   void operator[]=(Object object, T value) {
+    if (_jsWeakMapOrKey is! String) {
+      JS('void', '#.set(#, #)', _jsWeakMapOrKey, object, value);
+    } else {
+      _setOnObject(_jsWeakMapOrKey, object, value);
+    }
+  }
+
+  static Object _getFromObject(String key, Object object) {
+    var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
+    return (values == null) ? null : Primitives.getProperty(values, key);
+  }
+
+  static void _setOnObject(String key, Object object, Object value) {
     var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
     if (values == null) {
       values = new Object();
       Primitives.setProperty(object, _EXPANDO_PROPERTY_NAME, values);
     }
-    Primitives.setProperty(values, _getKey(), value);
+    Primitives.setProperty(values, key, value);
   }
 
-  String _getKey() {
-    String key = Primitives.getProperty(this, _KEY_PROPERTY_NAME);
-    if (key == null) {
-      key = "expando\$key\$${_keyCount++}";
-      Primitives.setProperty(this, _KEY_PROPERTY_NAME, key);
+  static String _createKey() => "expando\$key\$${_keyCount++}";
+
+  static _checkType(object) {
+    if (object == null || object is bool || object is num || object is String) {
+      throw new ArgumentError.value(object,
+          "Expandos are not allowed on strings, numbers, booleans or null");
     }
-    return key;
   }
-
-  static const String _KEY_PROPERTY_NAME = 'expando\$key';
-  static const String _EXPANDO_PROPERTY_NAME = 'expando\$values';
-  static int _keyCount = 0;
 }
 
 @patch
@@ -316,20 +340,11 @@
   static int _now() => Primitives.timerTicks();
 }
 
-class _ListConstructorSentinel extends JSInt {
-  const _ListConstructorSentinel();
-}
-
 // Patch for List implementation.
 @patch
 class List<E> {
   @patch
-  factory List([int length = const _ListConstructorSentinel()]) {
-    if (length == const _ListConstructorSentinel()) {
-      return new JSArray<E>.emptyGrowable();
-    }
-    return new JSArray<E>.fixed(length);
-  }
+  factory List([int length]) = JSArray<E>.list;
 
   @patch
   factory List.filled(int length, E fill, {bool growable: false}) {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index 78e53b1..004127b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -4,6 +4,11 @@
 
 part of _interceptors;
 
+class _Growable {
+  const _Growable();
+}
+const _ListConstructorSentinel = const _Growable();
+
 /**
  * The interceptor class for [List]. The compiler recognizes this
  * class as an interceptor, and changes references to [:this:] to
@@ -14,6 +19,16 @@
 
   const JSArray();
 
+  // This factory constructor is the redirection target of the List() factory
+  // constructor. [length] has no type to permit the sentinel value.
+  factory JSArray.list([length = _ListConstructorSentinel]) {
+    if (_ListConstructorSentinel == length) {
+      return new JSArray<E>.emptyGrowable();
+    }
+    return new JSArray<E>.fixed(length);
+  }
+
+
   /**
    * Returns a fresh JavaScript Array, marked as fixed-length.
    *
@@ -21,7 +36,8 @@
    */
   factory JSArray.fixed(int length)  {
     // Explicit type test is necessary to guard against JavaScript conversions
-    // in unchecked mode.
+    // in unchecked mode, and against `new Array(null)` which creates a single
+    // element Array containing `null`.
     if (length is !int) {
       throw new ArgumentError.value(length, "length", "is not an integer");
     }
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 6f4ddab..a926f1d 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -23,7 +23,7 @@
   // TODO(lrn): Use the _state field on _ControllerSubscription to
   // also store this state. Requires that the subscription implementation
   // does not assume that it's use of the state integer is the only use.
-  int _eventState;
+  int _eventState = 0;  // Initialized to help dart2js type inference.
 
   _BroadcastSubscriptionLink _next;
   _BroadcastSubscriptionLink _previous;
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 48f968f..709a73d 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -225,7 +225,7 @@
     _Future result = new _Future<T>();
     new Timer(duration, () {
       try {
-        result._complete(computation == null ? null : computation());
+        result._complete(computation?.call());
       } catch (e, s) {
         _completeWithErrorCallback(result, e, s);
       }
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index c2b6c68..510cccb 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -325,6 +325,10 @@
    * two arguments it is called with the stack trace (which could be `null` if
    * the stream itself received an error without stack trace).
    * Otherwise it is called with just the error object.
+   * If [onError] is omitted, any errors on the stream are considered unhandled,
+   * and will be passed to the current [Zone]'s error handler.
+   * By default unhandled async errors are treated
+   * as if they were uncaught top-level errors.
    *
    * If this stream closes, the [onDone] handler is called.
    *
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index c8a2465..cd69f44 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -68,9 +68,16 @@
    * If [sync] is true, the returned stream controller is a
    * [SynchronousStreamController], and must be used with the care
    * and attention necessary to not break the [Stream] contract.
+   * See [Completer.sync] for some explanations on when a synchronous
+   * dispatching can be used.
+   * If in doubt, keep the controller non-sync.
    *
-   * The controller will buffer all incoming events until the subscriber is
-   * registered.
+   * A Stream should be inert until a subscriber starts listening on it (using
+   * the [onListen] callback to start producing events). Streams should not
+   * leak resources (like websockets) when no user ever listens on the stream.
+   *
+   * The controller buffers all incoming events until a subscriber is
+   * registered, but this feature should only be used in rare circumstances.
    *
    * The [onPause] function is called when the stream becomes
    * paused. [onResume] is called when the stream resumed.
@@ -100,6 +107,12 @@
    * The [Stream] returned by [stream] is a broadcast stream.
    * It can be listened to more than once.
    *
+   * A Stream should be inert until a subscriber starts listening on it (using
+   * the [onListen] callback to start producing events). Streams should not
+   * leak resources (like websockets) when no user ever listens on the stream.
+   *
+   * Broadcast streams do not buffer events when there is no listener.
+   *
    * The controller distributes any events to all currently subscribed
    * listeners at the time when [add], [addError] or [close] is called.
    * It is not allowed to call `add`, `addError`, or `close` before a previous
@@ -116,6 +129,9 @@
    * The returned stream controller is a [SynchronousStreamController],
    * and must be used with the care and attention necessary to not break
    * the [Stream] contract.
+   * See [Completer.sync] for some explanations on when a synchronous
+   * dispatching can be used.
+   * If in doubt, keep the controller non-sync.
    *
    * If [sync] is false, the event will always be fired at a later time,
    * after the code adding the event has completed.
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index d84f01b..5cc4d88 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -135,33 +135,21 @@
               Map zoneValues): null
   }) {
     return new ZoneSpecification(
-      handleUncaughtError: handleUncaughtError != null
-                           ? handleUncaughtError
-                           : other.handleUncaughtError,
-      run: run != null ? run : other.run,
-      runUnary: runUnary != null ? runUnary : other.runUnary,
-      runBinary: runBinary != null ? runBinary : other.runBinary,
-      registerCallback: registerCallback != null
-                        ? registerCallback
-                        : other.registerCallback,
-      registerUnaryCallback: registerUnaryCallback != null
-                         ? registerUnaryCallback
-                         : other.registerUnaryCallback,
-      registerBinaryCallback: registerBinaryCallback != null
-                         ? registerBinaryCallback
-                         : other.registerBinaryCallback,
-      errorCallback: errorCallback != null
-                         ? errorCallback
-                         : other.errorCallback,
-      scheduleMicrotask: scheduleMicrotask != null
-                         ? scheduleMicrotask
-                         : other.scheduleMicrotask,
-      createTimer : createTimer != null ? createTimer : other.createTimer,
-      createPeriodicTimer: createPeriodicTimer != null
-                           ? createPeriodicTimer
-                           : other.createPeriodicTimer,
-      print : print != null ? print : other.print,
-      fork: fork != null ? fork : other.fork);
+      handleUncaughtError: handleUncaughtError ?? other.handleUncaughtError,
+      run: run ?? other.run,
+      runUnary: runUnary ?? other.runUnary,
+      runBinary: runBinary ?? other.runBinary,
+      registerCallback: registerCallback ?? other.registerCallback,
+      registerUnaryCallback: registerUnaryCallback ??
+                             other.registerUnaryCallback,
+      registerBinaryCallback: registerBinaryCallback ??
+                              other.registerBinaryCallback,
+      errorCallback: errorCallback ?? other.errorCallback,
+      scheduleMicrotask: scheduleMicrotask ?? other.scheduleMicrotask,
+      createTimer : createTimer ?? other.createTimer,
+      createPeriodicTimer: createPeriodicTimer ?? other.createPeriodicTimer,
+      print : print ?? other.print,
+      fork: fork ?? other.fork);
   }
 
   HandleUncaughtErrorHandler get handleUncaughtError;
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index 0d92345..09874c4 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -28,6 +28,10 @@
  *     RegExp exp = new RegExp(r"(\w+)");
  *     String str = "Parse my string";
  *     Iterable<Match> matches = exp.allMatches(str);
+ * 
+ * Note the use of a _raw string_ (a string prefixed with `r`)
+ * in the example above. Use a raw string to treat each character in a string
+ * as a literal character.
  */
 abstract class RegExp implements Pattern {
   /**
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index e4a31aa..a1a5b5d 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -76,6 +76,7 @@
    * Cache the computed return value of [queryParameters].
    */
   Map<String, String> _queryParameters;
+  Map<String, List<String>> _queryParameterLists;
 
   /// Internal non-verifying constructor. Only call with validated arguments.
   Uri._internal(this.scheme,
@@ -116,39 +117,46 @@
    * default port.
    *
    * If any of `userInfo`, `host` or `port` are provided,
-   * the URI will have an autority according to [hasAuthority].
+   * the URI has an autority according to [hasAuthority].
    *
    * The path component is set through either [path] or
-   * [pathSegments]. When [path] is used, it should be a valid URI path,
+   * [pathSegments].
+   * When [path] is used, it should be a valid URI path,
    * but invalid characters, except the general delimiters ':/@[]?#',
    * will be escaped if necessary.
    * When [pathSegments] is used, each of the provided segments
    * is first percent-encoded and then joined using the forward slash
-   * separator. The percent-encoding of the path segments encodes all
+   * separator.
+   *
+   * The percent-encoding of the path segments encodes all
    * characters except for the unreserved characters and the following
    * list of characters: `!$&'()*+,;=:@`. If the other components
-   * calls for an absolute path a leading slash `/` is prepended if
+   * necessitate an absolute path, a leading slash `/` is prepended if
    * not already there.
    *
-   * The query component is set through either [query] or
-   * [queryParameters]. When [query] is used the provided string should
-   * be a valid URI query, but invalid characters other than general delimiters,
+   * The query component is set through either [query] or [queryParameters].
+   * When [query] is used, the provided string should be a valid URI query,
+   * but invalid characters, other than general delimiters,
    * will be escaped if necessary.
    * When [queryParameters] is used the query is built from the
    * provided map. Each key and value in the map is percent-encoded
-   * and joined using equal and ampersand characters. The
-   * percent-encoding of the keys and values encodes all characters
-   * except for the unreserved characters.
+   * and joined using equal and ampersand characters.
+   * A value in the map must be either a string, or an [Iterable] of strings,
+   * where the latter corresponds to multiple values for the same key.
+   *
+   * The percent-encoding of the keys and values encodes all characters
+   * except for the unreserved characters, and replaces spaces with `+`.
    * If `query` is the empty string, it is equivalent to omitting it.
    * To have an actual empty query part,
    * use an empty list for `queryParameters`.
-   * If both `query` and `queryParameters` are omitted or `null`, the
-   * URI will have no query part.
+   *
+   * If both `query` and `queryParameters` are omitted or `null`,
+   * the URI has no query part.
    *
    * The fragment component is set through [fragment].
    * It should be a valid URI fragment, but invalid characters other than
-   * general delimiters, will be escaped if necessary.
-   * If `fragment` is omitted or `null`, the URI will have no fragment part.
+   * general delimiters, are escaped if necessary.
+   * If `fragment` is omitted or `null`, the URI has no fragment part.
    */
   factory Uri({String scheme : "",
                String userInfo : "",
@@ -157,7 +165,7 @@
                String path,
                Iterable<String> pathSegments,
                String query,
-               Map<String, String> queryParameters,
+               Map<String, dynamic> queryParameters,
                String fragment}) {
     scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
     userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
@@ -207,7 +215,7 @@
    *
    * The `userInfo`, `host` and `port` components are set from the
    * [authority] argument. If `authority` is `null` or empty,
-   * the created `Uri` will have no authority, and will not be directly usable
+   * the created `Uri` has no authority, and isn't directly usable
    * as an HTTP URL, which must have a non-empty host.
    *
    * The `path` component is set from the [unencodedPath]
@@ -1104,23 +1112,53 @@
    * Returns the URI query split into a map according to the rules
    * specified for FORM post in the [HTML 4.01 specification section
    * 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
-   * Each key and value in the returned map has been decoded. If there is no
-   * query the empty map is returned.
+   * Each key and value in the returned map has been decoded.
+   * If there is no query the empty map is returned.
    *
    * Keys in the query string that have no value are mapped to the
    * empty string.
+   * If a key occurs more than once in the query string, it is mapped to
+   * an arbitrary choice of possible value.
+   * The [queryParametersAll] getter can provide a map
+   * that maps keys to all of their values.
    *
-   * The returned map is unmodifiable and will throw [UnsupportedError] on any
-   * calls that would mutate it.
+   * The returned map is unmodifiable.
    */
   Map<String, String> get queryParameters {
     if (_queryParameters == null) {
-      _queryParameters = new UnmodifiableMapView(splitQueryString(query));
+      _queryParameters =
+          new UnmodifiableMapView<String, String>(splitQueryString(query));
     }
     return _queryParameters;
   }
 
   /**
+   * Returns the URI query split into a map according to the rules
+   * specified for FORM post in the [HTML 4.01 specification section
+   * 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
+   * Each key and value in the returned map has been decoded. If there is no
+   * query the empty map is returned.
+   *
+   * Keys are mapped to lists of their values. If a key occurs only once,
+   * its value is a singleton list. If a key occurs with no value, the
+   * empty string is used as the value for that occurrence.
+   *
+   * The returned map and the lists it contains are unmodifiable.
+   */
+  Map<String, List<String>> get queryParametersAll {
+    if (_queryParameterLists == null) {
+      Map queryParameterLists = _splitQueryStringAll(query);
+      for (var key in queryParameterLists.keys) {
+        queryParameterLists[key] =
+            new List<String>.unmodifiable(queryParameterLists[key]);
+      }
+      _queryParameterLists =
+          new Map<String, List<String>>.unmodifiable(queryParameterLists);
+    }
+    return _queryParameterLists;
+  }
+
+  /**
    * Returns a URI where the path has been normalized.
    *
    * A normalized path does not contain `.` segments or non-leading `..`
@@ -1344,17 +1382,27 @@
     if (query != null) return _normalize(query, start, end, _queryCharTable);
 
     var result = new StringBuffer();
-    var first = true;
-    queryParameters.forEach((key, value) {
-      if (!first) {
-        result.write("&");
-      }
-      first = false;
+    var separator = "";
+
+    void writeParameter(String key, String value) {
+      result.write(separator);
+      separator = "&";
       result.write(Uri.encodeQueryComponent(key));
-      if (value != null && !value.isEmpty) {
+      if (value != null && value.isNotEmpty) {
         result.write("=");
         result.write(Uri.encodeQueryComponent(value));
       }
+    }
+
+    queryParameters.forEach((key, value) {
+      if (value == null || value is String) {
+        writeParameter(key, value);
+      } else {
+        Iterable values = value;
+        for (String value in values) {
+          writeParameter(key, value);
+        }
+      }
     });
     return result.toString();
   }
@@ -2156,6 +2204,46 @@
     });
   }
 
+  static List _createList() => [];
+
+  static Map _splitQueryStringAll(
+      String query, {Encoding encoding: UTF8}) {
+    Map result = {};
+    int i = 0;
+    int start = 0;
+    int equalsIndex = -1;
+
+    void parsePair(int start, int equalsIndex, int end) {
+      String key;
+      String value;
+      if (start == end) return;
+      if (equalsIndex < 0) {
+        key =  _uriDecode(query, start, end, encoding, true);
+        value = "";
+      } else {
+        key = _uriDecode(query, start, equalsIndex, encoding, true);
+        value = _uriDecode(query, equalsIndex + 1, end, encoding, true);
+      }
+      result.putIfAbsent(key, _createList).add(value);
+    }
+
+    const int _equals = 0x3d;
+    const int _ampersand = 0x26;
+    while (i < query.length) {
+      int char = query.codeUnitAt(i);
+      if (char == _equals) {
+        if (equalsIndex < 0) equalsIndex = i;
+      } else if (char == _ampersand) {
+        parsePair(start, equalsIndex, i);
+        start = i + 1;
+        equalsIndex = -1;
+      }
+      i++;
+    }
+    parsePair(start, equalsIndex, i);
+    return result;
+  }
+
   /**
    * Parse the [host] as an IP version 4 (IPv4) address, returning the address
    * as a list of 4 bytes in network byte order (big endian).
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 3ef584b..8d4c3de 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -126,9 +126,9 @@
   '_DOMWindowCrossFrame': () => _DOMWindowCrossFrame,
   // FIXME: Move these to better locations.
   'DateTime': () => DateTime,
-  'JsObject': () => js.JsObjectImpl,
-  'JsFunction': () => js.JsFunctionImpl,
-  'JsArray': () => js.JsArrayImpl,
+  'JsObject': () => js.JsObject,
+  'JsFunction': () => js.JsFunction,
+  'JsArray': () => js.JsArray,
   'AbstractWorker': () => AbstractWorker,
   'Animation': () => Animation,
   'AnimationEffect': () => AnimationEffect,
@@ -1128,7 +1128,7 @@
   } else if (runtimeType == TemplateElement) {
     // Data binding with a Dart class.
     tag = element.attributes['is'];
-  } else if (runtimeType == js.JsObjectImpl) {
+  } else if (runtimeType == js.JsObject) {
     // It's a Polymer core element (written in JS).
     // Make sure it's an element anything else we can ignore.
     if (element.hasProperty('nodeType') && element['nodeType'] == 1) {
@@ -1141,7 +1141,7 @@
       }
     }
   } else {
-    throw new UnsupportedError('Element is incorrect type. Got ${runtimeType}, expected HtmlElement/HtmlTemplate/JsObjectImpl.');
+    throw new UnsupportedError('Element is incorrect type. Got ${runtimeType}, expected HtmlElement/HtmlTemplate/JsObject.');
   }
 
   return tag;
@@ -1149,15 +1149,9 @@
 
 /// An abstract class for all DOM objects we wrap in dart:html and related
 ///  libraries.
-///
-/// ** Internal Use Only **
 @Deprecated("Internal Use Only")
-class DartHtmlDomObject {
-
-  /// The underlying JS DOM object.
-  @Deprecated("Internal Use Only")
-  js.JsObject blink_jsObject;
-
+class DartHtmlDomObject extends js.JSObject {
+  DartHtmlDomObject() : super.internal();
 }
 
 @Deprecated("Internal Use Only")
@@ -1173,24 +1167,6 @@
   }
 }
 
-// TODO(terry): Manage JS interop JsFunctions for each listener used for add/
-//              removeEventListener.  These JsFunctions will leak look at
-//              fixing with weak-refs in C++.  The key are the hashcodes of the
-//              user's this (this is needed for futures) and listener function.
-Map<int, Map<int, js.JsFunction>> _knownListeners = {};
-
-@Deprecated("Internal Use Only")
-js.JsFunction wrap_event_listener(theObject, Function listener) {
-  var thisHashCode = theObject.hashCode;
-  var listenerHashCode = identityHashCode(listener);
-
-  _knownListeners.putIfAbsent(thisHashCode, () => new Map<int, js.JsFunction>());
-  _knownListeners[thisHashCode].putIfAbsent(listenerHashCode, () =>
-    new js.JsFunction.withThis((theObject, event) => listener(wrap_jso(event))));
-
-  return _knownListeners[thisHashCode][listenerHashCode];
-}
-
 @Deprecated("Internal Use Only")
 Map<String, dynamic> convertNativeObjectToDartMap(js.JsObject jsObject) {
   var result = new Map();
@@ -1279,9 +1255,7 @@
     return new AnchorElement._internalWrap();
   }
 
-  factory AnchorElement._internalWrap() {
-    return new AnchorElement.internal_();
-  }
+  external factory AnchorElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnchorElement.internal_() : super.internal_();
@@ -1474,9 +1448,7 @@
     return new Animation._internalWrap();
   }
 
-  factory Animation._internalWrap() {
-    return new Animation.internal_();
-  }
+  external factory Animation._internalWrap();
 
   @Deprecated("Internal Use Only")
   Animation.internal_() : super.internal_();
@@ -1535,9 +1507,7 @@
     return new AnimationEvent._internalWrap();
   }
 
-  factory AnimationEvent._internalWrap() {
-    return new AnimationEvent.internal_();
-  }
+  external factory AnimationEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimationEvent.internal_() : super.internal_();
@@ -1642,9 +1612,7 @@
     return new AnimationPlayer._internalWrap();
   }
 
-  factory AnimationPlayer._internalWrap() {
-    return new AnimationPlayer.internal_();
-  }
+  external factory AnimationPlayer._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimationPlayer.internal_() : super.internal_();
@@ -1744,9 +1712,7 @@
     return new AnimationPlayerEvent._internalWrap();
   }
 
-  factory AnimationPlayerEvent._internalWrap() {
-    return new AnimationPlayerEvent.internal_();
-  }
+  external factory AnimationPlayerEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimationPlayerEvent.internal_() : super.internal_();
@@ -1916,9 +1882,7 @@
     return new ApplicationCache._internalWrap();
   }
 
-  factory ApplicationCache._internalWrap() {
-    return new ApplicationCache.internal_();
-  }
+  external factory ApplicationCache._internalWrap();
 
   @Deprecated("Internal Use Only")
   ApplicationCache.internal_() : super.internal_();
@@ -2028,9 +1992,7 @@
     return new ApplicationCacheErrorEvent._internalWrap();
   }
 
-  factory ApplicationCacheErrorEvent._internalWrap() {
-    return new ApplicationCacheErrorEvent.internal_();
-  }
+  external factory ApplicationCacheErrorEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ApplicationCacheErrorEvent.internal_() : super.internal_();
@@ -2090,9 +2052,7 @@
     return new AreaElement._internalWrap();
   }
 
-  factory AreaElement._internalWrap() {
-    return new AreaElement.internal_();
-  }
+  external factory AreaElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AreaElement.internal_() : super.internal_();
@@ -2252,9 +2212,7 @@
     return new AudioElement._internalWrap();
   }
 
-  factory AudioElement._internalWrap() {
-    return new AudioElement.internal_();
-  }
+  external factory AudioElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioElement.internal_() : super.internal_();
@@ -2358,9 +2316,7 @@
     return new AudioTrackList._internalWrap();
   }
 
-  factory AudioTrackList._internalWrap() {
-    return new AudioTrackList.internal_();
-  }
+  external factory AudioTrackList._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioTrackList.internal_() : super.internal_();
@@ -2408,9 +2364,7 @@
     return new AutocompleteErrorEvent._internalWrap();
   }
 
-  factory AutocompleteErrorEvent._internalWrap() {
-    return new AutocompleteErrorEvent.internal_();
-  }
+  external factory AutocompleteErrorEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   AutocompleteErrorEvent.internal_() : super.internal_();
@@ -2444,9 +2398,7 @@
     return new BRElement._internalWrap();
   }
 
-  factory BRElement._internalWrap() {
-    return new BRElement.internal_();
-  }
+  external factory BRElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   BRElement.internal_() : super.internal_();
@@ -2517,9 +2469,7 @@
     return new BaseElement._internalWrap();
   }
 
-  factory BaseElement._internalWrap() {
-    return new BaseElement.internal_();
-  }
+  external factory BaseElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   BaseElement.internal_() : super.internal_();
@@ -2569,9 +2519,7 @@
     return new BatteryManager._internalWrap();
   }
 
-  factory BatteryManager._internalWrap() {
-    return new BatteryManager.internal_();
-  }
+  external factory BatteryManager._internalWrap();
 
   @Deprecated("Internal Use Only")
   BatteryManager.internal_() : super.internal_();
@@ -2613,9 +2561,7 @@
     return new BeforeUnloadEvent._internalWrap();
   }
 
-  factory BeforeUnloadEvent._internalWrap() {
-    return new BeforeUnloadEvent.internal_();
-  }
+  external factory BeforeUnloadEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   BeforeUnloadEvent.internal_() : super.internal_();
@@ -2899,9 +2845,7 @@
     return new BodyElement._internalWrap();
   }
 
-  factory BodyElement._internalWrap() {
-    return new BodyElement.internal_();
-  }
+  external factory BodyElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   BodyElement.internal_() : super.internal_();
@@ -3002,9 +2946,7 @@
     return new ButtonElement._internalWrap();
   }
 
-  factory ButtonElement._internalWrap() {
-    return new ButtonElement.internal_();
-  }
+  external factory ButtonElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ButtonElement.internal_() : super.internal_();
@@ -3147,9 +3089,7 @@
     return new CDataSection._internalWrap();
   }
 
-  factory CDataSection._internalWrap() {
-    return new CDataSection.internal_();
-  }
+  external factory CDataSection._internalWrap();
 
   @Deprecated("Internal Use Only")
   CDataSection.internal_() : super.internal_();
@@ -3305,9 +3245,7 @@
     return new CanvasElement._internalWrap();
   }
 
-  factory CanvasElement._internalWrap() {
-    return new CanvasElement.internal_();
-  }
+  external factory CanvasElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   CanvasElement.internal_() : super.internal_();
@@ -4377,9 +4315,7 @@
     return new CharacterData._internalWrap();
   }
 
-  factory CharacterData._internalWrap() {
-    return new CharacterData.internal_();
-  }
+  external factory CharacterData._internalWrap();
 
   @Deprecated("Internal Use Only")
   CharacterData.internal_() : super.internal_();
@@ -4483,9 +4419,7 @@
     return new CircularGeofencingRegion._internalWrap();
   }
 
-  factory CircularGeofencingRegion._internalWrap() {
-    return new CircularGeofencingRegion.internal_();
-  }
+  external factory CircularGeofencingRegion._internalWrap();
 
   @Deprecated("Internal Use Only")
   CircularGeofencingRegion.internal_() : super.internal_();
@@ -4536,9 +4470,7 @@
     return new CloseEvent._internalWrap();
   }
 
-  factory CloseEvent._internalWrap() {
-    return new CloseEvent.internal_();
-  }
+  external factory CloseEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   CloseEvent.internal_() : super.internal_();
@@ -4583,9 +4515,7 @@
     return new Comment._internalWrap();
   }
 
-  factory Comment._internalWrap() {
-    return new Comment.internal_();
-  }
+  external factory Comment._internalWrap();
 
   @Deprecated("Internal Use Only")
   Comment.internal_() : super.internal_();
@@ -4622,9 +4552,7 @@
     return new CompositionEvent._internalWrap();
   }
 
-  factory CompositionEvent._internalWrap() {
-    return new CompositionEvent.internal_();
-  }
+  external factory CompositionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   CompositionEvent.internal_() : super.internal_();
@@ -4673,9 +4601,7 @@
     return new Console._internalWrap();
   }
 
-  factory Console._internalWrap() {
-    return new Console.internal_();
-  }
+  external factory Console._internalWrap();
 
   @Deprecated("Internal Use Only")
   Console.internal_() : super.internal_();
@@ -4858,9 +4784,7 @@
     return new ContentElement._internalWrap();
   }
 
-  factory ContentElement._internalWrap() {
-    return new ContentElement.internal_();
-  }
+  external factory ContentElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ContentElement.internal_() : super.internal_();
@@ -5207,9 +5131,7 @@
     return new CssCharsetRule._internalWrap();
   }
 
-  factory CssCharsetRule._internalWrap() {
-    return new CssCharsetRule.internal_();
-  }
+  external factory CssCharsetRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssCharsetRule.internal_() : super.internal_();
@@ -5247,9 +5169,7 @@
     return new CssFilterRule._internalWrap();
   }
 
-  factory CssFilterRule._internalWrap() {
-    return new CssFilterRule.internal_();
-  }
+  external factory CssFilterRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssFilterRule.internal_() : super.internal_();
@@ -5279,9 +5199,7 @@
     return new CssFontFaceRule._internalWrap();
   }
 
-  factory CssFontFaceRule._internalWrap() {
-    return new CssFontFaceRule.internal_();
-  }
+  external factory CssFontFaceRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssFontFaceRule.internal_() : super.internal_();
@@ -5311,9 +5229,7 @@
     return new CssImportRule._internalWrap();
   }
 
-  factory CssImportRule._internalWrap() {
-    return new CssImportRule.internal_();
-  }
+  external factory CssImportRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssImportRule.internal_() : super.internal_();
@@ -5352,9 +5268,7 @@
     return new CssKeyframeRule._internalWrap();
   }
 
-  factory CssKeyframeRule._internalWrap() {
-    return new CssKeyframeRule.internal_();
-  }
+  external factory CssKeyframeRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssKeyframeRule.internal_() : super.internal_();
@@ -5396,9 +5310,7 @@
     return new CssKeyframesRule._internalWrap();
   }
 
-  factory CssKeyframesRule._internalWrap() {
-    return new CssKeyframesRule.internal_();
-  }
+  external factory CssKeyframesRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssKeyframesRule.internal_() : super.internal_();
@@ -5459,9 +5371,7 @@
     return new CssMediaRule._internalWrap();
   }
 
-  factory CssMediaRule._internalWrap() {
-    return new CssMediaRule.internal_();
-  }
+  external factory CssMediaRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssMediaRule.internal_() : super.internal_();
@@ -5503,9 +5413,7 @@
     return new CssPageRule._internalWrap();
   }
 
-  factory CssPageRule._internalWrap() {
-    return new CssPageRule.internal_();
-  }
+  external factory CssPageRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssPageRule.internal_() : super.internal_();
@@ -8940,9 +8848,7 @@
     return new CssStyleRule._internalWrap();
   }
 
-  factory CssStyleRule._internalWrap() {
-    return new CssStyleRule.internal_();
-  }
+  external factory CssStyleRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssStyleRule.internal_() : super.internal_();
@@ -8980,9 +8886,7 @@
     return new CssStyleSheet._internalWrap();
   }
 
-  factory CssStyleSheet._internalWrap() {
-    return new CssStyleSheet.internal_();
-  }
+  external factory CssStyleSheet._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssStyleSheet.internal_() : super.internal_();
@@ -9044,9 +8948,7 @@
     return new CssSupportsRule._internalWrap();
   }
 
-  factory CssSupportsRule._internalWrap() {
-    return new CssSupportsRule.internal_();
-  }
+  external factory CssSupportsRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssSupportsRule.internal_() : super.internal_();
@@ -9089,9 +8991,7 @@
     return new CssViewportRule._internalWrap();
   }
 
-  factory CssViewportRule._internalWrap() {
-    return new CssViewportRule.internal_();
-  }
+  external factory CssViewportRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   CssViewportRule.internal_() : super.internal_();
@@ -9155,9 +9055,7 @@
     return new CustomEvent._internalWrap();
   }
 
-  factory CustomEvent._internalWrap() {
-    return new CustomEvent.internal_();
-  }
+  external factory CustomEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   CustomEvent.internal_() : super.internal_();
@@ -9195,9 +9093,7 @@
     return new DListElement._internalWrap();
   }
 
-  factory DListElement._internalWrap() {
-    return new DListElement.internal_();
-  }
+  external factory DListElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DListElement.internal_() : super.internal_();
@@ -9237,9 +9133,7 @@
     return new DataListElement._internalWrap();
   }
 
-  factory DataListElement._internalWrap() {
-    return new DataListElement.internal_();
-  }
+  external factory DataListElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DataListElement.internal_() : super.internal_();
@@ -9524,9 +9418,7 @@
     return new DedicatedWorkerGlobalScope._internalWrap();
   }
 
-  factory DedicatedWorkerGlobalScope._internalWrap() {
-    return new DedicatedWorkerGlobalScope.internal_();
-  }
+  external factory DedicatedWorkerGlobalScope._internalWrap();
 
   @Deprecated("Internal Use Only")
   DedicatedWorkerGlobalScope.internal_() : super.internal_();
@@ -9688,9 +9580,7 @@
     return new DetailsElement._internalWrap();
   }
 
-  factory DetailsElement._internalWrap() {
-    return new DetailsElement.internal_();
-  }
+  external factory DetailsElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DetailsElement.internal_() : super.internal_();
@@ -9777,9 +9667,7 @@
     return new DeviceLightEvent._internalWrap();
   }
 
-  factory DeviceLightEvent._internalWrap() {
-    return new DeviceLightEvent.internal_();
-  }
+  external factory DeviceLightEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   DeviceLightEvent.internal_() : super.internal_();
@@ -9812,9 +9700,7 @@
     return new DeviceMotionEvent._internalWrap();
   }
 
-  factory DeviceMotionEvent._internalWrap() {
-    return new DeviceMotionEvent.internal_();
-  }
+  external factory DeviceMotionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   DeviceMotionEvent.internal_() : super.internal_();
@@ -9869,9 +9755,7 @@
     return new DeviceOrientationEvent._internalWrap();
   }
 
-  factory DeviceOrientationEvent._internalWrap() {
-    return new DeviceOrientationEvent.internal_();
-  }
+  external factory DeviceOrientationEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   DeviceOrientationEvent.internal_() : super.internal_();
@@ -9961,9 +9845,7 @@
     return new DialogElement._internalWrap();
   }
 
-  factory DialogElement._internalWrap() {
-    return new DialogElement.internal_();
-  }
+  external factory DialogElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DialogElement.internal_() : super.internal_();
@@ -10061,9 +9943,7 @@
     return new DirectoryEntry._internalWrap();
   }
 
-  factory DirectoryEntry._internalWrap() {
-    return new DirectoryEntry.internal_();
-  }
+  external factory DirectoryEntry._internalWrap();
 
   @Deprecated("Internal Use Only")
   DirectoryEntry.internal_() : super.internal_();
@@ -10234,9 +10114,7 @@
     return new DivElement._internalWrap();
   }
 
-  factory DivElement._internalWrap() {
-    return new DivElement.internal_();
-  }
+  external factory DivElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DivElement.internal_() : super.internal_();
@@ -10319,9 +10197,7 @@
     return new Document._internalWrap();
   }
 
-  factory Document._internalWrap() {
-    return new Document.internal_();
-  }
+  external factory Document._internalWrap();
 
   @Deprecated("Internal Use Only")
   Document.internal_() : super.internal_();
@@ -11258,9 +11134,7 @@
     return new DocumentFragment._internalWrap();
   }
 
-  factory DocumentFragment._internalWrap() {
-    return new DocumentFragment.internal_();
-  }
+  external factory DocumentFragment._internalWrap();
 
   @Deprecated("Internal Use Only")
   DocumentFragment.internal_() : super.internal_();
@@ -11390,12 +11264,7 @@
     return new DomException._internalWrap();
   }
 
-  @Deprecated("Internal Use Only")
-  js.JsObject blink_jsObject;
-
-  factory DomException._internalWrap() {
-    return new DomException.internal_();
-  }
+  external factory DomException._internalWrap();
 
   @Deprecated("Internal Use Only")
   DomException.internal_() { }
@@ -11539,9 +11408,7 @@
     return new DomMatrix._internalWrap();
   }
 
-  factory DomMatrix._internalWrap() {
-    return new DomMatrix.internal_();
-  }
+  external factory DomMatrix._internalWrap();
 
   @Deprecated("Internal Use Only")
   DomMatrix.internal_() : super.internal_();
@@ -12122,9 +11989,7 @@
     return new DomPoint._internalWrap();
   }
 
-  factory DomPoint._internalWrap() {
-    return new DomPoint.internal_();
-  }
+  external factory DomPoint._internalWrap();
 
   @Deprecated("Internal Use Only")
   DomPoint.internal_() : super.internal_();
@@ -12411,9 +12276,7 @@
     return new DomSettableTokenList._internalWrap();
   }
 
-  factory DomSettableTokenList._internalWrap() {
-    return new DomSettableTokenList.internal_();
-  }
+  external factory DomSettableTokenList._internalWrap();
 
   @Deprecated("Internal Use Only")
   DomSettableTokenList.internal_() : super.internal_();
@@ -15593,9 +15456,7 @@
     return new Element._internalWrap();
   }
 
-  factory Element._internalWrap() {
-    return new Element.internal_();
-  }
+  external factory Element._internalWrap();
 
   @Deprecated("Internal Use Only")
   Element.internal_() : super.internal_();
@@ -16481,9 +16342,7 @@
     return new EmbedElement._internalWrap();
   }
 
-  factory EmbedElement._internalWrap() {
-    return new EmbedElement.internal_();
-  }
+  external factory EmbedElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   EmbedElement.internal_() : super.internal_();
@@ -16770,9 +16629,7 @@
     return new ErrorEvent._internalWrap();
   }
 
-  factory ErrorEvent._internalWrap() {
-    return new ErrorEvent.internal_();
-  }
+  external factory ErrorEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ErrorEvent.internal_() : super.internal_();
@@ -17060,9 +16917,7 @@
     return new EventSource._internalWrap();
   }
 
-  factory EventSource._internalWrap() {
-    return new EventSource.internal_();
-  }
+  external factory EventSource._internalWrap();
 
   @Deprecated("Internal Use Only")
   EventSource.internal_() : super.internal_();
@@ -17257,11 +17112,11 @@
 
   void _addEventListener([String type, EventListener listener, bool useCapture]) {
     if (useCapture != null) {
-      _blink.BlinkEventTarget.instance.addEventListener_Callback_3_(unwrap_jso(this), type, wrap_event_listener(this, listener), useCapture);
+      _blink.BlinkEventTarget.instance.addEventListener_Callback_3_(unwrap_jso(this), type, unwrap_jso(js.allowInterop(listener)), useCapture);
       return;
     }
     if (listener != null) {
-      _blink.BlinkEventTarget.instance.addEventListener_Callback_2_(unwrap_jso(this), type, wrap_event_listener(this, listener));
+      _blink.BlinkEventTarget.instance.addEventListener_Callback_2_(unwrap_jso(this), type, unwrap_jso(js.allowInterop(listener)));
       return;
     }
     if (type != null) {
@@ -17278,11 +17133,11 @@
   
   void _removeEventListener([String type, EventListener listener, bool useCapture]) {
     if (useCapture != null) {
-      _blink.BlinkEventTarget.instance.removeEventListener_Callback_3_(unwrap_jso(this), type, _knownListeners[this.hashCode][identityHashCode(listener)], useCapture);
+      _blink.BlinkEventTarget.instance.removeEventListener_Callback_3_(unwrap_jso(this), type, unwrap_jso(js.allowInterop(listener)), useCapture);
       return;
     }
     if (listener != null) {
-      _blink.BlinkEventTarget.instance.removeEventListener_Callback_2_(unwrap_jso(this), type, _knownListeners[this.hashCode][identityHashCode(listener)]);
+      _blink.BlinkEventTarget.instance.removeEventListener_Callback_2_(unwrap_jso(this), type, unwrap_jso(js.allowInterop(listener)));
       return;
     }
     if (type != null) {
@@ -17314,9 +17169,7 @@
     return new ExtendableEvent._internalWrap();
   }
 
-  factory ExtendableEvent._internalWrap() {
-    return new ExtendableEvent.internal_();
-  }
+  external factory ExtendableEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ExtendableEvent.internal_() : super.internal_();
@@ -17354,9 +17207,7 @@
     return new FederatedCredential._internalWrap();
   }
 
-  factory FederatedCredential._internalWrap() {
-    return new FederatedCredential.internal_();
-  }
+  external factory FederatedCredential._internalWrap();
 
   @Deprecated("Internal Use Only")
   FederatedCredential.internal_() : super.internal_();
@@ -17388,9 +17239,7 @@
     return new FetchEvent._internalWrap();
   }
 
-  factory FetchEvent._internalWrap() {
-    return new FetchEvent.internal_();
-  }
+  external factory FetchEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   FetchEvent.internal_() : super.internal_();
@@ -17436,9 +17285,7 @@
     return new FieldSetElement._internalWrap();
   }
 
-  factory FieldSetElement._internalWrap() {
-    return new FieldSetElement.internal_();
-  }
+  external factory FieldSetElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FieldSetElement.internal_() : super.internal_();
@@ -17518,9 +17365,7 @@
     return new File._internalWrap();
   }
 
-  factory File._internalWrap() {
-    return new File.internal_();
-  }
+  external factory File._internalWrap();
 
   @Deprecated("Internal Use Only")
   File.internal_() : super.internal_();
@@ -17580,9 +17425,7 @@
     return new FileEntry._internalWrap();
   }
 
-  factory FileEntry._internalWrap() {
-    return new FileEntry.internal_();
-  }
+  external factory FileEntry._internalWrap();
 
   @Deprecated("Internal Use Only")
   FileEntry.internal_() : super.internal_();
@@ -17644,9 +17487,7 @@
     return new FileError._internalWrap();
   }
 
-  factory FileError._internalWrap() {
-    return new FileError.internal_();
-  }
+  external factory FileError._internalWrap();
 
   @Deprecated("Internal Use Only")
   FileError.internal_() : super.internal_();
@@ -17882,9 +17723,7 @@
     return new FileReader._internalWrap();
   }
 
-  factory FileReader._internalWrap() {
-    return new FileReader.internal_();
-  }
+  external factory FileReader._internalWrap();
 
   @Deprecated("Internal Use Only")
   FileReader.internal_() : super.internal_();
@@ -18136,9 +17975,7 @@
     return new FileWriter._internalWrap();
   }
 
-  factory FileWriter._internalWrap() {
-    return new FileWriter.internal_();
-  }
+  external factory FileWriter._internalWrap();
 
   @Deprecated("Internal Use Only")
   FileWriter.internal_() : super.internal_();
@@ -18249,9 +18086,7 @@
     return new FocusEvent._internalWrap();
   }
 
-  factory FocusEvent._internalWrap() {
-    return new FocusEvent.internal_();
-  }
+  external factory FocusEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   FocusEvent.internal_() : super.internal_();
@@ -18424,9 +18259,7 @@
     return new FontFaceSet._internalWrap();
   }
 
-  factory FontFaceSet._internalWrap() {
-    return new FontFaceSet.internal_();
-  }
+  external factory FontFaceSet._internalWrap();
 
   @Deprecated("Internal Use Only")
   FontFaceSet.internal_() : super.internal_();
@@ -18509,9 +18342,7 @@
     return new FontFaceSetLoadEvent._internalWrap();
   }
 
-  factory FontFaceSetLoadEvent._internalWrap() {
-    return new FontFaceSetLoadEvent.internal_();
-  }
+  external factory FontFaceSetLoadEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   FontFaceSetLoadEvent.internal_() : super.internal_();
@@ -18597,9 +18428,7 @@
     return new FormElement._internalWrap();
   }
 
-  factory FormElement._internalWrap() {
-    return new FormElement.internal_();
-  }
+  external factory FormElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FormElement.internal_() : super.internal_();
@@ -18837,9 +18666,7 @@
     return new GamepadEvent._internalWrap();
   }
 
-  factory GamepadEvent._internalWrap() {
-    return new GamepadEvent.internal_();
-  }
+  external factory GamepadEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   GamepadEvent.internal_() : super.internal_();
@@ -19662,9 +19489,7 @@
     return new HRElement._internalWrap();
   }
 
-  factory HRElement._internalWrap() {
-    return new HRElement.internal_();
-  }
+  external factory HRElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   HRElement.internal_() : super.internal_();
@@ -19719,9 +19544,7 @@
     return new HashChangeEvent._internalWrap();
   }
 
-  factory HashChangeEvent._internalWrap() {
-    return new HashChangeEvent.internal_();
-  }
+  external factory HashChangeEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   HashChangeEvent.internal_() : super.internal_();
@@ -19766,9 +19589,7 @@
     return new HeadElement._internalWrap();
   }
 
-  factory HeadElement._internalWrap() {
-    return new HeadElement.internal_();
-  }
+  external factory HeadElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   HeadElement.internal_() : super.internal_();
@@ -19894,9 +19715,7 @@
     return new HeadingElement._internalWrap();
   }
 
-  factory HeadingElement._internalWrap() {
-    return new HeadingElement.internal_();
-  }
+  external factory HeadingElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   HeadingElement.internal_() : super.internal_();
@@ -20086,9 +19905,7 @@
     return new HtmlDocument._internalWrap();
   }
 
-  factory HtmlDocument._internalWrap() {
-    return new HtmlDocument.internal_();
-  }
+  external factory HtmlDocument._internalWrap();
 
   @Deprecated("Internal Use Only")
   HtmlDocument.internal_() : super.internal_();
@@ -20888,9 +20705,7 @@
     return new HtmlElement._internalWrap();
   }
 
-  factory HtmlElement._internalWrap() {
-    return new HtmlElement.internal_();
-  }
+  external factory HtmlElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   HtmlElement.internal_() : super.internal_();
@@ -21309,9 +21124,7 @@
     return new HtmlFormControlsCollection._internalWrap();
   }
 
-  factory HtmlFormControlsCollection._internalWrap() {
-    return new HtmlFormControlsCollection.internal_();
-  }
+  external factory HtmlFormControlsCollection._internalWrap();
 
   @Deprecated("Internal Use Only")
   HtmlFormControlsCollection.internal_() : super.internal_();
@@ -21345,9 +21158,7 @@
     return new HtmlHtmlElement._internalWrap();
   }
 
-  factory HtmlHtmlElement._internalWrap() {
-    return new HtmlHtmlElement.internal_();
-  }
+  external factory HtmlHtmlElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   HtmlHtmlElement.internal_() : super.internal_();
@@ -21379,9 +21190,7 @@
     return new HtmlOptionsCollection._internalWrap();
   }
 
-  factory HtmlOptionsCollection._internalWrap() {
-    return new HtmlOptionsCollection.internal_();
-  }
+  external factory HtmlOptionsCollection._internalWrap();
 
   @Deprecated("Internal Use Only")
   HtmlOptionsCollection.internal_() : super.internal_();
@@ -21791,9 +21600,7 @@
     return new HttpRequest._internalWrap();
   }
 
-  factory HttpRequest._internalWrap() {
-    return new HttpRequest.internal_();
-  }
+  external factory HttpRequest._internalWrap();
 
   @Deprecated("Internal Use Only")
   HttpRequest.internal_() : super.internal_();
@@ -22204,9 +22011,7 @@
     return new HttpRequestEventTarget._internalWrap();
   }
 
-  factory HttpRequestEventTarget._internalWrap() {
-    return new HttpRequestEventTarget.internal_();
-  }
+  external factory HttpRequestEventTarget._internalWrap();
 
   @Deprecated("Internal Use Only")
   HttpRequestEventTarget.internal_() : super.internal_();
@@ -22284,9 +22089,7 @@
     return new HttpRequestUpload._internalWrap();
   }
 
-  factory HttpRequestUpload._internalWrap() {
-    return new HttpRequestUpload.internal_();
-  }
+  external factory HttpRequestUpload._internalWrap();
 
   @Deprecated("Internal Use Only")
   HttpRequestUpload.internal_() : super.internal_();
@@ -22316,9 +22119,7 @@
     return new IFrameElement._internalWrap();
   }
 
-  factory IFrameElement._internalWrap() {
-    return new IFrameElement.internal_();
-  }
+  external factory IFrameElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   IFrameElement.internal_() : super.internal_();
@@ -22527,9 +22328,7 @@
     return new ImageElement._internalWrap();
   }
 
-  factory ImageElement._internalWrap() {
-    return new ImageElement.internal_();
-  }
+  external factory ImageElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ImageElement.internal_() : super.internal_();
@@ -22729,9 +22528,7 @@
     return new InputElement._internalWrap();
   }
 
-  factory InputElement._internalWrap() {
-    return new InputElement.internal_();
-  }
+  external factory InputElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   InputElement.internal_() : super.internal_();
@@ -23751,9 +23548,7 @@
     return new InputMethodContext._internalWrap();
   }
 
-  factory InputMethodContext._internalWrap() {
-    return new InputMethodContext.internal_();
-  }
+  external factory InputMethodContext._internalWrap();
 
   @Deprecated("Internal Use Only")
   InputMethodContext.internal_() : super.internal_();
@@ -23803,9 +23598,7 @@
     return new InstallEvent._internalWrap();
   }
 
-  factory InstallEvent._internalWrap() {
-    return new InstallEvent.internal_();
-  }
+  external factory InstallEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   InstallEvent.internal_() : super.internal_();
@@ -23857,9 +23650,7 @@
     return new KeyboardEvent._internalWrap();
   }
 
-  factory KeyboardEvent._internalWrap() {
-    return new KeyboardEvent.internal_();
-  }
+  external factory KeyboardEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   KeyboardEvent.internal_() : super.internal_();
@@ -23958,9 +23749,7 @@
     return new KeygenElement._internalWrap();
   }
 
-  factory KeygenElement._internalWrap() {
-    return new KeygenElement.internal_();
-  }
+  external factory KeygenElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   KeygenElement.internal_() : super.internal_();
@@ -24072,9 +23861,7 @@
     return new LIElement._internalWrap();
   }
 
-  factory LIElement._internalWrap() {
-    return new LIElement.internal_();
-  }
+  external factory LIElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   LIElement.internal_() : super.internal_();
@@ -24118,9 +23905,7 @@
     return new LabelElement._internalWrap();
   }
 
-  factory LabelElement._internalWrap() {
-    return new LabelElement.internal_();
-  }
+  external factory LabelElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   LabelElement.internal_() : super.internal_();
@@ -24172,9 +23957,7 @@
     return new LegendElement._internalWrap();
   }
 
-  factory LegendElement._internalWrap() {
-    return new LegendElement.internal_();
-  }
+  external factory LegendElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   LegendElement.internal_() : super.internal_();
@@ -24212,9 +23995,7 @@
     return new LinkElement._internalWrap();
   }
 
-  factory LinkElement._internalWrap() {
-    return new LinkElement.internal_();
-  }
+  external factory LinkElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   LinkElement.internal_() : super.internal_();
@@ -24340,9 +24121,7 @@
     return new LocalCredential._internalWrap();
   }
 
-  factory LocalCredential._internalWrap() {
-    return new LocalCredential.internal_();
-  }
+  external factory LocalCredential._internalWrap();
 
   @Deprecated("Internal Use Only")
   LocalCredential.internal_() : super.internal_();
@@ -24518,9 +24297,7 @@
     return new MapElement._internalWrap();
   }
 
-  factory MapElement._internalWrap() {
-    return new MapElement.internal_();
-  }
+  external factory MapElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MapElement.internal_() : super.internal_();
@@ -24572,9 +24349,7 @@
     return new MediaController._internalWrap();
   }
 
-  factory MediaController._internalWrap() {
-    return new MediaController.internal_();
-  }
+  external factory MediaController._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaController.internal_() : super.internal_();
@@ -24793,9 +24568,7 @@
     return new MediaElement._internalWrap();
   }
 
-  factory MediaElement._internalWrap() {
-    return new MediaElement.internal_();
-  }
+  external factory MediaElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaElement.internal_() : super.internal_();
@@ -25279,9 +25052,7 @@
     return new MediaKeyEvent._internalWrap();
   }
 
-  factory MediaKeyEvent._internalWrap() {
-    return new MediaKeyEvent.internal_();
-  }
+  external factory MediaKeyEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaKeyEvent.internal_() : super.internal_();
@@ -25337,9 +25108,7 @@
     return new MediaKeyMessageEvent._internalWrap();
   }
 
-  factory MediaKeyMessageEvent._internalWrap() {
-    return new MediaKeyMessageEvent.internal_();
-  }
+  external factory MediaKeyMessageEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaKeyMessageEvent.internal_() : super.internal_();
@@ -25375,9 +25144,7 @@
     return new MediaKeyNeededEvent._internalWrap();
   }
 
-  factory MediaKeyNeededEvent._internalWrap() {
-    return new MediaKeyNeededEvent.internal_();
-  }
+  external factory MediaKeyNeededEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaKeyNeededEvent.internal_() : super.internal_();
@@ -25414,9 +25181,7 @@
     return new MediaKeySession._internalWrap();
   }
 
-  factory MediaKeySession._internalWrap() {
-    return new MediaKeySession.internal_();
-  }
+  external factory MediaKeySession._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaKeySession.internal_() : super.internal_();
@@ -25596,9 +25361,7 @@
     return new MediaQueryList._internalWrap();
   }
 
-  factory MediaQueryList._internalWrap() {
-    return new MediaQueryList.internal_();
-  }
+  external factory MediaQueryList._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaQueryList.internal_() : super.internal_();
@@ -25646,9 +25409,7 @@
     return new MediaQueryListEvent._internalWrap();
   }
 
-  factory MediaQueryListEvent._internalWrap() {
-    return new MediaQueryListEvent.internal_();
-  }
+  external factory MediaQueryListEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaQueryListEvent.internal_() : super.internal_();
@@ -25694,9 +25455,7 @@
     return new MediaSource._internalWrap();
   }
 
-  factory MediaSource._internalWrap() {
-    return new MediaSource.internal_();
-  }
+  external factory MediaSource._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaSource.internal_() : super.internal_();
@@ -25811,9 +25570,7 @@
     return new MediaStream._internalWrap();
   }
 
-  factory MediaStream._internalWrap() {
-    return new MediaStream.internal_();
-  }
+  external factory MediaStream._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaStream.internal_() : super.internal_();
@@ -25913,9 +25670,7 @@
     return new MediaStreamEvent._internalWrap();
   }
 
-  factory MediaStreamEvent._internalWrap() {
-    return new MediaStreamEvent.internal_();
-  }
+  external factory MediaStreamEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaStreamEvent.internal_() : super.internal_();
@@ -25981,9 +25736,7 @@
     return new MediaStreamTrack._internalWrap();
   }
 
-  factory MediaStreamTrack._internalWrap() {
-    return new MediaStreamTrack.internal_();
-  }
+  external factory MediaStreamTrack._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaStreamTrack.internal_() : super.internal_();
@@ -26078,9 +25831,7 @@
     return new MediaStreamTrackEvent._internalWrap();
   }
 
-  factory MediaStreamTrackEvent._internalWrap() {
-    return new MediaStreamTrackEvent.internal_();
-  }
+  external factory MediaStreamTrackEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaStreamTrackEvent.internal_() : super.internal_();
@@ -26179,9 +25930,7 @@
     return new MenuElement._internalWrap();
   }
 
-  factory MenuElement._internalWrap() {
-    return new MenuElement.internal_();
-  }
+  external factory MenuElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MenuElement.internal_() : super.internal_();
@@ -26234,9 +25983,7 @@
     return new MenuItemElement._internalWrap();
   }
 
-  factory MenuItemElement._internalWrap() {
-    return new MenuItemElement.internal_();
-  }
+  external factory MenuItemElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MenuItemElement.internal_() : super.internal_();
@@ -26367,9 +26114,7 @@
     return new MessageEvent._internalWrap();
   }
 
-  factory MessageEvent._internalWrap() {
-    return new MessageEvent.internal_();
-  }
+  external factory MessageEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MessageEvent.internal_() : super.internal_();
@@ -26427,9 +26172,7 @@
     return new MessagePort._internalWrap();
   }
 
-  factory MessagePort._internalWrap() {
-    return new MessagePort.internal_();
-  }
+  external factory MessagePort._internalWrap();
 
   @Deprecated("Internal Use Only")
   MessagePort.internal_() : super.internal_();
@@ -26476,9 +26219,7 @@
     return new MetaElement._internalWrap();
   }
 
-  factory MetaElement._internalWrap() {
-    return new MetaElement.internal_();
-  }
+  external factory MetaElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MetaElement.internal_() : super.internal_();
@@ -26592,9 +26333,7 @@
     return new MeterElement._internalWrap();
   }
 
-  factory MeterElement._internalWrap() {
-    return new MeterElement.internal_();
-  }
+  external factory MeterElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MeterElement.internal_() : super.internal_();
@@ -26704,9 +26443,7 @@
     return new MidiAccess._internalWrap();
   }
 
-  factory MidiAccess._internalWrap() {
-    return new MidiAccess.internal_();
-  }
+  external factory MidiAccess._internalWrap();
 
   @Deprecated("Internal Use Only")
   MidiAccess.internal_() : super.internal_();
@@ -26757,9 +26494,7 @@
     return new MidiConnectionEvent._internalWrap();
   }
 
-  factory MidiConnectionEvent._internalWrap() {
-    return new MidiConnectionEvent.internal_();
-  }
+  external factory MidiConnectionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MidiConnectionEvent.internal_() : super.internal_();
@@ -26801,9 +26536,7 @@
     return new MidiInput._internalWrap();
   }
 
-  factory MidiInput._internalWrap() {
-    return new MidiInput.internal_();
-  }
+  external factory MidiInput._internalWrap();
 
   @Deprecated("Internal Use Only")
   MidiInput.internal_() : super.internal_();
@@ -26896,9 +26629,7 @@
     return new MidiMessageEvent._internalWrap();
   }
 
-  factory MidiMessageEvent._internalWrap() {
-    return new MidiMessageEvent.internal_();
-  }
+  external factory MidiMessageEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MidiMessageEvent.internal_() : super.internal_();
@@ -26934,9 +26665,7 @@
     return new MidiOutput._internalWrap();
   }
 
-  factory MidiOutput._internalWrap() {
-    return new MidiOutput.internal_();
-  }
+  external factory MidiOutput._internalWrap();
 
   @Deprecated("Internal Use Only")
   MidiOutput.internal_() : super.internal_();
@@ -27043,9 +26772,7 @@
     return new MidiPort._internalWrap();
   }
 
-  factory MidiPort._internalWrap() {
-    return new MidiPort.internal_();
-  }
+  external factory MidiPort._internalWrap();
 
   @Deprecated("Internal Use Only")
   MidiPort.internal_() : super.internal_();
@@ -27235,9 +26962,7 @@
     return new ModElement._internalWrap();
   }
 
-  factory ModElement._internalWrap() {
-    return new ModElement.internal_();
-  }
+  external factory ModElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ModElement.internal_() : super.internal_();
@@ -27299,9 +27024,7 @@
     return new MouseEvent._internalWrap();
   }
 
-  factory MouseEvent._internalWrap() {
-    return new MouseEvent.internal_();
-  }
+  external factory MouseEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   MouseEvent.internal_() : super.internal_();
@@ -28118,9 +27841,7 @@
     return new NetworkInformation._internalWrap();
   }
 
-  factory NetworkInformation._internalWrap() {
-    return new NetworkInformation.internal_();
-  }
+  external factory NetworkInformation._internalWrap();
 
   @Deprecated("Internal Use Only")
   NetworkInformation.internal_() : super.internal_();
@@ -28420,9 +28141,7 @@
     return new Node._internalWrap();
   }
 
-  factory Node._internalWrap() {
-    return new Node.internal_();
-  }
+  external factory Node._internalWrap();
 
   @Deprecated("Internal Use Only")
   Node.internal_() : super.internal_();
@@ -29026,9 +28745,7 @@
     return new Notification._internalWrap();
   }
 
-  factory Notification._internalWrap() {
-    return new Notification.internal_();
-  }
+  external factory Notification._internalWrap();
 
   @Deprecated("Internal Use Only")
   Notification.internal_() : super.internal_();
@@ -29146,9 +28863,7 @@
     return new OListElement._internalWrap();
   }
 
-  factory OListElement._internalWrap() {
-    return new OListElement.internal_();
-  }
+  external factory OListElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   OListElement.internal_() : super.internal_();
@@ -29212,9 +28927,7 @@
     return new ObjectElement._internalWrap();
   }
 
-  factory ObjectElement._internalWrap() {
-    return new ObjectElement.internal_();
-  }
+  external factory ObjectElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ObjectElement.internal_() : super.internal_();
@@ -29343,9 +29056,7 @@
     return new OptGroupElement._internalWrap();
   }
 
-  factory OptGroupElement._internalWrap() {
-    return new OptGroupElement.internal_();
-  }
+  external factory OptGroupElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   OptGroupElement.internal_() : super.internal_();
@@ -29397,9 +29108,7 @@
     return new OptionElement._internalWrap();
   }
 
-  factory OptionElement._internalWrap() {
-    return new OptionElement.internal_();
-  }
+  external factory OptionElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   OptionElement.internal_() : super.internal_();
@@ -29486,9 +29195,7 @@
     return new OutputElement._internalWrap();
   }
 
-  factory OutputElement._internalWrap() {
-    return new OutputElement.internal_();
-  }
+  external factory OutputElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   OutputElement.internal_() : super.internal_();
@@ -29585,9 +29292,7 @@
     return new OverflowEvent._internalWrap();
   }
 
-  factory OverflowEvent._internalWrap() {
-    return new OverflowEvent.internal_();
-  }
+  external factory OverflowEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   OverflowEvent.internal_() : super.internal_();
@@ -29639,9 +29344,7 @@
     return new PageTransitionEvent._internalWrap();
   }
 
-  factory PageTransitionEvent._internalWrap() {
-    return new PageTransitionEvent.internal_();
-  }
+  external factory PageTransitionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   PageTransitionEvent.internal_() : super.internal_();
@@ -29675,9 +29378,7 @@
     return new ParagraphElement._internalWrap();
   }
 
-  factory ParagraphElement._internalWrap() {
-    return new ParagraphElement.internal_();
-  }
+  external factory ParagraphElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ParagraphElement.internal_() : super.internal_();
@@ -29714,9 +29415,7 @@
     return new ParamElement._internalWrap();
   }
 
-  factory ParamElement._internalWrap() {
-    return new ParamElement.internal_();
-  }
+  external factory ParamElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ParamElement.internal_() : super.internal_();
@@ -29925,9 +29624,7 @@
     return new Performance._internalWrap();
   }
 
-  factory Performance._internalWrap() {
-    return new Performance.internal_();
-  }
+  external factory Performance._internalWrap();
 
   @Deprecated("Internal Use Only")
   Performance.internal_() : super.internal_();
@@ -30087,9 +29784,7 @@
     return new PerformanceMark._internalWrap();
   }
 
-  factory PerformanceMark._internalWrap() {
-    return new PerformanceMark.internal_();
-  }
+  external factory PerformanceMark._internalWrap();
 
   @Deprecated("Internal Use Only")
   PerformanceMark.internal_() : super.internal_();
@@ -30117,9 +29812,7 @@
     return new PerformanceMeasure._internalWrap();
   }
 
-  factory PerformanceMeasure._internalWrap() {
-    return new PerformanceMeasure.internal_();
-  }
+  external factory PerformanceMeasure._internalWrap();
 
   @Deprecated("Internal Use Only")
   PerformanceMeasure.internal_() : super.internal_();
@@ -30201,9 +29894,7 @@
     return new PerformanceResourceTiming._internalWrap();
   }
 
-  factory PerformanceResourceTiming._internalWrap() {
-    return new PerformanceResourceTiming.internal_();
-  }
+  external factory PerformanceResourceTiming._internalWrap();
 
   @Deprecated("Internal Use Only")
   PerformanceResourceTiming.internal_() : super.internal_();
@@ -30395,9 +30086,7 @@
     return new PictureElement._internalWrap();
   }
 
-  factory PictureElement._internalWrap() {
-    return new PictureElement.internal_();
-  }
+  external factory PictureElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PictureElement.internal_() : super.internal_();
@@ -30584,9 +30273,7 @@
     return new PluginPlaceholderElement._internalWrap();
   }
 
-  factory PluginPlaceholderElement._internalWrap() {
-    return new PluginPlaceholderElement.internal_();
-  }
+  external factory PluginPlaceholderElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PluginPlaceholderElement.internal_() : super.internal_();
@@ -30637,9 +30324,7 @@
     return new PopStateEvent._internalWrap();
   }
 
-  factory PopStateEvent._internalWrap() {
-    return new PopStateEvent.internal_();
-  }
+  external factory PopStateEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   PopStateEvent.internal_() : super.internal_();
@@ -30743,9 +30428,7 @@
     return new PreElement._internalWrap();
   }
 
-  factory PreElement._internalWrap() {
-    return new PreElement.internal_();
-  }
+  external factory PreElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PreElement.internal_() : super.internal_();
@@ -30778,9 +30461,7 @@
     return new Presentation._internalWrap();
   }
 
-  factory Presentation._internalWrap() {
-    return new Presentation.internal_();
-  }
+  external factory Presentation._internalWrap();
 
   @Deprecated("Internal Use Only")
   Presentation.internal_() : super.internal_();
@@ -30807,9 +30488,7 @@
     return new ProcessingInstruction._internalWrap();
   }
 
-  factory ProcessingInstruction._internalWrap() {
-    return new ProcessingInstruction.internal_();
-  }
+  external factory ProcessingInstruction._internalWrap();
 
   @Deprecated("Internal Use Only")
   ProcessingInstruction.internal_() : super.internal_();
@@ -30852,9 +30531,7 @@
     return new ProgressElement._internalWrap();
   }
 
-  factory ProgressElement._internalWrap() {
-    return new ProgressElement.internal_();
-  }
+  external factory ProgressElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ProgressElement.internal_() : super.internal_();
@@ -30914,9 +30591,7 @@
     return new ProgressEvent._internalWrap();
   }
 
-  factory ProgressEvent._internalWrap() {
-    return new ProgressEvent.internal_();
-  }
+  external factory ProgressEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ProgressEvent.internal_() : super.internal_();
@@ -30955,9 +30630,7 @@
     return new PushEvent._internalWrap();
   }
 
-  factory PushEvent._internalWrap() {
-    return new PushEvent.internal_();
-  }
+  external factory PushEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   PushEvent.internal_() : super.internal_();
@@ -31067,9 +30740,7 @@
     return new QuoteElement._internalWrap();
   }
 
-  factory QuoteElement._internalWrap() {
-    return new QuoteElement.internal_();
-  }
+  external factory QuoteElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   QuoteElement.internal_() : super.internal_();
@@ -31399,9 +31070,7 @@
     return new RelatedEvent._internalWrap();
   }
 
-  factory RelatedEvent._internalWrap() {
-    return new RelatedEvent.internal_();
-  }
+  external factory RelatedEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   RelatedEvent.internal_() : super.internal_();
@@ -31443,9 +31112,7 @@
     return new ResourceProgressEvent._internalWrap();
   }
 
-  factory ResourceProgressEvent._internalWrap() {
-    return new ResourceProgressEvent.internal_();
-  }
+  external factory ResourceProgressEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ResourceProgressEvent.internal_() : super.internal_();
@@ -31517,9 +31184,7 @@
     return new RtcDataChannel._internalWrap();
   }
 
-  factory RtcDataChannel._internalWrap() {
-    return new RtcDataChannel.internal_();
-  }
+  external factory RtcDataChannel._internalWrap();
 
   @Deprecated("Internal Use Only")
   RtcDataChannel.internal_() : super.internal_();
@@ -31661,9 +31326,7 @@
     return new RtcDataChannelEvent._internalWrap();
   }
 
-  factory RtcDataChannelEvent._internalWrap() {
-    return new RtcDataChannelEvent.internal_();
-  }
+  external factory RtcDataChannelEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   RtcDataChannelEvent.internal_() : super.internal_();
@@ -31705,9 +31368,7 @@
     return new RtcDtmfSender._internalWrap();
   }
 
-  factory RtcDtmfSender._internalWrap() {
-    return new RtcDtmfSender.internal_();
-  }
+  external factory RtcDtmfSender._internalWrap();
 
   @Deprecated("Internal Use Only")
   RtcDtmfSender.internal_() : super.internal_();
@@ -31773,9 +31434,7 @@
     return new RtcDtmfToneChangeEvent._internalWrap();
   }
 
-  factory RtcDtmfToneChangeEvent._internalWrap() {
-    return new RtcDtmfToneChangeEvent.internal_();
-  }
+  external factory RtcDtmfToneChangeEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   RtcDtmfToneChangeEvent.internal_() : super.internal_();
@@ -31870,9 +31529,7 @@
     return new RtcIceCandidateEvent._internalWrap();
   }
 
-  factory RtcIceCandidateEvent._internalWrap() {
-    return new RtcIceCandidateEvent.internal_();
-  }
+  external factory RtcIceCandidateEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   RtcIceCandidateEvent.internal_() : super.internal_();
@@ -32012,9 +31669,7 @@
     return new RtcPeerConnection._internalWrap();
   }
 
-  factory RtcPeerConnection._internalWrap() {
-    return new RtcPeerConnection.internal_();
-  }
+  external factory RtcPeerConnection._internalWrap();
 
   @Deprecated("Internal Use Only")
   RtcPeerConnection.internal_() : super.internal_();
@@ -32436,9 +32091,7 @@
     return new ScreenOrientation._internalWrap();
   }
 
-  factory ScreenOrientation._internalWrap() {
-    return new ScreenOrientation.internal_();
-  }
+  external factory ScreenOrientation._internalWrap();
 
   @Deprecated("Internal Use Only")
   ScreenOrientation.internal_() : super.internal_();
@@ -32493,9 +32146,7 @@
     return new ScriptElement._internalWrap();
   }
 
-  factory ScriptElement._internalWrap() {
-    return new ScriptElement.internal_();
-  }
+  external factory ScriptElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ScriptElement.internal_() : super.internal_();
@@ -32603,9 +32254,7 @@
     return new SecurityPolicyViolationEvent._internalWrap();
   }
 
-  factory SecurityPolicyViolationEvent._internalWrap() {
-    return new SecurityPolicyViolationEvent.internal_();
-  }
+  external factory SecurityPolicyViolationEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   SecurityPolicyViolationEvent.internal_() : super.internal_();
@@ -32673,9 +32322,7 @@
     return new SelectElement._internalWrap();
   }
 
-  factory SelectElement._internalWrap() {
-    return new SelectElement.internal_();
-  }
+  external factory SelectElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SelectElement.internal_() : super.internal_();
@@ -33137,9 +32784,7 @@
     return new ServiceWorkerGlobalScope._internalWrap();
   }
 
-  factory ServiceWorkerGlobalScope._internalWrap() {
-    return new ServiceWorkerGlobalScope.internal_();
-  }
+  external factory ServiceWorkerGlobalScope._internalWrap();
 
   @Deprecated("Internal Use Only")
   ServiceWorkerGlobalScope.internal_() : super.internal_();
@@ -33207,9 +32852,7 @@
     return new ServiceWorkerRegistration._internalWrap();
   }
 
-  factory ServiceWorkerRegistration._internalWrap() {
-    return new ServiceWorkerRegistration.internal_();
-  }
+  external factory ServiceWorkerRegistration._internalWrap();
 
   @Deprecated("Internal Use Only")
   ServiceWorkerRegistration.internal_() : super.internal_();
@@ -33267,9 +32910,7 @@
     return new ShadowElement._internalWrap();
   }
 
-  factory ShadowElement._internalWrap() {
-    return new ShadowElement.internal_();
-  }
+  external factory ShadowElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ShadowElement.internal_() : super.internal_();
@@ -33311,9 +32952,7 @@
     return new ShadowRoot._internalWrap();
   }
 
-  factory ShadowRoot._internalWrap() {
-    return new ShadowRoot.internal_();
-  }
+  external factory ShadowRoot._internalWrap();
 
   @Deprecated("Internal Use Only")
   ShadowRoot.internal_() : super.internal_();
@@ -33439,9 +33078,7 @@
     return new SharedWorker._internalWrap();
   }
 
-  factory SharedWorker._internalWrap() {
-    return new SharedWorker.internal_();
-  }
+  external factory SharedWorker._internalWrap();
 
   @Deprecated("Internal Use Only")
   SharedWorker.internal_() : super.internal_();
@@ -33493,9 +33130,7 @@
     return new SharedWorkerGlobalScope._internalWrap();
   }
 
-  factory SharedWorkerGlobalScope._internalWrap() {
-    return new SharedWorkerGlobalScope.internal_();
-  }
+  external factory SharedWorkerGlobalScope._internalWrap();
 
   @Deprecated("Internal Use Only")
   SharedWorkerGlobalScope.internal_() : super.internal_();
@@ -33534,9 +33169,7 @@
     return new SourceBuffer._internalWrap();
   }
 
-  factory SourceBuffer._internalWrap() {
-    return new SourceBuffer.internal_();
-  }
+  external factory SourceBuffer._internalWrap();
 
   @Deprecated("Internal Use Only")
   SourceBuffer.internal_() : super.internal_();
@@ -33639,9 +33272,7 @@
     return new SourceBufferList._internalWrap();
   }
 
-  factory SourceBufferList._internalWrap() {
-    return new SourceBufferList.internal_();
-  }
+  external factory SourceBufferList._internalWrap();
 
   @Deprecated("Internal Use Only")
   SourceBufferList.internal_() : super.internal_();
@@ -33725,9 +33356,7 @@
     return new SourceElement._internalWrap();
   }
 
-  factory SourceElement._internalWrap() {
-    return new SourceElement.internal_();
-  }
+  external factory SourceElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SourceElement.internal_() : super.internal_();
@@ -33867,9 +33496,7 @@
     return new SpanElement._internalWrap();
   }
 
-  factory SpanElement._internalWrap() {
-    return new SpanElement.internal_();
-  }
+  external factory SpanElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpanElement.internal_() : super.internal_();
@@ -34182,9 +33809,7 @@
     return new SpeechRecognition._internalWrap();
   }
 
-  factory SpeechRecognition._internalWrap() {
-    return new SpeechRecognition.internal_();
-  }
+  external factory SpeechRecognition._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpeechRecognition.internal_() : super.internal_();
@@ -34363,9 +33988,7 @@
     return new SpeechRecognitionError._internalWrap();
   }
 
-  factory SpeechRecognitionError._internalWrap() {
-    return new SpeechRecognitionError.internal_();
-  }
+  external factory SpeechRecognitionError._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpeechRecognitionError.internal_() : super.internal_();
@@ -34402,9 +34025,7 @@
     return new SpeechRecognitionEvent._internalWrap();
   }
 
-  factory SpeechRecognitionEvent._internalWrap() {
-    return new SpeechRecognitionEvent.internal_();
-  }
+  external factory SpeechRecognitionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpeechRecognitionEvent.internal_() : super.internal_();
@@ -34492,9 +34113,7 @@
     return new SpeechSynthesis._internalWrap();
   }
 
-  factory SpeechSynthesis._internalWrap() {
-    return new SpeechSynthesis.internal_();
-  }
+  external factory SpeechSynthesis._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpeechSynthesis.internal_() : super.internal_();
@@ -34554,9 +34173,7 @@
     return new SpeechSynthesisEvent._internalWrap();
   }
 
-  factory SpeechSynthesisEvent._internalWrap() {
-    return new SpeechSynthesisEvent.internal_();
-  }
+  external factory SpeechSynthesisEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpeechSynthesisEvent.internal_() : super.internal_();
@@ -34672,9 +34289,7 @@
     return new SpeechSynthesisUtterance._internalWrap();
   }
 
-  factory SpeechSynthesisUtterance._internalWrap() {
-    return new SpeechSynthesisUtterance.internal_();
-  }
+  external factory SpeechSynthesisUtterance._internalWrap();
 
   @Deprecated("Internal Use Only")
   SpeechSynthesisUtterance.internal_() : super.internal_();
@@ -35016,9 +34631,7 @@
     return new StorageEvent._internalWrap();
   }
 
-  factory StorageEvent._internalWrap() {
-    return new StorageEvent.internal_();
-  }
+  external factory StorageEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   StorageEvent.internal_() : super.internal_();
@@ -35192,9 +34805,7 @@
     return new StyleElement._internalWrap();
   }
 
-  factory StyleElement._internalWrap() {
-    return new StyleElement.internal_();
-  }
+  external factory StyleElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   StyleElement.internal_() : super.internal_();
@@ -35358,9 +34969,7 @@
     return new TableCaptionElement._internalWrap();
   }
 
-  factory TableCaptionElement._internalWrap() {
-    return new TableCaptionElement.internal_();
-  }
+  external factory TableCaptionElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TableCaptionElement.internal_() : super.internal_();
@@ -35396,9 +35005,7 @@
     return new TableCellElement._internalWrap();
   }
 
-  factory TableCellElement._internalWrap() {
-    return new TableCellElement.internal_();
-  }
+  external factory TableCellElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TableCellElement.internal_() : super.internal_();
@@ -35462,9 +35069,7 @@
     return new TableColElement._internalWrap();
   }
 
-  factory TableColElement._internalWrap() {
-    return new TableColElement.internal_();
-  }
+  external factory TableColElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TableColElement.internal_() : super.internal_();
@@ -35526,9 +35131,7 @@
     return new TableElement._internalWrap();
   }
 
-  factory TableElement._internalWrap() {
-    return new TableElement.internal_();
-  }
+  external factory TableElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TableElement.internal_() : super.internal_();
@@ -35644,9 +35247,7 @@
     return new TableRowElement._internalWrap();
   }
 
-  factory TableRowElement._internalWrap() {
-    return new TableRowElement.internal_();
-  }
+  external factory TableRowElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TableRowElement.internal_() : super.internal_();
@@ -35710,9 +35311,7 @@
     return new TableSectionElement._internalWrap();
   }
 
-  factory TableSectionElement._internalWrap() {
-    return new TableSectionElement.internal_();
-  }
+  external factory TableSectionElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TableSectionElement.internal_() : super.internal_();
@@ -35765,9 +35364,7 @@
     return new TemplateElement._internalWrap();
   }
 
-  factory TemplateElement._internalWrap() {
-    return new TemplateElement.internal_();
-  }
+  external factory TemplateElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TemplateElement.internal_() : super.internal_();
@@ -35822,9 +35419,7 @@
     return new Text._internalWrap();
   }
 
-  factory Text._internalWrap() {
-    return new Text.internal_();
-  }
+  external factory Text._internalWrap();
 
   @Deprecated("Internal Use Only")
   Text.internal_() : super.internal_();
@@ -35867,9 +35462,7 @@
     return new TextAreaElement._internalWrap();
   }
 
-  factory TextAreaElement._internalWrap() {
-    return new TextAreaElement.internal_();
-  }
+  external factory TextAreaElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextAreaElement.internal_() : super.internal_();
@@ -36114,9 +35707,7 @@
     return new TextEvent._internalWrap();
   }
 
-  factory TextEvent._internalWrap() {
-    return new TextEvent.internal_();
-  }
+  external factory TextEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextEvent.internal_() : super.internal_();
@@ -36250,9 +35841,7 @@
     return new TextTrack._internalWrap();
   }
 
-  factory TextTrack._internalWrap() {
-    return new TextTrack.internal_();
-  }
+  external factory TextTrack._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextTrack.internal_() : super.internal_();
@@ -36361,9 +35950,7 @@
     return new TextTrackCue._internalWrap();
   }
 
-  factory TextTrackCue._internalWrap() {
-    return new TextTrackCue.internal_();
-  }
+  external factory TextTrackCue._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextTrackCue.internal_() : super.internal_();
@@ -36541,9 +36128,7 @@
     return new TextTrackList._internalWrap();
   }
 
-  factory TextTrackList._internalWrap() {
-    return new TextTrackList.internal_();
-  }
+  external factory TextTrackList._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextTrackList.internal_() : super.internal_();
@@ -36813,9 +36398,7 @@
     return new TitleElement._internalWrap();
   }
 
-  factory TitleElement._internalWrap() {
-    return new TitleElement.internal_();
-  }
+  external factory TitleElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TitleElement.internal_() : super.internal_();
@@ -36982,9 +36565,7 @@
     return new TouchEvent._internalWrap();
   }
 
-  factory TouchEvent._internalWrap() {
-    return new TouchEvent.internal_();
-  }
+  external factory TouchEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   TouchEvent.internal_() : super.internal_();
@@ -37151,9 +36732,7 @@
     return new TrackElement._internalWrap();
   }
 
-  factory TrackElement._internalWrap() {
-    return new TrackElement.internal_();
-  }
+  external factory TrackElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TrackElement.internal_() : super.internal_();
@@ -37263,9 +36842,7 @@
     return new TrackEvent._internalWrap();
   }
 
-  factory TrackEvent._internalWrap() {
-    return new TrackEvent.internal_();
-  }
+  external factory TrackEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   TrackEvent.internal_() : super.internal_();
@@ -37295,9 +36872,7 @@
     return new TransitionEvent._internalWrap();
   }
 
-  factory TransitionEvent._internalWrap() {
-    return new TransitionEvent.internal_();
-  }
+  external factory TransitionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   TransitionEvent.internal_() : super.internal_();
@@ -37428,9 +37003,7 @@
     return new UIEvent._internalWrap();
   }
 
-  factory UIEvent._internalWrap() {
-    return new UIEvent.internal_();
-  }
+  external factory UIEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   UIEvent.internal_() : super.internal_();
@@ -37519,9 +37092,7 @@
     return new UListElement._internalWrap();
   }
 
-  factory UListElement._internalWrap() {
-    return new UListElement.internal_();
-  }
+  external factory UListElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   UListElement.internal_() : super.internal_();
@@ -37553,9 +37124,7 @@
     return new UnknownElement._internalWrap();
   }
 
-  factory UnknownElement._internalWrap() {
-    return new UnknownElement.internal_();
-  }
+  external factory UnknownElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   UnknownElement.internal_() : super.internal_();
@@ -38015,9 +37584,7 @@
     return new VideoElement._internalWrap();
   }
 
-  factory VideoElement._internalWrap() {
-    return new VideoElement.internal_();
-  }
+  external factory VideoElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   VideoElement.internal_() : super.internal_();
@@ -38232,9 +37799,7 @@
     return new VideoTrackList._internalWrap();
   }
 
-  factory VideoTrackList._internalWrap() {
-    return new VideoTrackList.internal_();
-  }
+  external factory VideoTrackList._internalWrap();
 
   @Deprecated("Internal Use Only")
   VideoTrackList.internal_() : super.internal_();
@@ -38303,9 +37868,7 @@
     return new VttCue._internalWrap();
   }
 
-  factory VttCue._internalWrap() {
-    return new VttCue.internal_();
-  }
+  external factory VttCue._internalWrap();
 
   @Deprecated("Internal Use Only")
   VttCue.internal_() : super.internal_();
@@ -38677,9 +38240,7 @@
     return new WebSocket._internalWrap();
   }
 
-  factory WebSocket._internalWrap() {
-    return new WebSocket.internal_();
-  }
+  external factory WebSocket._internalWrap();
 
   @Deprecated("Internal Use Only")
   WebSocket.internal_() : super.internal_();
@@ -38851,9 +38412,7 @@
     return new WheelEvent._internalWrap();
   }
 
-  factory WheelEvent._internalWrap() {
-    return new WheelEvent.internal_();
-  }
+  external factory WheelEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   WheelEvent.internal_() : super.internal_();
@@ -39193,9 +38752,7 @@
     return new Window._internalWrap();
   }
 
-  factory Window._internalWrap() {
-    return new Window.internal_();
-  }
+  external factory Window._internalWrap();
 
   @Deprecated("Internal Use Only")
   Window.internal_() : super.internal_();
@@ -40663,9 +40220,7 @@
     return new Worker._internalWrap();
   }
 
-  factory Worker._internalWrap() {
-    return new Worker.internal_();
-  }
+  external factory Worker._internalWrap();
 
   @Deprecated("Internal Use Only")
   Worker.internal_() : super.internal_();
@@ -40714,9 +40269,7 @@
     return new WorkerConsole._internalWrap();
   }
 
-  factory WorkerConsole._internalWrap() {
-    return new WorkerConsole.internal_();
-  }
+  external factory WorkerConsole._internalWrap();
 
   @Deprecated("Internal Use Only")
   WorkerConsole.internal_() : super.internal_();
@@ -40754,9 +40307,7 @@
     return new WorkerGlobalScope._internalWrap();
   }
 
-  factory WorkerGlobalScope._internalWrap() {
-    return new WorkerGlobalScope.internal_();
-  }
+  external factory WorkerGlobalScope._internalWrap();
 
   @Deprecated("Internal Use Only")
   WorkerGlobalScope.internal_() : super.internal_();
@@ -41194,9 +40745,7 @@
     return new XmlDocument._internalWrap();
   }
 
-  factory XmlDocument._internalWrap() {
-    return new XmlDocument.internal_();
-  }
+  external factory XmlDocument._internalWrap();
 
   @Deprecated("Internal Use Only")
   XmlDocument.internal_() : super.internal_();
@@ -41337,9 +40886,7 @@
     return new _Attr._internalWrap();
   }
 
-  factory _Attr._internalWrap() {
-    return new _Attr.internal_();
-  }
+  external factory _Attr._internalWrap();
 
   @Deprecated("Internal Use Only")
   _Attr.internal_() : super.internal_();
@@ -41404,9 +40951,7 @@
     return new _CSSPrimitiveValue._internalWrap();
   }
 
-  factory _CSSPrimitiveValue._internalWrap() {
-    return new _CSSPrimitiveValue.internal_();
-  }
+  external factory _CSSPrimitiveValue._internalWrap();
 
   @Deprecated("Internal Use Only")
   _CSSPrimitiveValue.internal_() : super.internal_();
@@ -41434,9 +40979,7 @@
     return new _CSSUnknownRule._internalWrap();
   }
 
-  factory _CSSUnknownRule._internalWrap() {
-    return new _CSSUnknownRule.internal_();
-  }
+  external factory _CSSUnknownRule._internalWrap();
 
   @Deprecated("Internal Use Only")
   _CSSUnknownRule.internal_() : super.internal_();
@@ -41912,9 +41455,7 @@
     return new _CssValueList._internalWrap();
   }
 
-  factory _CssValueList._internalWrap() {
-    return new _CssValueList.internal_();
-  }
+  external factory _CssValueList._internalWrap();
 
   @Deprecated("Internal Use Only")
   _CssValueList.internal_() : super.internal_();
@@ -42028,9 +41569,7 @@
     return new _DirectoryEntrySync._internalWrap();
   }
 
-  factory _DirectoryEntrySync._internalWrap() {
-    return new _DirectoryEntrySync.internal_();
-  }
+  external factory _DirectoryEntrySync._internalWrap();
 
   @Deprecated("Internal Use Only")
   _DirectoryEntrySync.internal_() : super.internal_();
@@ -42087,9 +41626,7 @@
     return new _DocumentType._internalWrap();
   }
 
-  factory _DocumentType._internalWrap() {
-    return new _DocumentType.internal_();
-  }
+  external factory _DocumentType._internalWrap();
 
   @Deprecated("Internal Use Only")
   _DocumentType.internal_() : super.internal_();
@@ -42138,9 +41675,7 @@
     return new _DomRect._internalWrap();
   }
 
-  factory _DomRect._internalWrap() {
-    return new _DomRect.internal_();
-  }
+  external factory _DomRect._internalWrap();
 
   @Deprecated("Internal Use Only")
   _DomRect.internal_() : super.internal_();
@@ -42239,9 +41774,7 @@
     return new _FileEntrySync._internalWrap();
   }
 
-  factory _FileEntrySync._internalWrap() {
-    return new _FileEntrySync.internal_();
-  }
+  external factory _FileEntrySync._internalWrap();
 
   @Deprecated("Internal Use Only")
   _FileEntrySync.internal_() : super.internal_();
@@ -42457,9 +41990,7 @@
     return new _HTMLAppletElement._internalWrap();
   }
 
-  factory _HTMLAppletElement._internalWrap() {
-    return new _HTMLAppletElement.internal_();
-  }
+  external factory _HTMLAppletElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _HTMLAppletElement.internal_() : super.internal_();
@@ -42493,9 +42024,7 @@
     return new _HTMLDirectoryElement._internalWrap();
   }
 
-  factory _HTMLDirectoryElement._internalWrap() {
-    return new _HTMLDirectoryElement.internal_();
-  }
+  external factory _HTMLDirectoryElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _HTMLDirectoryElement.internal_() : super.internal_();
@@ -42529,9 +42058,7 @@
     return new _HTMLFontElement._internalWrap();
   }
 
-  factory _HTMLFontElement._internalWrap() {
-    return new _HTMLFontElement.internal_();
-  }
+  external factory _HTMLFontElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _HTMLFontElement.internal_() : super.internal_();
@@ -42565,9 +42092,7 @@
     return new _HTMLFrameElement._internalWrap();
   }
 
-  factory _HTMLFrameElement._internalWrap() {
-    return new _HTMLFrameElement.internal_();
-  }
+  external factory _HTMLFrameElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _HTMLFrameElement.internal_() : super.internal_();
@@ -42599,9 +42124,7 @@
     return new _HTMLFrameSetElement._internalWrap();
   }
 
-  factory _HTMLFrameSetElement._internalWrap() {
-    return new _HTMLFrameSetElement.internal_();
-  }
+  external factory _HTMLFrameSetElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _HTMLFrameSetElement.internal_() : super.internal_();
@@ -42644,9 +42167,7 @@
     return new _HTMLMarqueeElement._internalWrap();
   }
 
-  factory _HTMLMarqueeElement._internalWrap() {
-    return new _HTMLMarqueeElement.internal_();
-  }
+  external factory _HTMLMarqueeElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _HTMLMarqueeElement.internal_() : super.internal_();
@@ -42686,9 +42207,7 @@
     return new _MutationEvent._internalWrap();
   }
 
-  factory _MutationEvent._internalWrap() {
-    return new _MutationEvent.internal_();
-  }
+  external factory _MutationEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   _MutationEvent.internal_() : super.internal_();
@@ -42885,9 +42404,7 @@
     return new _RadioNodeList._internalWrap();
   }
 
-  factory _RadioNodeList._internalWrap() {
-    return new _RadioNodeList.internal_();
-  }
+  external factory _RadioNodeList._internalWrap();
 
   @Deprecated("Internal Use Only")
   _RadioNodeList.internal_() : super.internal_();
@@ -42965,9 +42482,7 @@
     return new _Request._internalWrap();
   }
 
-  factory _Request._internalWrap() {
-    return new _Request.internal_();
-  }
+  external factory _Request._internalWrap();
 
   @Deprecated("Internal Use Only")
   _Request.internal_() : super.internal_();
@@ -43058,9 +42573,7 @@
     return new _Response._internalWrap();
   }
 
-  factory _Response._internalWrap() {
-    return new _Response.internal_();
-  }
+  external factory _Response._internalWrap();
 
   @Deprecated("Internal Use Only")
   _Response.internal_() : super.internal_();
@@ -43085,9 +42598,7 @@
     return new _ServiceWorker._internalWrap();
   }
 
-  factory _ServiceWorker._internalWrap() {
-    return new _ServiceWorker.internal_();
-  }
+  external factory _ServiceWorker._internalWrap();
 
   @Deprecated("Internal Use Only")
   _ServiceWorker.internal_() : super.internal_();
@@ -43320,9 +42831,7 @@
     return new _WebKitCSSFilterValue._internalWrap();
   }
 
-  factory _WebKitCSSFilterValue._internalWrap() {
-    return new _WebKitCSSFilterValue.internal_();
-  }
+  external factory _WebKitCSSFilterValue._internalWrap();
 
   @Deprecated("Internal Use Only")
   _WebKitCSSFilterValue.internal_() : super.internal_();
@@ -43390,9 +42899,7 @@
     return new _WebKitCSSTransformValue._internalWrap();
   }
 
-  factory _WebKitCSSTransformValue._internalWrap() {
-    return new _WebKitCSSTransformValue.internal_();
-  }
+  external factory _WebKitCSSTransformValue._internalWrap();
 
   @Deprecated("Internal Use Only")
   _WebKitCSSTransformValue.internal_() : super.internal_();
@@ -43534,9 +43041,7 @@
     return new _XMLHttpRequestProgressEvent._internalWrap();
   }
 
-  factory _XMLHttpRequestProgressEvent._internalWrap() {
-    return new _XMLHttpRequestProgressEvent.internal_();
-  }
+  external factory _XMLHttpRequestProgressEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   _XMLHttpRequestProgressEvent.internal_() : super.internal_();
@@ -47719,7 +47224,7 @@
         throw new UnsupportedError('$tag is not registered.');
       }
       jsObject = unwrap_jso(element);
-    } else if (element.runtimeType == js.JsObjectImpl) {
+    } else if (element.runtimeType == js.JsObject) {
       // It's a Polymer core element (written in JS).
       jsObject = element;
     } else if (isNativeElementExtension) {
@@ -47731,7 +47236,7 @@
     } else if (tag != null && element.localName != tag) {
       throw new UnsupportedError('Element is incorrect type. Got ${element.runtimeType}, expected native Html or Svg element to extend.');
     } else if (tag == null) {
-      throw new UnsupportedError('Element is incorrect type. Got ${element.runtimeType}, expected HtmlElement/JsObjectImpl.');
+      throw new UnsupportedError('Element is incorrect type. Got ${element.runtimeType}, expected HtmlElement/JsObject.');
     }
 
     // Remember Dart class to tagName for any upgrading done in wrap_jso.
diff --git a/sdk/lib/html/html_common/conversions_dartium.dart b/sdk/lib/html/html_common/conversions_dartium.dart
index 2403387..3e3e5c1 100644
--- a/sdk/lib/html/html_common/conversions_dartium.dart
+++ b/sdk/lib/html/html_common/conversions_dartium.dart
@@ -126,9 +126,14 @@
     }
 
     if (jsObject is js.JsArray) {
-      var wrappingList = new DartHtmlWrappingList(jsObject);
-      js.setDartHtmlWrapperFor(jsObject, wrappingList);
-      return wrappingList;
+      wrapper = new js.JSArray.create(jsObject);
+      js.setDartHtmlWrapperFor(jsObject, wrapper);
+      return wrapper;
+    }
+    if (jsObject is js.JsFunction) {
+      wrapper = new js.JSFunction.create(jsObject);
+      js.setDartHtmlWrapperFor(jsObject, wrapper);
+      return wrapper;
     }
 
     // Try the most general type conversions on it.
@@ -144,14 +149,15 @@
     if (constructor == null) {
       // Perfectly valid case for JavaScript objects where __proto__ has
       // intentionally been set to null.
-      js.setDartHtmlWrapperFor(jsObject, jsObject);
+      js.setDartHtmlWrapperFor(jsObject, new js.JSObject.create(jsObject));
       return jsObject;
     }
     var jsTypeName = js.JsNative.getProperty(constructor, 'name');
     if (jsTypeName is! String || jsTypeName.length == 0) {
       // Not an html type.
-      js.setDartHtmlWrapperFor(jsObject, jsObject);
-      return jsObject;
+      wrapper = new js.JSObject.create(jsObject);
+      js.setDartHtmlWrapperFor(jsObject, wrapper);
+      return wrapper;
     }
 
     var dartClass_instance;
@@ -204,12 +210,11 @@
 
     // TODO(jacobr): cache that this is not a dart:html JS class.
     return dartClass_instance;
-  } catch(e, stacktrace){
+  } catch (e, stacktrace) {
     if (interop_checks) {
-      if (e is DebugAssertException)
-        window.console.log("${e.message}\n ${stacktrace}");
-      else
-        window.console.log("${stacktrace}");
+      if (e is DebugAssertException) window.console
+          .log("${e.message}\n ${stacktrace}");
+      else window.console.log("${stacktrace}");
     }
   }
 
@@ -236,31 +241,30 @@
       return wrapper;
     }
 
-    // TODO(jacobr): auomatically wrapping JsArray here is fundamentally broken
-    // as it hijacks adding custom methods on JS Array classes as part of the
-    // new typed DartJsInterop.
-    // To make this work we really need to make DartHtmlWrappingList extend
-    // JsArrayImpl. Fixing this issue needs to be part of a broader refactor
-    // that allows calling custom typed JS interop methods on all dart:html
-    // classes.
     if (jsObject is js.JsArray) {
-      var wrappingList = new DartHtmlWrappingList(jsObject);
-      js.setDartHtmlWrapperFor(jsObject, wrappingList);
-      return wrappingList;
+      wrapper = new js.JSArray.create(jsObject);
+      js.setDartHtmlWrapperFor(jsObject, wrapper);
+      return wrapper;
+    }
+    if (jsObject is js.JsFunction) {
+      wrapper = new js.JSFunction.create(jsObject);
+      js.setDartHtmlWrapperFor(jsObject, wrapper);
+      return wrapper;
     }
 
     var constructor = js.JsNative.getProperty(jsObject, 'constructor');
     if (constructor == null) {
       // Perfectly valid case for JavaScript objects where __proto__ has
       // intentionally been set to null.
-      js.setDartHtmlWrapperFor(jsObject, jsObject);
+      js.setDartHtmlWrapperFor(jsObject, new js.JSObject.create(jsObject));
       return jsObject;
     }
     var jsTypeName = js.JsNative.getProperty(constructor, 'name');
     if (jsTypeName is! String || jsTypeName.length == 0) {
       // Not an html type.
-      js.setDartHtmlWrapperFor(jsObject, jsObject);
-      return jsObject;
+      wrapper = new js.JSObject.create(jsObject);
+      js.setDartHtmlWrapperFor(jsObject, wrapper);
+      return wrapper;
     }
 
     var func = getHtmlCreateFunction(jsTypeName);
@@ -270,13 +274,14 @@
       js.setDartHtmlWrapperFor(jsObject, dartClass_instance);
       return dartClass_instance;
     }
-    return jsObject;
-  } catch(e, stacktrace){
+    wrapper = new js.JSObject.create(jsObject);
+    js.setDartHtmlWrapperFor(jsObject, wrapper);
+    return wrapper;
+  } catch (e, stacktrace) {
     if (interop_checks) {
-      if (e is DebugAssertException)
-        window.console.log("${e.message}\n ${stacktrace}");
-      else
-        window.console.log("${stacktrace}");
+      if (e is DebugAssertException) window.console
+          .log("${e.message}\n ${stacktrace}");
+      else window.console.log("${stacktrace}");
     }
   }
 
@@ -333,7 +338,7 @@
   } else if (runtimeType == TemplateElement) {
     // Data binding with a Dart class.
     tag = element.attributes['is'];
-  } else if (runtimeType == js.JsObjectImpl) {
+  } else if (runtimeType == js.JsObject) {
     // It's a Polymer core element (written in JS).
     // Make sure it's an element anything else we can ignore.
     if (element.hasProperty('nodeType') && element['nodeType'] == 1) {
@@ -347,7 +352,8 @@
       }
     }
   } else {
-    throw new UnsupportedError('Element is incorrect type. Got ${runtimeType}, expected HtmlElement/HtmlTemplate/JsObjectImpl.');
+    throw new UnsupportedError(
+        'Element is incorrect type. Got ${runtimeType}, expected HtmlElement/HtmlTemplate/JsObject.');
   }
 
   var entry = _knownCustomElements[tag];
@@ -378,19 +384,3 @@
   }
   return null;
 }
-
-/**
- * Wraps a JsArray and will call wrap_jso on its entries.
- */
-class DartHtmlWrappingList extends ListBase implements NativeFieldWrapperClass2 {
-  DartHtmlWrappingList(this.blink_jsObject);
-
-  final js.JsArray blink_jsObject;
-
-  operator [](int index) => wrap_jso_no_SerializedScriptvalue(js.JsNative.getArrayIndex(blink_jsObject, index));
-
-  operator []=(int index, value) => blink_jsObject[index] = value;
-
-  int get length => blink_jsObject.length;
-  int set length(int newLength) => blink_jsObject.length = newLength;
-}
diff --git a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
index 4ab3e30..36b35e3 100644
--- a/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
+++ b/sdk/lib/indexed_db/dartium/indexed_db_dartium.dart
@@ -247,9 +247,7 @@
     return new CursorWithValue._internalWrap();
   }
 
-  factory CursorWithValue._internalWrap() {
-    return new CursorWithValue.internal_();
-  }
+  external factory CursorWithValue._internalWrap();
 
   @Deprecated("Internal Use Only")
   CursorWithValue.internal_() : super.internal_();
@@ -365,9 +363,7 @@
     return new Database._internalWrap();
   }
 
-  factory Database._internalWrap() {
-    return new Database.internal_();
-  }
+  external factory Database._internalWrap();
 
   @Deprecated("Internal Use Only")
   Database.internal_() : super.internal_();
@@ -1126,9 +1122,7 @@
     return new OpenDBRequest._internalWrap();
   }
 
-  factory OpenDBRequest._internalWrap() {
-    return new OpenDBRequest.internal_();
-  }
+  external factory OpenDBRequest._internalWrap();
 
   @Deprecated("Internal Use Only")
   OpenDBRequest.internal_() : super.internal_();
@@ -1185,9 +1179,7 @@
     return new Request._internalWrap();
   }
 
-  factory Request._internalWrap() {
-    return new Request.internal_();
-  }
+  external factory Request._internalWrap();
 
   @Deprecated("Internal Use Only")
   Request.internal_() : super.internal_();
@@ -1300,9 +1292,7 @@
     return new Transaction._internalWrap();
   }
 
-  factory Transaction._internalWrap() {
-    return new Transaction.internal_();
-  }
+  external factory Transaction._internalWrap();
 
   @Deprecated("Internal Use Only")
   Transaction.internal_() : super.internal_();
@@ -1364,9 +1354,7 @@
     return new VersionChangeEvent._internalWrap();
   }
 
-  factory VersionChangeEvent._internalWrap() {
-    return new VersionChangeEvent.internal_();
-  }
+  external factory VersionChangeEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   VersionChangeEvent.internal_() : super.internal_();
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index 326597f..d881ce5 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -181,20 +181,20 @@
   static List<String> get executableArguments => _Platform.executableArguments;
 
   /**
-   * Returns the value of the --package-root flag passed to the executable
+   * Returns the value of the `--package-root` flag passed to the executable
    * used to run the script in this isolate.  This is the directory in which
    * Dart packages are looked up.
    *
-   * If there is no --package-root flag, then null is returned.
+   * If there is no `--package-root` flag, `null` is returned.
    */
   static String get packageRoot => _Platform.packageRoot;
 
 /**
- * Returns the value of the --packages flag passed to the executable
- * used to run the script in this isolate.  This is the configuration which
+ * Returns the value of the `--packages` flag passed to the executable
+ * used to run the script in this isolate. This is the configuration which
  * specifies how Dart packages are looked up.
  *
- * If there is no --packages flag, then the null is returned.
+ * If there is no `--packages` flag, `null` is returned.
  */
   static String get packageConfig => _Platform.packageConfig;
 
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index ce2c5a2..d2b1f39 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -101,6 +101,26 @@
 @Deprecated("Internal Use Only")
 final bool CHECK_JS_INVOCATIONS = true;
 
+final String _DART_RESERVED_NAME_PREFIX = r'JS$';
+
+String _stripReservedNamePrefix(String name) =>
+    name.startsWith(_DART_RESERVED_NAME_PREFIX)
+        ? name.substring(_DART_RESERVED_NAME_PREFIX.length)
+        : name;
+
+_buildArgs(Invocation invocation) {
+  if (invocation.namedArguments.isEmpty) {
+    return invocation.positionalArguments;
+  } else {
+    var varArgs = new Map<String, Object>();
+    invocation.namedArguments.forEach((symbol, val) {
+      varArgs[mirrors.MirrorSystem.getName(symbol)] = val;
+    });
+    return invocation.positionalArguments.toList()
+      ..add(maybeWrapTypedInterop(new JsObject.jsify(varArgs)));
+  }
+}
+
 final _allowedMethods = new Map<Symbol, _DeclarationSet>();
 final _allowedGetters = new Map<Symbol, _DeclarationSet>();
 final _allowedSetters = new Map<Symbol, _DeclarationSet>();
@@ -292,6 +312,20 @@
 
 bool _hasJsName(mirrors.DeclarationMirror mirror) => _getJsName(mirror) != null;
 
+bool hasDomName(mirrors.DeclarationMirror mirror) {
+  var location = mirror.location;
+  if (location == null || location.sourceUri.scheme != 'dart') return false;
+  for (var annotation in mirror.metadata) {
+    if (mirrors.MirrorSystem.getName(annotation.type.simpleName) == "DomName") {
+      // We can't make sure the annotation is in dart: as Dartium believes it
+      // is file://dart/sdk/lib/html/html_common/metadata.dart
+      // instead of a proper dart: location.
+      return true;
+    }
+  }
+  return false;
+}
+
 _getJsMemberName(mirrors.DeclarationMirror mirror) {
   var name = _getJsName(mirror);
   return name == null || name.isEmpty ? _getDeclarationName(mirror) : name;
@@ -304,7 +338,7 @@
     assert(name.endsWith("="));
     name = name.substring(0, name.length - 1);
   }
-  return name;
+  return _stripReservedNamePrefix(name);
 }
 
 final _JS_LIBRARY_PREFIX = "js_library";
@@ -347,16 +381,20 @@
   }
   sb.write(" ");
   if (declaration.isGetter) {
-    sb.write("get $name => ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(${_accessJsPath(path)});");
+    sb.write(
+        "get $name => ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(${_accessJsPath(path)});");
   } else if (declaration.isSetter) {
-    sb.write("set $name(v) => ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(${_accessJsPathSetter(path)});");
+    sb.write("set $name(v) {\n"
+        "  ${_JS_LIBRARY_PREFIX}.safeForTypedInterop(v);\n"
+        "  return ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(${_accessJsPathSetter(path)});\n"
+        "}\n");
   } else {
     sb.write("$name(");
     bool hasOptional = false;
     int i = 0;
     var args = <String>[];
     for (var p in declaration.parameters) {
-      assert(!p.isNamed); // XXX throw
+      assert(!p.isNamed); // TODO(jacobr): throw.
       assert(!p.hasDefaultValue);
       if (i > 0) {
         sb.write(", ");
@@ -377,8 +415,11 @@
       sb.write("]");
     }
     // TODO(jacobr):
-    sb.write(") => ");
-    sb.write('${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(');
+    sb.write(") {\n");
+    for (var arg in args) {
+      sb.write("  ${_JS_LIBRARY_PREFIX}.safeForTypedInterop($arg);\n");
+    }
+    sb.write("  return ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(");
     if (declaration.isConstructor) {
       sb.write("new ${_JS_LIBRARY_PREFIX}.JsObject(");
     }
@@ -391,6 +432,7 @@
       sb.write(".takeWhile((i) => i != ${_UNDEFINED_VAR}).toList()");
     }
     sb.write("));");
+    sb.write("}\n");
   }
   sb.write("\n");
 }
@@ -399,7 +441,7 @@
   // This try-catch block is a workaround for BUG:24834.
   try {
     return mirror.isExternal;
-  } catch (e) { }
+  } catch (e) {}
   return false;
 }
 
@@ -416,195 +458,106 @@
         }
       } else if (declaration is mirrors.ClassMirror) {
         mirrors.ClassMirror clazz = declaration;
-        if (_hasJsName(clazz)) {
+        var isDom = hasDomName(clazz);
+        var isJsInterop = _hasJsName(clazz);
+        if (isDom || isJsInterop) {
           // TODO(jacobr): verify class implements JavaScriptObject.
-          String jsClassName = _getJsMemberName(clazz);
           var className = mirrors.MirrorSystem.getName(clazz.simpleName);
+          var classNameImpl = '${className}Impl';
           var sbPatch = new StringBuffer();
-          jsInterfaceTypes.add(clazz);
-          clazz.declarations.forEach((name, declaration) {
-            if (declaration is! mirrors.MethodMirror ||
-                !_isExternal(declaration)) return;
-            if (declaration.isFactoryConstructor && _isAnonymousClass(clazz)) {
-              sbPatch.write("  factory ${className}(");
-              int i = 0;
-              var args = <String>[];
-              for (var p in declaration.parameters) {
-                args.add(mirrors.MirrorSystem.getName(p.simpleName));
-                i++;
-              }
-              if (args.isNotEmpty) {
-                sbPatch
-                  ..write('{')
-                  ..write(
-                      args.map((name) => '$name:${_UNDEFINED_VAR}').join(", "))
-                  ..write('}');
-              }
-              sbPatch.write(") {\n"
+          if (isJsInterop) {
+            String jsClassName = _getJsMemberName(clazz);
+
+            jsInterfaceTypes.add(clazz);
+            clazz.declarations.forEach((name, declaration) {
+              if (declaration is! mirrors.MethodMirror ||
+                  !_isExternal(declaration)) return;
+              if (declaration.isFactoryConstructor &&
+                  _isAnonymousClass(clazz)) {
+                sbPatch.write("  factory ${className}(");
+                int i = 0;
+                var args = <String>[];
+                for (var p in declaration.parameters) {
+                  args.add(mirrors.MirrorSystem.getName(p.simpleName));
+                  i++;
+                }
+                if (args.isNotEmpty) {
+                  sbPatch
+                    ..write('{')
+                    ..write(args
+                        .map((name) => '$name:${_UNDEFINED_VAR}')
+                        .join(", "))
+                    ..write('}');
+                }
+                sbPatch.write(") {\n"
                     "    var ret = new ${_JS_LIBRARY_PREFIX}.JsObject.jsify({});\n");
-              i = 0;
-              for (var p in declaration.parameters) {
-                assert(p.isNamed); // XXX throw
-                var name = args[i];
-                var jsName = mirrors.MirrorSystem.getName(p.simpleName);
-                // XXX apply name conversion rules.
+                i = 0;
+                for (var p in declaration.parameters) {
+                  assert(p.isNamed); // TODO(jacobr): throw.
+                  var name = args[i];
+                  var jsName = _stripReservedNamePrefix(
+                      mirrors.MirrorSystem.getName(p.simpleName));
+                  sbPatch.write("    if($name != ${_UNDEFINED_VAR}) {\n"
+                      "      ${_JS_LIBRARY_PREFIX}.safeForTypedInterop($name);\n"
+                      "      ret['$jsName'] = $name;\n"
+                      "    }\n");
+                  i++;
+                }
+
                 sbPatch.write(
-                    "    if($name != ${_UNDEFINED_VAR}) ret['$jsName'] = $name;\n");
-                i++;
+                    "    return new ${_JS_LIBRARY_PREFIX}.JSObject.create(ret);\n"
+                    "  }\n");
+              } else if (declaration.isConstructor ||
+                  declaration.isFactoryConstructor) {
+                sbPatch.write("  ");
+                addMemberHelper(
+                    declaration,
+                    (jsLibraryName != null && jsLibraryName.isNotEmpty)
+                        ? "${jsLibraryName}.${jsClassName}"
+                        : jsClassName,
+                    sbPatch,
+                    isStatic: true,
+                    memberName: className);
               }
+            });
 
-              sbPatch.write("    return ret;\n"
-                  "  }\n");
-            } else if (declaration.isConstructor ||
-                declaration.isFactoryConstructor) {
-              sbPatch.write("  ");
-              addMemberHelper(
-                  declaration,
-                  (jsLibraryName != null && jsLibraryName.isNotEmpty)
-                      ? "${jsLibraryName}.${jsClassName}"
-                      : jsClassName,
-                  sbPatch,
-                  isStatic: true,
-                  memberName: className);
-            }
-          });
-
-          clazz.staticMembers.forEach((memberName, member) {
-            if (_isExternal(member)) {
-              sbPatch.write("  ");
-              addMemberHelper(
-                  member,
-                  (jsLibraryName != null && jsLibraryName.isNotEmpty)
-                      ? "${jsLibraryName}.${jsClassName}"
-                      : jsClassName,
-                  sbPatch,
-                  isStatic: true);
-            }
-          });
-          var typeVariablesClause = '';
-          if (!clazz.typeVariables.isEmpty) {
-            typeVariablesClause =
-                '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName(m.simpleName)).join(',')}>';
+            clazz.staticMembers.forEach((memberName, member) {
+              if (_isExternal(member)) {
+                sbPatch.write("  ");
+                addMemberHelper(
+                    member,
+                    (jsLibraryName != null && jsLibraryName.isNotEmpty)
+                        ? "${jsLibraryName}.${jsClassName}"
+                        : jsClassName,
+                    sbPatch,
+                    isStatic: true);
+              }
+            });
+          }
+          if (isDom) {
+            sbPatch.write("  factory ${className}._internalWrap() => "
+                "new ${classNameImpl}.internal_();\n");
           }
           if (sbPatch.isNotEmpty) {
+            var typeVariablesClause = '';
+            if (!clazz.typeVariables.isEmpty) {
+              typeVariablesClause =
+                  '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName(m.simpleName)).join(',')}>';
+            }
             sb.write("""
 patch class $className$typeVariablesClause {
 $sbPatch
 }
 """);
-          }
-        }
-      }
-    });
-    if (sb.isNotEmpty) {
-      staticCodegen
-        ..add(uri.toString())
-        ..add("${uri}_js_interop_patch.dart")
-        ..add("""
-import 'dart:js' as ${_JS_LIBRARY_PREFIX};
-
-/**
- * Placeholder object for cases where we need to determine exactly how many
- * args were passed to a function.
- */
-const ${_UNDEFINED_VAR} = const Object();
-
-${sb}
-""");
-    }
-  });
-
-  return staticCodegen;
-}
-
-List<String> _generateExternalMethods2() {
-  var staticCodegen = <String>[];
-  mirrors.currentMirrorSystem().libraries.forEach((uri, library) {
-    var sb = new StringBuffer();
-    String jsLibraryName = _getJsName(library);
-    library.declarations.forEach((name, declaration) {
-      var isExternal = _isExternal(declaration);
-      if (declaration is mirrors.MethodMirror) {
-        if (isExternal && (_hasJsName(declaration) || jsLibraryName != null)) {
-          addMemberHelper(declaration, jsLibraryName, sb);
-        }
-      } else if (declaration is mirrors.ClassMirror) {
-        mirrors.ClassMirror clazz = declaration;
-        if (_hasJsName(clazz)) {
-          // TODO(jacobr): verify class implements JavaScriptObject.
-          String jsClassName = _getJsMemberName(clazz);
-          var className = mirrors.MirrorSystem.getName(clazz.simpleName);
-          var sbPatch = new StringBuffer();
-          jsInterfaceTypes.add(clazz);
-          clazz.declarations.forEach((name, declaration) {
-            if (declaration is! mirrors.MethodMirror ||
-                !declaration.isAbstract ||
-                !isExternal) return;
-            if (_hasLiteralAnnotation(declaration) &&
-                declaration.isFactoryConstructor) {
-              sbPatch.write("  factory ${className}({");
-              int i = 0;
-              var args = <String>[];
-              for (var p in declaration.parameters) {
-                assert(p.isNamed); // XXX throw
-                args.add(mirrors.MirrorSystem.getName(p.simpleName));
-                i++;
-              }
-              sbPatch
-                ..write(
-                    args.map((name) => '$name:${_UNDEFINED_VAR}').join(", "))
-                ..write("}) {\n"
-                    "    var ret = new ${_JS_LIBRARY_PREFIX}.JsObject.jsify({});\n");
-              i = 0;
-              for (var p in declaration.parameters) {
-                assert(p.isNamed); // XXX throw
-                var name = args[i];
-                var jsName = mirrors.MirrorSystem.getName(p.simpleName);
-                // XXX apply name conversion rules.
-                sbPatch.write(
-                    "    if($name != ${_UNDEFINED_VAR}) ret['$jsName'] = $name;\n");
-                i++;
-              }
-
-              sbPatch.write("    return ret;\n"
-                  "  }\n");
-            } else if (declaration.isConstructor ||
-                declaration.isFactoryConstructor) {
-              sbPatch.write("  ");
-              addMemberHelper(
-                  declaration,
-                  (jsLibraryName != null && jsLibraryName.isNotEmpty)
-                      ? "${jsLibraryName}.${jsClassName}"
-                      : jsClassName,
-                  sbPatch,
-                  isStatic: true,
-                  memberName: className);
-            }
-          });
-
-          clazz.staticMembers.forEach((memberName, member) {
-            if (_isExternal(member)) {
-              sbPatch.write("  ");
-              addMemberHelper(
-                  member,
-                  (jsLibraryName != null && jsLibraryName.isNotEmpty)
-                      ? "${jsLibraryName}.${jsClassName}"
-                      : jsClassName,
-                  sbPatch,
-                  isStatic: true);
-            }
-          });
-          var typeVariablesClause = '';
-          if (!clazz.typeVariables.isEmpty) {
-            typeVariablesClause =
-                '<${clazz.typeVariables.map((m) => mirrors.MirrorSystem.getName(m.simpleName)).join(',')}>';
-          }
-          if (sbPatch.isNotEmpty) {
-            sb.write("""
-patch class $className$typeVariablesClause {
-$sbPatch
+            if (isDom) {
+              sb.write("""
+class $classNameImpl$typeVariablesClause extends $className implements ${_JS_LIBRARY_PREFIX}.JSObjectInterfacesDom {
+  ${classNameImpl}.internal_() : super.internal_();
+  get runtimeType => $className;
+  toString() => super.toString();
 }
 """);
+            }
           }
         }
       }
@@ -631,9 +584,9 @@
 }
 
 /**
- * Generates a part file defining source code for JsObjectImpl and related
- * classes. This calass is needed so that type checks for all registered JavaScript
- * interop classes pass.
+ * Generates part files defining source code for JSObjectImpl, all DOM classes
+ * classes. This codegen  is needed so that type checks for all registered
+ * JavaScript interop classes pass.
  */
 List<String> _generateInteropPatchFiles() {
   var ret = _generateExternalMethods();
@@ -643,7 +596,10 @@
 
   var implements = <String>[];
   var implementsArray = <String>[];
+  var implementsDom = <String>[];
   var listMirror = mirrors.reflectType(List);
+  var functionMirror = mirrors.reflectType(Function);
+  var jsObjectMirror = mirrors.reflectType(JSObject);
 
   for (var typeMirror in jsInterfaceTypes) {
     mirrors.LibraryMirror libraryMirror = typeMirror.owner;
@@ -665,8 +621,25 @@
       libraryPrefixes[libraryMirror] = prefixName;
     }
     var isArray = typeMirror.isSubtypeOf(listMirror);
-    (isArray ? implementsArray : implements).add(
-        '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}');
+    var isFunction = typeMirror.isSubtypeOf(functionMirror);
+    var isJSObject = typeMirror.isSubtypeOf(jsObjectMirror);
+    var fullName =
+        '${prefixName}.${mirrors.MirrorSystem.getName(typeMirror.simpleName)}';
+    (isArray ? implementsArray : implements).add(fullName);
+    if (!isArray && !isFunction && !isJSObject) {
+      // For DOM classes we need to be a bit more conservative at tagging them
+      // as implementing JS inteorp classes risks strange unintended
+      // consequences as unrleated code may have instanceof checks.  Checking
+      // for isJSObject ensures we do not accidentally pull in existing
+      // dart:html classes as they all have JSObject as a base class.
+      // Note that methods from these classes can still be called on a
+      // dart:html instance but checked mode type checks will fail. This is
+      // not ideal but is better than causing strange breaks in existing
+      // code that uses dart:html.
+      // TODO(jacobr): consider throwing compile time errors if @JS classes
+      // extend JSObject as that case cannot be safely handled in Dartium.
+      implementsDom.add(fullName);
+    }
   }
   libraryPrefixes.forEach((libraryMirror, prefix) {
     sb.writeln('import "${libraryMirror.uri}" as $prefix;');
@@ -674,20 +647,51 @@
   buildImplementsClause(classes) =>
       classes.isEmpty ? "" : "implements ${classes.join(', ')}";
   var implementsClause = buildImplementsClause(implements);
+  var implementsClauseDom = buildImplementsClause(implementsDom);
   // TODO(jacobr): only certain classes need to be implemented by
   // JsFunctionImpl.
   var allTypes = []..addAll(implements)..addAll(implementsArray);
   sb.write('''
-class JsObjectImpl extends JsObject $implementsClause {
-  JsObjectImpl.internal() : super.internal();
+class JSObjectImpl extends JSObject $implementsClause {
+  JSObjectImpl.internal() : super.internal();
 }
 
-class JsFunctionImpl extends JsFunction $implementsClause {
-  JsFunctionImpl.internal() : super.internal();
+class JSFunctionImpl extends JSFunction $implementsClause {
+  JSFunctionImpl.internal() : super.internal();
 }
 
-class JsArrayImpl<E> extends JsArray<E> ${buildImplementsClause(implementsArray)} {
-  JsArrayImpl.internal() : super.internal();
+class JSArrayImpl extends JSArray ${buildImplementsClause(implementsArray)} {
+  JSArrayImpl.internal() : super.internal();
+}
+
+// Interfaces that are safe to slam on all DOM classes.
+// Adding implementsClause would be risky as it could contain Function which
+// is likely to break a lot of instanceof checks.
+abstract class JSObjectInterfacesDom $implementsClauseDom {
+}
+
+patch class JSObject {
+  factory JSObject.create(JsObject jsObject) {
+    var ret = new JSObjectImpl.internal()..blink_jsObject = jsObject;
+    jsObject._dartHtmlWrapper = ret;
+    return ret;
+  }
+}
+
+patch class JSFunction {
+  factory JSFunction.create(JsObject jsObject) {
+    var ret = new JSFunctionImpl.internal()..blink_jsObject = jsObject;
+    jsObject._dartHtmlWrapper = ret;
+    return ret;
+  }
+}
+
+patch class JSArray {
+  factory JSArray.create(JsObject jsObject) {
+    var ret = new JSArrayImpl.internal()..blink_jsObject = jsObject;
+    jsObject._dartHtmlWrapper = ret;
+    return ret;
+  }
 }
 
 _registerAllJsInterfaces() {
@@ -695,7 +699,7 @@
 }
 
 ''');
-  ret..addAll(["dart:js", "JsInteropImpl.dart", sb.toString()]);
+  ret..addAll(["dart:js", "JSInteropImpl.dart", sb.toString()]);
   return ret;
 }
 
@@ -870,8 +874,7 @@
 }
 
 @Deprecated("Internal Use Only")
-maybeWrapTypedInterop(o) =>
-    html_common.wrap_jso_no_SerializedScriptvalue(o);
+maybeWrapTypedInterop(o) => html_common.wrap_jso_no_SerializedScriptvalue(o);
 
 _maybeWrap(o) {
   var wrapped = html_common.wrap_jso_no_SerializedScriptvalue(o);
@@ -910,7 +913,7 @@
  */
 @Deprecated("Internal Use Only")
 unwrap_jso(dartClass_instance) {
-  if (dartClass_instance is html.DartHtmlDomObject &&
+  if (dartClass_instance is JSObject &&
       dartClass_instance is! JsObject) return dartClass_instance.blink_jsObject;
   else return dartClass_instance;
 }
@@ -946,19 +949,6 @@
   static JsObject _create(JsFunction constructor, arguments)
       native "JsObject_constructorCallback";
 
-  _buildArgs(Invocation invocation) {
-    if (invocation.namedArguments.isEmpty) {
-      return invocation.positionalArguments;
-    } else {
-      var varArgs = new Map<String, Object>();
-      invocation.namedArguments.forEach((symbol, val) {
-        varArgs[mirrors.MirrorSystem.getName(symbol)] = val;
-      });
-      return invocation.positionalArguments.toList()
-        ..add(new JsObject.jsify(varArgs));
-    }
-  }
-
   /**
    * Constructs a [JsObject] that proxies a native Dart object; _for expert use
    * only_.
@@ -1099,13 +1089,28 @@
     }
   }
 
+  _callMethod(String name, List args) native "JsObject_callMethod";
+}
+
+/// Base class for all JS objects used through dart:html and typed JS interop.
+@Deprecated("Internal Use Only")
+class JSObject {
+  JSObject.internal() {}
+  external factory JSObject.create(JsObject jsObject);
+
+  @Deprecated("Internal Use Only")
+  JsObject blink_jsObject;
+
+  String toString() => blink_jsObject.toString();
+
   noSuchMethod(Invocation invocation) {
     throwError() {
-      throw new NoSuchMethodError(this, invocation.memberName,
-          invocation.positionalArguments, invocation.namedArguments);
+      super.noSuchMethod(invocation);
     }
 
-    String name = mirrors.MirrorSystem.getName(invocation.memberName);
+    String name = _stripReservedNamePrefix(
+        mirrors.MirrorSystem.getName(invocation.memberName));
+    argsSafeForTypedInterop(invocation.positionalArguments);
     if (invocation.isGetter) {
       if (CHECK_JS_INVOCATIONS) {
         var matches = _allowedGetters[invocation.memberName];
@@ -1113,8 +1118,8 @@
             !_allowedMethods.containsKey(invocation.memberName)) {
           throwError();
         }
-        var ret = this[name];
-        if (matches != null && matches._checkReturnType(ret)) return ret;
+        var ret = maybeWrapTypedInterop(blink_jsObject._operator_getter(name));
+        if (matches != null) return ret;
         if (ret is Function ||
             (ret is JsFunction /* shouldn't be needed in the future*/) &&
                 _allowedMethods.containsKey(
@@ -1122,7 +1127,7 @@
         throwError();
       } else {
         // TODO(jacobr): should we throw if the JavaScript object doesn't have the property?
-        return maybeWrapTypedInterop(this._operator_getter(name));
+        return maybeWrapTypedInterop(blink_jsObject._operator_getter(name));
       }
     } else if (invocation.isSetter) {
       if (CHECK_JS_INVOCATIONS) {
@@ -1132,7 +1137,7 @@
       }
       assert(name.endsWith("="));
       name = name.substring(0, name.length - 1);
-      return maybeWrapTypedInterop(_operator_setter(
+      return maybeWrapTypedInterop(blink_jsObject._operator_setter(
           name, invocation.positionalArguments.first));
     } else {
       // TODO(jacobr): also allow calling getters that look like functions.
@@ -1142,15 +1147,61 @@
         if (matches == null ||
             !matches.checkInvocation(invocation)) throwError();
       }
-      var ret = maybeWrapTypedInterop(this._callMethod(name, _buildArgs(invocation)));
+      var ret = maybeWrapTypedInterop(
+          blink_jsObject._callMethod(name, _buildArgs(invocation)));
       if (CHECK_JS_INVOCATIONS) {
-        if (!matches._checkReturnType(ret)) throwError();
+        if (!matches._checkReturnType(ret)) {
+          html.window.console.error("Return value for method: ${name} is "
+              "${ret.runtimeType} which is inconsistent with all typed "
+              "JS interop definitions for method ${name}.");
+        }
       }
       return ret;
     }
   }
+}
 
-  _callMethod(String name, List args) native "JsObject_callMethod";
+@Deprecated("Internal Use Only")
+class JSArray extends JSObject with ListMixin {
+  JSArray.internal() : super.internal();
+  external factory JSArray.create(JsObject jsObject);
+  operator [](int index) =>
+      maybeWrapTypedInterop(JsNative.getArrayIndex(blink_jsObject, index));
+
+  operator []=(int index, value) => blink_jsObject[index] = value;
+
+  int get length => blink_jsObject.length;
+  int set length(int newLength) => blink_jsObject.length = newLength;
+}
+
+@Deprecated("Internal Use Only")
+class JSFunction extends JSObject implements Function {
+  JSFunction.internal() : super.internal();
+
+  external factory JSFunction.create(JsObject jsObject);
+
+  call(
+      [a1 = _UNDEFINED,
+      a2 = _UNDEFINED,
+      a3 = _UNDEFINED,
+      a4 = _UNDEFINED,
+      a5 = _UNDEFINED,
+      a6 = _UNDEFINED,
+      a7 = _UNDEFINED,
+      a8 = _UNDEFINED,
+      a9 = _UNDEFINED,
+      a10 = _UNDEFINED]) {
+    return maybeWrapTypedInterop(blink_jsObject
+        .apply(_stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10])));
+  }
+
+  noSuchMethod(Invocation invocation) {
+    if (invocation.isMethod && invocation.memberName == #call) {
+      return maybeWrapTypedInterop(
+          blink_jsObject.apply(_buildArgs(invocation)));
+    }
+    return super.noSuchMethod(invocation);
+  }
 }
 
 // JavaScript interop methods that do not automatically wrap to dart:html types.
@@ -1185,7 +1236,7 @@
 /**
  * Proxies a JavaScript Function object.
  */
-class JsFunction extends JsObject implements Function {
+class JsFunction extends JsObject {
   JsFunction.internal() : super.internal();
 
   /**
@@ -1203,27 +1254,6 @@
 
   dynamic _apply(List args, {thisArg}) native "JsFunction_apply";
 
-  call([a1 = _UNDEFINED,
-        a2 = _UNDEFINED,
-        a3 = _UNDEFINED,
-        a4 = _UNDEFINED,
-        a5 = _UNDEFINED,
-        a6 = _UNDEFINED,
-        a7 = _UNDEFINED,
-        a8 = _UNDEFINED,
-        a9 = _UNDEFINED,
-        a10 = _UNDEFINED]) {
-    return apply(
-        _stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
-  }
-
-  noSuchMethod(Invocation invocation) {
-    if (invocation.isMethod && invocation.memberName == #call) {
-      return apply(_buildArgs(invocation));
-    }
-    return super.noSuchMethod(invocation);
-  }
-
   /**
    * Internal only version of apply which uses debugger proxies of Dart objects
    * rather than opaque handles. This method is private because it cannot be
@@ -1349,6 +1379,39 @@
     args.takeWhile((i) => i != _UNDEFINED).toList();
 
 /**
+ * Check that that if [arg] is a [Function] it is safe to pass to JavaScript.
+ * To make a function safe, call [allowInterop] or [allowInteropCaptureThis].
+ */
+@Deprecated("Internal Use Only")
+safeForTypedInterop(arg) {
+  if (CHECK_JS_INVOCATIONS && arg is Function && arg is! JSFunction) {
+    throw new ArgumentError(
+        "Attempt to pass Function '$arg' to JavaScript via without calling allowInterop or allowInteropCaptureThis");
+  }
+}
+
+/**
+ * Check that that if any elements of [args] are [Function] it is safe to pass
+ * to JavaScript. To make a function safe, call [allowInterop] or
+ * [allowInteropCaptureThis].
+ */
+@Deprecated("Internal Use Only")
+void argsSafeForTypedInterop(Iterable args) {
+  for (var arg in args) {
+    safeForTypedInterop(arg);
+  }
+}
+
+List _stripAndWrapArgs(Iterable args) {
+  var ret = [];
+  for (var arg in args) {
+    if (arg == _UNDEFINED) break;
+    ret.add(maybeWrapTypedInterop(arg));
+  }
+  return ret;
+}
+
+/**
  * Returns a method that can be called with an arbitrary number (for n less
  * than 11) of arguments without violating Dart type checks.
  */
@@ -1366,9 +1429,89 @@
     jsFunction._applyDebuggerOnly(
         _stripUndefinedArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
 
-// The allowInterop method is a no-op in Dartium.
-// TODO(jacobr): tag methods so we can throw if a Dart method is passed to
-// JavaScript using the new interop without calling allowInterop.
+/// This helper is purely a hack so we can reuse JsFunction.withThis even when
+/// we don't care about passing JS "this". In an ideal world we would implement
+/// helpers in C++ that directly implement allowInterop and
+/// allowInteropCaptureThis.
+class _CreateDartFunctionForInteropIgnoreThis implements Function {
+  Function _fn;
+
+  _CreateDartFunctionForInteropIgnoreThis(this._fn);
+
+  call(
+      [ignoredThis = _UNDEFINED,
+      a1 = _UNDEFINED,
+      a2 = _UNDEFINED,
+      a3 = _UNDEFINED,
+      a4 = _UNDEFINED,
+      a5 = _UNDEFINED,
+      a6 = _UNDEFINED,
+      a7 = _UNDEFINED,
+      a8 = _UNDEFINED,
+      a9 = _UNDEFINED,
+      a10 = _UNDEFINED]) {
+    var ret = Function.apply(
+        _fn, _stripAndWrapArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
+    safeForTypedInterop(ret);
+    return ret;
+  }
+
+  noSuchMethod(Invocation invocation) {
+    if (invocation.isMethod && invocation.memberName == #call) {
+      // Named arguments not yet supported.
+      if (invocation.namedArguments.isNotEmpty) return;
+      var ret = Function.apply(
+          _fn, _stripAndWrapArgs(invocation.positionalArguments.skip(1)));
+      // TODO(jacobr): it would be nice to check that the return value is safe
+      // for interop but we don't want to break existing addEventListener users.
+      // safeForTypedInterop(ret);
+      safeForTypedInterop(ret);
+      return ret;
+    }
+    return super.noSuchMethod(invocation);
+  }
+}
+
+/// See comment for [_CreateDartFunctionForInteropIgnoreThis].
+/// This Function exists purely because JsObject doesn't have the DOM type
+/// conversion semantics we want for JS typed interop.
+class _CreateDartFunctionForInterop implements Function {
+  Function _fn;
+
+  _CreateDartFunctionForInterop(this._fn);
+
+  call(
+      [a1 = _UNDEFINED,
+      a2 = _UNDEFINED,
+      a3 = _UNDEFINED,
+      a4 = _UNDEFINED,
+      a5 = _UNDEFINED,
+      a6 = _UNDEFINED,
+      a7 = _UNDEFINED,
+      a8 = _UNDEFINED,
+      a9 = _UNDEFINED,
+      a10 = _UNDEFINED]) {
+    var ret = Function.apply(
+        _fn, _stripAndWrapArgs([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]));
+    safeForTypedInterop(ret);
+    return ret;
+  }
+
+  noSuchMethod(Invocation invocation) {
+    if (invocation.isMethod && invocation.memberName == #call) {
+      // Named arguments not yet supported.
+      if (invocation.namedArguments.isNotEmpty) return;
+      var ret = Function.apply(
+          _fn, _stripAndWrapArgs(invocation.positionalArguments));
+      safeForTypedInterop(ret);
+      return ret;
+    }
+    return super.noSuchMethod(invocation);
+  }
+}
+
+/// Cached JSFunction associated with the Dart Function.
+Expando<JSFunction> _interopExpando = new Expando<JSFunction>();
 
 /// Returns a wrapper around function [f] that can be called from JavaScript
 /// using the package:js Dart-JavaScript interop.
@@ -1381,9 +1524,25 @@
 /// JavaScript. We may remove the need to call this method completely in the
 /// future if Dart2Js is refactored so that its function calling conventions
 /// are more compatible with JavaScript.
-Function allowInterop(Function f) => f;
+JSFunction allowInterop(Function f) {
+  if (f is JSFunction) {
+    // The function is already a JSFunction... no need to do anything.
+    return f;
+  } else {
+    var ret = _interopExpando[f];
+    if (ret == null) {
+      // TODO(jacobr): we could optimize this.
+      ret = new JSFunction.create(new JsFunction.withThis(
+          new _CreateDartFunctionForInteropIgnoreThis(f)));
+      _interopExpando[f] = ret;
+    }
+    return ret;
+  }
+}
 
-Expando<JsFunction> _interopCaptureThisExpando = new Expando<JsFunction>();
+/// Cached JSFunction associated with the Dart function when "this" is
+/// captured.
+Expando<JSFunction> _interopCaptureThisExpando = new Expando<JSFunction>();
 
 /// Returns a [Function] that when called from JavaScript captures its 'this'
 /// binding and calls [f] with the value of this passed as the first argument.
@@ -1391,8 +1550,8 @@
 ///
 /// See the documention for [allowInterop]. This method should only be used with
 /// package:js Dart-JavaScript interop.
-Function allowInteropCaptureThis(Function f) {
-  if (f is JsFunction) {
+JSFunction allowInteropCaptureThis(Function f) {
+  if (f is JSFunction) {
     // Behavior when the function is already a JS function is unspecified.
     throw new ArgumentError(
         "Function is already a JS function so cannot capture this.");
@@ -1400,7 +1559,9 @@
   } else {
     var ret = _interopCaptureThisExpando[f];
     if (ret == null) {
-      ret = new JsFunction.withThis(f);
+      // TODO(jacobr): we could optimize this.
+      ret = new JSFunction.create(
+          new JsFunction.withThis(new _CreateDartFunctionForInterop(f)));
       _interopCaptureThisExpando[f] = ret;
     }
     return ret;
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index c093cab..7795952 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -349,9 +349,7 @@
     return new AElement._internalWrap();
   }
 
-  factory AElement._internalWrap() {
-    return new AElement.internal_();
-  }
+  external factory AElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AElement.internal_() : super.internal_();
@@ -399,9 +397,7 @@
     return new AltGlyphElement._internalWrap();
   }
 
-  factory AltGlyphElement._internalWrap() {
-    return new AltGlyphElement.internal_();
-  }
+  external factory AltGlyphElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AltGlyphElement.internal_() : super.internal_();
@@ -550,9 +546,7 @@
     return new AnimateElement._internalWrap();
   }
 
-  factory AnimateElement._internalWrap() {
-    return new AnimateElement.internal_();
-  }
+  external factory AnimateElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimateElement.internal_() : super.internal_();
@@ -595,9 +589,7 @@
     return new AnimateMotionElement._internalWrap();
   }
 
-  factory AnimateMotionElement._internalWrap() {
-    return new AnimateMotionElement.internal_();
-  }
+  external factory AnimateMotionElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimateMotionElement.internal_() : super.internal_();
@@ -640,9 +632,7 @@
     return new AnimateTransformElement._internalWrap();
   }
 
-  factory AnimateTransformElement._internalWrap() {
-    return new AnimateTransformElement.internal_();
-  }
+  external factory AnimateTransformElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimateTransformElement.internal_() : super.internal_();
@@ -1158,9 +1148,7 @@
     return new AnimationElement._internalWrap();
   }
 
-  factory AnimationElement._internalWrap() {
-    return new AnimationElement.internal_();
-  }
+  external factory AnimationElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnimationElement.internal_() : super.internal_();
@@ -1245,9 +1233,7 @@
     return new CircleElement._internalWrap();
   }
 
-  factory CircleElement._internalWrap() {
-    return new CircleElement.internal_();
-  }
+  external factory CircleElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   CircleElement.internal_() : super.internal_();
@@ -1296,9 +1282,7 @@
     return new ClipPathElement._internalWrap();
   }
 
-  factory ClipPathElement._internalWrap() {
-    return new ClipPathElement.internal_();
-  }
+  external factory ClipPathElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ClipPathElement.internal_() : super.internal_();
@@ -1339,9 +1323,7 @@
     return new DefsElement._internalWrap();
   }
 
-  factory DefsElement._internalWrap() {
-    return new DefsElement.internal_();
-  }
+  external factory DefsElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DefsElement.internal_() : super.internal_();
@@ -1378,9 +1360,7 @@
     return new DescElement._internalWrap();
   }
 
-  factory DescElement._internalWrap() {
-    return new DescElement.internal_();
-  }
+  external factory DescElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DescElement.internal_() : super.internal_();
@@ -1413,9 +1393,7 @@
     return new DiscardElement._internalWrap();
   }
 
-  factory DiscardElement._internalWrap() {
-    return new DiscardElement.internal_();
-  }
+  external factory DiscardElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   DiscardElement.internal_() : super.internal_();
@@ -1452,9 +1430,7 @@
     return new EllipseElement._internalWrap();
   }
 
-  factory EllipseElement._internalWrap() {
-    return new EllipseElement.internal_();
-  }
+  external factory EllipseElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   EllipseElement.internal_() : super.internal_();
@@ -1511,9 +1487,7 @@
     return new FEBlendElement._internalWrap();
   }
 
-  factory FEBlendElement._internalWrap() {
-    return new FEBlendElement.internal_();
-  }
+  external factory FEBlendElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEBlendElement.internal_() : super.internal_();
@@ -1613,9 +1587,7 @@
     return new FEColorMatrixElement._internalWrap();
   }
 
-  factory FEColorMatrixElement._internalWrap() {
-    return new FEColorMatrixElement.internal_();
-  }
+  external factory FEColorMatrixElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEColorMatrixElement.internal_() : super.internal_();
@@ -1711,9 +1683,7 @@
     return new FEComponentTransferElement._internalWrap();
   }
 
-  factory FEComponentTransferElement._internalWrap() {
-    return new FEComponentTransferElement.internal_();
-  }
+  external factory FEComponentTransferElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEComponentTransferElement.internal_() : super.internal_();
@@ -1773,9 +1743,7 @@
     return new FECompositeElement._internalWrap();
   }
 
-  factory FECompositeElement._internalWrap() {
-    return new FECompositeElement.internal_();
-  }
+  external factory FECompositeElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FECompositeElement.internal_() : super.internal_();
@@ -1892,9 +1860,7 @@
     return new FEConvolveMatrixElement._internalWrap();
   }
 
-  factory FEConvolveMatrixElement._internalWrap() {
-    return new FEConvolveMatrixElement.internal_();
-  }
+  external factory FEConvolveMatrixElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEConvolveMatrixElement.internal_() : super.internal_();
@@ -2022,9 +1988,7 @@
     return new FEDiffuseLightingElement._internalWrap();
   }
 
-  factory FEDiffuseLightingElement._internalWrap() {
-    return new FEDiffuseLightingElement.internal_();
-  }
+  external factory FEDiffuseLightingElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEDiffuseLightingElement.internal_() : super.internal_();
@@ -2108,9 +2072,7 @@
     return new FEDisplacementMapElement._internalWrap();
   }
 
-  factory FEDisplacementMapElement._internalWrap() {
-    return new FEDisplacementMapElement.internal_();
-  }
+  external factory FEDisplacementMapElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEDisplacementMapElement.internal_() : super.internal_();
@@ -2214,9 +2176,7 @@
     return new FEDistantLightElement._internalWrap();
   }
 
-  factory FEDistantLightElement._internalWrap() {
-    return new FEDistantLightElement.internal_();
-  }
+  external factory FEDistantLightElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEDistantLightElement.internal_() : super.internal_();
@@ -2268,9 +2228,7 @@
     return new FEFloodElement._internalWrap();
   }
 
-  factory FEFloodElement._internalWrap() {
-    return new FEFloodElement.internal_();
-  }
+  external factory FEFloodElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEFloodElement.internal_() : super.internal_();
@@ -2334,9 +2292,7 @@
     return new FEFuncAElement._internalWrap();
   }
 
-  factory FEFuncAElement._internalWrap() {
-    return new FEFuncAElement.internal_();
-  }
+  external factory FEFuncAElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEFuncAElement.internal_() : super.internal_();
@@ -2380,9 +2336,7 @@
     return new FEFuncBElement._internalWrap();
   }
 
-  factory FEFuncBElement._internalWrap() {
-    return new FEFuncBElement.internal_();
-  }
+  external factory FEFuncBElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEFuncBElement.internal_() : super.internal_();
@@ -2426,9 +2380,7 @@
     return new FEFuncGElement._internalWrap();
   }
 
-  factory FEFuncGElement._internalWrap() {
-    return new FEFuncGElement.internal_();
-  }
+  external factory FEFuncGElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEFuncGElement.internal_() : super.internal_();
@@ -2472,9 +2424,7 @@
     return new FEFuncRElement._internalWrap();
   }
 
-  factory FEFuncRElement._internalWrap() {
-    return new FEFuncRElement.internal_();
-  }
+  external factory FEFuncRElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEFuncRElement.internal_() : super.internal_();
@@ -2518,9 +2468,7 @@
     return new FEGaussianBlurElement._internalWrap();
   }
 
-  factory FEGaussianBlurElement._internalWrap() {
-    return new FEGaussianBlurElement.internal_();
-  }
+  external factory FEGaussianBlurElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEGaussianBlurElement.internal_() : super.internal_();
@@ -2600,9 +2548,7 @@
     return new FEImageElement._internalWrap();
   }
 
-  factory FEImageElement._internalWrap() {
-    return new FEImageElement.internal_();
-  }
+  external factory FEImageElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEImageElement.internal_() : super.internal_();
@@ -2674,9 +2620,7 @@
     return new FEMergeElement._internalWrap();
   }
 
-  factory FEMergeElement._internalWrap() {
-    return new FEMergeElement.internal_();
-  }
+  external factory FEMergeElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEMergeElement.internal_() : super.internal_();
@@ -2740,9 +2684,7 @@
     return new FEMergeNodeElement._internalWrap();
   }
 
-  factory FEMergeNodeElement._internalWrap() {
-    return new FEMergeNodeElement.internal_();
-  }
+  external factory FEMergeNodeElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEMergeNodeElement.internal_() : super.internal_();
@@ -2786,9 +2728,7 @@
     return new FEMorphologyElement._internalWrap();
   }
 
-  factory FEMorphologyElement._internalWrap() {
-    return new FEMorphologyElement.internal_();
-  }
+  external factory FEMorphologyElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEMorphologyElement.internal_() : super.internal_();
@@ -2877,9 +2817,7 @@
     return new FEOffsetElement._internalWrap();
   }
 
-  factory FEOffsetElement._internalWrap() {
-    return new FEOffsetElement.internal_();
-  }
+  external factory FEOffsetElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEOffsetElement.internal_() : super.internal_();
@@ -2955,9 +2893,7 @@
     return new FEPointLightElement._internalWrap();
   }
 
-  factory FEPointLightElement._internalWrap() {
-    return new FEPointLightElement.internal_();
-  }
+  external factory FEPointLightElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FEPointLightElement.internal_() : super.internal_();
@@ -3013,9 +2949,7 @@
     return new FESpecularLightingElement._internalWrap();
   }
 
-  factory FESpecularLightingElement._internalWrap() {
-    return new FESpecularLightingElement.internal_();
-  }
+  external factory FESpecularLightingElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FESpecularLightingElement.internal_() : super.internal_();
@@ -3095,9 +3029,7 @@
     return new FESpotLightElement._internalWrap();
   }
 
-  factory FESpotLightElement._internalWrap() {
-    return new FESpotLightElement.internal_();
-  }
+  external factory FESpotLightElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FESpotLightElement.internal_() : super.internal_();
@@ -3173,9 +3105,7 @@
     return new FETileElement._internalWrap();
   }
 
-  factory FETileElement._internalWrap() {
-    return new FETileElement.internal_();
-  }
+  external factory FETileElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FETileElement.internal_() : super.internal_();
@@ -3243,9 +3173,7 @@
     return new FETurbulenceElement._internalWrap();
   }
 
-  factory FETurbulenceElement._internalWrap() {
-    return new FETurbulenceElement.internal_();
-  }
+  external factory FETurbulenceElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FETurbulenceElement.internal_() : super.internal_();
@@ -3357,9 +3285,7 @@
     return new FilterElement._internalWrap();
   }
 
-  factory FilterElement._internalWrap() {
-    return new FilterElement.internal_();
-  }
+  external factory FilterElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   FilterElement.internal_() : super.internal_();
@@ -3500,9 +3426,7 @@
     return new ForeignObjectElement._internalWrap();
   }
 
-  factory ForeignObjectElement._internalWrap() {
-    return new ForeignObjectElement.internal_();
-  }
+  external factory ForeignObjectElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ForeignObjectElement.internal_() : super.internal_();
@@ -3558,9 +3482,7 @@
     return new GElement._internalWrap();
   }
 
-  factory GElement._internalWrap() {
-    return new GElement.internal_();
-  }
+  external factory GElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   GElement.internal_() : super.internal_();
@@ -3593,9 +3515,7 @@
     return new GeometryElement._internalWrap();
   }
 
-  factory GeometryElement._internalWrap() {
-    return new GeometryElement.internal_();
-  }
+  external factory GeometryElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   GeometryElement.internal_() : super.internal_();
@@ -3638,9 +3558,7 @@
     return new GraphicsElement._internalWrap();
   }
 
-  factory GraphicsElement._internalWrap() {
-    return new GraphicsElement.internal_();
-  }
+  external factory GraphicsElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   GraphicsElement.internal_() : super.internal_();
@@ -3732,9 +3650,7 @@
     return new ImageElement._internalWrap();
   }
 
-  factory ImageElement._internalWrap() {
-    return new ImageElement.internal_();
-  }
+  external factory ImageElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ImageElement.internal_() : super.internal_();
@@ -4021,9 +3937,7 @@
     return new LineElement._internalWrap();
   }
 
-  factory LineElement._internalWrap() {
-    return new LineElement.internal_();
-  }
+  external factory LineElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   LineElement.internal_() : super.internal_();
@@ -4076,9 +3990,7 @@
     return new LinearGradientElement._internalWrap();
   }
 
-  factory LinearGradientElement._internalWrap() {
-    return new LinearGradientElement.internal_();
-  }
+  external factory LinearGradientElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   LinearGradientElement.internal_() : super.internal_();
@@ -4131,9 +4043,7 @@
     return new MarkerElement._internalWrap();
   }
 
-  factory MarkerElement._internalWrap() {
-    return new MarkerElement.internal_();
-  }
+  external factory MarkerElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MarkerElement.internal_() : super.internal_();
@@ -4238,9 +4148,7 @@
     return new MaskElement._internalWrap();
   }
 
-  factory MaskElement._internalWrap() {
-    return new MaskElement.internal_();
-  }
+  external factory MaskElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MaskElement.internal_() : super.internal_();
@@ -4435,9 +4343,7 @@
     return new MetadataElement._internalWrap();
   }
 
-  factory MetadataElement._internalWrap() {
-    return new MetadataElement.internal_();
-  }
+  external factory MetadataElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   MetadataElement.internal_() : super.internal_();
@@ -4628,9 +4534,7 @@
     return new PathElement._internalWrap();
   }
 
-  factory PathElement._internalWrap() {
-    return new PathElement.internal_();
-  }
+  external factory PathElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathElement.internal_() : super.internal_();
@@ -4889,9 +4793,7 @@
     return new PathSegArcAbs._internalWrap();
   }
 
-  factory PathSegArcAbs._internalWrap() {
-    return new PathSegArcAbs.internal_();
-  }
+  external factory PathSegArcAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegArcAbs.internal_() : super.internal_();
@@ -4974,9 +4876,7 @@
     return new PathSegArcRel._internalWrap();
   }
 
-  factory PathSegArcRel._internalWrap() {
-    return new PathSegArcRel.internal_();
-  }
+  external factory PathSegArcRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegArcRel.internal_() : super.internal_();
@@ -5059,9 +4959,7 @@
     return new PathSegClosePath._internalWrap();
   }
 
-  factory PathSegClosePath._internalWrap() {
-    return new PathSegClosePath.internal_();
-  }
+  external factory PathSegClosePath._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegClosePath.internal_() : super.internal_();
@@ -5088,9 +4986,7 @@
     return new PathSegCurvetoCubicAbs._internalWrap();
   }
 
-  factory PathSegCurvetoCubicAbs._internalWrap() {
-    return new PathSegCurvetoCubicAbs.internal_();
-  }
+  external factory PathSegCurvetoCubicAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoCubicAbs.internal_() : super.internal_();
@@ -5165,9 +5061,7 @@
     return new PathSegCurvetoCubicRel._internalWrap();
   }
 
-  factory PathSegCurvetoCubicRel._internalWrap() {
-    return new PathSegCurvetoCubicRel.internal_();
-  }
+  external factory PathSegCurvetoCubicRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoCubicRel.internal_() : super.internal_();
@@ -5242,9 +5136,7 @@
     return new PathSegCurvetoCubicSmoothAbs._internalWrap();
   }
 
-  factory PathSegCurvetoCubicSmoothAbs._internalWrap() {
-    return new PathSegCurvetoCubicSmoothAbs.internal_();
-  }
+  external factory PathSegCurvetoCubicSmoothAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoCubicSmoothAbs.internal_() : super.internal_();
@@ -5303,9 +5195,7 @@
     return new PathSegCurvetoCubicSmoothRel._internalWrap();
   }
 
-  factory PathSegCurvetoCubicSmoothRel._internalWrap() {
-    return new PathSegCurvetoCubicSmoothRel.internal_();
-  }
+  external factory PathSegCurvetoCubicSmoothRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoCubicSmoothRel.internal_() : super.internal_();
@@ -5364,9 +5254,7 @@
     return new PathSegCurvetoQuadraticAbs._internalWrap();
   }
 
-  factory PathSegCurvetoQuadraticAbs._internalWrap() {
-    return new PathSegCurvetoQuadraticAbs.internal_();
-  }
+  external factory PathSegCurvetoQuadraticAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoQuadraticAbs.internal_() : super.internal_();
@@ -5425,9 +5313,7 @@
     return new PathSegCurvetoQuadraticRel._internalWrap();
   }
 
-  factory PathSegCurvetoQuadraticRel._internalWrap() {
-    return new PathSegCurvetoQuadraticRel.internal_();
-  }
+  external factory PathSegCurvetoQuadraticRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoQuadraticRel.internal_() : super.internal_();
@@ -5486,9 +5372,7 @@
     return new PathSegCurvetoQuadraticSmoothAbs._internalWrap();
   }
 
-  factory PathSegCurvetoQuadraticSmoothAbs._internalWrap() {
-    return new PathSegCurvetoQuadraticSmoothAbs.internal_();
-  }
+  external factory PathSegCurvetoQuadraticSmoothAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoQuadraticSmoothAbs.internal_() : super.internal_();
@@ -5531,9 +5415,7 @@
     return new PathSegCurvetoQuadraticSmoothRel._internalWrap();
   }
 
-  factory PathSegCurvetoQuadraticSmoothRel._internalWrap() {
-    return new PathSegCurvetoQuadraticSmoothRel.internal_();
-  }
+  external factory PathSegCurvetoQuadraticSmoothRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegCurvetoQuadraticSmoothRel.internal_() : super.internal_();
@@ -5576,9 +5458,7 @@
     return new PathSegLinetoAbs._internalWrap();
   }
 
-  factory PathSegLinetoAbs._internalWrap() {
-    return new PathSegLinetoAbs.internal_();
-  }
+  external factory PathSegLinetoAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegLinetoAbs.internal_() : super.internal_();
@@ -5621,9 +5501,7 @@
     return new PathSegLinetoHorizontalAbs._internalWrap();
   }
 
-  factory PathSegLinetoHorizontalAbs._internalWrap() {
-    return new PathSegLinetoHorizontalAbs.internal_();
-  }
+  external factory PathSegLinetoHorizontalAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegLinetoHorizontalAbs.internal_() : super.internal_();
@@ -5658,9 +5536,7 @@
     return new PathSegLinetoHorizontalRel._internalWrap();
   }
 
-  factory PathSegLinetoHorizontalRel._internalWrap() {
-    return new PathSegLinetoHorizontalRel.internal_();
-  }
+  external factory PathSegLinetoHorizontalRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegLinetoHorizontalRel.internal_() : super.internal_();
@@ -5695,9 +5571,7 @@
     return new PathSegLinetoRel._internalWrap();
   }
 
-  factory PathSegLinetoRel._internalWrap() {
-    return new PathSegLinetoRel.internal_();
-  }
+  external factory PathSegLinetoRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegLinetoRel.internal_() : super.internal_();
@@ -5740,9 +5614,7 @@
     return new PathSegLinetoVerticalAbs._internalWrap();
   }
 
-  factory PathSegLinetoVerticalAbs._internalWrap() {
-    return new PathSegLinetoVerticalAbs.internal_();
-  }
+  external factory PathSegLinetoVerticalAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegLinetoVerticalAbs.internal_() : super.internal_();
@@ -5777,9 +5649,7 @@
     return new PathSegLinetoVerticalRel._internalWrap();
   }
 
-  factory PathSegLinetoVerticalRel._internalWrap() {
-    return new PathSegLinetoVerticalRel.internal_();
-  }
+  external factory PathSegLinetoVerticalRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegLinetoVerticalRel.internal_() : super.internal_();
@@ -5930,9 +5800,7 @@
     return new PathSegMovetoAbs._internalWrap();
   }
 
-  factory PathSegMovetoAbs._internalWrap() {
-    return new PathSegMovetoAbs.internal_();
-  }
+  external factory PathSegMovetoAbs._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegMovetoAbs.internal_() : super.internal_();
@@ -5975,9 +5843,7 @@
     return new PathSegMovetoRel._internalWrap();
   }
 
-  factory PathSegMovetoRel._internalWrap() {
-    return new PathSegMovetoRel.internal_();
-  }
+  external factory PathSegMovetoRel._internalWrap();
 
   @Deprecated("Internal Use Only")
   PathSegMovetoRel.internal_() : super.internal_();
@@ -6024,9 +5890,7 @@
     return new PatternElement._internalWrap();
   }
 
-  factory PatternElement._internalWrap() {
-    return new PatternElement.internal_();
-  }
+  external factory PatternElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PatternElement.internal_() : super.internal_();
@@ -6241,9 +6105,7 @@
     return new PolygonElement._internalWrap();
   }
 
-  factory PolygonElement._internalWrap() {
-    return new PolygonElement.internal_();
-  }
+  external factory PolygonElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PolygonElement.internal_() : super.internal_();
@@ -6288,9 +6150,7 @@
     return new PolylineElement._internalWrap();
   }
 
-  factory PolylineElement._internalWrap() {
-    return new PolylineElement.internal_();
-  }
+  external factory PolylineElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   PolylineElement.internal_() : super.internal_();
@@ -6437,9 +6297,7 @@
     return new RadialGradientElement._internalWrap();
   }
 
-  factory RadialGradientElement._internalWrap() {
-    return new RadialGradientElement.internal_();
-  }
+  external factory RadialGradientElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   RadialGradientElement.internal_() : super.internal_();
@@ -6562,9 +6420,7 @@
     return new RectElement._internalWrap();
   }
 
-  factory RectElement._internalWrap() {
-    return new RectElement.internal_();
-  }
+  external factory RectElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   RectElement.internal_() : super.internal_();
@@ -6679,9 +6535,7 @@
     return new ScriptElement._internalWrap();
   }
 
-  factory ScriptElement._internalWrap() {
-    return new ScriptElement.internal_();
-  }
+  external factory ScriptElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ScriptElement.internal_() : super.internal_();
@@ -6733,9 +6587,7 @@
     return new SetElement._internalWrap();
   }
 
-  factory SetElement._internalWrap() {
-    return new SetElement.internal_();
-  }
+  external factory SetElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SetElement.internal_() : super.internal_();
@@ -6775,9 +6627,7 @@
     return new StopElement._internalWrap();
   }
 
-  factory StopElement._internalWrap() {
-    return new StopElement.internal_();
-  }
+  external factory StopElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   StopElement.internal_() : super.internal_();
@@ -6935,9 +6785,7 @@
     return new StyleElement._internalWrap();
   }
 
-  factory StyleElement._internalWrap() {
-    return new StyleElement.internal_();
-  }
+  external factory StyleElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   StyleElement.internal_() : super.internal_();
@@ -7416,9 +7264,7 @@
     return new SvgElement._internalWrap();
   }
 
-  factory SvgElement._internalWrap() {
-    return new SvgElement.internal_();
-  }
+  external factory SvgElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SvgElement.internal_() : super.internal_();
@@ -7771,9 +7617,7 @@
     return new SvgSvgElement._internalWrap();
   }
 
-  factory SvgSvgElement._internalWrap() {
-    return new SvgSvgElement.internal_();
-  }
+  external factory SvgSvgElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SvgSvgElement.internal_() : super.internal_();
@@ -7974,9 +7818,7 @@
     return new SwitchElement._internalWrap();
   }
 
-  factory SwitchElement._internalWrap() {
-    return new SwitchElement.internal_();
-  }
+  external factory SwitchElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SwitchElement.internal_() : super.internal_();
@@ -8013,9 +7855,7 @@
     return new SymbolElement._internalWrap();
   }
 
-  factory SymbolElement._internalWrap() {
-    return new SymbolElement.internal_();
-  }
+  external factory SymbolElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   SymbolElement.internal_() : super.internal_();
@@ -8060,9 +7900,7 @@
     return new TSpanElement._internalWrap();
   }
 
-  factory TSpanElement._internalWrap() {
-    return new TSpanElement.internal_();
-  }
+  external factory TSpanElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TSpanElement.internal_() : super.internal_();
@@ -8126,9 +7964,7 @@
     return new TextContentElement._internalWrap();
   }
 
-  factory TextContentElement._internalWrap() {
-    return new TextContentElement.internal_();
-  }
+  external factory TextContentElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextContentElement.internal_() : super.internal_();
@@ -8221,9 +8057,7 @@
     return new TextElement._internalWrap();
   }
 
-  factory TextElement._internalWrap() {
-    return new TextElement.internal_();
-  }
+  external factory TextElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextElement.internal_() : super.internal_();
@@ -8256,9 +8090,7 @@
     return new TextPathElement._internalWrap();
   }
 
-  factory TextPathElement._internalWrap() {
-    return new TextPathElement.internal_();
-  }
+  external factory TextPathElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextPathElement.internal_() : super.internal_();
@@ -8331,9 +8163,7 @@
     return new TextPositioningElement._internalWrap();
   }
 
-  factory TextPositioningElement._internalWrap() {
-    return new TextPositioningElement.internal_();
-  }
+  external factory TextPositioningElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TextPositioningElement.internal_() : super.internal_();
@@ -8390,9 +8220,7 @@
     return new TitleElement._internalWrap();
   }
 
-  factory TitleElement._internalWrap() {
-    return new TitleElement.internal_();
-  }
+  external factory TitleElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   TitleElement.internal_() : super.internal_();
@@ -8708,9 +8536,7 @@
     return new UseElement._internalWrap();
   }
 
-  factory UseElement._internalWrap() {
-    return new UseElement.internal_();
-  }
+  external factory UseElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   UseElement.internal_() : super.internal_();
@@ -8767,9 +8593,7 @@
     return new ViewElement._internalWrap();
   }
 
-  factory ViewElement._internalWrap() {
-    return new ViewElement.internal_();
-  }
+  external factory ViewElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   ViewElement.internal_() : super.internal_();
@@ -8931,9 +8755,7 @@
     return new ZoomEvent._internalWrap();
   }
 
-  factory ZoomEvent._internalWrap() {
-    return new ZoomEvent.internal_();
-  }
+  external factory ZoomEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ZoomEvent.internal_() : super.internal_();
@@ -8980,9 +8802,7 @@
     return new _GradientElement._internalWrap();
   }
 
-  factory _GradientElement._internalWrap() {
-    return new _GradientElement.internal_();
-  }
+  external factory _GradientElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _GradientElement.internal_() : super.internal_();
@@ -9047,9 +8867,7 @@
     return new _SVGAltGlyphDefElement._internalWrap();
   }
 
-  factory _SVGAltGlyphDefElement._internalWrap() {
-    return new _SVGAltGlyphDefElement.internal_();
-  }
+  external factory _SVGAltGlyphDefElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGAltGlyphDefElement.internal_() : super.internal_();
@@ -9082,9 +8900,7 @@
     return new _SVGAltGlyphItemElement._internalWrap();
   }
 
-  factory _SVGAltGlyphItemElement._internalWrap() {
-    return new _SVGAltGlyphItemElement.internal_();
-  }
+  external factory _SVGAltGlyphItemElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGAltGlyphItemElement.internal_() : super.internal_();
@@ -9117,9 +8933,7 @@
     return new _SVGComponentTransferFunctionElement._internalWrap();
   }
 
-  factory _SVGComponentTransferFunctionElement._internalWrap() {
-    return new _SVGComponentTransferFunctionElement.internal_();
-  }
+  external factory _SVGComponentTransferFunctionElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGComponentTransferFunctionElement.internal_() : super.internal_();
@@ -9154,9 +8968,7 @@
     return new _SVGCursorElement._internalWrap();
   }
 
-  factory _SVGCursorElement._internalWrap() {
-    return new _SVGCursorElement.internal_();
-  }
+  external factory _SVGCursorElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGCursorElement.internal_() : super.internal_();
@@ -9197,9 +9009,7 @@
     return new _SVGFEDropShadowElement._internalWrap();
   }
 
-  factory _SVGFEDropShadowElement._internalWrap() {
-    return new _SVGFEDropShadowElement.internal_();
-  }
+  external factory _SVGFEDropShadowElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFEDropShadowElement.internal_() : super.internal_();
@@ -9239,9 +9049,7 @@
     return new _SVGFontElement._internalWrap();
   }
 
-  factory _SVGFontElement._internalWrap() {
-    return new _SVGFontElement.internal_();
-  }
+  external factory _SVGFontElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFontElement.internal_() : super.internal_();
@@ -9274,9 +9082,7 @@
     return new _SVGFontFaceElement._internalWrap();
   }
 
-  factory _SVGFontFaceElement._internalWrap() {
-    return new _SVGFontFaceElement.internal_();
-  }
+  external factory _SVGFontFaceElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFontFaceElement.internal_() : super.internal_();
@@ -9309,9 +9115,7 @@
     return new _SVGFontFaceFormatElement._internalWrap();
   }
 
-  factory _SVGFontFaceFormatElement._internalWrap() {
-    return new _SVGFontFaceFormatElement.internal_();
-  }
+  external factory _SVGFontFaceFormatElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFontFaceFormatElement.internal_() : super.internal_();
@@ -9344,9 +9148,7 @@
     return new _SVGFontFaceNameElement._internalWrap();
   }
 
-  factory _SVGFontFaceNameElement._internalWrap() {
-    return new _SVGFontFaceNameElement.internal_();
-  }
+  external factory _SVGFontFaceNameElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFontFaceNameElement.internal_() : super.internal_();
@@ -9379,9 +9181,7 @@
     return new _SVGFontFaceSrcElement._internalWrap();
   }
 
-  factory _SVGFontFaceSrcElement._internalWrap() {
-    return new _SVGFontFaceSrcElement.internal_();
-  }
+  external factory _SVGFontFaceSrcElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFontFaceSrcElement.internal_() : super.internal_();
@@ -9414,9 +9214,7 @@
     return new _SVGFontFaceUriElement._internalWrap();
   }
 
-  factory _SVGFontFaceUriElement._internalWrap() {
-    return new _SVGFontFaceUriElement.internal_();
-  }
+  external factory _SVGFontFaceUriElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGFontFaceUriElement.internal_() : super.internal_();
@@ -9453,9 +9251,7 @@
     return new _SVGGlyphElement._internalWrap();
   }
 
-  factory _SVGGlyphElement._internalWrap() {
-    return new _SVGGlyphElement.internal_();
-  }
+  external factory _SVGGlyphElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGGlyphElement.internal_() : super.internal_();
@@ -9486,9 +9282,7 @@
     return new _SVGGlyphRefElement._internalWrap();
   }
 
-  factory _SVGGlyphRefElement._internalWrap() {
-    return new _SVGGlyphRefElement.internal_();
-  }
+  external factory _SVGGlyphRefElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGGlyphRefElement.internal_() : super.internal_();
@@ -9528,9 +9322,7 @@
     return new _SVGHKernElement._internalWrap();
   }
 
-  factory _SVGHKernElement._internalWrap() {
-    return new _SVGHKernElement.internal_();
-  }
+  external factory _SVGHKernElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGHKernElement.internal_() : super.internal_();
@@ -9564,9 +9356,7 @@
     return new _SVGMPathElement._internalWrap();
   }
 
-  factory _SVGMPathElement._internalWrap() {
-    return new _SVGMPathElement.internal_();
-  }
+  external factory _SVGMPathElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGMPathElement.internal_() : super.internal_();
@@ -9602,9 +9392,7 @@
     return new _SVGMissingGlyphElement._internalWrap();
   }
 
-  factory _SVGMissingGlyphElement._internalWrap() {
-    return new _SVGMissingGlyphElement.internal_();
-  }
+  external factory _SVGMissingGlyphElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGMissingGlyphElement.internal_() : super.internal_();
@@ -9641,9 +9429,7 @@
     return new _SVGVKernElement._internalWrap();
   }
 
-  factory _SVGVKernElement._internalWrap() {
-    return new _SVGVKernElement.internal_();
-  }
+  external factory _SVGVKernElement._internalWrap();
 
   @Deprecated("Internal Use Only")
   _SVGVKernElement.internal_() : super.internal_();
diff --git a/sdk/lib/web_audio/dartium/web_audio_dartium.dart b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
index cc99534..7a3a9c4 100644
--- a/sdk/lib/web_audio/dartium/web_audio_dartium.dart
+++ b/sdk/lib/web_audio/dartium/web_audio_dartium.dart
@@ -104,9 +104,7 @@
     return new AnalyserNode._internalWrap();
   }
 
-  factory AnalyserNode._internalWrap() {
-    return new AnalyserNode.internal_();
-  }
+  external factory AnalyserNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   AnalyserNode.internal_() : super.internal_();
@@ -262,9 +260,7 @@
     return new AudioBufferSourceNode._internalWrap();
   }
 
-  factory AudioBufferSourceNode._internalWrap() {
-    return new AudioBufferSourceNode.internal_();
-  }
+  external factory AudioBufferSourceNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioBufferSourceNode.internal_() : super.internal_();
@@ -375,9 +371,7 @@
     return new AudioContext._internalWrap();
   }
 
-  factory AudioContext._internalWrap() {
-    return new AudioContext.internal_();
-  }
+  external factory AudioContext._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioContext.internal_() : super.internal_();
@@ -542,9 +536,7 @@
     return new AudioDestinationNode._internalWrap();
   }
 
-  factory AudioDestinationNode._internalWrap() {
-    return new AudioDestinationNode.internal_();
-  }
+  external factory AudioDestinationNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioDestinationNode.internal_() : super.internal_();
@@ -632,9 +624,7 @@
     return new AudioNode._internalWrap();
   }
 
-  factory AudioNode._internalWrap() {
-    return new AudioNode.internal_();
-  }
+  external factory AudioNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioNode.internal_() : super.internal_();
@@ -788,9 +778,7 @@
     return new AudioProcessingEvent._internalWrap();
   }
 
-  factory AudioProcessingEvent._internalWrap() {
-    return new AudioProcessingEvent.internal_();
-  }
+  external factory AudioProcessingEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioProcessingEvent.internal_() : super.internal_();
@@ -831,9 +819,7 @@
     return new AudioSourceNode._internalWrap();
   }
 
-  factory AudioSourceNode._internalWrap() {
-    return new AudioSourceNode.internal_();
-  }
+  external factory AudioSourceNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   AudioSourceNode.internal_() : super.internal_();
@@ -861,9 +847,7 @@
     return new BiquadFilterNode._internalWrap();
   }
 
-  factory BiquadFilterNode._internalWrap() {
-    return new BiquadFilterNode.internal_();
-  }
+  external factory BiquadFilterNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   BiquadFilterNode.internal_() : super.internal_();
@@ -919,9 +903,7 @@
     return new ChannelMergerNode._internalWrap();
   }
 
-  factory ChannelMergerNode._internalWrap() {
-    return new ChannelMergerNode.internal_();
-  }
+  external factory ChannelMergerNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   ChannelMergerNode.internal_() : super.internal_();
@@ -949,9 +931,7 @@
     return new ChannelSplitterNode._internalWrap();
   }
 
-  factory ChannelSplitterNode._internalWrap() {
-    return new ChannelSplitterNode.internal_();
-  }
+  external factory ChannelSplitterNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   ChannelSplitterNode.internal_() : super.internal_();
@@ -979,9 +959,7 @@
     return new ConvolverNode._internalWrap();
   }
 
-  factory ConvolverNode._internalWrap() {
-    return new ConvolverNode.internal_();
-  }
+  external factory ConvolverNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   ConvolverNode.internal_() : super.internal_();
@@ -1025,9 +1003,7 @@
     return new DelayNode._internalWrap();
   }
 
-  factory DelayNode._internalWrap() {
-    return new DelayNode.internal_();
-  }
+  external factory DelayNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   DelayNode.internal_() : super.internal_();
@@ -1059,9 +1035,7 @@
     return new DynamicsCompressorNode._internalWrap();
   }
 
-  factory DynamicsCompressorNode._internalWrap() {
-    return new DynamicsCompressorNode.internal_();
-  }
+  external factory DynamicsCompressorNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   DynamicsCompressorNode.internal_() : super.internal_();
@@ -1113,9 +1087,7 @@
     return new GainNode._internalWrap();
   }
 
-  factory GainNode._internalWrap() {
-    return new GainNode.internal_();
-  }
+  external factory GainNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   GainNode.internal_() : super.internal_();
@@ -1147,9 +1119,7 @@
     return new MediaElementAudioSourceNode._internalWrap();
   }
 
-  factory MediaElementAudioSourceNode._internalWrap() {
-    return new MediaElementAudioSourceNode.internal_();
-  }
+  external factory MediaElementAudioSourceNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaElementAudioSourceNode.internal_() : super.internal_();
@@ -1182,9 +1152,7 @@
     return new MediaStreamAudioDestinationNode._internalWrap();
   }
 
-  factory MediaStreamAudioDestinationNode._internalWrap() {
-    return new MediaStreamAudioDestinationNode.internal_();
-  }
+  external factory MediaStreamAudioDestinationNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaStreamAudioDestinationNode.internal_() : super.internal_();
@@ -1216,9 +1184,7 @@
     return new MediaStreamAudioSourceNode._internalWrap();
   }
 
-  factory MediaStreamAudioSourceNode._internalWrap() {
-    return new MediaStreamAudioSourceNode.internal_();
-  }
+  external factory MediaStreamAudioSourceNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   MediaStreamAudioSourceNode.internal_() : super.internal_();
@@ -1250,9 +1216,7 @@
     return new OfflineAudioCompletionEvent._internalWrap();
   }
 
-  factory OfflineAudioCompletionEvent._internalWrap() {
-    return new OfflineAudioCompletionEvent.internal_();
-  }
+  external factory OfflineAudioCompletionEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   OfflineAudioCompletionEvent.internal_() : super.internal_();
@@ -1290,9 +1254,7 @@
     return new OfflineAudioContext._internalWrap();
   }
 
-  factory OfflineAudioContext._internalWrap() {
-    return new OfflineAudioContext.internal_();
-  }
+  external factory OfflineAudioContext._internalWrap();
 
   @Deprecated("Internal Use Only")
   OfflineAudioContext.internal_() : super.internal_();
@@ -1331,9 +1293,7 @@
     return new OscillatorNode._internalWrap();
   }
 
-  factory OscillatorNode._internalWrap() {
-    return new OscillatorNode.internal_();
-  }
+  external factory OscillatorNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   OscillatorNode.internal_() : super.internal_();
@@ -1414,9 +1374,7 @@
     return new PannerNode._internalWrap();
   }
 
-  factory PannerNode._internalWrap() {
-    return new PannerNode.internal_();
-  }
+  external factory PannerNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   PannerNode.internal_() : super.internal_();
@@ -1561,9 +1519,7 @@
     return new ScriptProcessorNode._internalWrap();
   }
 
-  factory ScriptProcessorNode._internalWrap() {
-    return new ScriptProcessorNode.internal_();
-  }
+  external factory ScriptProcessorNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   ScriptProcessorNode.internal_() : super.internal_();
@@ -1613,9 +1569,7 @@
     return new WaveShaperNode._internalWrap();
   }
 
-  factory WaveShaperNode._internalWrap() {
-    return new WaveShaperNode.internal_();
-  }
+  external factory WaveShaperNode._internalWrap();
 
   @Deprecated("Internal Use Only")
   WaveShaperNode.internal_() : super.internal_();
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 1fdf4c7..707af2d 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -824,9 +824,7 @@
     return new ContextEvent._internalWrap();
   }
 
-  factory ContextEvent._internalWrap() {
-    return new ContextEvent.internal_();
-  }
+  external factory ContextEvent._internalWrap();
 
   @Deprecated("Internal Use Only")
   ContextEvent.internal_() : super.internal_();
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index a5781a6..f47d3ce 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -149,8 +149,8 @@
 LibTest/core/List/getRange_A03_t01: RuntimeError, OK # Tests that fail because they use the legacy try-catch syntax. co19 issue 184.
 LibTest/core/List/removeAt_A02_t01: RuntimeError # Issue 1533
 LibTest/core/List/sort_A01_t06: Slow, Pass # Slow tests that needs extra time to finish.
-LibTest/core/double/INFINITY_A01_t04: RuntimeError # Please triage this failure.
-LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # Please triage this failure.
+LibTest/core/double/INFINITY_A01_t04: RuntimeError # Expected to fail because double.INFINITY is int.
+LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # Expected to fail because double.NEGATIVE_INFINITY is int.
 LibTest/core/int/hashCode_A01_t01: RuntimeError, OK # co19 issue 308
 LibTest/core/int/isEven_A01_t01: RuntimeError, OK # co19 issue 277
 LibTest/core/int/isOdd_A01_t01: RuntimeError, OK # co19 issue 277
@@ -687,7 +687,7 @@
 LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-layer-update_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/hit-test-generated-content_t01: Pass, RuntimeError # Please triage this failure
-LayoutTests/fast/css-generated-content/malformed-url_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css-generated-content/malformed-url_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation-display_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/css-generated-content/pseudo-animation_t01: Pass, RuntimeError # Please triage this failure
@@ -9616,9 +9616,7 @@
 WebPlatformTest/webstorage/storage_local_setitem_quotaexceedederr_t01: Skip # Times out. Please triage this failure
 
 [ $compiler == dart2js && $cps_ir ]
-Language/Statements/Labels/scope_t04: Crash # (switch (i){L:case 0:flag=true;break;case 2:continue L;}): continue to a labeled switch case
-Language/Statements/Continue/label_t12: Crash # (switch (2){L:case 1:flag=true;break;case 2:continue L;}): continue to a labeled switch case
-Language/Statements/Continue/label_t13: Crash # (switch (2){case 2:continue L;L:case 1:flag=true;}): continue to a labeled switch case
+Language/Types/Interface_Types/subtype_t09: Crash # Pending static: JSArray
 Language/Types/Interface_Types/subtype_t39: RuntimeError # Please triage this failure.
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Timeout
 LibTest/core/Invocation/isAccessor_A01_t01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
@@ -9632,5 +9630,3 @@
 LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # Please triage this failure.
 LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # Please triage this failure.
 LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # Please triage this failure.
-LibTest/core/double/INFINITY_A01_t04: Pass # Please triage this failure.
-LibTest/core/double/NEGATIVE_INFINITY_A01_t04: Pass # Please triage this failure.
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index f97f79d..061649b 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -20,7 +20,6 @@
 LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/dom/navigatorcontentutils/is-protocol-handler-registered_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/dom/navigatorcontentutils/unregister-protocol-handler_t01: RuntimeError # Dartium JSInterop failure
-LayoutTests/fast/events/remove-event-listener_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
 LayoutTests/fast/xpath/attr-namespace_t01: RuntimeError # Dartium JsInterop failure
 LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
@@ -241,7 +240,6 @@
 LayoutTests/fast/css3-text/css3-text-indent/getComputedStyle/getComputedStyle-text-indent-inherited_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/css3-text/css3-text-indent/getComputedStyle/getComputedStyle-text-indent_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/css3-text/css3-text-justify/getComputedStyle/getComputedStyle-text-justify_t01: Pass, RuntimeError # co19-roll r786: Please triage this failure.
-LayoutTests/fast/dom/52776_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/dom/DOMImplementation/createDocument-namespace-err_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/basic_t01: RuntimeError # co19-roll r706.  Please triage this failure.
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-in-strict-mode-wtih-checkbox_t01: Pass, RuntimeError # co19-roll r801: Please triage this failure.
@@ -265,7 +263,6 @@
 LayoutTests/fast/dom/HTMLDialogElement/dialog-scrolled-viewport_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLDialogElement/dialog-show-modal_t01: RuntimeError, Pass # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLDialogElement/inert-node-is-unfocusable_t01: RuntimeError # co19-roll r722: Please triage this failure.
-LayoutTests/fast/dom/HTMLDialogElement/inert-node-is-unselectable_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLDialogElement/multiple-centered-dialogs_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLDialogElement/non-anchored-dialog-positioning_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLDialogElement/show-modal-focusing-steps_t01: RuntimeError # co19-roll r722: Please triage this failure.
@@ -285,7 +282,6 @@
 LayoutTests/fast/dom/HTMLLinkElement/resolve-url-on-insertion_t01: RuntimeError # co19-roll r722: Issue 18010
 LayoutTests/fast/dom/HTMLObjectElement/beforeload-set-text-crash_t01: Skip # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLOptionElement/collection-setter-getter_t01: RuntimeError # co19-roll r722: Please triage this failure.
-LayoutTests/fast/dom/HTMLOutputElement/dom-settable-token-list_t01: RuntimeError # Issue 18931
 LayoutTests/fast/dom/HTMLScriptElement/async-false-inside-async-false-load_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLScriptElement/async-inline-script_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/HTMLScriptElement/async-onbeforeload_t01: RuntimeError # co19-roll r722: Please triage this failure.
@@ -303,14 +299,8 @@
 LayoutTests/fast/dom/Node/fragment-mutation_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/dom/Node/initial-values_t01: RuntimeError # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/Range/bug-19527_t01: RuntimeError # Please triage this failure.
-LayoutTests/fast/dom/Range/insertNode-empty-fragment-crash_t01: RuntimeError # Please triage this failure.
-LayoutTests/fast/dom/Range/mutation_t01: RuntimeError # Please triage this failure.
-LayoutTests/fast/dom/Range/range-constructor_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/dom/Range/range-created-during-remove-children_t01: RuntimeError, Pass # co19-roll r722: Please triage this failure.
 LayoutTests/fast/dom/Range/range-detached-exceptions_t01: RuntimeError # Please triage this failure.
-LayoutTests/fast/dom/Range/range-expand_t01: RuntimeError # Please triage this failure.
-LayoutTests/fast/dom/Range/range-insertNode-separate-endContainer_t01: RuntimeError # Please triage this failure.
-LayoutTests/fast/dom/Range/range-insertNode-splittext_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/dom/StyleSheet/discarded-sheet-owner-null_t01: Skip # Test reloads itself. Issue 18558.
 LayoutTests/fast/dom/Window/window-resize-contents_t01: Pass, RuntimeError # co19-roll r738: Please triage this failure.
 LayoutTests/fast/dom/Window/window-resize_t01: RuntimeError # co19-roll r738: Please triage this failure.
@@ -331,7 +321,6 @@
 LayoutTests/fast/dom/focus-contenteditable_t01: RuntimeError, Pass # co19-roll r738: Please triage this failure.
 LayoutTests/fast/dom/getElementsByClassName/011_t01: RuntimeError # Chrome 39 roll. Please triage this failure
 LayoutTests/fast/dom/horizontal-scrollbar-in-rtl-doesnt-fire-onscroll_t01: RuntimeError # co19-roll r738: Please triage this failure.
-LayoutTests/fast/dom/horizontal-scrollbar-in-rtl_t01: RuntimeError # Please triage this failure.
 LayoutTests/fast/dom/horizontal-scrollbar-when-dir-change_t01: RuntimeError # co19-roll r738: Please triage this failure.
 LayoutTests/fast/dom/location-hash_t01: Pass, RuntimeError # co19-roll r738: Please triage this failure.
 LayoutTests/fast/dom/option-properties_t01: RuntimeError # co19-roll r738: Please triage this failure.
@@ -636,7 +625,6 @@
 LayoutTests/fast/text/font-ligatures-linebreak-word_t01: Skip # co19 issue 11.
 LayoutTests/fast/text/font-ligatures-linebreak_t01: Pass, RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/text/glyph-reordering_t01: Pass, RuntimeError # This is a false pass. The font gets sanitized, so whether it works or not probably depends on default sizes. # co19 issue 11.
-LayoutTests/fast/text/international/cjk-segmentation_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/text/international/complex-text-rectangle_t01: Skip # co19 issue 732.
 LayoutTests/fast/text/international/iso-8859-8_t01: RuntimeError # co19-roll r786: Please triage this failure.
 LayoutTests/fast/text/international/listbox-width-rtl_t01: RuntimeError # co19 issue 11.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index a11b526..ae94df1 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -74,7 +74,7 @@
 LibTest/isolate/Isolate/spawnUri_A01_t04: Crash, Pass # Issue 17440
 LibTest/isolate/Isolate/spawn_A01_t04: Crash, Pass # Issue 17440
 
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == simarm || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ($arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips || $arch == simarm64) ]
 LibTest/core/Uri/Uri_A06_t03: Skip  # Timeout
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip  # Timeout
 LibTest/collection/ListBase/ListBase_class_A01_t01: Skip  # Timeout
@@ -135,9 +135,6 @@
 Language/Mixins/not_object_superclass_t01: MissingCompileTimeError # Please triage this failure
 Language/Mixins/reference_to_super_t01: MissingCompileTimeError # Please triage this failure
 
-[ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug ]
-Language/Mixins/Mixin_Application/wrong_type_t02: Crash # Please triage this failure
-
 [ ($runtime == vm || $runtime == dart_precompiled) && $checked ]
 Language/Errors_and_Warnings/static_warning_t01: RuntimeError # Please triage this failure
 Language/Errors_and_Warnings/static_warning_t02: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
index d88745d..71fbd97 100644
--- a/tests/compiler/dart2js/class_set_test.dart
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -17,7 +17,14 @@
 import 'package:compiler/src/world.dart';
 
 void main() {
-  asyncTest(() => TypeEnvironment.create(r"""
+  asyncTest(() async {
+    await testIterators();
+    await testForEach();
+  });
+}
+
+testIterators() async {
+  var env = await TypeEnvironment.create(r"""
       ///        A
       ///       / \
       ///      B   C
@@ -42,305 +49,536 @@
         new G();
       }
       """,
-      useMockCompiler: false).then((env) {
-    World world = env.compiler.world;
+      useMockCompiler: false);
+  World world = env.compiler.world;
 
-    ClassElement A = env.getElement("A");
-    ClassElement B = env.getElement("B");
-    ClassElement C = env.getElement("C");
-    ClassElement D = env.getElement("D");
-    ClassElement E = env.getElement("E");
-    ClassElement F = env.getElement("F");
-    ClassElement G = env.getElement("G");
+  ClassElement A = env.getElement("A");
+  ClassElement B = env.getElement("B");
+  ClassElement C = env.getElement("C");
+  ClassElement D = env.getElement("D");
+  ClassElement E = env.getElement("E");
+  ClassElement F = env.getElement("F");
+  ClassElement G = env.getElement("G");
 
-    void checkClass(ClassElement cls,
-                    {bool directlyInstantiated: false,
-                     bool indirectlyInstantiated: false}) {
-      ClassHierarchyNode node = world.getClassHierarchyNode(cls);
-      Expect.isNotNull(node, "Expected ClassHierarchyNode for $cls.");
-      Expect.equals(
-          directlyInstantiated || indirectlyInstantiated,
-          node.isInstantiated,
-          "Unexpected `isInstantiated` on ClassHierarchyNode for $cls.");
-      Expect.equals(
-          directlyInstantiated,
-          node.isDirectlyInstantiated,
-          "Unexpected `isDirectlyInstantiated` on ClassHierarchyNode for "
-          "$cls.");
-      Expect.equals(
-          indirectlyInstantiated,
-          node.isIndirectlyInstantiated,
-          "Unexpected `isIndirectlyInstantiated` on ClassHierarchyNode for "
-          "$cls.");
+  void checkClass(ClassElement cls,
+                  {bool directlyInstantiated: false,
+                   bool indirectlyInstantiated: false}) {
+    ClassHierarchyNode node = world.getClassHierarchyNode(cls);
+    Expect.isNotNull(node, "Expected ClassHierarchyNode for $cls.");
+    Expect.equals(
+        directlyInstantiated || indirectlyInstantiated,
+        node.isInstantiated,
+        "Unexpected `isInstantiated` on ClassHierarchyNode for $cls.");
+    Expect.equals(
+        directlyInstantiated,
+        node.isDirectlyInstantiated,
+        "Unexpected `isDirectlyInstantiated` on ClassHierarchyNode for "
+        "$cls.");
+    Expect.equals(
+        indirectlyInstantiated,
+        node.isIndirectlyInstantiated,
+        "Unexpected `isIndirectlyInstantiated` on ClassHierarchyNode for "
+        "$cls.");
+  }
+
+
+  checkClass(A, directlyInstantiated: true, indirectlyInstantiated: true);
+  checkClass(B, indirectlyInstantiated: true);
+  checkClass(C, directlyInstantiated: true, indirectlyInstantiated: true);
+  checkClass(D, directlyInstantiated: true);
+  checkClass(E, directlyInstantiated: true);
+  checkClass(F, directlyInstantiated: true);
+  checkClass(G, directlyInstantiated: true);
+
+  ClassHierarchyNodeIterator iterator;
+
+  void checkState(
+      ClassElement root,
+      {ClassElement currentNode,
+       List<List<ClassElement>> stack}) {
+
+    ClassElement classOf(ClassHierarchyNode node) {
+      return node != null ? node.cls : null;
     }
 
-
-    checkClass(A, directlyInstantiated: true, indirectlyInstantiated: true);
-    checkClass(B, indirectlyInstantiated: true);
-    checkClass(C, directlyInstantiated: true, indirectlyInstantiated: true);
-    checkClass(D, directlyInstantiated: true);
-    checkClass(E, directlyInstantiated: true);
-    checkClass(F, directlyInstantiated: true);
-    checkClass(G, directlyInstantiated: true);
-
-    ClassHierarchyNodeIterator iterator;
-
-    void checkState(
-        ClassElement root,
-        {ClassElement currentNode,
-         List<List<ClassElement>> stack}) {
-
-      ClassElement classOf(ClassHierarchyNode node) {
-        return node != null ? node.cls : null;
-      }
-
-      List<ClassElement> classesOf(Link<ClassHierarchyNode> link) {
-        if (link == null) return null;
-        return link.map(classOf).toList();
-      }
-
-      ClassElement foundRoot = iterator.root.cls;
-      ClassElement foundCurrentNode = classOf(iterator.currentNode);
-      List<ClassElement> foundStack = classesOf(iterator.stack);
-
-      StringBuffer sb = new StringBuffer();
-      sb.write('{\n root: $foundRoot');
-      sb.write('\n currentNode: $foundCurrentNode');
-      sb.write('\n stack: $foundStack\n}');
-
-      Expect.equals(root, foundRoot,
-          "Expected root $root in $sb.");
-      if (currentNode == null) {
-        Expect.isNull(iterator.currentNode,
-            "Unexpected non-null currentNode in $sb.");
-      } else {
-        Expect.isNotNull(foundCurrentNode,
-            "Expected non-null currentNode ${currentNode} in $sb.");
-        Expect.equals(currentNode, foundCurrentNode,
-            "Expected currentNode $currentNode in $sb.");
-      }
-      if (stack == null) {
-        Expect.isNull(foundStack,
-            "Unexpected non-null stack in $sb.");
-      } else {
-        Expect.isNotNull(foundStack,
-            "Expected non-null stack ${stack} in $sb.");
-        Expect.listEquals(stack, foundStack,
-            "Expected stack ${stack}, "
-            "found ${foundStack} in $sb.");
-      }
+    List<ClassElement> classesOf(Link<ClassHierarchyNode> link) {
+      if (link == null) return null;
+      return link.map(classOf).toList();
     }
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(G),
-        ClassHierarchyNode.ALL).iterator;
-    checkState(G, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(G, currentNode: G, stack: []);
-    Expect.equals(G, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(G, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+    ClassElement foundRoot = iterator.root.cls;
+    ClassElement foundCurrentNode = classOf(iterator.currentNode);
+    List<ClassElement> foundStack = classesOf(iterator.stack);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(G),
-        ClassHierarchyNode.ALL,
-        includeRoot: false).iterator;
-    checkState(G, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(G, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+    StringBuffer sb = new StringBuffer();
+    sb.write('{\n root: $foundRoot');
+    sb.write('\n currentNode: $foundCurrentNode');
+    sb.write('\n stack: $foundStack\n}');
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(C),
-        ClassHierarchyNode.ALL).iterator;
-    checkState(C, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(C, currentNode: C, stack: [E, F, G]);
-    Expect.equals(C, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(C, currentNode: E, stack: [F, G]);
-    Expect.equals(E, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(C, currentNode: F, stack: [G]);
-    Expect.equals(F, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(C, currentNode: G, stack: []);
-    Expect.equals(G, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(C, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+    Expect.equals(root, foundRoot,
+        "Expected root $root in $sb.");
+    if (currentNode == null) {
+      Expect.isNull(iterator.currentNode,
+          "Unexpected non-null currentNode in $sb.");
+    } else {
+      Expect.isNotNull(foundCurrentNode,
+          "Expected non-null currentNode ${currentNode} in $sb.");
+      Expect.equals(currentNode, foundCurrentNode,
+          "Expected currentNode $currentNode in $sb.");
+    }
+    if (stack == null) {
+      Expect.isNull(foundStack,
+          "Unexpected non-null stack in $sb.");
+    } else {
+      Expect.isNotNull(foundStack,
+          "Expected non-null stack ${stack} in $sb.");
+      Expect.listEquals(stack, foundStack,
+          "Expected stack ${stack}, "
+          "found ${foundStack} in $sb.");
+    }
+  }
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(D),
-        ClassHierarchyNode.ALL).iterator;
-    checkState(D, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(D, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(D, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(G),
+      ClassHierarchyNode.ALL).iterator;
+  checkState(G, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(G, currentNode: G, stack: []);
+  Expect.equals(G, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(G, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(B),
-        ClassHierarchyNode.ALL).iterator;
-    checkState(B, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(B, currentNode: B, stack: [D]);
-    Expect.equals(B, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(B, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(B, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(G),
+      ClassHierarchyNode.ALL,
+      includeRoot: false).iterator;
+  checkState(G, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(G, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(B),
-        ClassHierarchyNode.ALL,
-        includeRoot: false).iterator;
-    checkState(B, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(B, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(B, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(C),
+      ClassHierarchyNode.ALL).iterator;
+  checkState(C, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(C, currentNode: C, stack: [E, F, G]);
+  Expect.equals(C, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(C, currentNode: E, stack: [F, G]);
+  Expect.equals(E, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(C, currentNode: F, stack: [G]);
+  Expect.equals(F, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(C, currentNode: G, stack: []);
+  Expect.equals(G, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(C, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(B),
-        new EnumSet<Instantiation>.fromValues(<Instantiation>[
-            Instantiation.DIRECTLY_INSTANTIATED,
-            Instantiation.UNINSTANTIATED])).iterator;
-    checkState(B, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(B, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(B, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(D),
+      ClassHierarchyNode.ALL).iterator;
+  checkState(D, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(D, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(D, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(A),
-        ClassHierarchyNode.ALL).iterator;
-    checkState(A, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: A, stack: [C, B]);
-    Expect.equals(A, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: C, stack: [E, F, G, B]);
-    Expect.equals(C, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: E, stack: [F, G, B]);
-    Expect.equals(E, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: F, stack: [G, B]);
-    Expect.equals(F, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: G, stack: [B]);
-    Expect.equals(G, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: B, stack: [D]);
-    Expect.equals(B, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(A, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(B),
+      ClassHierarchyNode.ALL).iterator;
+  checkState(B, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(B, currentNode: B, stack: [D]);
+  Expect.equals(B, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(B, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(B, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(A),
-        ClassHierarchyNode.ALL,
-        includeRoot: false).iterator;
-    checkState(A, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: C, stack: [E, F, G, B]);
-    Expect.equals(C, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: E, stack: [F, G, B]);
-    Expect.equals(E, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: F, stack: [G, B]);
-    Expect.equals(F, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: G, stack: [B]);
-    Expect.equals(G, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: B, stack: [D]);
-    Expect.equals(B, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(A, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(B),
+      ClassHierarchyNode.ALL,
+      includeRoot: false).iterator;
+  checkState(B, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(B, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(B, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(A),
-        new EnumSet<Instantiation>.fromValues(<Instantiation>[
-            Instantiation.DIRECTLY_INSTANTIATED,
-            Instantiation.UNINSTANTIATED])).iterator;
-    checkState(A, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: A, stack: [C, B]);
-    Expect.equals(A, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: C, stack: [E, F, G, B]);
-    Expect.equals(C, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: E, stack: [F, G, B]);
-    Expect.equals(E, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: F, stack: [G, B]);
-    Expect.equals(F, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: G, stack: [B]);
-    Expect.equals(G, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(A, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(B),
+      new EnumSet<Instantiation>.fromValues(<Instantiation>[
+          Instantiation.DIRECTLY_INSTANTIATED,
+          Instantiation.UNINSTANTIATED])).iterator;
+  checkState(B, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(B, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(B, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 
-    iterator = new ClassHierarchyNodeIterable(
-        world.getClassHierarchyNode(A),
-        new EnumSet<Instantiation>.fromValues(<Instantiation>[
-            Instantiation.DIRECTLY_INSTANTIATED,
-            Instantiation.UNINSTANTIATED]),
-        includeRoot: false).iterator;
-    checkState(A, currentNode: null, stack: null);
-    Expect.isNull(iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: C, stack: [E, F, G, B]);
-    Expect.equals(C, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: E, stack: [F, G, B]);
-    Expect.equals(E, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: F, stack: [G, B]);
-    Expect.equals(F, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: G, stack: [B]);
-    Expect.equals(G, iterator.current);
-    Expect.isTrue(iterator.moveNext());
-    checkState(A, currentNode: D, stack: []);
-    Expect.equals(D, iterator.current);
-    Expect.isFalse(iterator.moveNext());
-    checkState(A, currentNode: null, stack: []);
-    Expect.isNull(iterator.current);
-  }));
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(A),
+      ClassHierarchyNode.ALL).iterator;
+  checkState(A, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: A, stack: [C, B]);
+  Expect.equals(A, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: C, stack: [E, F, G, B]);
+  Expect.equals(C, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: E, stack: [F, G, B]);
+  Expect.equals(E, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: F, stack: [G, B]);
+  Expect.equals(F, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: G, stack: [B]);
+  Expect.equals(G, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: B, stack: [D]);
+  Expect.equals(B, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(A, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
+
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(A),
+      ClassHierarchyNode.ALL,
+      includeRoot: false).iterator;
+  checkState(A, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: C, stack: [E, F, G, B]);
+  Expect.equals(C, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: E, stack: [F, G, B]);
+  Expect.equals(E, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: F, stack: [G, B]);
+  Expect.equals(F, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: G, stack: [B]);
+  Expect.equals(G, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: B, stack: [D]);
+  Expect.equals(B, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(A, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
+
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(A),
+      new EnumSet<Instantiation>.fromValues(<Instantiation>[
+          Instantiation.DIRECTLY_INSTANTIATED,
+          Instantiation.UNINSTANTIATED])).iterator;
+  checkState(A, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: A, stack: [C, B]);
+  Expect.equals(A, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: C, stack: [E, F, G, B]);
+  Expect.equals(C, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: E, stack: [F, G, B]);
+  Expect.equals(E, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: F, stack: [G, B]);
+  Expect.equals(F, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: G, stack: [B]);
+  Expect.equals(G, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(A, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
+
+  iterator = new ClassHierarchyNodeIterable(
+      world.getClassHierarchyNode(A),
+      new EnumSet<Instantiation>.fromValues(<Instantiation>[
+          Instantiation.DIRECTLY_INSTANTIATED,
+          Instantiation.UNINSTANTIATED]),
+      includeRoot: false).iterator;
+  checkState(A, currentNode: null, stack: null);
+  Expect.isNull(iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: C, stack: [E, F, G, B]);
+  Expect.equals(C, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: E, stack: [F, G, B]);
+  Expect.equals(E, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: F, stack: [G, B]);
+  Expect.equals(F, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: G, stack: [B]);
+  Expect.equals(G, iterator.current);
+  Expect.isTrue(iterator.moveNext());
+  checkState(A, currentNode: D, stack: []);
+  Expect.equals(D, iterator.current);
+  Expect.isFalse(iterator.moveNext());
+  checkState(A, currentNode: null, stack: []);
+  Expect.isNull(iterator.current);
 }
 
+testForEach() async {
+  var env = await TypeEnvironment.create(r"""
+      ///        A
+      ///       / \
+      ///      B   C
+      ///     /   /|\
+      ///    D   E F G
+      ///         / \
+      ///         H I
+      ///
+      class A implements X {}
+      class B extends A {}
+      class C extends A {}
+      class D extends B {}
+      class E extends C {}
+      class F extends C implements B {}
+      class G extends C implements D {}
+      class H extends F {}
+      class I extends F {}
+      class X {}
+      """,
+        mainSource: r"""
+      main() {
+        new A();
+        new C();
+        new D();
+        new E();
+        new F();
+        new G();
+        new H();
+        new I();
+      }
+      """,
+      useMockCompiler: false);
+  World world = env.compiler.world;
+
+  ClassElement A = env.getElement("A");
+  ClassElement B = env.getElement("B");
+  ClassElement C = env.getElement("C");
+  ClassElement D = env.getElement("D");
+  ClassElement E = env.getElement("E");
+  ClassElement F = env.getElement("F");
+  ClassElement G = env.getElement("G");
+  ClassElement H = env.getElement("H");
+  ClassElement I = env.getElement("I");
+  ClassElement X = env.getElement("X");
+
+  void checkForEachSubclass(ClassElement cls, List<ClassElement> expected) {
+    ClassSet classSet = world.getClassSet(cls);
+    List<ClassElement> visited = <ClassElement>[];
+    classSet.forEachSubclass((ClassElement cls) {
+      visited.add(cls);
+    }, ClassHierarchyNode.ALL);
+
+    Expect.listEquals(expected, visited,
+        "Unexpected classes on $cls.forEachSubclass:\n"
+        "Actual: $visited, expected: $expected\n$classSet");
+
+    visited = <ClassElement>[];
+    classSet.forEachSubclass((ClassElement cls) {
+      visited.add(cls);
+      return ForEach.CONTINUE;
+    }, ClassHierarchyNode.ALL);
+
+    Expect.listEquals(expected, visited,
+        "Unexpected classes on $cls.forEachSubclass:\n"
+        "Actual: $visited, expected: $expected\n$classSet");
+  }
+
+  checkForEachSubclass(A, [A, B, D, C, G, F, I, H, E]);
+  checkForEachSubclass(B, [B, D]);
+  checkForEachSubclass(C, [C, G, F, I, H, E]);
+  checkForEachSubclass(D, [D]);
+  checkForEachSubclass(E, [E]);
+  checkForEachSubclass(F, [F, I, H]);
+  checkForEachSubclass(G, [G]);
+  checkForEachSubclass(H, [H]);
+  checkForEachSubclass(I, [I]);
+  checkForEachSubclass(X, [X]);
+
+  void checkForEachSubtype(ClassElement cls, List<ClassElement> expected) {
+    ClassSet classSet = world.getClassSet(cls);
+    List<ClassElement> visited = <ClassElement>[];
+    classSet.forEachSubtype((ClassElement cls) {
+      visited.add(cls);
+    }, ClassHierarchyNode.ALL);
+
+    Expect.listEquals(expected, visited,
+        "Unexpected classes on $cls.forEachSubtype:\n"
+        "Actual: $visited, expected: $expected\n$classSet");
+
+    visited = <ClassElement>[];
+    classSet.forEachSubtype((ClassElement cls) {
+      visited.add(cls);
+      return ForEach.CONTINUE;
+    }, ClassHierarchyNode.ALL);
+
+    Expect.listEquals(expected, visited,
+        "Unexpected classes on $cls.forEachSubtype:\n"
+        "Actual: $visited, expected: $expected\n$classSet");
+  }
+
+  checkForEachSubtype(A, [A, B, D, C, G, F, I, H, E]);
+  checkForEachSubtype(B, [B, D, F, I, H, G]);
+  checkForEachSubtype(C, [C, G, F, I, H, E]);
+  checkForEachSubtype(D, [D, G]);
+  checkForEachSubtype(E, [E]);
+  checkForEachSubtype(F, [F, I, H]);
+  checkForEachSubtype(G, [G]);
+  checkForEachSubtype(H, [H]);
+  checkForEachSubtype(I, [I]);
+  checkForEachSubtype(X, [X, A, B, D, C, G, F, I, H, E]);
+
+  void checkForEach(
+      ClassElement cls,
+      List<ClassElement> expected,
+      {ClassElement stop,
+       List<ClassElement> skipSubclasses: const <ClassElement>[],
+       bool forEachSubtype: false,
+       EnumSet<Instantiation> mask}) {
+
+    if (mask == null) {
+      mask = ClassHierarchyNode.ALL;
+    }
+
+    ClassSet classSet = world.getClassSet(cls);
+    List<ClassElement> visited = <ClassElement>[];
+
+    ForEach visit(ClassElement cls) {
+      visited.add(cls);
+      if (cls == stop) {
+        return ForEach.STOP;
+      } else if (skipSubclasses.contains(cls)) {
+        return ForEach.SKIP_SUBCLASSES;
+      }
+      return ForEach.CONTINUE;
+    }
+
+    if (forEachSubtype) {
+      classSet.forEachSubtype(visit, mask);
+    } else {
+      classSet.forEachSubclass(visit, mask);
+    }
+
+    Expect.listEquals(expected, visited,
+        "Unexpected classes on $cls."
+        "forEach${forEachSubtype ? 'Subtype' : 'Subclass'} "
+        "(stop:$stop, skipSubclasses:$skipSubclasses):\n"
+        "Actual: $visited, expected: $expected\n$classSet");
+  }
+
+  checkForEach(A, [A, B, D, C, G, F, I, H, E]);
+  checkForEach(A, [A], stop: A);
+  checkForEach(A, [A, B, C, G, F, I, H, E], skipSubclasses: [B]);
+  checkForEach(A, [A, B, C], skipSubclasses: [B, C]);
+  checkForEach(A, [A, B, C, G], stop: G, skipSubclasses: [B]);
+
+  checkForEach(B, [B, D, F, I, H, G], forEachSubtype: true);
+  checkForEach(B, [B, D], stop: D, forEachSubtype: true);
+  checkForEach(B, [B, D, F, G], skipSubclasses: [F], forEachSubtype: true);
+  checkForEach(B, [B, F, I, H, G], skipSubclasses: [B], forEachSubtype: true);
+  checkForEach(B, [B, D, F, I, H, G], skipSubclasses: [D], forEachSubtype: true);
+
+  checkForEach(X, [X, A, B, D, C, G, F, I, H, E], forEachSubtype: true);
+  checkForEach(X, [X, A, B, D], stop: D, forEachSubtype: true);
+  checkForEach(X, [X, A, B, D, C, G, F, E],
+      skipSubclasses: [F], forEachSubtype: true);
+  checkForEach(X, [X, A, B, D, C, G, F, I, H, E],
+      skipSubclasses: [X], forEachSubtype: true);
+  checkForEach(X, [X, A, B, D, C, G, F, I, H, E],
+      skipSubclasses: [D], forEachSubtype: true);
+  checkForEach(X, [A, D, C, G, F, I, H, E],
+      forEachSubtype: true,
+      mask: ClassHierarchyNode.DIRECTLY_INSTANTIATED);
+  checkForEach(X, [A, B, D, C, G, F, I, H, E],
+      forEachSubtype: true,
+      mask: ClassHierarchyNode.INSTANTIATED);
+
+  void checkAny(
+      ClassElement cls,
+      List<ClassElement> expected,
+      {ClassElement find,
+       bool expectedResult,
+       bool anySubtype: false}) {
+    ClassSet classSet = world.getClassSet(cls);
+    List<ClassElement> visited = <ClassElement>[];
+
+    bool visit(ClassElement cls) {
+      visited.add(cls);
+      return cls == find;
+    }
+
+    bool result;
+    if (anySubtype) {
+      result = classSet.anySubtype(visit, ClassHierarchyNode.ALL);
+    } else {
+      result = classSet.anySubclass(visit, ClassHierarchyNode.ALL);
+    }
+
+    Expect.equals(expectedResult, result,
+        "Unexpected result on $cls."
+        "any${anySubtype ? 'Subtype' : 'Subclass'} "
+        "(find:$find).");
+
+    Expect.listEquals(expected, visited,
+        "Unexpected classes on $cls."
+        "any${anySubtype ? 'Subtype' : 'Subclass'} "
+        "(find:$find):\n"
+        "Actual: $visited, expected: $expected\n$classSet");
+  }
+
+  checkAny(A, [A, B, D, C, G, F, I, H, E], expectedResult: false);
+  checkAny(A, [A], find: A, expectedResult: true);
+  checkAny(A, [A, B, D, C, G, F, I], find: I, expectedResult: true);
+
+  checkAny(B, [B, D, F, I, H, G], anySubtype: true, expectedResult: false);
+  checkAny(B, [B, D, F, I, H, G],
+      find: A, anySubtype: true, expectedResult: false);
+  checkAny(B, [B, D],
+      find: D, anySubtype: true, expectedResult: true);
+  checkAny(B, [B, D, F, I],
+      find: I, anySubtype: true, expectedResult: true);
+
+  checkAny(X, [X, A, B, D, C, G, F, I, H, E],
+      anySubtype: true, expectedResult: false);
+  checkAny(X, [X, A],
+      find: A, anySubtype: true, expectedResult: true);
+  checkAny(X, [X, A, B, D],
+      find: D, anySubtype: true, expectedResult: true);
+  checkAny(X, [X, A, B, D, C, G, F, I],
+      find: I, anySubtype: true, expectedResult: true);
+}
diff --git a/tests/compiler/dart2js/cps_ir/closures_16_test.dart b/tests/compiler/dart2js/cps_ir/closures_16_test.dart
new file mode 100644
index 0000000..6b359ec
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/closures_16_test.dart
@@ -0,0 +1,15 @@
+// ---- AUTO-GENERATED -------------------
+// This file was autogenerated by running:
+//
+//     dart path/to/up_to_date_test.dart update
+//
+// Do not edit this file by hand.
+// ---------------------------------------
+
+library tests.compiler.dart2js.cps_ir.closures_16.dart;
+
+import 'runner.dart';
+
+main(args) {
+  runTest("closures_16.dart", update: args.length > 0 && args[0] == "update");
+}
diff --git a/tests/compiler/dart2js/cps_ir/expected/argument_refinement_21.js b/tests/compiler/dart2js/cps_ir/expected/argument_refinement_21.js
index 589d358..2c4e7c7 100644
--- a/tests/compiler/dart2js/cps_ir/expected/argument_refinement_21.js
+++ b/tests/compiler/dart2js/cps_ir/expected/argument_refinement_21.js
@@ -16,15 +16,6 @@
   P.print(v0);
   if (!v0)
     throw H.wrapException(H.argumentErrorValue(y));
-  if (x < y)
-    v0 = -1;
-  else if (x > y)
-    v0 = 1;
-  else if (x === y) {
-    v0 = x === 0;
-    v0 = v0 ? (y === 0 ? 1 / y < 0 : y < 0) === (v0 ? 1 / x < 0 : x < 0) ? 0 : (v0 ? 1 / x < 0 : x < 0) ? -1 : 1 : 0;
-  } else
-    v0 = isNaN(x) ? isNaN(y) ? 0 : 1 : -1;
-  P.print(v0);
+  P.print(x < y ? -1 : x > y ? 1 : x === y ? x === 0 ? 1 / x < 0 === (y === 0 ? 1 / y < 0 : y < 0) ? 0 : 1 / x < 0 ? -1 : 1 : 0 : isNaN(x) ? isNaN(y) ? 0 : 1 : -1);
   P.print(true);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_1.js b/tests/compiler/dart2js/cps_ir/expected/basic_1.js
index 1cf4ed5..5ae55be 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_1.js
@@ -15,12 +15,12 @@
 // }
 
 function() {
-  var l = [1, 2, 3], m = P.LinkedHashMap_LinkedHashMap$_literal(["s", 1]);
+  var l = [1, 2, 3], m = P.LinkedHashMap__makeLiteral(["s", 1]);
   P.print("()");
   P.print("(true)");
   P.print("(1)");
   P.print("(" + P.IterableBase_iterableToFullString([1, 2, 3], "[", "]") + ")");
-  P.print("(" + P.Maps_mapToString(P.LinkedHashMap_LinkedHashMap$_literal(["s", 1])) + ")");
+  P.print("(" + P.Maps_mapToString(P.LinkedHashMap__makeLiteral(["s", 1])) + ")");
   P.print("(1)");
   P.print("(" + P.IterableBase_iterableToFullString(l, "[", "]") + ")");
   P.print("(" + P.Maps_mapToString(m) + ")");
diff --git a/tests/compiler/dart2js/cps_ir/expected/basic_10.js b/tests/compiler/dart2js/cps_ir/expected/basic_10.js
index cfd6571..104f614 100644
--- a/tests/compiler/dart2js/cps_ir/expected/basic_10.js
+++ b/tests/compiler/dart2js/cps_ir/expected/basic_10.js
@@ -4,7 +4,7 @@
 // }
 
 function() {
-  var v0 = Date.now() < Date.now(), line = v0 ? "true" : false === v0 ? "false" : String(v0);
+  var line = Date.now() < Date.now() ? "true" : "false";
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_10.js b/tests/compiler/dart2js/cps_ir/expected/closures_10.js
index a628815..64e5e31 100644
--- a/tests/compiler/dart2js/cps_ir/expected/closures_10.js
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_10.js
@@ -8,7 +8,7 @@
 // }
 
 function() {
-  var line = H.S(new V.A_b_closure(V.A$()).call$0());
+  var line = H.S(V.A$().a$0());
   if (typeof dartPrint == "function")
     dartPrint(line);
   else if (typeof console == "object" && typeof console.log != "undefined")
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_15.js b/tests/compiler/dart2js/cps_ir/expected/closures_15.js
index 46c7d38..cf37dd2 100644
--- a/tests/compiler/dart2js/cps_ir/expected/closures_15.js
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_15.js
@@ -13,5 +13,5 @@
 function(x) {
   V.Foo$();
   P.print("getter");
-  P.print(new V.Foo_getter_closure().call$1(123));
+  P.print(123);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/closures_16.js b/tests/compiler/dart2js/cps_ir/expected/closures_16.js
new file mode 100644
index 0000000..e589971
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/expected/closures_16.js
@@ -0,0 +1,17 @@
+// Expectation for test: 
+// class Foo {
+//   get getter {
+//     print('getter');
+//     return (x) { try { return x; } finally { } };  // Inhibit inlining.
+//   }
+// }
+// main(x) {
+//   // Getter may or may not be inlined.
+//   var notTearOff = new Foo().getter;
+//   // Closure is not inlined.
+//   print(notTearOff(123));
+// }
+
+function(x) {
+  P.print(V.Foo$().get$getter().call$1(123));
+}
diff --git a/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_2.js b/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_2.js
index 73e278b..4fdd8a2 100644
--- a/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_2.js
+++ b/tests/compiler/dart2js/cps_ir/expected/codeUnitAt_2.js
@@ -11,13 +11,12 @@
 // }
 
 function() {
-  var v0 = "ABC".length, sum = 0, i = 0;
-  for (; i < v0; sum += "ABC".charCodeAt(i), ++i)
+  var sum = 0, i = 0;
+  for (; i < 3; sum += "ABC".charCodeAt(i), ++i)
     ;
   P.print(sum);
-  v0 = "Hello".length;
   sum = 0;
-  for (i = 0; i < v0; sum += "Hello".charCodeAt(i), ++i)
+  for (i = 0; i < 5; sum += "Hello".charCodeAt(i), ++i)
     ;
   P.print(sum);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/control_flow_1.js b/tests/compiler/dart2js/cps_ir/expected/control_flow_1.js
index 950d594..7fd9aff 100644
--- a/tests/compiler/dart2js/cps_ir/expected/control_flow_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/control_flow_1.js
@@ -4,6 +4,6 @@
 // }
 
 function() {
-  while (true)
+  for (;;)
     ;
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/control_flow_2.js b/tests/compiler/dart2js/cps_ir/expected/control_flow_2.js
index 79c2ddd..3cb9718 100644
--- a/tests/compiler/dart2js/cps_ir/expected/control_flow_2.js
+++ b/tests/compiler/dart2js/cps_ir/expected/control_flow_2.js
@@ -1,5 +1,5 @@
 // Expectation for test: 
-// foo(a) { print(a); return a; }
+// foo(a) { try { print(a); } finally { return a; } }
 // 
 // main() {
 //   while (true) {
@@ -14,20 +14,14 @@
 // }
 
 function() {
-  L1:
-    while (true)
-      L0:
-        while (true)
-          while (true) {
-            P.print(true);
-            if (false) {
-              P.print(1);
-              continue L0;
-            }
-            P.print(false);
-            if (false) {
-              P.print(2);
-              continue L1;
-            }
+  L0:
+    for (;;)
+      for (;;) {
+        while (V.foo(true))
+          if (V.foo(false)) {
+            P.print(2);
+            continue L0;
           }
+        P.print(1);
+      }
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/control_flow_3.js b/tests/compiler/dart2js/cps_ir/expected/control_flow_3.js
index 514ed7b..f7c0900 100644
--- a/tests/compiler/dart2js/cps_ir/expected/control_flow_3.js
+++ b/tests/compiler/dart2js/cps_ir/expected/control_flow_3.js
@@ -1,5 +1,5 @@
 // Expectation for test: 
-// foo(a) { print(a); return a; }
+// foo(a) { try { print(a); } finally { return a; } }
 // 
 // main() {
 //   for (int i = 0; foo(true); i = foo(i)) {
@@ -10,17 +10,11 @@
 // }
 
 function() {
-  while (true) {
-    P.print(true);
-    if (true === true) {
-      P.print(1);
-      P.print(false);
-      if (false !== true) {
-        P.print(0);
-        continue;
-      }
-    }
-    P.print(2);
-    return null;
+  var i = 0;
+  for (; V.foo(true) === true; i = V.foo(i)) {
+    P.print(1);
+    if (V.foo(false) === true)
+      break;
   }
+  P.print(2);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/control_flow_4.js b/tests/compiler/dart2js/cps_ir/expected/control_flow_4.js
index 00099d0..dae4cc7 100644
--- a/tests/compiler/dart2js/cps_ir/expected/control_flow_4.js
+++ b/tests/compiler/dart2js/cps_ir/expected/control_flow_4.js
@@ -1,5 +1,5 @@
 // Expectation for test: 
-// foo(a) { print(a); return a; }
+// foo(a) { try { print(a); } finally { return a; } }
 // 
 // main() {
 //  foo(false);
@@ -12,8 +12,7 @@
 // }
 
 function() {
-  P.print(false);
-  P.print(true);
-  true ? P.print(1) : P.print(2);
+  V.foo(false);
+  V.foo(true) ? P.print(1) : P.print(2);
   P.print(3);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/control_flow_5.js b/tests/compiler/dart2js/cps_ir/expected/control_flow_5.js
index 78c0641..0f28201 100644
--- a/tests/compiler/dart2js/cps_ir/expected/control_flow_5.js
+++ b/tests/compiler/dart2js/cps_ir/expected/control_flow_5.js
@@ -1,5 +1,5 @@
 // Expectation for test: 
-// foo(a) { print(a); return a; }
+// foo(a) { try { print(a); } finally { return a; } }
 // 
 // main() {
 //  foo(false);
@@ -14,9 +14,8 @@
 // }
 
 function() {
-  P.print(false);
-  P.print(true);
-  if (true) {
+  V.foo(false);
+  if (V.foo(true)) {
     P.print(1);
     P.print(1);
   } else {
diff --git a/tests/compiler/dart2js/cps_ir/expected/literals_1.js b/tests/compiler/dart2js/cps_ir/expected/literals_1.js
index ef654f5..d70ebf8 100644
--- a/tests/compiler/dart2js/cps_ir/expected/literals_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/literals_1.js
@@ -14,7 +14,7 @@
   P.print([1]);
   P.print([1, 2]);
   P.print([1, [1, 2]]);
-  P.print(P.LinkedHashMap_LinkedHashMap$_empty());
-  P.print(P.LinkedHashMap_LinkedHashMap$_literal([1, 2]));
-  P.print(P.LinkedHashMap_LinkedHashMap$_literal([[1, 2], [3, 4]]));
+  P.print(P.LinkedHashMap__makeEmpty());
+  P.print(P.LinkedHashMap__makeLiteral([1, 2]));
+  P.print(P.LinkedHashMap__makeLiteral([[1, 2], [3, 4]]));
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators2_1.js b/tests/compiler/dart2js/cps_ir/expected/operators2_1.js
index 5e39b1e..71a1da5 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators2_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators2_1.js
@@ -1,11 +1,12 @@
 // Expectation for test: 
+// // Method to test: function(foo)
 // foo(a, b) => ((a & 0xff0000) >> 1) & b;
 // main() {
+//   print(foo.toString());
 //   print(foo(123, 234));
 //   print(foo(0, 2));
 // }
 
-function() {
-  P.print((123 & 16711680) >>> 1 & 234);
-  P.print((0 & 16711680) >>> 1 & 2);
+function(a, b) {
+  return (a & 16711680) >>> 1 & b;
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators2_2.js b/tests/compiler/dart2js/cps_ir/expected/operators2_2.js
index 8d6d52d..7858649 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators2_2.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators2_2.js
@@ -1,11 +1,12 @@
 // Expectation for test: 
+// // Method to test: function(foo)
 // foo(a) => ~a;
 // main() {
+//   print(foo.toString());
 //   print(foo(1));
 //   print(foo(10));
 // }
 
-function() {
-  P.print(~1 >>> 0);
-  P.print(~10 >>> 0);
+function(a) {
+  return ~a >>> 0;
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators2_3.js b/tests/compiler/dart2js/cps_ir/expected/operators2_3.js
index ff5d25d..bf578b2 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators2_3.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators2_3.js
@@ -8,5 +8,5 @@
 
 function(a) {
   var result = a % 13;
-  return result === 0 ? 0 : result > 0 ? result : 13 < 0 ? result - 13 : result + 13;
+  return result === 0 ? 0 : result > 0 ? result : result + 13;
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators2_7.js b/tests/compiler/dart2js/cps_ir/expected/operators2_7.js
index 837393f..9faff59 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators2_7.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators2_7.js
@@ -1,11 +1,12 @@
 // Expectation for test: 
+// // Method to test: function(foo)
 // foo(a) => a ~/ 13;
 // main() {
+//   print(foo.toString());
 //   print(foo(5));
 //   print(foo(100));
 // }
 
-function() {
-  P.print(5 / 13 | 0);
-  P.print(100 / 13 | 0);
+function(a) {
+  return a / 13 | 0;
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_4.js b/tests/compiler/dart2js/cps_ir/expected/operators_4.js
index f86a490..ccfc0a8 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_4.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_4.js
@@ -16,7 +16,7 @@
       v0 = false;
     } else
       v0 = false;
-    line = false === v0 ? "false" : String(v0);
+    line = v0 ? String(v0) : "false";
   }
   if (typeof dartPrint == "function")
     dartPrint(line);
diff --git a/tests/compiler/dart2js/cps_ir/expected/operators_5.js b/tests/compiler/dart2js/cps_ir/expected/operators_5.js
index 3ff812c..d2986cc 100644
--- a/tests/compiler/dart2js/cps_ir/expected/operators_5.js
+++ b/tests/compiler/dart2js/cps_ir/expected/operators_5.js
@@ -10,7 +10,7 @@
     if (!(v0 > 10)) {
       $.x = v0 = $.x + 1;
       if (!(v0 > 10)) {
-        line = false === false ? "false" : String(false);
+        line = "false";
         break L0;
       }
     }
diff --git a/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js b/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
new file mode 100644
index 0000000..21c1d71
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/expected/optimize_indexers.js
@@ -0,0 +1,37 @@
+// Expectation for test: 
+// // Method to test: function(test)
+// import 'package:expect/expect.dart';
+// 
+// // This example illustrates a case we wish to do better in terms of inlining and
+// // code generation.
+// //
+// // Today this function is compiled without inlining Wrapper.[], JSArray.[] and
+// // Wrapper.[]= because:
+// // JSArray.[] is too big (14 nodes)
+// // Wrapper.[] is too big if we force inlining of JSArray (15 nodes)
+// // Wrapper.[]= is even bigger (46 nodes)
+// //
+// // See #25478 for ideas on how to make this better.
+// @NoInline()
+// test(data, x) {
+//   data[x + 1] = data[x];
+// }
+// 
+// main() {
+//   var wrapper = new Wrapper();
+//   wrapper[33] = wrapper[1]; // make Wrapper.[]= and [] used more than once.
+//   print(test(new Wrapper(), int.parse('2')));
+// }
+// 
+// class Wrapper {
+//   final List arr = <bool>[true, false, false, true];
+//   operator[](int i) => this.arr[i];
+//   operator[]=(int i, v) {
+//     if (i > arr.length - 1) arr.length = i + 1;
+//     return arr[i] = v;
+//   }
+// }
+
+function(data, x) {
+  data.$indexSet(0, J.$add$ns(x, 1), C.JSArray_methods.$index(data.arr, x));
+}
diff --git a/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js b/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
new file mode 100644
index 0000000..a3a2ae0
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/expected/redundant_condition.js
@@ -0,0 +1,35 @@
+// Expectation for test: 
+// // This test illustrates an opportunity to remove redundant code by
+// // propagating inforamtion after inlining.
+// //
+// // The code below inlines `foo` twice, but we don't propagate that we already
+// // know from the first `foo` that `a` is an int, so the second check can be
+// // removed entirely.
+// 
+// import 'package:expect/expect.dart';
+// 
+// main() {
+//   var a = nextNumber();
+//   action(foo(a));
+//   action(foo(a));
+// }
+// 
+// foo(x) {
+//   if (x is! int) throw "error 1";
+//   return x + 5 % 100;
+// }
+// 
+// @NoInline() @AssumeDynamic()
+// nextNumber() => int.parse('33');
+// 
+// @NoInline()
+// action(v) => print(v);
+
+function() {
+  var a = V.nextNumber();
+  if (!(typeof a === "number" && Math.floor(a) === a))
+    throw H.wrapException("error 1");
+  a += 5;
+  V.action(a);
+  V.action(a);
+}
diff --git a/tests/compiler/dart2js/cps_ir/expected/supercall_1.js b/tests/compiler/dart2js/cps_ir/expected/supercall_1.js
index 4c7ee26..cc601dd 100644
--- a/tests/compiler/dart2js/cps_ir/expected/supercall_1.js
+++ b/tests/compiler/dart2js/cps_ir/expected/supercall_1.js
@@ -1,7 +1,7 @@
 // Expectation for test: 
 // class Base {
 //   m(x) {
-//     print(x+1);
+//     try { print(x+1); } finally { }
 //   }
 // }
 // class Sub extends Base {
@@ -12,15 +12,6 @@
 // }
 
 function() {
-  var line = "" + (100 + 10 + 1);
-  V.Sub$();
-  if (typeof dartPrint == "function")
-    dartPrint(line);
-  else if (typeof console == "object" && typeof console.log != "undefined")
-    console.log(line);
-  else if (!(typeof window == "object")) {
-    if (!(typeof print == "function"))
-      throw "Unable to print message: " + String(line);
-    print(line);
-  }
+  var v0 = V.Sub$();
+  V.Base.prototype.m$1.call(v0, 110);
 }
diff --git a/tests/compiler/dart2js/cps_ir/expected/supercall_2.js b/tests/compiler/dart2js/cps_ir/expected/supercall_2.js
index 13b1d21..27f6c2b 100644
--- a/tests/compiler/dart2js/cps_ir/expected/supercall_2.js
+++ b/tests/compiler/dart2js/cps_ir/expected/supercall_2.js
@@ -25,5 +25,5 @@
 
 function() {
   var v0 = V.Sub$();
-  V.Base.prototype.$add.call(v0, v0, 10000 + 1);
+  V.Base.prototype.$add.call(v0, v0, 10001);
 }
diff --git a/tests/compiler/dart2js/cps_ir/input/closures_16.dart b/tests/compiler/dart2js/cps_ir/input/closures_16.dart
new file mode 100644
index 0000000..0d57270
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/input/closures_16.dart
@@ -0,0 +1,12 @@
+class Foo {
+  get getter {
+    print('getter');
+    return (x) { try { return x; } finally { } };  // Inhibit inlining.
+  }
+}
+main(x) {
+  // Getter may or may not be inlined.
+  var notTearOff = new Foo().getter;
+  // Closure is not inlined.
+  print(notTearOff(123));
+}
diff --git a/tests/compiler/dart2js/cps_ir/input/control_flow_2.dart b/tests/compiler/dart2js/cps_ir/input/control_flow_2.dart
index dd06bed..a7baf52 100644
--- a/tests/compiler/dart2js/cps_ir/input/control_flow_2.dart
+++ b/tests/compiler/dart2js/cps_ir/input/control_flow_2.dart
@@ -1,4 +1,4 @@
-foo(a) { print(a); return a; }
+foo(a) { try { print(a); } finally { return a; } }
 
 main() {
   while (true) {
diff --git a/tests/compiler/dart2js/cps_ir/input/control_flow_3.dart b/tests/compiler/dart2js/cps_ir/input/control_flow_3.dart
index 51cead4..8335da4 100644
--- a/tests/compiler/dart2js/cps_ir/input/control_flow_3.dart
+++ b/tests/compiler/dart2js/cps_ir/input/control_flow_3.dart
@@ -1,4 +1,4 @@
-foo(a) { print(a); return a; }
+foo(a) { try { print(a); } finally { return a; } }
 
 main() {
   for (int i = 0; foo(true); i = foo(i)) {
diff --git a/tests/compiler/dart2js/cps_ir/input/control_flow_4.dart b/tests/compiler/dart2js/cps_ir/input/control_flow_4.dart
index 881d8ce..dd9fa9c 100644
--- a/tests/compiler/dart2js/cps_ir/input/control_flow_4.dart
+++ b/tests/compiler/dart2js/cps_ir/input/control_flow_4.dart
@@ -1,4 +1,4 @@
-foo(a) { print(a); return a; }
+foo(a) { try { print(a); } finally { return a; } }
 
 main() {
  foo(false);
diff --git a/tests/compiler/dart2js/cps_ir/input/control_flow_5.dart b/tests/compiler/dart2js/cps_ir/input/control_flow_5.dart
index 6efe03c..ee75818 100644
--- a/tests/compiler/dart2js/cps_ir/input/control_flow_5.dart
+++ b/tests/compiler/dart2js/cps_ir/input/control_flow_5.dart
@@ -1,4 +1,4 @@
-foo(a) { print(a); return a; }
+foo(a) { try { print(a); } finally { return a; } }
 
 main() {
  foo(false);
diff --git a/tests/compiler/dart2js/cps_ir/input/operators2_1.dart b/tests/compiler/dart2js/cps_ir/input/operators2_1.dart
index 05da19c..38b8f4f 100644
--- a/tests/compiler/dart2js/cps_ir/input/operators2_1.dart
+++ b/tests/compiler/dart2js/cps_ir/input/operators2_1.dart
@@ -1,5 +1,7 @@
+// Method to test: function(foo)
 foo(a, b) => ((a & 0xff0000) >> 1) & b;
 main() {
+  print(foo.toString());
   print(foo(123, 234));
   print(foo(0, 2));
 }
diff --git a/tests/compiler/dart2js/cps_ir/input/operators2_2.dart b/tests/compiler/dart2js/cps_ir/input/operators2_2.dart
index 56bebd9..f38e967 100644
--- a/tests/compiler/dart2js/cps_ir/input/operators2_2.dart
+++ b/tests/compiler/dart2js/cps_ir/input/operators2_2.dart
@@ -1,5 +1,7 @@
+// Method to test: function(foo)
 foo(a) => ~a;
 main() {
+  print(foo.toString());
   print(foo(1));
   print(foo(10));
 }
diff --git a/tests/compiler/dart2js/cps_ir/input/operators2_7.dart b/tests/compiler/dart2js/cps_ir/input/operators2_7.dart
index f2c68ee..225701b 100644
--- a/tests/compiler/dart2js/cps_ir/input/operators2_7.dart
+++ b/tests/compiler/dart2js/cps_ir/input/operators2_7.dart
@@ -1,5 +1,7 @@
+// Method to test: function(foo)
 foo(a) => a ~/ 13;
 main() {
+  print(foo.toString());
   print(foo(5));
   print(foo(100));
 }
diff --git a/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart b/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
new file mode 100644
index 0000000..084bc34
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/input/optimize_indexers.dart
@@ -0,0 +1,32 @@
+// Method to test: function(test)
+import 'package:expect/expect.dart';
+
+// This example illustrates a case we wish to do better in terms of inlining and
+// code generation.
+//
+// Today this function is compiled without inlining Wrapper.[], JSArray.[] and
+// Wrapper.[]= because:
+// JSArray.[] is too big (14 nodes)
+// Wrapper.[] is too big if we force inlining of JSArray (15 nodes)
+// Wrapper.[]= is even bigger (46 nodes)
+//
+// See #25478 for ideas on how to make this better.
+@NoInline()
+test(data, x) {
+  data[x + 1] = data[x];
+}
+
+main() {
+  var wrapper = new Wrapper();
+  wrapper[33] = wrapper[1]; // make Wrapper.[]= and [] used more than once.
+  print(test(new Wrapper(), int.parse('2')));
+}
+
+class Wrapper {
+  final List arr = <bool>[true, false, false, true];
+  operator[](int i) => this.arr[i];
+  operator[]=(int i, v) {
+    if (i > arr.length - 1) arr.length = i + 1;
+    return arr[i] = v;
+  }
+}
diff --git a/tests/compiler/dart2js/cps_ir/input/redundant_condition.dart b/tests/compiler/dart2js/cps_ir/input/redundant_condition.dart
new file mode 100644
index 0000000..913dfc5
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/input/redundant_condition.dart
@@ -0,0 +1,25 @@
+// This test illustrates an opportunity to remove redundant code by
+// propagating inforamtion after inlining.
+//
+// The code below inlines `foo` twice, but we don't propagate that we already
+// know from the first `foo` that `a` is an int, so the second check can be
+// removed entirely.
+
+import 'package:expect/expect.dart';
+
+main() {
+  var a = nextNumber();
+  action(foo(a));
+  action(foo(a));
+}
+
+foo(x) {
+  if (x is! int) throw "error 1";
+  return x + 5 % 100;
+}
+
+@NoInline() @AssumeDynamic()
+nextNumber() => int.parse('33');
+
+@NoInline()
+action(v) => print(v);
diff --git a/tests/compiler/dart2js/cps_ir/input/supercall_1.dart b/tests/compiler/dart2js/cps_ir/input/supercall_1.dart
index 04d5817..0ac95c8d 100644
--- a/tests/compiler/dart2js/cps_ir/input/supercall_1.dart
+++ b/tests/compiler/dart2js/cps_ir/input/supercall_1.dart
@@ -1,6 +1,6 @@
 class Base {
   m(x) {
-    print(x+1);
+    try { print(x+1); } finally { }
   }
 }
 class Sub extends Base {
diff --git a/tests/compiler/dart2js/cps_ir/optimize_indexers_test.dart b/tests/compiler/dart2js/cps_ir/optimize_indexers_test.dart
new file mode 100644
index 0000000..eaf0b4a
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/optimize_indexers_test.dart
@@ -0,0 +1,15 @@
+// ---- AUTO-GENERATED -------------------
+// This file was autogenerated by running:
+//
+//     dart path/to/up_to_date_test.dart update
+//
+// Do not edit this file by hand.
+// ---------------------------------------
+
+library tests.compiler.dart2js.cps_ir.optimize_indexers.dart;
+
+import 'runner.dart';
+
+main(args) {
+  runTest("optimize_indexers.dart", update: args.length > 0 && args[0] == "update");
+}
diff --git a/tests/compiler/dart2js/cps_ir/redundant_condition_test.dart b/tests/compiler/dart2js/cps_ir/redundant_condition_test.dart
new file mode 100644
index 0000000..e97e0ac
--- /dev/null
+++ b/tests/compiler/dart2js/cps_ir/redundant_condition_test.dart
@@ -0,0 +1,15 @@
+// ---- AUTO-GENERATED -------------------
+// This file was autogenerated by running:
+//
+//     dart path/to/up_to_date_test.dart update
+//
+// Do not edit this file by hand.
+// ---------------------------------------
+
+library tests.compiler.dart2js.cps_ir.redundant_condition.dart;
+
+import 'runner.dart';
+
+main(args) {
+  runTest("redundant_condition.dart", update: args.length > 0 && args[0] == "update");
+}
diff --git a/tests/compiler/dart2js/cps_ir/runner.dart b/tests/compiler/dart2js/cps_ir/runner.dart
index a71bd9a..af77384 100644
--- a/tests/compiler/dart2js/cps_ir/runner.dart
+++ b/tests/compiler/dart2js/cps_ir/runner.dart
@@ -33,7 +33,20 @@
   var match = elementNameRegExp.firstMatch(source);
   var elementName = match?.group(1);
 
-  Map files = {TEST_MAIN_FILE: source};
+  Map files = {
+      TEST_MAIN_FILE: source,
+      'package:expect/expect.dart': '''
+          class NoInline {
+            const NoInline();
+          }
+          class TrustTypeAnnotations {
+            const TrustTypeAnnotations();
+          }
+          class AssumeDynamic {
+            const AssumeDynamic();
+          }
+       ''',
+   };
   asyncTest(() async {
     Uri uri = Uri.parse('memory:$TEST_MAIN_FILE');
     String found = null;
@@ -105,7 +118,7 @@
 String _getCodeForMain(CompilerImpl compiler) {
   Element mainFunction = compiler.mainFunction;
   js.Node ast = compiler.enqueuer.codegen.generatedCode[mainFunction];
-  return js.prettyPrint(ast, compiler).getText();
+  return js.prettyPrint(ast, compiler);
 }
 
 String _getCodeForMethod(CompilerImpl compiler,
@@ -125,5 +138,5 @@
   }
 
   js.Node ast = compiler.enqueuer.codegen.generatedCode[foundElement];
-  return js.prettyPrint(ast, compiler).getText();
+  return js.prettyPrint(ast, compiler);
 }
diff --git a/tests/compiler/dart2js/cps_ir/update_all.dart b/tests/compiler/dart2js/cps_ir/update_all.dart
index 726f2e4..5874a25 100644
--- a/tests/compiler/dart2js/cps_ir/update_all.dart
+++ b/tests/compiler/dart2js/cps_ir/update_all.dart
@@ -79,6 +79,7 @@
   runTest('closures_13.dart', update: true);
   runTest('closures_14.dart', update: true);
   runTest('closures_15.dart', update: true);
+  runTest('closures_16.dart', update: true);
   runTest('closures_2.dart', update: true);
   runTest('closures_3.dart', update: true);
   runTest('closures_4.dart', update: true);
@@ -132,6 +133,8 @@
   runTest('operators_6.dart', update: true);
   runTest('operators_7.dart', update: true);
   runTest('operators_8.dart', update: true);
+  runTest('optimize_indexers.dart', update: true);
+  runTest('redundant_condition.dart', update: true);
   runTest('runtime_types_1.dart', update: true);
   runTest('runtime_types_2.dart', update: true);
   runTest('runtime_types_3.dart', update: true);
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
index 2c68f48..781ef91 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_source_information_test.dart
@@ -60,7 +60,7 @@
   }
 
   js.Node ast = compiler.enqueuer.codegen.generatedCode[foundElement];
-  return js.prettyPrint(ast, compiler).getText();
+  return js.prettyPrint(ast, compiler);
 }
 
 runTests(List<TestEntry> tests) {
diff --git a/tests/compiler/dart2js/js_parser_statements_test.dart b/tests/compiler/dart2js/js_parser_statements_test.dart
index 2c12440..6c18de3 100644
--- a/tests/compiler/dart2js/js_parser_statements_test.dart
+++ b/tests/compiler/dart2js/js_parser_statements_test.dart
@@ -14,8 +14,7 @@
   jsAst.Node node = js.statement(statement, arguments);
   return MockCompiler.create((MockCompiler compiler) {
     String jsText =
-        jsAst.prettyPrint(node, compiler, allowVariableMinification: false)
-        .getText();
+        jsAst.prettyPrint(node, compiler, allowVariableMinification: false);
 
     Expect.stringEquals(expect.trim(), jsText.trim());
   });
diff --git a/tests/compiler/dart2js/js_parser_test.dart b/tests/compiler/dart2js/js_parser_test.dart
index 4022724..89d51070 100644
--- a/tests/compiler/dart2js/js_parser_test.dart
+++ b/tests/compiler/dart2js/js_parser_test.dart
@@ -15,7 +15,7 @@
     String jsText =
         jsAst.prettyPrint(node,
                           compiler,
-                          allowVariableMinification: false).getText();
+                          allowVariableMinification: false);
     if (expect == "") {
       Expect.stringEquals(expression, jsText);
     } else {
diff --git a/tests/compiler/dart2js/library_env_test.dart b/tests/compiler/dart2js/library_env_test.dart
new file mode 100644
index 0000000..0f0ff6d
--- /dev/null
+++ b/tests/compiler/dart2js/library_env_test.dart
@@ -0,0 +1,152 @@
+// 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.
+
+/// Check that 'dart:' libraries have their corresponding dart.library.X
+/// environment variable set.
+
+import "dart:io";
+
+import "dart:async";
+
+import "memory_source_file_helper.dart";
+
+import "package:async_helper/async_helper.dart";
+
+import 'package:expect/expect.dart' show
+    Expect;
+
+import 'package:compiler/src/elements/elements.dart' show
+    LibraryElement;
+
+import 'package:compiler/src/null_compiler_output.dart' show
+    NullCompilerOutput;
+
+import 'package:compiler/compiler_new.dart' show
+    CompilerInput,
+    CompilerDiagnostics;
+
+import 'package:sdk_library_metadata/libraries.dart' show
+    LibraryInfo;
+
+const clientPlatform = r'''
+[dart-spec]
+spec: 3rd edition.
+
+[features]
+# No extra features
+
+[libraries]
+mock.client: mock1.dart
+mock.shared: mock3.dart
+collection: collection/collection.dart
+html: html/dart2js/html_dart2js.dart
+''';
+
+const serverPlatform = r'''
+[dart-spec]
+spec: 3rd edition.
+
+[features]
+# No extra features
+
+[libraries]
+mock.server: mock2.dart
+mock.shared: mock3.dart
+collection: collection/collection.dart
+io: io/io.dart
+''';
+
+class DummyCompilerInput implements CompilerInput {
+  const DummyCompilerInput();
+
+  readFromUri(uri) async {
+    if (uri.toString().endsWith("dart_client.platform")) {
+      return clientPlatform;
+    } else if (uri.toString().endsWith("dart_server.platform")) {
+      return serverPlatform;
+    } else {
+      throw "should not be needed $uri";
+    }
+  }
+}
+
+class DummyCompilerDiagnostics implements CompilerDiagnostics {
+  const DummyCompilerDiagnostics();
+
+  report(code, uri, begin, end, text, kind) {
+    throw "should not be needed";
+  }
+}
+
+class CustomCompiler extends CompilerImpl {
+  CustomCompiler(
+      options,
+      environment)
+      : super(
+          const DummyCompilerInput(),
+          const NullCompilerOutput(),
+          const DummyCompilerDiagnostics(),
+          Uri.base.resolve("sdk/"),
+          null,
+          options,
+          environment);
+}
+
+runTest() async {
+  var compiler = new CustomCompiler(
+      [],
+      {});
+
+  await compiler.setupSdk();
+
+  // Core libraries are always present.
+  Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
+  // Non-existing entries in the environment return 'null'.
+  Expect.isNull(compiler.fromEnvironment("not in env"));
+  // Check for client libraries (default if there are no flags to the compiler).
+  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.client"));
+  Expect.equals("true", compiler.fromEnvironment("dart.library.html"));
+  // Check for shared libraries..
+  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
+  // Check server libraries are not present.
+  Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
+  Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
+
+  compiler = new CustomCompiler(
+      ['--categories=Server'],
+      {});
+
+  await compiler.setupSdk();
+
+  // Core libraries are always present.
+  Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
+  // Non-existing entries in the environment return 'null'.
+  Expect.isNull(compiler.fromEnvironment("not in env"));
+  // Check client libraries are not present.
+  Expect.equals(null, compiler.fromEnvironment("dart.library.mock.client"));
+  Expect.equals(null, compiler.fromEnvironment("dart.library.html"));
+  // Check for shared libraries..
+  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
+  // Check for server libraries.
+  Expect.equals("true", compiler.fromEnvironment("dart.library.mock.server"));
+  Expect.equals("true", compiler.fromEnvironment("dart.library.io"));
+
+  // Check that user-defined env-variables win.
+  compiler = new CustomCompiler(
+      [],
+      {'dart.library.collection': "false",
+       'dart.library.mock.client': "foo"});
+
+  await compiler.setupSdk();
+
+  Expect.equals("false", compiler.fromEnvironment("dart.library.collection"));
+  Expect.equals("foo", compiler.fromEnvironment("dart.library.mock.client"));
+}
+
+main() {
+  asyncStart();
+  runTest().then((_) {
+    asyncEnd();
+  });
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/message_kind_test.dart b/tests/compiler/dart2js/message_kind_test.dart
index c3954f0..a886f42 100644
--- a/tests/compiler/dart2js/message_kind_test.dart
+++ b/tests/compiler/dart2js/message_kind_test.dart
@@ -7,13 +7,19 @@
 import "package:async_helper/async_helper.dart";
 import 'package:compiler/src/diagnostics/messages.dart' show
     MessageKind,
-    MessageTemplate;
+    MessageTemplate,
+    SharedMessageKind;
 
 import 'message_kind_helper.dart';
 
 main(List<String> arguments) {
   List<MessageTemplate> examples = <MessageTemplate>[];
-  for (MessageKind kind in MessageKind.values) {
+  List allMessageKinds = []
+      ..addAll(MessageKind.values)
+      ..addAll(SharedMessageKind.values);
+  for (var kind in allMessageKinds) {
+    if (kind == SharedMessageKind.exampleMessage) continue;
+
     MessageTemplate template = MessageTemplate.TEMPLATES[kind];
     Expect.isNotNull(template, "No template for $kind.");
     Expect.equals(kind, template.kind,
diff --git a/tests/compiler/dart2js/override_inheritance_test.dart b/tests/compiler/dart2js/override_inheritance_test.dart
index 628f625..ef4387f 100644
--- a/tests/compiler/dart2js/override_inheritance_test.dart
+++ b/tests/compiler/dart2js/override_inheritance_test.dart
@@ -1548,7 +1548,6 @@
           }
           class Class extends A {
           }
-          """, warnings: MessageKind.UNIMPLEMENTED_METHOD_ONE,
-               infos: MessageKind.UNIMPLEMENTED_METHOD_CONT),
+          """),
   ]);
 }
diff --git a/tests/compiler/dart2js/proxy_test.dart b/tests/compiler/dart2js/proxy_test.dart
index bdba67f..3a0af23 100644
--- a/tests/compiler/dart2js/proxy_test.dart
+++ b/tests/compiler/dart2js/proxy_test.dart
@@ -15,6 +15,9 @@
 const Map<String, dynamic> TESTS = const {
     'language/proxy_test.dart': null,
     'language/proxy2_test.dart': null,
+    'language/proxy3_test.dart': null,
+    'language/proxy4_test.dart': null,
+    'language/proxy5_test.dart': null,
 };
 
 void main(List<String> args) {
diff --git a/tests/compiler/dart2js/sourcemaps/diff_view.dart b/tests/compiler/dart2js/sourcemaps/diff_view.dart
new file mode 100644
index 0000000..0448a7f
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/diff_view.dart
@@ -0,0 +1,871 @@
+// 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 sourcemap.diff_view;
+
+import 'dart:async';
+import 'dart:io';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/diagnostics/invariant.dart';
+import 'package:compiler/src/io/position_information.dart';
+import 'package:compiler/src/js/js.dart' as js;
+import 'sourcemap_helper.dart';
+import 'sourcemap_html_helper.dart';
+import 'trace_graph.dart';
+import 'js_tracer.dart';
+
+const String WITH_SOURCE_INFO_STYLE = 'background-color:#FF8080;';
+const String WITHOUT_SOURCE_INFO_STYLE = 'border: solid 1px #FF8080;';
+const String ADDITIONAL_SOURCE_INFO_STYLE = 'border: solid 1px #8080FF;';
+
+main(List<String> args) async {
+  DEBUG_MODE = true;
+  String out = 'out.js.diff_view.html';
+  String filename;
+  List<String> currentOptions = [];
+  List<List<String>> options = [currentOptions];
+  int argGroup = 0;
+  for (String arg in args) {
+    if (arg == '--') {
+      currentOptions = [];
+      options.add(currentOptions);
+      argGroup++;
+    } else if (arg.startsWith('-o')) {
+      out = arg.substring('-o'.length);
+    } else if (arg.startsWith('--out=')) {
+      out = arg.substring('--out='.length);
+    } else if (arg.startsWith('-')) {
+      currentOptions.add(arg);
+    } else {
+      filename = arg;
+    }
+  }
+  List<String> commonArguments = options[0];
+  List<String> options1;
+  List<String> options2;
+  if (options.length == 1) {
+    // Use default options; comparing SSA and CPS output using the new
+    // source information strategy.
+    options1 = [USE_NEW_SOURCE_INFO]..addAll(commonArguments);
+    options2 = [USE_NEW_SOURCE_INFO, Flags.useCpsIr]..addAll(commonArguments);
+  } else if (options.length == 2) {
+    // Use alternative options for the second output column.
+    options1 = commonArguments;
+    options2 = options[1]..addAll(commonArguments);
+  } else {
+    // Use specific options for both output columns.
+    options1 = options[1]..addAll(commonArguments);
+    options2 = options[2]..addAll(commonArguments);
+  }
+
+  print('Compiling ${options1.join(' ')} $filename');
+  CodeLinesResult result1 = await computeCodeLines(options1, filename);
+  print('Compiling ${options2.join(' ')} $filename');
+  CodeLinesResult result2 = await computeCodeLines(options2, filename);
+
+  StringBuffer sb = new StringBuffer();
+  sb.write('''
+<html>
+<head>
+<title>Diff for $filename</title>
+<style>
+.lineNumber {
+  font-size: smaller;
+  color: #888;
+}
+.header {
+  position: fixed;
+  width: 50%;
+  background-color: #400000;
+  color: #FFFFFF;
+  height: 20px;
+  top: 0px;
+  z-index: 1000;
+}
+.cell {
+  max-width:500px;
+  overflow-x:auto;
+  vertical-align:top;
+}
+.corresponding1 {
+  background-color: #FFFFE0;
+}
+.corresponding2 {
+  background-color: #EFEFD0;
+}
+.identical1 {
+  background-color: #E0F0E0;
+}
+.identical2 {
+  background-color: #C0E0C0;
+}
+</style>
+</head>
+<body>''');
+
+  sb.write('''
+<div class="header" style="left: 0px;">[${options1.join(',')}]</div>
+<div class="header" style="right: 0px;">[${options2.join(',')}]</div>
+<div style="position:absolute;top:22px;width:100%;height:18px;">
+  <span class="identical1">&nbsp;&nbsp;&nbsp;</span> 
+  <span class="identical2">&nbsp;&nbsp;&nbsp;</span>
+  identical blocks
+  <span class="corresponding1">&nbsp;&nbsp;&nbsp;</span>
+  <span class="corresponding2">&nbsp;&nbsp;&nbsp;</span> 
+  corresponding blocks
+  <span style="$WITH_SOURCE_INFO_STYLE">&nbsp;&nbsp;&nbsp;</span>
+  offset with source information
+  <span style="$WITHOUT_SOURCE_INFO_STYLE">&nbsp;&nbsp;&nbsp;</span>
+  offset without source information
+  <span style="$ADDITIONAL_SOURCE_INFO_STYLE">&nbsp;&nbsp;&nbsp;</span>
+  offset with unneeded source information
+</div>
+<table style="position:absolute;top:40px;width:100%;"><tr>
+''');
+
+  void addCell(String content) {
+    sb.write('''
+<td class="cell"><pre>
+''');
+    sb.write(content);
+    sb.write('''
+</pre></td>
+''');
+  }
+
+  List<OutputStructure> structures = [
+      OutputStructure.parse(result1.codeLines),
+      OutputStructure.parse(result2.codeLines)];
+  List<List<CodeLine>> inputLines = [result1.codeLines, result2.codeLines];
+  List<List<HtmlPart>> outputLines = [<HtmlPart>[], <HtmlPart>[]];
+
+  /// Marker to alternate output colors.
+  bool alternating = false;
+
+  /// Enable 'corresponding' background colors for [f].
+  void withMatching(f()) {
+    HtmlPart start = new ConstHtmlPart(
+        '<div class="corresponding${alternating ? '1' : '2'}">');
+    HtmlPart end = new ConstHtmlPart('</div>');
+    alternating = !alternating;
+    outputLines[0].add(start);
+    outputLines[1].add(start);
+    f();
+    outputLines[0].add(end);
+    outputLines[1].add(end);
+  }
+
+  /// Enable 'identical' background colors for [f].
+  void withIdentical(f()) {
+    HtmlPart start = new ConstHtmlPart(
+        '<div class="identical${alternating ? '1' : '2'}">');
+    HtmlPart end = new ConstHtmlPart('</div>');
+    alternating = !alternating;
+    outputLines[0].add(start);
+    outputLines[1].add(start);
+    f();
+    outputLines[0].add(end);
+    outputLines[1].add(end);
+  }
+
+  /// Output code lines in [range] from input number [index], padding the other
+  /// column with empty lines.
+  void handleSkew(int index, Interval range) {
+    int from = range.from;
+    while (from < range.to) {
+      outputLines[1 - index].add(const ConstHtmlPart('\n'));
+      outputLines[index].add(
+          new CodeLineHtmlPart(inputLines[index][from++]));
+    }
+  }
+
+  /// Output code lines of the [indices] from the corresponding inputs.
+  void addBoth(List<int> indices) {
+    outputLines[0].add(new CodeLineHtmlPart(inputLines[0][indices[0]]));
+    outputLines[1].add(new CodeLineHtmlPart(inputLines[1][indices[1]]));
+  }
+
+  /// Output code lines of the [ranges] from the corresponding inputs.
+  void addBothLines(List<Interval> ranges) {
+    Interval range1 = ranges[0];
+    Interval range2 = ranges[1];
+    int offset = 0;
+    while (range1.from + offset < range1.to &&
+           range2.from + offset < range2.to) {
+      addBoth([range1.from + offset, range2.from + offset]);
+      offset++;
+    }
+    if (range1.from + offset < range1.to) {
+      handleSkew(0, new Interval(range1.from + offset, range1.to));
+    }
+    if (range2.from + offset < range2.to) {
+      handleSkew(1, new Interval(range2.from + offset, range2.to));
+    }
+  }
+
+  /// Merge the code lines in [range1] and [range2] of the corresponding input.
+  void addRaw(Interval range1, Interval range2) {
+    match(a, b) => a.code == b.code;
+
+    List<Interval> currentMatchedIntervals;
+
+    void flushMatching() {
+      if (currentMatchedIntervals != null) {
+        withIdentical(() {
+          addBothLines(currentMatchedIntervals);
+        });
+      }
+      currentMatchedIntervals = null;
+    }
+
+    align(
+        inputLines[0],
+        inputLines[1],
+        range1: range1,
+        range2: range2,
+        match: match,
+        handleSkew: (int listIndex, Interval range) {
+          flushMatching();
+          handleSkew(listIndex, range);
+        },
+        handleMatched: (List<int> indices) {
+          if (currentMatchedIntervals == null) {
+            currentMatchedIntervals = [
+              new Interval(indices[0], indices[0] + 1),
+              new Interval(indices[1], indices[1] + 1)];
+          } else {
+            currentMatchedIntervals[0] =
+                new Interval(currentMatchedIntervals[0].from, indices[0] + 1);
+            currentMatchedIntervals[1] =
+                new Interval(currentMatchedIntervals[1].from, indices[1] + 1);
+          }
+        },
+        handleUnmatched: (List<int> indices) {
+          flushMatching();
+          addBoth(indices);
+        });
+
+    flushMatching();
+  }
+
+  /// Output the lines of the library blocks in [childRange] in
+  /// `structures[index]`, padding the other column with empty lines.
+  void addBlock(int index, Interval childRange) {
+    handleSkew(index, structures[index].getChildInterval(childRange));
+  }
+
+  /// Output the members of the [classes] aligned.
+  void addMatchingClasses(List<LibraryClass> classes) {
+    withMatching(() {
+      addBothLines(classes.map((c) => c.header).toList());
+    });
+    align(classes[0].children, classes[1].children,
+        match: (a, b) => a.name == b.name,
+        handleSkew: (int listIndex, Interval childRange) {
+          handleSkew(listIndex,
+              classes[listIndex].getChildInterval(childRange));
+        },
+        handleMatched: (List<int> indices) {
+          List<Interval> intervals =  [
+              classes[0].getChild(indices[0]).interval,
+              classes[1].getChild(indices[1]).interval];
+          withMatching(() {
+            addBothLines(intervals);
+          });
+        },
+        handleUnmatched: (List<int> indices) {
+          List<Interval> intervals =  [
+              classes[0].getChild(indices[0]).interval,
+              classes[1].getChild(indices[1]).interval];
+          addBothLines(intervals);
+        });
+    withMatching(() {
+      addBothLines(classes.map((c) => c.footer).toList());
+    });
+  }
+
+  /// Output the library blocks in [indices] from the corresponding
+  /// [OutputStructure]s, aligning their content.
+  void addMatchingBlocks(List<int> indices) {
+    List<LibraryBlock> blocks = [
+      structures[0].getChild(indices[0]),
+      structures[1].getChild(indices[1])];
+
+    withMatching(() {
+      addBothLines(blocks.map((b) => b.header).toList());
+    });
+    align(blocks[0].children, blocks[1].children,
+        match: (a, b) => a.name == b.name,
+        handleSkew: (int listIndex, Interval childRange) {
+          handleSkew(listIndex, blocks[listIndex].getChildInterval(childRange));
+        },
+        handleMatched: (List<int> indices) {
+          List<BasicEntity> entities =  [
+              blocks[0].getChild(indices[0]),
+              blocks[1].getChild(indices[1])];
+          if (entities.every((e) => e is LibraryClass)) {
+            addMatchingClasses(entities);
+          } else {
+            withMatching(() {
+              addBothLines(entities.map((e) => e.interval).toList());
+            });
+          }
+        },
+        handleUnmatched: (List<int> indices) {
+          List<Interval> intervals =  [
+              blocks[0].getChild(indices[0]).interval,
+              blocks[1].getChild(indices[1]).interval];
+          addBothLines(intervals);
+        });
+    withMatching(() {
+      addBothLines(blocks.map((b) => b.footer).toList());
+    });
+  }
+
+  /// Output the lines of the blocks in [indices] from the corresponding
+  /// [OutputStructure]s.
+  void addUnmatchedBlocks(List<int> indices) {
+    List<LibraryBlock> blocks = [
+       structures[0].getChild(indices[0]),
+       structures[1].getChild(indices[1])];
+    addBothLines([blocks[0].interval, blocks[1].interval]);
+  }
+
+
+  addRaw(structures[0].header, structures[1].header);
+
+  align(structures[0].children,
+        structures[1].children,
+        match: (a, b) => a.name == b.name,
+        handleSkew: addBlock,
+        handleMatched: addMatchingBlocks,
+        handleUnmatched: addUnmatchedBlocks);
+
+  addRaw(structures[0].footer, structures[1].footer);
+
+  addCell(htmlPartsToString(outputLines[0], inputLines[0]));
+  addCell(htmlPartsToString(outputLines[1], inputLines[1]));
+
+  sb.write('''</tr><tr>''');
+  addCell(result1.coverage.getCoverageReport());
+  addCell(result2.coverage.getCoverageReport());
+
+  sb.write('''
+</tr></table>
+</body>
+</html>
+''');
+
+  new File(out).writeAsStringSync(sb.toString());
+  print('Diff generated in $out');
+}
+
+/// Align the content of [list1] and [list2].
+///
+/// If provided, [range1] and [range2] aligned the subranges of [list1] and
+/// [list2], otherwise the whole lists are aligned.
+///
+/// If provided, [match] determines the equality between members of [list1] and
+/// [list2], otherwise `==` is used.
+///
+/// [handleSkew] is called when a subrange of one list is not found in the
+/// other.
+///
+/// [handleMatched] is called when two indices match up.
+///
+/// [handleUnmatched] is called when two indices don't match up (none are found
+/// in the other list).
+void align(List list1,
+           List list2,
+           {Interval range1,
+            Interval range2,
+            bool match(a, b),
+            void handleSkew(int listIndex, Interval range),
+            void handleMatched(List<int> indices),
+            void handleUnmatched(List<int> indices)}) {
+  if (match == null) {
+    match = (a, b) => a == b;
+  }
+
+  if (range1 == null) {
+    range1 = new Interval(0, list1.length);
+  }
+  if (range2 == null) {
+    range2 = new Interval(0, list2.length);
+  }
+
+  Interval findInOther(
+      List thisLines, Interval thisRange,
+      List otherLines, Interval otherRange) {
+    for (int index = otherRange.from; index < otherRange.to; index++) {
+      if (match(thisLines[thisRange.from], otherLines[index])) {
+        int offset = 1;
+        while (thisRange.from + offset < thisRange.to &&
+               otherRange.from + offset < otherRange.to &&
+               match(thisLines[thisRange.from + offset],
+                     otherLines[otherRange.from + offset])) {
+          offset++;
+        }
+        return new Interval(index, index + offset);
+      }
+    }
+    return null;
+  }
+
+  int start1 = range1.from;
+  int end1 = range1.to;
+  int start2 = range2.from;
+  int end2 = range2.to;
+
+  const int ALIGN1 = -1;
+  const int UNMATCHED = 0;
+  const int ALIGN2 = 1;
+
+  while (start1 < end1 && start2 < end2) {
+    if (match(list1[start1], list2[start2])) {
+      handleMatched([start1++, start2++]);
+    } else {
+      Interval subrange1 = new Interval(start1, end1);
+      Interval subrange2 = new Interval(start2, end2);
+      Interval element2inList1 =
+          findInOther(list1, subrange1, list2, subrange2);
+      Interval element1inList2 =
+          findInOther(list2, subrange2, list1, subrange1);
+      int choice = 0;
+      if (element2inList1 != null) {
+        if (element1inList2 != null) {
+          if (element1inList2.length > 1 && element2inList1.length > 1) {
+            choice =
+                element2inList1.from < element1inList2.from ? ALIGN2 : ALIGN1;
+          } else if (element2inList1.length > 1) {
+            choice = ALIGN2;
+          } else if (element1inList2.length > 1) {
+            choice = ALIGN1;
+          } else {
+            choice =
+                element2inList1.from < element1inList2.from ? ALIGN2 : ALIGN1;
+          }
+        } else {
+          choice = ALIGN2;
+        }
+      } else if (element1inList2 != null) {
+        choice = ALIGN1;
+      }
+      switch (choice) {
+        case ALIGN1:
+          handleSkew(0, new Interval(start1, element1inList2.from));
+          start1 = element1inList2.from;
+          break;
+        case ALIGN2:
+          handleSkew(1, new Interval(start2, element2inList1.from));
+          start2 = element2inList1.from;
+          break;
+        case UNMATCHED:
+          handleUnmatched([start1++, start2++]);
+          break;
+      }
+    }
+  }
+  if (start1 < end1) {
+    handleSkew(0, new Interval(start1, end1));
+  }
+  if (start2 < end2) {
+    handleSkew(1, new Interval(start2, end2));
+  }
+}
+
+// Constants used to identify the subsection of the JavaScript output. These
+// are specifically for the unminified full_emitter output.
+const String HEAD = '  var dart = [';
+const String TAIL = '  }], ';
+const String END = '  setupProgram(dart';
+
+final RegExp TOP_LEVEL_VALUE = new RegExp(r'^    (".+?"):');
+final RegExp TOP_LEVEL_FUNCTION =
+    new RegExp(r'^    ([a-zA-Z0-9_$]+): \[?function');
+final RegExp TOP_LEVEL_CLASS = new RegExp(r'^    ([a-zA-Z0-9_$]+): \[?\{');
+
+final RegExp MEMBER_VALUE = new RegExp(r'^      (".+?"):');
+final RegExp MEMBER_FUNCTION =
+    new RegExp(r'^      ([a-zA-Z0-9_$]+): \[?function');
+final RegExp MEMBER_OBJECT = new RegExp(r'^      ([a-zA-Z0-9_$]+): \[?\{');
+
+/// Subrange of the JavaScript output.
+abstract class OutputEntity {
+  Interval get interval;
+  Interval get header;
+  Interval get footer;
+
+  List<OutputEntity> get children;
+
+  Interval getChildInterval(Interval childIndex) {
+    return new Interval(
+        children[childIndex.from].interval.from,
+        children[childIndex.to - 1].interval.to);
+
+  }
+
+  OutputEntity getChild(int index) {
+    return children[index];
+  }
+}
+
+/// The whole JavaScript output.
+class OutputStructure extends OutputEntity {
+  final List<CodeLine> lines;
+  final int headerEnd;
+  final int footerStart;
+  final List<LibraryBlock> children;
+
+  OutputStructure(
+      this.lines,
+      this.headerEnd,
+      this.footerStart,
+      this.children);
+
+  Interval get interval => new Interval(0, lines.length);
+
+  Interval get header => new Interval(0, headerEnd);
+
+  Interval get footer => new Interval(footerStart, lines.length);
+
+  /// Compute the structure of the JavaScript [lines].
+  static OutputStructure parse(List<CodeLine> lines) {
+
+    int findHeaderStart(List<CodeLine> lines) {
+      int index = 0;
+      for (CodeLine line in lines) {
+        if (line.code.startsWith(HEAD)) {
+          return index;
+        }
+        index++;
+      }
+      return lines.length;
+    }
+
+    int findHeaderEnd(int start, List<CodeLine> lines) {
+      int index = start;
+      for (CodeLine line in lines.skip(start)) {
+        if (line.code.startsWith(END)) {
+          return index;
+        }
+        index++;
+      }
+      return lines.length;
+    }
+
+    String readHeader(CodeLine line) {
+      String code = line.code;
+      String ssaLineHeader;
+      if (code.startsWith(HEAD)) {
+        return code.substring(HEAD.length);
+      } else if (code.startsWith(TAIL)) {
+        return code.substring(TAIL.length);
+      }
+      return null;
+    }
+
+    List<LibraryBlock> computeHeaderMap(
+        List<CodeLine> lines, int start, int end) {
+      List<LibraryBlock> libraryBlocks = <LibraryBlock>[];
+      LibraryBlock current;
+      for (int index = start; index < end; index++) {
+        String header = readHeader(lines[index]);
+        if (header != null) {
+          if (current != null) {
+            current.to = index;
+          }
+          libraryBlocks.add(current = new LibraryBlock(header, index));
+        }
+      }
+      if (current != null) {
+        current.to = end;
+      }
+      return libraryBlocks;
+    }
+
+    int headerEnd = findHeaderStart(lines);
+    int footerStart = findHeaderEnd(headerEnd, lines);
+    List<LibraryBlock> libraryBlocks =
+        computeHeaderMap(lines, headerEnd, footerStart);
+    for (LibraryBlock block in libraryBlocks) {
+      block.preprocess(lines);
+    }
+
+    return new OutputStructure(
+        lines, headerEnd, footerStart, libraryBlocks);
+  }
+}
+
+abstract class AbstractEntity extends OutputEntity {
+  final String name;
+  final int from;
+  int to;
+
+  AbstractEntity(this.name, this.from);
+
+  Interval get interval => new Interval(from, to);
+}
+
+/// A block defining the content of a Dart library.
+class LibraryBlock extends AbstractEntity {
+  List<BasicEntity> children = <BasicEntity>[];
+  int get headerEnd => from + 2;
+  int get footerStart => to - 1;
+
+  LibraryBlock(String name, int from) : super(name, from);
+
+  Interval get header => new Interval(from, headerEnd);
+
+  Interval get footer => new Interval(footerStart, to);
+
+  void preprocess(List<CodeLine> lines) {
+    int index = headerEnd;
+    BasicEntity current;
+    while (index < footerStart) {
+      String line = lines[index].code;
+      BasicEntity next;
+      Match matchFunction = TOP_LEVEL_FUNCTION.firstMatch(line);
+      if (matchFunction != null) {
+        next = new BasicEntity(matchFunction.group(1), index);
+      } else {
+        Match matchClass = TOP_LEVEL_CLASS.firstMatch(line);
+        if (matchClass != null) {
+          next = new LibraryClass(matchClass.group(1), index);
+        } else {
+          Match matchValue = TOP_LEVEL_VALUE.firstMatch(line);
+          if (matchValue != null) {
+            next = new BasicEntity(matchValue.group(1), index);
+          }
+        }
+      }
+      if (next != null) {
+        if (current != null) {
+          current.to = index;
+        }
+        children.add(current = next);
+      } else if (index == headerEnd) {
+        throw 'Failed to match first library block line:\n$line';
+      }
+
+      index++;
+    }
+    if (current != null) {
+      current.to = footerStart;
+    }
+
+    for (BasicEntity entity in children) {
+      entity.preprocess(lines);
+    }
+  }
+}
+
+/// A simple member of a library or class.
+class BasicEntity extends AbstractEntity {
+  BasicEntity(String name, int from) : super(name, from);
+
+  Interval get header => new Interval(from, to);
+
+  Interval get footer => new Interval(to, to);
+
+  List<OutputEntity> get children => const <OutputEntity>[];
+
+  void preprocess(List<CodeLine> lines) {}
+}
+
+/// A block defining a Dart class.
+class LibraryClass extends BasicEntity {
+  List<BasicEntity> children = <BasicEntity>[];
+  int get headerEnd => from + 1;
+  int get footerStart => to - 1;
+
+  LibraryClass(String name, int from) : super(name, from);
+
+  Interval get header => new Interval(from, headerEnd);
+
+  Interval get footer => new Interval(footerStart, to);
+
+  void preprocess(List<CodeLine> lines) {
+    int index = headerEnd;
+    BasicEntity current;
+    while (index < footerStart) {
+      String line = lines[index].code;
+      BasicEntity next;
+      Match matchFunction = MEMBER_FUNCTION.firstMatch(line);
+      if (matchFunction != null) {
+        next = new BasicEntity(matchFunction.group(1), index);
+      } else {
+        Match matchClass = MEMBER_OBJECT.firstMatch(line);
+        if (matchClass != null) {
+          next = new BasicEntity(matchClass.group(1), index);
+        } else {
+          Match matchValue = MEMBER_VALUE.firstMatch(line);
+          if (matchValue != null) {
+            next = new BasicEntity(matchValue.group(1), index);
+          }
+        }
+      }
+      if (next != null) {
+        if (current != null) {
+          current.to = index;
+        }
+        children.add(current = next);
+      } else if (index == headerEnd) {
+        throw 'Failed to match first library block line:\n$line';
+      }
+
+      index++;
+    }
+    if (current != null) {
+      current.to = footerStart;
+    }
+  }
+}
+
+class Interval {
+  final int from;
+  final int to;
+
+  const Interval(this.from, this.to);
+
+  int get length => to - from;
+}
+
+class HtmlPart {
+  void printHtmlOn(StringBuffer buffer) {}
+}
+
+class ConstHtmlPart implements HtmlPart {
+  final String html;
+
+  const ConstHtmlPart(this.html);
+
+  @override
+  void printHtmlOn(StringBuffer buffer) {
+    buffer.write(html);
+  }
+}
+
+class CodeLineHtmlPart implements HtmlPart {
+  final CodeLine line;
+
+  CodeLineHtmlPart(this.line);
+
+  @override
+  void printHtmlOn(StringBuffer buffer, [int lineNoWidth]) {
+    line.printHtmlOn(buffer, lineNoWidth);
+  }
+}
+
+/// Convert [parts] to an HTML string while checking invariants for [lines].
+String htmlPartsToString(List<HtmlPart> parts, List<CodeLine> lines) {
+  int lineNoWidth;
+  if (lines.isNotEmpty) {
+    lineNoWidth = '${lines.last.lineNo + 1}'.length;
+  }
+  StringBuffer buffer = new StringBuffer();
+  int expectedLineNo = 0;
+  for (HtmlPart part in parts) {
+    if (part is CodeLineHtmlPart) {
+      if (part.line.lineNo != expectedLineNo) {
+        print('Expected line no $expectedLineNo, found ${part.line.lineNo}');
+        if (part.line.lineNo < expectedLineNo) {
+          print('Duplicate lines:');
+          int index = part.line.lineNo;
+          while (index <= expectedLineNo) {
+            print(lines[index++].code);
+          }
+        } else {
+          print('Missing lines:');
+          int index = expectedLineNo;
+          while (index <= part.line.lineNo) {
+            print(lines[index++].code);
+          }
+        }
+        expectedLineNo = part.line.lineNo;
+      }
+      expectedLineNo++;
+      part.printHtmlOn(buffer, lineNoWidth);
+    } else {
+      part.printHtmlOn(buffer);
+    }
+  }
+  return buffer.toString();
+}
+
+class CodeLinesResult {
+  final List<CodeLine> codeLines;
+  final Coverage coverage;
+
+  CodeLinesResult(this.codeLines, this.coverage);
+}
+
+/// Compute [CodeLine]s and [Coverage] for [filename] using the given [options].
+Future<CodeLinesResult> computeCodeLines(
+    List<String> options,
+    String filename) async {
+  SourceMapProcessor processor = new SourceMapProcessor(filename);
+  List<SourceMapInfo> sourceMapInfoList =
+      await processor.process(options, perElement: false);
+
+  const int WITH_SOURCE_INFO = 0;
+  const int WITHOUT_SOURCE_INFO = 1;
+  const int ADDITIONAL_SOURCE_INFO = 2;
+
+  for (SourceMapInfo info in sourceMapInfoList) {
+    if (info.element != null) continue;
+
+    List<CodeLine> codeLines;
+    Coverage coverage = new Coverage();
+    List<Annotation> annotations = <Annotation>[];
+    String code = info.code;
+    TraceGraph graph = createTraceGraph(info, coverage);
+    Set<js.Node> mappedNodes = new Set<js.Node>();
+    for (TraceStep step in graph.steps) {
+      int offset;
+      if (options.contains(USE_NEW_SOURCE_INFO)) {
+        offset = step.offset.subexpressionOffset;
+      } else {
+        offset = info.jsCodePositions[step.node].startPosition;
+      }
+      if (offset != null) {
+        int id = step.sourceLocation != null
+            ? WITH_SOURCE_INFO : WITHOUT_SOURCE_INFO;
+        annotations.add(
+            new Annotation(id, offset, null));
+      }
+    }
+    if (!options.contains(USE_NEW_SOURCE_INFO)) {
+      for (js.Node node in info.nodeMap.nodes) {
+        if (!mappedNodes.contains(node)) {
+          int offset = info.jsCodePositions[node].startPosition;
+          annotations.add(
+                      new Annotation(ADDITIONAL_SOURCE_INFO, offset, null));
+        }
+      }
+    }
+    codeLines = convertAnnotatedCodeToCodeLines(
+        code,
+        annotations,
+        colorScheme: new CustomColorScheme(
+          single: (int id) {
+            if (id == WITH_SOURCE_INFO) {
+              return WITH_SOURCE_INFO_STYLE;
+            } else if (id == ADDITIONAL_SOURCE_INFO) {
+              return ADDITIONAL_SOURCE_INFO_STYLE;
+            }
+            return WITHOUT_SOURCE_INFO_STYLE;
+          },
+          multi: (List ids) {
+            if (ids.contains(WITH_SOURCE_INFO)) {
+              return WITH_SOURCE_INFO_STYLE;
+            } else if (ids.contains(ADDITIONAL_SOURCE_INFO)) {
+              return ADDITIONAL_SOURCE_INFO_STYLE;
+            }
+            return WITHOUT_SOURCE_INFO_STYLE;
+          }
+        ));
+    return new CodeLinesResult(codeLines, coverage);
+  }
+}
diff --git a/tests/compiler/dart2js/sourcemaps/js_tracer.dart b/tests/compiler/dart2js/sourcemaps/js_tracer.dart
new file mode 100644
index 0000000..1aa40fe
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/js_tracer.dart
@@ -0,0 +1,138 @@
+// 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 sourcemap.js_tracer;
+
+import 'package:compiler/src/io/source_information.dart';
+import 'package:compiler/src/io/position_information.dart';
+import 'package:compiler/src/js/js.dart' as js;
+import 'sourcemap_helper.dart';
+import 'trace_graph.dart';
+
+/// Create a [TraceGraph] for [info] registering usage in [coverage].
+TraceGraph createTraceGraph(SourceMapInfo info, Coverage coverage) {
+  TraceGraph graph = new TraceGraph();
+  TraceListener listener = new StepTraceListener(graph);
+  CodePositionMap codePositions =
+      new CodePositionCoverage(info.jsCodePositions, coverage);
+  JavaScriptTracer tracer = new JavaScriptTracer(
+      codePositions, [new CoverageListener(coverage), listener]);
+  info.node.accept(tracer);
+  return graph;
+}
+
+class StepTraceListener extends TraceListener {
+  Map<js.Node, TraceStep> steppableMap = <js.Node, TraceStep>{};
+  final TraceGraph graph;
+
+  StepTraceListener(this.graph);
+
+  @override
+  void onStep(js.Node node, Offset offset, StepKind kind) {
+    SourceInformation sourceInformation = node.sourceInformation;
+    SourcePositionKind sourcePositionKind = SourcePositionKind.START;
+    List text = [node];
+    switch (kind) {
+      case StepKind.FUN:
+        sourcePositionKind = SourcePositionKind.INNER;
+        text = ['<exit>'];
+        break;
+      case StepKind.CALL:
+        CallPosition callPosition =
+            CallPosition.getSemanticPositionForCall(node);
+        sourcePositionKind = callPosition.sourcePositionKind;
+        break;
+      case StepKind.NEW:
+      case StepKind.RETURN:
+      case StepKind.BREAK:
+      case StepKind.CONTINUE:
+      case StepKind.THROW:
+      case StepKind.EXPRESSION_STATEMENT:
+        break;
+      case StepKind.IF_CONDITION:
+        js.If ifNode = node;
+        text = ['if(', ifNode.condition, ') ...'];
+        break;
+      case StepKind.FOR_INITIALIZER:
+        js.For forNode = node;
+        text = ['for(', forNode.init, '; ...) ...'];
+        break;
+      case StepKind.FOR_CONDITION:
+        js.For forNode = node;
+        text = ['for(...;', forNode.condition, '; ...) ...'];
+        break;
+      case StepKind.FOR_UPDATE:
+        js.For forNode = node;
+        text = ['for(...; ...', forNode.update, ') ...'];
+        break;
+      case StepKind.WHILE_CONDITION:
+        js.While whileNode = node;
+        text = ['while(', whileNode.condition, ') ...'];
+        break;
+      case StepKind.DO_CONDITION:
+        js.Do doNode = node;
+        text = ['do {... } (', doNode.condition, ')'];
+        break;
+      case StepKind.SWITCH_EXPRESSION:
+        js.Switch switchNode = node;
+        text = ['switch(', switchNode.key, ') ...'];
+        break;
+
+    }
+    createTraceStep(
+        node,
+        offset: offset,
+        sourceLocation: getSourceLocation(
+            node.sourceInformation, sourcePositionKind),
+        text: text);
+  }
+
+  void createTraceStep(
+      js.Node node,
+      {Offset offset,
+       List text,
+       String note,
+       SourceLocation sourceLocation}) {
+    int id = steppableMap.length;
+
+    if (text == null) {
+      text = [node];
+    }
+
+    TraceStep step = new TraceStep(
+        id, node,
+        offset,
+        text, sourceLocation);
+    graph.addStep(step);
+
+    steppableMap[node] = step;
+  }
+
+
+  void pushBranch(BranchKind kind, [value]) {
+    var branch;
+    switch (kind) {
+      case BranchKind.CONDITION:
+        branch = value ? 't' : 'f';
+        break;
+      case BranchKind.LOOP:
+        branch = 'l';
+        break;
+      case BranchKind.CATCH:
+        branch = 'c';
+        break;
+      case BranchKind.FINALLY:
+        branch = 'F';
+        break;
+      case BranchKind.CASE:
+        branch = '$value';
+        break;
+    }
+    graph.pushBranch(branch);
+  }
+
+  void popBranch() {
+    graph.popBranch();
+  }
+}
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index 9cb53e5..123cbe2 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -11,8 +11,10 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/helpers/helpers.dart';
 import 'package:compiler/src/filenames.dart';
+import 'package:compiler/src/io/code_output.dart';
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/io/source_information.dart';
+import 'package:compiler/src/io/position_information.dart';
 import 'package:compiler/src/js/js.dart' as js;
 import 'package:compiler/src/js/js_debug.dart';
 import 'package:compiler/src/js/js_source_mapping.dart';
@@ -21,15 +23,51 @@
 import '../memory_compiler.dart';
 import '../output_collector.dart';
 
+class SourceFileSink implements EventSink<String> {
+  final String filename;
+  StringBuffer sb = new StringBuffer();
+  SourceFile sourceFile;
+
+  SourceFileSink(this.filename);
+
+  @override
+  void add(String event) {
+    sb.write(event);
+  }
+
+  @override
+  void addError(errorEvent, [StackTrace stackTrace]) {
+    // Ignore.
+  }
+
+  @override
+  void close() {
+    sourceFile = new StringSourceFile.fromName(filename, sb.toString());
+  }
+}
+
 class OutputProvider implements CompilerOutput {
-  BufferedEventSink jsMapOutput;
+  Map<Uri, SourceFileSink> outputMap = <Uri, SourceFileSink>{};
+
+  SourceFile getSourceFile(Uri uri) {
+    SourceFileSink sink = outputMap[uri];
+    if (sink != null) {
+      return sink.sourceFile;
+    }
+    return null;
+  }
+
+  SourceFileSink createSourceFileSink(String name, String extension) {
+    String filename = '$name.$extension';
+    SourceFileSink sink = new SourceFileSink(filename);
+    Uri uri = Uri.parse(filename);
+    outputMap[uri] = sink;
+    return sink;
+  }
 
   @override
   EventSink<String> createEventSink(String name, String extension) {
-    if (extension == 'js.map') {
-      return jsMapOutput = new BufferedEventSink();
-    }
-    return new NullSink('$name.$extension');
+    return createSourceFileSink(name, extension);
   }
 }
 
@@ -42,11 +80,8 @@
   @override
   EventSink<String> createEventSink(String name, String extension) {
     EventSink<String> output = outputProvider(name, extension);
-    if (extension == 'js.map') {
-      output = new CloningEventSink(
-          [output, jsMapOutput = new BufferedEventSink()]);
-    }
-    return output;
+    return new CloningEventSink(
+        [output, createSourceFileSink(name, extension)]);
   }
 }
 
@@ -56,17 +91,23 @@
 
 class ProviderSourceFileManager implements SourceFileManager {
   final SourceFileProvider sourceFileProvider;
+  final OutputProvider outputProvider;
 
-  ProviderSourceFileManager(this.sourceFileProvider);
+  ProviderSourceFileManager(this.sourceFileProvider, this.outputProvider);
 
   @override
   SourceFile getSourceFile(uri) {
-    return sourceFileProvider.getSourceFile(uri);
+    SourceFile sourceFile = sourceFileProvider.getSourceFile(uri);
+    if (sourceFile == null) {
+      sourceFile = outputProvider.getSourceFile(uri);
+    }
+    return sourceFile;
   }
 }
 
 class RecordingPrintingContext extends LenientPrintingContext {
   CodePositionListener listener;
+  Map<js.Node, CodePosition> codePositions = <js.Node, CodePosition>{};
 
   RecordingPrintingContext(this.listener);
 
@@ -75,11 +116,163 @@
                 int startPosition,
                 int endPosition,
                 int closingPosition) {
+    codePositions[node] =
+        new CodePosition(startPosition, endPosition, closingPosition);
     listener.onPositions(
         node, startPosition, endPosition, closingPosition);
   }
 }
 
+/// A [SourceMapper] that records the source locations on each node.
+class RecordingSourceMapper implements SourceMapper {
+  final SourceMapper sourceMapper;
+  final _LocationRecorder nodeToSourceLocationsMap;
+
+  RecordingSourceMapper(this.sourceMapper, this.nodeToSourceLocationsMap);
+
+  @override
+  void register(js.Node node, int codeOffset, SourceLocation sourceLocation) {
+    nodeToSourceLocationsMap.register(node, codeOffset, sourceLocation);
+    sourceMapper.register(node, codeOffset, sourceLocation);
+  }
+}
+
+/// A wrapper of [SourceInformationProcessor] that records source locations and
+/// code positions.
+class RecordingSourceInformationProcessor
+    implements SourceInformationProcessor {
+  final RecordingSourceInformationStrategy wrapper;
+  final SourceInformationProcessor processor;
+  final CodePositionRecorder codePositions;
+  final LocationMap nodeToSourceLocationsMap;
+
+  RecordingSourceInformationProcessor(
+      this.wrapper,
+      this.processor,
+      this.codePositions,
+      this.nodeToSourceLocationsMap);
+
+  @override
+  void onPositions(js.Node node,
+                   int startPosition,
+                   int endPosition,
+                   int closingPosition) {
+    codePositions.registerPositions(
+        node, startPosition, endPosition, closingPosition);
+    processor.onPositions(node, startPosition, endPosition, closingPosition);
+  }
+
+  @override
+  void process(js.Node node, BufferedCodeOutput code) {
+    processor.process(node, code);
+    wrapper.registerProcess(
+        node, code, codePositions, nodeToSourceLocationsMap);
+  }
+}
+
+/// Information recording for a use of [SourceInformationProcessor].
+class RecordedSourceInformationProcess {
+  final js.Node root;
+  final String code;
+  final CodePositionRecorder codePositions;
+  final LocationMap nodeToSourceLocationsMap;
+
+  RecordedSourceInformationProcess(
+      this.root,
+      this.code,
+      this.codePositions,
+      this.nodeToSourceLocationsMap);
+}
+
+
+/// A wrapper of [JavaScriptSourceInformationStrategy] that records
+/// [RecordedSourceInformationProcess].
+class RecordingSourceInformationStrategy
+    extends JavaScriptSourceInformationStrategy {
+  final JavaScriptSourceInformationStrategy strategy;
+  final Map<RecordedSourceInformationProcess, js.Node> processMap =
+      <RecordedSourceInformationProcess, js.Node>{};
+  final Map<js.Node, RecordedSourceInformationProcess> nodeMap =
+      <js.Node, RecordedSourceInformationProcess>{};
+
+  RecordingSourceInformationStrategy(this.strategy);
+
+  @override
+  SourceInformationBuilder createBuilderForContext(AstElement element) {
+    return strategy.createBuilderForContext(element);
+  }
+
+  @override
+  SourceInformationProcessor createProcessor(SourceMapper sourceMapper) {
+    LocationMap nodeToSourceLocationsMap =
+        new _LocationRecorder();
+    CodePositionRecorder codePositions = new CodePositionRecorder();
+    return new RecordingSourceInformationProcessor(
+        this,
+        strategy.createProcessor(new RecordingSourceMapper(
+            sourceMapper, nodeToSourceLocationsMap)),
+            codePositions, nodeToSourceLocationsMap);
+  }
+
+  void registerProcess(js.Node root,
+                       BufferedCodeOutput code,
+                       CodePositionRecorder codePositions,
+                       LocationMap nodeToSourceLocationsMap) {
+    RecordedSourceInformationProcess subProcess =
+        new RecordedSourceInformationProcess(
+            root, code.getText(), codePositions, nodeToSourceLocationsMap);
+    processMap[subProcess] = root;
+  }
+
+  RecordedSourceInformationProcess subProcessForNode(js.Node node) {
+    return nodeMap.putIfAbsent(node, () {
+      for (RecordedSourceInformationProcess subProcess in processMap.keys) {
+        js.Node root = processMap[subProcess];
+        FindVisitor visitor = new FindVisitor(node);
+        root.accept(visitor);
+        if (visitor.found) {
+          return new RecordedSourceInformationProcess(
+              node,
+              subProcess.code,
+              subProcess.codePositions,
+              new _FilteredLocationMap(
+                  visitor.nodes, subProcess.nodeToSourceLocationsMap));
+        }
+        return null;
+      }
+    });
+  }
+}
+
+/// Visitor that collects all nodes that are within a function. Used by the
+/// [RecordingSourceInformationStrategy] to filter what is recorded in a
+/// [RecordedSourceInformationProcess].
+class FindVisitor extends js.BaseVisitor {
+  final js.Node soughtNode;
+  bool found = false;
+  bool add = false;
+  final Set<js.Node> nodes = new Set<js.Node>();
+
+  FindVisitor(this.soughtNode);
+
+  visitNode(js.Node node) {
+    if (node == soughtNode) {
+      found = true;
+      add = true;
+    }
+    if (add) {
+      nodes.add(node);
+    }
+    node.visitChildren(this);
+    if (node == soughtNode) {
+      add = false;
+    }
+  }
+}
+
+const String USE_NEW_SOURCE_INFO =  '--use-new-source-info';
+const String DISABLE_INLINING = '--disable-inlining';
+
 /// Processor that computes [SourceMapInfo] for the JavaScript compiled for a
 /// given Dart file.
 class SourceMapProcessor {
@@ -112,11 +305,12 @@
   /// Computes the [SourceMapInfo] for the compiled elements.
   Future<List<SourceMapInfo>> process(
       List<String> options,
-      {bool verbose: true}) async {
+      {bool verbose: true,
+       bool perElement: true}) async {
     OutputProvider outputProvider = outputToFile
-        ? new OutputProvider()
-        : new CloningOutputProvider(targetUri, sourceMapFileUri);
-    if (options.contains('--use-new-source-info')) {
+        ? new CloningOutputProvider(targetUri, sourceMapFileUri)
+        : new OutputProvider();
+    if (options.contains(USE_NEW_SOURCE_INFO)) {
       if (verbose) print('Using the new source information system.');
       useNewSourceInfo = true;
     }
@@ -125,7 +319,7 @@
         // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
         options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
             ..addAll(options));
-    if (options.contains('--disable-inlining')) {
+    if (options.contains(DISABLE_INLINING)) {
       if (verbose) print('Inlining disabled');
       compiler.disableInlining = true;
     }
@@ -133,30 +327,58 @@
     JavaScriptBackend backend = compiler.backend;
     var handler = compiler.handler;
     SourceFileProvider sourceFileProvider = handler.provider;
-    sourceFileManager = new ProviderSourceFileManager(sourceFileProvider);
+    sourceFileManager = new ProviderSourceFileManager(
+        sourceFileProvider,
+        outputProvider);
+    RecordingSourceInformationStrategy strategy =
+        new RecordingSourceInformationStrategy(backend.sourceInformationStrategy);
+    backend.sourceInformationStrategy = strategy;
     await compiler.run(inputUri);
 
     List<SourceMapInfo> infoList = <SourceMapInfo>[];
-    backend.generatedCode.forEach((Element element, js.Expression node) {
-      js.JavaScriptPrintingOptions options =
-          new js.JavaScriptPrintingOptions();
-      JavaScriptSourceInformationStrategy sourceInformationStrategy =
-          compiler.backend.sourceInformationStrategy;
-      NodeToSourceLocationsMap nodeMap = new NodeToSourceLocationsMap();
-      SourceInformationProcessor sourceInformationProcessor =
-          sourceInformationStrategy.createProcessor(nodeMap);
-      RecordingPrintingContext printingContext =
-          new RecordingPrintingContext(sourceInformationProcessor);
-      new js.Printer(options, printingContext).visit(node);
-      sourceInformationProcessor.process(node);
-
-      String code = printingContext.getText();
+    if (perElement) {
+      backend.generatedCode.forEach((Element element, js.Expression node) {
+        RecordedSourceInformationProcess subProcess =
+            strategy.subProcessForNode(node);
+        if (subProcess == null) {
+          // TODO(johnniwinther): Find out when this is happening and if it
+          // is benign. (Known to happen for `bool#fromString`)
+          print('No subProcess found for $element');
+          return;
+        }
+        LocationMap nodeMap = subProcess.nodeToSourceLocationsMap;
+        String code = subProcess.code;
+        CodePositionRecorder codePositions = subProcess.codePositions;
+        CodePointComputer visitor =
+            new CodePointComputer(sourceFileManager, code, nodeMap);
+        visitor.apply(node);
+        List<CodePoint> codePoints = visitor.codePoints;
+        infoList.add(new SourceMapInfo(
+            element, code, node,
+            codePoints,
+            codePositions/*strategy.codePositions*/,
+            nodeMap));
+      });
+    } else {
+      // TODO(johnniwinther): Supported multiple output units.
+      RecordedSourceInformationProcess process = strategy.processMap.keys.first;
+      js.Node node = strategy.processMap[process];
+      String code;
+      LocationMap nodeMap;
+      CodePositionRecorder codePositions;
+      nodeMap = process.nodeToSourceLocationsMap;
+      code = process.code;
+      codePositions = process.codePositions;
       CodePointComputer visitor =
           new CodePointComputer(sourceFileManager, code, nodeMap);
       visitor.apply(node);
       List<CodePoint> codePoints = visitor.codePoints;
-      infoList.add(new SourceMapInfo(element, code, node, codePoints, nodeMap));
-    });
+      infoList.add(new SourceMapInfo(
+          null, code, node,
+          codePoints,
+          codePositions,
+          nodeMap));
+    }
 
     return infoList;
   }
@@ -167,19 +389,43 @@
   final String name;
   final Element element;
   final String code;
-  final js.Expression node;
+  final js.Node node;
   final List<CodePoint> codePoints;
-  final NodeToSourceLocationsMap nodeMap;
+  final CodePositionMap jsCodePositions;
+  final LocationMap nodeMap;
 
   SourceMapInfo(
-      Element element, this.code, this.node, this.codePoints, this.nodeMap)
-      : this.name = computeElementNameForSourceMaps(element),
+      Element element,
+      this.code,
+      this.node,
+      this.codePoints,
+      this.jsCodePositions,
+      this.nodeMap)
+      : this.name =
+          element != null ? computeElementNameForSourceMaps(element) : '',
         this.element = element;
+
+  String toString() {
+    return '$name:$element';
+  }
 }
 
 /// Collection of JavaScript nodes with their source mapped target offsets
 /// and source locations.
-class NodeToSourceLocationsMap implements SourceMapper {
+abstract class LocationMap {
+  Iterable<js.Node> get nodes;
+
+  Map<int, List<SourceLocation>> operator[] (js.Node node);
+
+  factory LocationMap.recorder() = _LocationRecorder;
+
+  factory LocationMap.filter(Set<js.Node> nodes, LocationMap map) =
+      _FilteredLocationMap;
+
+}
+
+class _LocationRecorder
+    implements SourceMapper, LocationMap {
   final Map<js.Node, Map<int, List<SourceLocation>>> _nodeMap = {};
 
   @override
@@ -196,11 +442,25 @@
   }
 }
 
+class _FilteredLocationMap implements LocationMap {
+  final Set<js.Node> _nodes;
+  final LocationMap map;
+
+  _FilteredLocationMap(this._nodes, this.map);
+
+  Iterable<js.Node> get nodes => map.nodes.where((n) => _nodes.contains(n));
+
+  Map<int, List<SourceLocation>> operator[] (js.Node node) {
+    return map[node];
+  }
+}
+
+
 /// Visitor that computes the [CodePoint]s for source mapping locations.
 class CodePointComputer extends js.BaseVisitor {
   final SourceFileManager sourceFileManager;
   final String code;
-  final NodeToSourceLocationsMap nodeMap;
+  final LocationMap nodeMap;
   List<CodePoint> codePoints = [];
 
   CodePointComputer(this.sourceFileManager, this.code, this.nodeMap);
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
index 4227fee..52e871d 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
@@ -8,6 +8,7 @@
 library sourcemap.html.helper;
 
 import 'dart:convert';
+import 'dart:math' as Math;
 
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/io/source_information.dart';
@@ -40,9 +41,14 @@
   return 'linear-gradient(to right, ${startColor.toCss}, ${endColor.toCss})';
 }
 
-/// Return the html for the [index] line number.
-String lineNumber(int index) {
-  return '<span class="lineNumber">${index + 1} </span>';
+/// Return the html for the [index] line number. If [width] is provided, shorter
+/// line numbers will be prefixed with spaces to match the width.
+String lineNumber(int index, [int width]) {
+  String text = '${index + 1}';
+  if (width != null && text.length < width) {
+    text = (' ' * (width - text.length)) + text;
+  }
+  return '<span class="lineNumber">$text </span>';
 }
 
 /// Return the html escaped [text].
@@ -59,6 +65,10 @@
   SourceMapHtmlInfo(this.sourceMapInfo,
                     this.codeProcessor,
                     this.sourceLocationCollection);
+
+  String toString() {
+    return sourceMapInfo.toString();
+  }
 }
 
 /// A collection of source locations.
@@ -84,16 +94,98 @@
   }
 }
 
+abstract class CssColorScheme {
+  String singleLocationToCssColor(var id);
+
+  String multiLocationToCssColor(List ids);
+
+  bool get showLocationAsSpan;
+}
+
+class CustomColorScheme implements CssColorScheme {
+  final bool showLocationAsSpan;
+  final Function single;
+  final Function multi;
+
+  CustomColorScheme(
+      {this.showLocationAsSpan: false,
+       String this.single(var id),
+       String this.multi(List ids)});
+
+  String singleLocationToCssColor(var id) => single != null ? single(id) : null;
+
+  String multiLocationToCssColor(List ids) => multi != null ? multi(ids) : null;
+}
+
+class PatternCssColorScheme implements CssColorScheme {
+  const PatternCssColorScheme();
+
+  bool get showLocationAsSpan => true;
+
+  String singleLocationToCssColor(int index) {
+    return "background:${toPattern(index)};";
+  }
+
+  String multiLocationToCssColor(List<int> indices) {
+
+    StringBuffer sb = new StringBuffer();
+    double delta = 100.0 / (indices.length);
+    double position = 0.0;
+
+    void addColor(String color) {
+      sb.write(', ${color} ${position.toInt()}%');
+      position += delta;
+      sb.write(', ${color} ${position.toInt()}%');
+    }
+
+    for (int index in indices) {
+      addColor('${toColorCss(index)}');
+    }
+    return 'background: linear-gradient(to right${sb}); '
+           'background-size: 10px 10px;';
+  }
+}
+
+class SingleColorScheme implements CssColorScheme {
+  const SingleColorScheme();
+
+  bool get showLocationAsSpan => false;
+
+  String singleLocationToCssColor(int index) {
+    return "background:${toColorCss(index)};";
+  }
+
+  String multiLocationToCssColor(List<int> indices) {
+    StringBuffer sb = new StringBuffer();
+    double delta = 100.0 / (indices.length);
+    double position = 0.0;
+
+    void addColor(String color) {
+      sb.write(', ${color} ${position.toInt()}%');
+      position += delta;
+      sb.write(', ${color} ${position.toInt()}%');
+    }
+
+    for (int index in indices) {
+      addColor('${toColorCss(index)}');
+    }
+    return 'background: linear-gradient(to bottom${sb}); '
+           'background-size: 10px 3px;';
+  }
+}
+
 /// Processor that computes the HTML representation of a block of JavaScript
 /// code and collects the source locations mapped in the code.
 class CodeProcessor {
   int lineIndex = 0;
-  final String onclick;
+  final String name;
   int currentJsSourceOffset = 0;
   final SourceLocationCollection collection;
   final Map<int, List<SourceLocation>> codeLocations = {};
+  final CssColorScheme colorScheme;
 
-  CodeProcessor(this.onclick, this.collection);
+  CodeProcessor(this.name, this.collection,
+      {this.colorScheme: const PatternCssColorScheme()});
 
   void addSourceLocation(int targetOffset, SourceLocation sourceLocation) {
     codeLocations.putIfAbsent(targetOffset, () => []).add(sourceLocation);
@@ -101,102 +193,275 @@
   }
 
   String convertToHtml(String text) {
-    StringBuffer htmlBuffer = new StringBuffer();
-    int offset = 0;
-    int lineIndex = 0;
-    bool pendingSourceLocationsEnd = false;
-    htmlBuffer.write(lineNumber(lineIndex));
-    SourceLocation currentLocation;
-
-    void endCurrentLocation() {
-      if (currentLocation != null) {
-        htmlBuffer.write('</a>');
-      }
-      currentLocation = null;
-    }
-
-    void addSubstring(int until) {
-      if (until <= offset) return;
-
-      String substring = text.substring(offset, until);
-      offset = until;
-      bool first = true;
-      for (String line in substring.split('\n')) {
-        if (!first) {
-          endCurrentLocation();
-          htmlBuffer.write('\n');
-          lineIndex++;
-          htmlBuffer.write(lineNumber(lineIndex));
+    List<Annotation> annotations = <Annotation>[];
+    codeLocations.forEach((int codeOffset, List<SourceLocation> locations) {
+      for (SourceLocation location in locations) {
+        if (location != null) {
+          annotations.add(new Annotation(
+              collection.getIndex(location),
+              codeOffset,
+              location.shortText));
         }
-        htmlBuffer.write(escape(line));
-        first = false;
       }
-    }
-
-    void insertSourceLocations(List<SourceLocation> lastSourceLocations) {
-      endCurrentLocation();
-
-      String color;
-      int index;
-      String title;
-      if (lastSourceLocations.length == 1) {
-        SourceLocation sourceLocation = lastSourceLocations.single;
-        if (sourceLocation != null) {
-          index = collection.getIndex(sourceLocation);
-          color = "background:${toPattern(index)};";
-          title = sourceLocation.shortText;
-          currentLocation = sourceLocation;
-        }
-      } else {
-
-        index = collection.getIndex(lastSourceLocations.first);
-        StringBuffer sb = new StringBuffer();
-        double delta = 100.0 / (lastSourceLocations.length);
-        double position = 0.0;
-
-        void addColor(String color) {
-          sb.write(', ${color} ${position.toInt()}%');
-          position += delta;
-          sb.write(', ${color} ${position.toInt()}%');
-        }
-
-        for (SourceLocation sourceLocation in lastSourceLocations) {
-          if (sourceLocation == null) continue;
-          int colorIndex = collection.getIndex(sourceLocation);
-          addColor('${toColorCss(colorIndex)}');
-          currentLocation = sourceLocation;
-        }
-        color = 'background: linear-gradient(to right${sb}); '
-                'background-size: 10px 10px;';
-        title = lastSourceLocations.map((l) => l.shortText).join(',');
-      }
-      if (index != null) {
-        Set<int> indices =
-            lastSourceLocations.map((l) => collection.getIndex(l)).toSet();
-        String onmouseover = indices.map((i) => '\'$i\'').join(',');
-        htmlBuffer.write(
-            '<a name="js$index" href="#${index}" style="$color" title="$title" '
-            'onclick="${onclick}" onmouseover="highlight([${onmouseover}]);"'
-            'onmouseout="highlight([]);">');
-        pendingSourceLocationsEnd = true;
-      }
-      if (lastSourceLocations.last == null) {
-        endCurrentLocation();
-      }
-    }
-
-    for (int targetOffset in codeLocations.keys.toList()..sort()) {
-      List<SourceLocation> sourceLocations = codeLocations[targetOffset];
-      addSubstring(targetOffset);
-      insertSourceLocations(sourceLocations);
-    }
-
-    addSubstring(text.length);
-    endCurrentLocation();
-    return htmlBuffer.toString();
+    });
+    return convertAnnotatedCodeToHtml(
+        text, annotations, colorScheme: colorScheme,
+        elementScheme: new HighlightLinkScheme(name),
+        windowSize: 3);
   }
 }
 
+class Annotation {
+  final id;
+  final int codeOffset;
+  final String title;
+
+  Annotation(this.id, this.codeOffset, this.title);
+}
+
+class ElementScheme {
+  const ElementScheme();
+
+  String getName(var id, Set ids) => null;
+  String getHref(var id, Set ids) => null;
+  String onClick(var id, Set ids) => null;
+  String onMouseOver(var id, Set ids) => null;
+  String onMouseOut(var id, Set ids) => null;
+}
+
+class HighlightLinkScheme implements ElementScheme {
+  final String name;
+
+  HighlightLinkScheme(this.name);
+
+  @override
+  String getName(int id, Set<int> indices) {
+    return 'js$id';
+  }
+
+  @override
+  String getHref(int id, Set<int> indices) {
+    return "#${id}";
+  }
+
+  @override
+  String onClick(int id, Set<int> indices) {
+    return "show(\'$name\');";
+  }
+
+  @override
+  String onMouseOut(int id, Set<int> indices) {
+    String onmouseover = indices.map((i) => '\'$i\'').join(',');
+    return "highlight([${onmouseover}]);";
+  }
+
+  @override
+  String onMouseOver(int id, Set<int> indices) {
+    return "highlight([]);";
+  }
+}
+
+String convertAnnotatedCodeToHtml(
+    String code,
+    Iterable<Annotation> annotations,
+    {CssColorScheme colorScheme: const SingleColorScheme(),
+     ElementScheme elementScheme: const ElementScheme(),
+     int windowSize}) {
+  StringBuffer htmlBuffer = new StringBuffer();
+  List<CodeLine> lines = convertAnnotatedCodeToCodeLines(
+      code, annotations,
+      colorScheme: colorScheme,
+      elementScheme: elementScheme,
+      windowSize: windowSize);
+  int lineNoWidth;
+  if (lines.isNotEmpty) {
+    lineNoWidth = '${lines.last.lineNo + 1}'.length;
+  }
+  for (CodeLine line in lines) {
+    line.printHtmlOn(htmlBuffer, lineNoWidth);
+  }
+  return htmlBuffer.toString();
+}
+
+List<CodeLine> convertAnnotatedCodeToCodeLines(
+    String code,
+    Iterable<Annotation> annotations,
+    {CssColorScheme colorScheme: const SingleColorScheme(),
+     ElementScheme elementScheme: const ElementScheme(),
+     int windowSize}) {
+
+  List<CodeLine> lines = <CodeLine>[];
+  CodeLine currentLine;
+  int offset = 0;
+  int lineIndex = 0;
+  int firstLine;
+  int lastLine;
+  bool pendingSourceLocationsEnd = false;
+
+  void write(String code, String html) {
+    if (currentLine != null) {
+      currentLine.codeBuffer.write(code);
+      currentLine.htmlParts.add(html);
+    }
+  }
+
+  void startLine() {
+    lines.add(currentLine = new CodeLine(lines.length));
+  }
+
+  void endCurrentLocation() {
+    if (pendingSourceLocationsEnd) {
+      write('', '</a>');
+    }
+    pendingSourceLocationsEnd = false;
+  }
+
+  void addSubstring(int until, {bool isFirst: false, bool isLast: false}) {
+    if (until <= offset) return;
+    if (offset >= code.length) return;
+
+    String substring = code.substring(offset, until);
+    offset = until;
+    bool first = true;
+
+    if (isLast) {
+      lastLine = lineIndex;
+    }
+    if (isFirst) {
+      startLine();
+    }
+    for (String line in substring.split('\n')) {
+      if (!first) {
+        endCurrentLocation();
+        write('', '\n');
+        lineIndex++;
+        startLine();
+      }
+      if (pendingSourceLocationsEnd && !colorScheme.showLocationAsSpan) {
+        if (line.isNotEmpty) {
+          String before = line.substring(0, 1);
+          write(before, escape(before));
+          endCurrentLocation();
+          String after = line.substring(1);
+          write(after, escape(after));
+        }
+      } else {
+        write(line, escape(line));
+      }
+      first = false;
+    }
+    if (isFirst) {
+      firstLine = lineIndex;
+    }
+  }
+
+  void insertAnnotations(List<Annotation> annotations) {
+    endCurrentLocation();
+
+    String color;
+    var id;
+    String title;
+    if (annotations.length == 1) {
+      Annotation annotation = annotations.single;
+      if (annotation != null) {
+        id = annotation.id;
+        color = colorScheme.singleLocationToCssColor(id);
+        title = annotation.title;
+      }
+    } else {
+      id = annotations.first.id;
+      List ids = [];
+      for (Annotation annotation in annotations) {
+        ids.add(annotation.id);
+      }
+      color = colorScheme.multiLocationToCssColor(ids);
+      title = annotations.map((l) => l.title).join(',');
+    }
+    if (id != null) {
+      Set ids = annotations.map((l) => l.id).toSet();
+      String name = elementScheme.getName(id, ids);
+      String href = elementScheme.getHref(id, ids);
+      String onclick = elementScheme.onClick(id, ids);
+      String onmouseover = elementScheme.onMouseOver(id, ids);
+      String onmouseout = elementScheme.onMouseOut(id, ids);
+      write('', '<a');
+      if (href != null) {
+        write('', ' href="${href}"');
+      }
+      if (name != null) {
+        write('', ' name="${name}"');
+      }
+      if (title != null) {
+        write('', ' title="${escape(title)}"');
+      }
+      write('', ' style="${color}"');
+      if (onclick != null) {
+        write('', ' onclick="${onclick}"');
+      }
+      if (onmouseover != null) {
+        write('', ' onmouseover="${onmouseover}"');
+      }
+      if (onmouseout != null) {
+        write('', ' onmouseout="${onmouseout}"');
+      }
+      write('', '>');
+      pendingSourceLocationsEnd = true;
+    }
+    if (annotations.last == null) {
+      endCurrentLocation();
+    }
+  }
+
+  Map<int, List<Annotation>> annotationMap = <int, List<Annotation>>{};
+  for (Annotation annotation in annotations) {
+    annotationMap.putIfAbsent(annotation.codeOffset, () => <Annotation>[])
+                 .add(annotation);
+  }
+
+  bool first = true;
+  for (int codeOffset in annotationMap.keys.toList()..sort()) {
+    List<Annotation> annotationList = annotationMap[codeOffset];
+    addSubstring(codeOffset, isFirst: first);
+    insertAnnotations(annotationList);
+    first = false;
+  }
+
+  addSubstring(code.length, isFirst: first, isLast: true);
+  endCurrentLocation();
+
+  int start = 0;
+  int end = lines.length - 1;
+  if (windowSize != null) {
+    start = Math.max(firstLine - windowSize, start);
+    end = Math.min(lastLine + windowSize, end);
+  }
+  return lines.sublist(start, end);
+}
+
+class CodeLine {
+  final int lineNo;
+  final StringBuffer codeBuffer = new StringBuffer();
+  final List<String> htmlParts = <String>[];
+  String _code;
+
+  CodeLine(this.lineNo);
+
+  String get code {
+    if (_code == null) {
+      _code = codeBuffer.toString();
+    }
+    return _code;
+  }
+
+  void printHtmlOn(StringBuffer htmlBuffer, [int lineNoWidth]) {
+    htmlBuffer.write(lineNumber(lineNo, lineNoWidth));
+    for (String part in htmlParts) {
+      htmlBuffer.write(part);
+    }
+  }
+}
+
+
 /// Computes the HTML representation for a collection of JavaScript code blocks.
 String computeJsHtml(Iterable<SourceMapHtmlInfo> infoList) {
 
@@ -240,10 +505,10 @@
   js.Node node = info.node;
   String code = info.code;
   String name = info.name;
-  String onclick = 'show(\'$name\');';
   SourceLocationCollection subcollection =
       new SourceLocationCollection(collection);
-  CodeProcessor codeProcessor = new CodeProcessor(onclick, subcollection);
+  CodeProcessor codeProcessor = new CodeProcessor(name, subcollection);
+  //print('${info.element}:${info.nodeMap.nodes.length}');
   for (js.Node node in info.nodeMap.nodes) {
     info.nodeMap[node].forEach(
         (int targetOffset, List<SourceLocation> sourceLocations) {
@@ -312,6 +577,11 @@
 
     int firstLineIndex;
     int lastLineIndex;
+    List<int> lineIndices = uriMap.keys.toList()..sort();
+    int lineNoWidth;
+    if (lineIndices.isNotEmpty) {
+      lineNoWidth = '${lineIndices.last + windowSize + 1}'.length;
+    }
 
     void flush() {
       if (firstLineIndex != null && lastLineIndex != null) {
@@ -325,7 +595,7 @@
              line < firstLineIndex;
              line++) {
           if (line >= 0) {
-            dartCodeBuffer.write(lineNumber(line));
+            dartCodeBuffer.write(lineNumber(line, lineNoWidth));
             dartCodeBuffer.write(sourceFile.getLineText(line));
           }
         }
@@ -334,7 +604,7 @@
              line <= lastLineIndex + windowSize;
              line++) {
           if (line < sourceFile.lines) {
-            dartCodeBuffer.write(lineNumber(line));
+            dartCodeBuffer.write(lineNumber(line, lineNoWidth));
             dartCodeBuffer.write(sourceFile.getLineText(line));
           }
         }
@@ -345,7 +615,6 @@
       codeBuffer.clear();
     }
 
-    List<int> lineIndices = uriMap.keys.toList()..sort();
     lineIndices.forEach((int lineIndex) {
       List<SourceLocation> locations = uriMap[lineIndex];
       if (lastLineIndex != null &&
@@ -356,7 +625,7 @@
         firstLineIndex = lineIndex;
       } else {
         for (int line = lastLineIndex + 1; line < lineIndex; line++) {
-          codeBuffer.write(lineNumber(line));
+          codeBuffer.write(lineNumber(line, lineNoWidth));
           codeBuffer.write(sourceFile.getLineText(line));
         }
       }
@@ -371,7 +640,7 @@
           end = locations[i + 1].column;
         }
         if (i == 0) {
-          codeBuffer.write(lineNumber(lineIndex));
+          codeBuffer.write(lineNumber(lineIndex, lineNoWidth));
           codeBuffer.write(line.substring(0, start));
         }
         codeBuffer.write(
diff --git a/tests/compiler/dart2js/sourcemaps/trace_graph.dart b/tests/compiler/dart2js/sourcemaps/trace_graph.dart
new file mode 100644
index 0000000..b21014b
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/trace_graph.dart
@@ -0,0 +1,54 @@
+// 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 sourcemap.trace_graph;
+
+import 'dart:collection';
+
+import 'package:compiler/src/io/source_information.dart';
+import 'package:compiler/src/io/position_information.dart';
+
+import 'sourcemap_html_helper.dart';
+
+class TraceGraph {
+  List<TraceStep> steps = <TraceStep>[];
+  TraceStep entry;
+  Queue stack = new Queue();
+
+  void addStep(TraceStep step) {
+    steps.add(step);
+    step.stack = stack.toList();
+  }
+
+  void pushBranch(branch) {
+    stack.addLast(branch);
+  }
+
+  void popBranch() {
+    stack.removeLast();
+  }
+}
+
+class TraceStep {
+  final int id;
+  final node;
+  final Offset offset;
+  final List text;
+  final SourceLocation sourceLocation;
+
+  TraceStep next;
+  Map<dynamic, TraceStep> branchMap;
+
+  List stack;
+
+  TraceStep(
+      this.id,
+      this.node,
+      this.offset,
+      this.text,
+      [this.sourceLocation]);
+
+  String toString() => '<span style="background:${toColorCss(id)}">$id</span>';
+}
+
diff --git a/tests/compiler/dart2js/type_mask_disjoint_test.dart b/tests/compiler/dart2js/type_mask_disjoint_test.dart
new file mode 100644
index 0000000..4cc7a00
--- /dev/null
+++ b/tests/compiler/dart2js/type_mask_disjoint_test.dart
@@ -0,0 +1,184 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+import 'package:compiler/src/types/types.dart';
+
+import 'compiler_helper.dart';
+
+const String CODE = """
+class A {}
+class B extends A {}
+class C extends A {}
+
+class D implements A {}
+
+class E {}
+class F extends E {}
+class G implements E {}
+
+class H {}
+class I implements H {}
+class J extends D implements I {}
+
+class K {}
+class M extends K with A {}
+
+main() {
+  print([new A(), new B(), new C(), new D(), new E(), new F(), new G(),
+      new H(), new I(), new J(), new K(), new M()]);
+}
+""";
+
+Uri uri = new Uri(scheme: 'source');
+var compiler = compilerFor(CODE, uri);
+var world = compiler.world;
+
+main() {
+  asyncTest(() => compiler.run(uri).then((_) {
+
+    // Empty
+    check(' ! ', ' ! ');  // both non-null
+    check(' ! ', '   ');  // one non-null
+    check('   ', ' ! ');  // one non-null
+    check('   ', '   ', areDisjoint: false); // null is common
+
+    // Exact
+    check('A!=', 'A!=', areDisjoint: false);
+    check('A!=', 'B!=');
+    check('A!=', 'E!=');
+    check('A =', 'E =', areDisjoint: false); // null is common
+    check('M!=', 'K!=');
+    check('M!=', 'A!=');
+
+    // Exact with subclass
+    check('A!=', 'A!<', areDisjoint: false);
+    check('B!=', 'A!<', areDisjoint: false);
+    check('A!=', 'B!<');
+    check('A!=', 'E!<');
+    check('A =', 'E!<');
+    check('A =', 'E <', areDisjoint: false);
+    check('M!=', 'K!<', areDisjoint: false);
+    check('M!=', 'A!<');
+
+    // Exact with subtype
+    check('A!=', 'A!*', areDisjoint: false);
+    check('B!=', 'A!*', areDisjoint: false);
+    check('A!=', 'B!*');
+    check('A!=', 'E!*');
+    check('A!=', 'I!*');
+    check('J!=', 'H!*', areDisjoint: false);
+    check('M!=', 'K!*', areDisjoint: false);
+    check('M!=', 'A!*', areDisjoint: false);
+
+    // Subclass with subclass
+    check('A!<', 'A!<', areDisjoint: false);
+    check('A!<', 'B!<', areDisjoint: false);
+    check('A!<', 'E!<');
+    check('A!<', 'H!<');
+    check('D!<', 'I!<');
+
+    // Subclass with subtype
+    check('A!<', 'A!*', areDisjoint: false);
+    check('A!<', 'B!*', areDisjoint: false);
+    check('A!<', 'E!*');
+    check('A!<', 'H!*');
+    check('D!<', 'I!*', areDisjoint: false);
+
+    // Subtype with subtype
+    check('A!*', 'A!*', areDisjoint: false);
+    check('A!*', 'B!*', areDisjoint: false);
+    check('A!*', 'E!*');
+    check('A!*', 'H!*', areDisjoint: false);
+    check('D!*', 'I!*', areDisjoint: false);
+
+    // Unions!
+    checkUnions(['B!=', 'C!='], ['A!=']);
+    checkUnions(['B!=', 'C!='], ['A =']);
+    checkUnions(['B!=', 'C ='], ['A ='], areDisjoint: false);
+
+    checkUnions(['B!=', 'C!='], ['A!<'], areDisjoint: false);
+    checkUnions(['B!=', 'C!='], ['B!='], areDisjoint: false);
+    checkUnions(['A!<', 'E!<'], ['C!='], areDisjoint: false);
+    checkUnions(['A!<', 'E!<'], ['F!='], areDisjoint: false);
+
+    checkUnions(['A!=', 'E!='], ['C!=', 'F!=']);
+    checkUnions(['A!=', 'E!='], ['A!=', 'F!='], areDisjoint: false);
+    checkUnions(['B!=', 'E!='], ['A!<', 'F!='], areDisjoint: false);
+    checkUnions(['A!<', 'E!<'], ['C!=', 'F!='], areDisjoint: false);
+    checkUnions(['A!=', 'E!='], ['C!=', 'F!=']);
+  }));
+}
+
+/// Checks the expectation of `isDisjoint` for two mask. Also checks that the
+/// result is consistent with an equivalent (but slower) implementation based on
+/// intersection.
+checkMask(TypeMask m1, TypeMask m2, {areDisjoint: false}) {
+  print('masks: $m1 $m2');
+  Expect.equals(areDisjoint, m1.isDisjoint(m2, world));
+  Expect.equals(areDisjoint, m2.isDisjoint(m1, world));
+  var i1 = m1.intersection(m2, world);
+  Expect.equals(areDisjoint, i1.isEmpty && !i1.isNullable);
+  var i2 = m2.intersection(m1, world);
+  Expect.equals(areDisjoint, i2.isEmpty && !i2.isNullable);
+}
+
+/// Checks the expectation of `isDisjoint` for two mask descriptors (see
+/// [maskOf] for details).
+check(String typeMaskDescriptor1, String typeMaskDescriptor2,
+    {areDisjoint: true}) {
+  print('[$typeMaskDescriptor1] & [$typeMaskDescriptor2]');
+  checkMask(maskOf(typeMaskDescriptor1), maskOf(typeMaskDescriptor2),
+      areDisjoint: areDisjoint);
+}
+
+
+checkUnions(List descriptors1, List descriptors2, {areDisjoint: true}) {
+  print('[$descriptors1] & [$descriptors2]');
+  var m1 = new TypeMask.unionOf(descriptors1.map(maskOf).toList(), world);
+  var m2 = new TypeMask.unionOf(descriptors2.map(maskOf).toList(), world);
+  checkMask(m1, m2, areDisjoint: areDisjoint);
+}
+
+Map _maskCache = {};
+Map _elementCache = {};
+
+/// Parses a descriptor of a flat mask. A descriptor is of the form "AXY" where:
+///   A: either a type T or " " (base class or empty)
+///   X: can be either ! or " " (nullable/nonnullable)
+///   Y: can be either " " (no flag), = (exact), < (subclass), * (subtype)
+///
+/// Examples:
+///   "-! " - empty, non-null
+///   "-  " - null
+///   "Type!=" - non-null exact Type
+///   "Type =" - nullable exact Type
+///   "Type!<" - non-null subclass of Type
+///   "Type!*" - non-null subtype of Type
+TypeMask maskOf(String descriptor) =>
+  _maskCache.putIfAbsent(descriptor, () {
+    Expect.isTrue(descriptor.length >= 3);
+    var type = descriptor.substring(0, descriptor.length - 2);
+    bool isNullable = descriptor[descriptor.length - 2] != '!';
+    bool isExact = descriptor[descriptor.length - 1] == '=';
+    bool isSubclass = descriptor[descriptor.length - 1] == '<';
+    bool isSubtype = descriptor[descriptor.length - 1] == '*';
+
+    if (type == " ") {
+      Expect.isFalse(isExact || isSubclass || isSubtype);
+      return isNullable ? new TypeMask.empty() : new TypeMask.nonNullEmpty();
+    }
+
+    Expect.isTrue(isExact || isSubclass || isSubtype);
+    var element = _elementCache.putIfAbsent(type,
+        () => type == " " ? null : findElement(compiler, type));
+
+    var mask = isExact
+        ? new TypeMask.nonNullExact(element, world)
+        : (isSubclass
+            ? new TypeMask.nonNullSubclass(element, world)
+            : new TypeMask.nonNullSubtype(element, world));
+    return isNullable ? mask.nullable() : mask;
+  });
diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart
index 0a2d4e0..ce4f3c8 100644
--- a/tests/compiler/dart2js/type_representation_test.dart
+++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -50,7 +50,7 @@
     }
 
     String stringify(Expression expression) {
-      return prettyPrint(expression, env.compiler).buffer.toString();
+      return prettyPrint(expression, env.compiler);
     }
 
     void expect(DartType type,
diff --git a/tests/compiler/dart2js/world_test.dart b/tests/compiler/dart2js/world_test.dart
index 13a0821..0109f8d 100644
--- a/tests/compiler/dart2js/world_test.dart
+++ b/tests/compiler/dart2js/world_test.dart
@@ -7,13 +7,22 @@
 import 'package:expect/expect.dart';
 import 'package:async_helper/async_helper.dart';
 import 'type_test_helper.dart';
+import 'package:compiler/src/common.dart';
 import 'package:compiler/src/elements/elements.dart'
        show Element, ClassElement;
+import 'package:compiler/src/universe/class_set.dart';
 import 'package:compiler/src/world.dart' show ClassWorld;
 
 void main() {
-  asyncTest(() => TypeEnvironment.create(r"""
-      class A {}
+  asyncTest(() async {
+    await testClassSets();
+    await testProperties();
+  });
+}
+
+testClassSets() async {
+  var env = await TypeEnvironment.create(r"""
+      class A implements X {}
       class B {}
       class C_Super extends A {}
       class C extends C_Super {}
@@ -21,6 +30,7 @@
       class E extends B implements A {}
       class F extends Object with A implements B {}
       class G extends Object with A, B {}
+      class X {}
       """,
       mainSource: r"""
       main() {
@@ -33,120 +43,283 @@
         new G();
       }
       """,
-      useMockCompiler: false).then((env) {
-    ClassWorld classWorld = env.compiler.world;
+      useMockCompiler: false);
+  ClassWorld classWorld = env.compiler.world;
 
-    ClassElement Object_ = env.getElement("Object");
-    ClassElement A = env.getElement("A");
-    ClassElement B = env.getElement("B");
-    ClassElement C = env.getElement("C");
-    ClassElement D = env.getElement("D");
-    ClassElement E = env.getElement("E");
-    ClassElement F = env.getElement("F");
-    ClassElement G = env.getElement("G");
+  ClassElement Object_ = env.getElement("Object");
+  ClassElement A = env.getElement("A");
+  ClassElement B = env.getElement("B");
+  ClassElement C = env.getElement("C");
+  ClassElement D = env.getElement("D");
+  ClassElement E = env.getElement("E");
+  ClassElement F = env.getElement("F");
+  ClassElement G = env.getElement("G");
+  ClassElement X = env.getElement("X");
 
-    void check(
-        String property,
-        ClassElement cls,
-        Iterable<ClassElement> foundClasses,
-        List<ClassElement> expectedClasses,
-        {bool exact: true}) {
-      for (ClassElement expectedClass in expectedClasses) {
-        Expect.isTrue(foundClasses.contains(expectedClass),
-            "Expect $expectedClass in '$property' on $cls. "
-            "Found:\n ${foundClasses.join('\n ')}");
+  void checkClasses(
+      String property,
+      ClassElement cls,
+      Iterable<ClassElement> foundClasses,
+      List<ClassElement> expectedClasses,
+      {bool exact: true}) {
+
+    for (ClassElement expectedClass in expectedClasses) {
+      Expect.isTrue(foundClasses.contains(expectedClass),
+          "Expect $expectedClass in '$property' on $cls. "
+          "Found:\n ${foundClasses.join('\n ')}\n"
+          "${env.compiler.world.dump(cls)}");
+    }
+    if (exact) {
+      Expect.equals(expectedClasses.length, foundClasses.length,
+          "Unexpected classes "
+          "${foundClasses.where((c) => !expectedClasses.contains(c))} "
+          "in '$property' on $cls.\n"
+          "${env.compiler.world.dump(cls)}");
+    }
+  }
+
+  void check(
+      String property,
+      ClassElement cls,
+      Iterable<ClassElement> foundClasses,
+      List<ClassElement> expectedClasses,
+      {bool exact: true,
+       void forEach(ClassElement cls, ForEachFunction f),
+       int getCount(ClassElement cls)}) {
+    checkClasses(property, cls, foundClasses, expectedClasses, exact: exact);
+
+    if (forEach != null) {
+      List<ClassElement> visited = <ClassElement>[];
+      forEach(cls, (ClassElement c) {
+        visited.add(c);
+      });
+      checkClasses(
+          'forEach($property)', cls, visited, expectedClasses, exact: exact);
+    }
+
+    if (getCount != null && exact) {
+      int count = getCount(cls);
+      Expect.equals(expectedClasses.length, count,
+          "Unexpected class count in '$property' on $cls.\n"
+          "${env.compiler.world.dump(cls)}");
+    }
+
+  }
+
+  void testSubclasses(
+      ClassElement cls,
+      List<ClassElement> expectedClasses,
+      {bool exact: true}) {
+    check(
+      'subclassesOf',
+      cls,
+      classWorld.subclassesOf(cls),
+      expectedClasses,
+      exact: exact);
+  }
+
+  void testStrictSubclasses(
+      ClassElement cls,
+      List<ClassElement> expectedClasses,
+      {bool exact: true}) {
+    check(
+      'strictSubclassesOf',
+      cls,
+      classWorld.strictSubclassesOf(cls),
+      expectedClasses,
+      exact: exact,
+      forEach: classWorld.forEachStrictSubclassOf,
+      getCount: classWorld.strictSubclassCount);
+  }
+
+  void testStrictSubtypes(
+      ClassElement cls,
+      List<ClassElement> expectedClasses,
+      {bool exact: true}) {
+    check(
+      'strictSubtypesOf',
+      cls,
+      classWorld.strictSubtypesOf(cls),
+      expectedClasses,
+      exact: exact,
+      forEach: classWorld.forEachStrictSubtypeOf,
+      getCount: classWorld.strictSubtypeCount);
+  }
+
+  void testMixinUses(
+      ClassElement cls,
+      List<ClassElement> expectedClasses,
+      {bool exact: true}) {
+    check(
+      'mixinUsesOf',
+      cls,
+      classWorld.mixinUsesOf(cls),
+      expectedClasses,
+      exact: exact);
+  }
+
+  testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
+  testSubclasses(A, [A, C]);
+  testSubclasses(B, [B, E]);
+  testSubclasses(C, [C]);
+  testSubclasses(D, [D]);
+  testSubclasses(E, [E]);
+  testSubclasses(F, [F]);
+  testSubclasses(G, [G]);
+  testSubclasses(X, []);
+
+  testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
+  testStrictSubclasses(A, [C]);
+  testStrictSubclasses(B, [E]);
+  testStrictSubclasses(C, []);
+  testStrictSubclasses(D, []);
+  testStrictSubclasses(E, []);
+  testStrictSubclasses(F, []);
+  testStrictSubclasses(G, []);
+  testStrictSubclasses(X, []);
+
+  testStrictSubtypes(Object_, [A, B, C, D, E, F, G], exact: false);
+  testStrictSubtypes(A, [C, D, E, F, G]);
+  testStrictSubtypes(B, [E, F, G]);
+  testStrictSubtypes(C, []);
+  testStrictSubtypes(D, []);
+  testStrictSubtypes(E, []);
+  testStrictSubtypes(F, []);
+  testStrictSubtypes(G, []);
+  testStrictSubtypes(X, [A, C, D, E, F, G]);
+
+  testMixinUses(Object_, []);
+  testMixinUses(A, [F.superclass, G.superclass.superclass]);
+  testMixinUses(B, [G.superclass]);
+  testMixinUses(C, []);
+  testMixinUses(D, []);
+  testMixinUses(E, []);
+  testMixinUses(F, []);
+  testMixinUses(G, []);
+  testMixinUses(X, []);
+}
+
+testProperties() async {
+  var env = await TypeEnvironment.create(r"""
+      class A {}
+      class A1 extends A {}
+      class A2 implements A {}
+      class A3 extends Object with A {}
+
+      class B {}
+      class B1 extends B {}
+      class B2 implements B {}
+      class B3 extends Object with B {}
+
+      class C {}
+      class C1 extends C {}
+      class C2 implements C {}
+      class C3 extends Object with C {}
+
+      class D {}
+      class D1 extends D {}
+      class D2 implements D {}
+      class D3 extends Object with D {}
+
+      class E {}
+      class E1 extends E {}
+      class E2 implements E {}
+      class E3 extends Object with E {}
+
+      class F {}
+      class F1 extends F {}
+      class F2 implements F {}
+      class F3 extends Object with F {}
+
+      class G {}
+      class G1 extends G {}
+      class G2 extends G1 {}
+      class G3 extends G2 implements G {}
+      class G4 extends G2 with G {}
+
+      class H {}
+      class H1 extends H {}
+      class H2 extends H1 {}
+      class H3 extends H2 implements H {}
+      class H4 extends H2 with H {}
+      """,
+      mainSource: r"""
+      main() {
+        new B();
+        new C1();
+        new D2();
+        new E3();
+        new F1();
+        new F2();
+        new G2();
+        new G3();
+        new H4();
       }
-      if (exact) {
-        Expect.equals(expectedClasses.length, foundClasses.length,
-            "Unexpected classes "
-            "${foundClasses.where((c) => !expectedClasses.contains(c))} "
-            "in '$property' on $cls.");
-      }
-    }
+      """,
+      useMockCompiler: false);
+  ClassWorld classWorld = env.compiler.world;
 
-    void testSubclasses(
-        ClassElement cls,
-        List<ClassElement> expectedClasses,
-        {bool exact: true}) {
-      check(
-        'subclassesOf',
-        cls,
-        classWorld.subclassesOf(cls),
-        expectedClasses,
-        exact: exact);
-    }
+  check(String name,
+      {bool hasStrictSubtype,
+       bool hasOnlySubclasses}) {
+    ClassElement cls = env.getElement(name);
+    Expect.equals(hasStrictSubtype, classWorld.hasAnyStrictSubtype(cls),
+        "Unexpected hasAnyStrictSubtype property on $cls.");
+    Expect.equals(hasOnlySubclasses, classWorld.hasOnlySubclasses(cls),
+        "Unexpected hasOnlySubclasses property on $cls.");
+  }
 
-    void testStrictSubclasses(
-        ClassElement cls,
-        List<ClassElement> expectedClasses,
-        {bool exact: true}) {
-      check(
-        'strictSubclassesOf',
-        cls,
-        classWorld.strictSubclassesOf(cls),
-        expectedClasses,
-        exact: exact);
-    }
+  check("Object", hasStrictSubtype: true, hasOnlySubclasses: true);
 
-    void testStrictSubtypes(
-        ClassElement cls,
-        List<ClassElement> expectedClasses,
-        {bool exact: true}) {
-      check(
-        'strictSubtypesOf',
-        cls,
-        classWorld.strictSubtypesOf(cls),
-        expectedClasses,
-        exact: exact);
-    }
+  // No instantiated Ax classes.
+  check("A", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("A1", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("A2", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("A3", hasStrictSubtype: false, hasOnlySubclasses: true);
 
-    void testMixinUses(
-        ClassElement cls,
-        List<ClassElement> expectedClasses,
-        {bool exact: true}) {
-      check(
-        'mixinUsesOf',
-        cls,
-        classWorld.mixinUsesOf(cls),
-        expectedClasses,
-        exact: exact);
-    }
+  // class B instantiated
+  check("B", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("B1", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("B2", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("B3", hasStrictSubtype: false, hasOnlySubclasses: true);
 
-    testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
-    testSubclasses(A, [A, C]);
-    testSubclasses(B, [B, E]);
-    testSubclasses(C, [C]);
-    testSubclasses(D, [D]);
-    testSubclasses(E, [E]);
-    testSubclasses(F, [F]);
-    testSubclasses(G, [G]);
+  // class C1 extends C instantiated
+  check("C", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("C1", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("C2", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("C3", hasStrictSubtype: false, hasOnlySubclasses: true);
 
-    testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false);
-    testStrictSubclasses(A, [C]);
-    testStrictSubclasses(B, [E]);
-    testStrictSubclasses(C, []);
-    testStrictSubclasses(D, []);
-    testStrictSubclasses(E, []);
-    testStrictSubclasses(F, []);
-    testStrictSubclasses(G, []);
+  // class D2 implements D instantiated
+  check("D", hasStrictSubtype: true, hasOnlySubclasses: false);
+  check("D1", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("D2", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("D3", hasStrictSubtype: false, hasOnlySubclasses: true);
 
-    testStrictSubtypes(Object_, [A, B, C, D, E, F, G], exact: false);
-    testStrictSubtypes(A, [C, D, E, F, G]);
-    testStrictSubtypes(B, [E, F, G]);
-    testStrictSubtypes(C, []);
-    testStrictSubtypes(D, []);
-    testStrictSubtypes(E, []);
-    testStrictSubtypes(F, []);
-    testStrictSubtypes(G, []);
+  // class E2 extends Object with E instantiated
+  check("E", hasStrictSubtype: true, hasOnlySubclasses: false);
+  check("E1", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("E2", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("E3", hasStrictSubtype: false, hasOnlySubclasses: true);
 
-    testMixinUses(Object_, []);
-    testMixinUses(A, [F.superclass, G.superclass.superclass]);
-    testMixinUses(B, [G.superclass]);
-    testMixinUses(C, []);
-    testMixinUses(D, []);
-    testMixinUses(E, []);
-    testMixinUses(F, []);
-    testMixinUses(G, []);
+  // class F1 extends F instantiated
+  // class F2 implements F instantiated
+  check("F", hasStrictSubtype: true, hasOnlySubclasses: false);
+  check("F1", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("F2", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("F3", hasStrictSubtype: false, hasOnlySubclasses: true);
 
-  }));
+  // class G2 extends G1 extends G instantiated
+  // class G3 extends G2 extends G1 extends G instantiated
+  check("G", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("G1", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("G2", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("G3", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("G4", hasStrictSubtype: false, hasOnlySubclasses: true);
+
+  // class H4 extends H2 with H extends H1 extends H instantiated
+  check("H", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("H1", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("H2", hasStrictSubtype: true, hasOnlySubclasses: true);
+  check("H3", hasStrictSubtype: false, hasOnlySubclasses: true);
+  check("H4", hasStrictSubtype: false, hasOnlySubclasses: true);
 }
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 3d00167..2cb3918 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -3,7 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2js ]
-16407_test: Fail # Issue 16407
 class_test: Fail
 statements_test: Fail
 typed_locals_test: Fail
@@ -68,6 +67,4 @@
 big_allocation_expression_test: Crash # Issue 24635
 
 [ $compiler == dart2js && $cps_ir ]
-16407_test: Pass # Please triage this failure.
 async_stacktrace_test/asyncStar: Crash # (foo()async*{try {tr...  cannot handle sync*/async* functions
-switch_test/none: Crash # (switch (val){foo:ba...  continue to a labeled switch case
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 88b3ccd..407ea29 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -189,16 +189,6 @@
 [ $compiler == dart2js && $cps_ir ]
 data_resource_test: Crash # (await for(var byteSlice in resource.openRead()){streamBytes.addAll(byteSlice);}): await for
 error_stack_trace1_test: Pass # H.unwrapException(...).get$stackTrace is not a function
-growable_list_test: RuntimeError # Typed lists
-iterable_empty_test: RuntimeError # Please triage this failure.
-iterable_return_type_test/none: RuntimeError # Please triage this failure.
-iterable_to_list_test: RuntimeError # Please triage this failure.
-iterable_to_set_test: RuntimeError # Please triage this failure.
-list_filled_type_argument_test: RuntimeError # Please triage this failure.
-list_unmodifiable_test: RuntimeError # Please triage this failure.
-map_values2_test: RuntimeError # Please triage this failure.
-map_values3_test: RuntimeError # Please triage this failure.
-map_values4_test: RuntimeError # Please triage this failure.
 package_resource_test: Crash # (await for(var byteSlice in resource.openRead()){streamBytes.addAll(byteSlice);}): await for
 regexp/pcre_test: Crash # Stack Overflow in LoopHierarchy.
 symbol_operator_test/03: RuntimeError # Issue 24878
diff --git a/tests/corelib/expando_test.dart b/tests/corelib/expando_test.dart
index d55aecf..a7fb1c4 100644
--- a/tests/corelib/expando_test.dart
+++ b/tests/corelib/expando_test.dart
@@ -18,7 +18,7 @@
       testUnnamedExpando(object);
     }
     for (var object in legal) {
-      Expect.equals(2, visits[object]);
+      Expect.equals(2, visits[object], "$object");
     }
     testIllegal();
     testIdentity();
@@ -65,19 +65,19 @@
   static testIllegal() {
     Expando<int> expando = new Expando<int>();
     Expect.throws(() => expando[null], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "null");
     Expect.throws(() => expando['string'], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "'string'");
     Expect.throws(() => expando['string'], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "'string'");
     Expect.throws(() => expando[42], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "42");
     Expect.throws(() => expando[42.87], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "42.87");
     Expect.throws(() => expando[true], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "true");
     Expect.throws(() => expando[false], (exception)
-                  => exception is ArgumentError);
+                  => exception is ArgumentError, "false");
   }
 
   static testIdentity() {
diff --git a/tests/corelib/uri_parameters_all_test.dart b/tests/corelib/uri_parameters_all_test.dart
new file mode 100644
index 0000000..ea40ad8
--- /dev/null
+++ b/tests/corelib/uri_parameters_all_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+import "package:expect/expect.dart";
+import 'dart:convert';
+
+main() {
+  testAll(["a", "b", "c"]);
+  testAll([""]);
+  testAll(["a"]);
+  testAll(["",""]);
+  testAll(["baz"]);
+
+  testParse("z&y&w&z", {"z": ["", ""], "y": [""], "w": [""]});
+  testParse("x=42&y=42&x=37&y=37", {"x": ["42", "37"], "y": ["42", "37"]});
+  testParse("x&x&x&x&x", {"x": ["", "", "", "", ""]});
+  testParse("x=&&y", {"x": [""], "y": [""]});
+}
+
+testAll(List values) {
+  var uri = new Uri(scheme: "foo", path: "bar",
+                    queryParameters: {"baz": values});
+  var list = uri.queryParametersAll["baz"];
+  Expect.listEquals(values, list);
+}
+
+testParse(query, results) {
+  var uri = new Uri(scheme: "foo", path: "bar", query: query);
+  var params = uri.queryParametersAll;
+  for (var k in results.keys) {
+    Expect.listEquals(results[k], params[k]);
+  }
+  uri = new Uri(scheme: "foo", path: "bar", queryParameters: results);
+  params = uri.queryParametersAll;
+  for (var k in results.keys) {
+    Expect.listEquals(results[k], params[k]);
+  }
+}
diff --git a/tests/html/html.status b/tests/html/html.status
index cf5e043..402fe6e 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -429,3 +429,33 @@
 
 [ $compiler == dart2js && $cps_ir ]
 resource_http_test: Crash # (await for(var b in r.openRead()){bytes.addAll(b);}): await for
+
+[ $compiler == dart2js && $cps_ir && $browser ]
+custom/element_upgrade_test: RuntimeError # Please triage
+js_dart_to_string_test: RuntimeError # Please triage
+custom_elements_23127_test/c2t: RuntimeError # Please triage
+custom_elements_23127_test/c2: RuntimeError # Please triage
+custom_elements_23127_test/baseline: RuntimeError # Please triage
+keyboard_event_test: RuntimeError # Please triage
+js_typed_interop_test: RuntimeError # Please triage
+js_typed_interop_side_cast_test: RuntimeError # Please triage
+js_typed_interop_anonymous_exp_test: RuntimeError # Please triage
+custom_elements_test/register: RuntimeError # Please triage
+js_typed_interop_anonymous2_test: RuntimeError # Please triage
+js_typed_interop_anonymous_test: RuntimeError # Please triage
+js_array_test: RuntimeError # Please triage
+js_function_getter_test/call: RuntimeError # Please triage
+custom/mirrors_test: RuntimeError # Please triage
+custom/constructor_calls_created_synchronously_test: RuntimeError # Please triage
+input_element_test/attributes: Pass # Please triage
+js_function_getter_trust_types_test: RuntimeError # Please triage
+js_typed_interop_side_cast_exp_test: RuntimeError # Please triage
+js_typed_interop_anonymous2_exp_test: RuntimeError # Please triage
+mirrors_js_typed_interop_test: RuntimeError # Please triage
+js_function_getter_test: RuntimeError # Please triage
+custom_elements_23127_test/c1t: RuntimeError # Please triage
+custom_elements_test/innerHtml: RuntimeError # Please triage
+mouse_event_test: RuntimeError # Please triage
+js_test/JsObject_methods: RuntimeError # Please triage
+js_test/Dart_functions: RuntimeError # Please triage
+js_test/new_JsObject: RuntimeError # Please triage
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart
index 37c73ab..a902d59 100644
--- a/tests/html/js_test.dart
+++ b/tests/html/js_test.dart
@@ -322,7 +322,7 @@
 
   });
 
-  group('new JsObject()', () {
+  group('new_JsObject', () {
 
     test('new Foo()', () {
       var foo = new JsObject(context['Foo'], [42]);
@@ -649,7 +649,7 @@
 
   });
 
-  group('Dart functions', () {
+  group('Dart_functions', () {
     test('invoke Dart callback from JS', () {
       expect(() => context.callMethod('invokeCallback'), throws);
 
@@ -752,7 +752,7 @@
     });
   });
 
-  group('JsObject methods', () {
+  group('JsObject_methods', () {
 
     test('hashCode and ==', () {
       final o1 = context['Object'];
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index e11f91a..7e51060 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -56,9 +56,6 @@
 browser/issue_12474_test: CompileTimeError # Issue 22529
 enum_const_test/02: RuntimeError # Issue 21817
 
-[ $compiler == dart2js && $cps_ir ]
-isolate_current_test: RuntimeError # Please triage this failure.
-
 [ $compiler == dart2js && $runtime != d8 ]
 error_exit_at_spawn_test: Skip # Issue 23876
 error_at_spawn_test: Skip # Issue 23876
diff --git a/tests/language/built_in_identifier_prefix_test.dart b/tests/language/built_in_identifier_prefix_test.dart
deleted file mode 100644
index de995c9..0000000
--- a/tests/language/built_in_identifier_prefix_test.dart
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// Test that built-in identifiers can be used as library prefixes.
-
-// From The Dart Programming Language Specification, section 11.30
-// "Identifier Reference":
-//
-// "A built-in identifier is one of the identifiers produced by the
-// production BUILT IN IDENTIFIER. It is a compile-time error if a
-// built-in identifier is used as the declared name of a class, type
-// parameter or type alias. It is a compile-time error to use a
-// built-in identifier other than dynamic as a type annotation."
-//
-// Observation: it is not illegal to use a built-in identifier as a library
-// prefix.
-//
-// Observation: it is not legal to use a built-in identifer as a type
-// annotation. A type annotation is not fully defined in the
-// specification, so we assume this means that the grammar production
-// "type" cannot match a built-in identifier. Unfortunately, this
-// doesn't prevent us from using built-in identifiers *in* type
-// annotations. For example, "final abstract foo;" is illegal as
-// "abstract" is used as a type annotation. However, "final
-// abstract<dynamic> foo;" is not illegal because "abstract" is used
-// as a typeName.
-
-import "package:expect/expect.dart";
-import 'built_in_identifier_prefix_library_abstract.dart' as abstract;
-import 'built_in_identifier_prefix_library_as.dart' as as;
-import 'built_in_identifier_prefix_library_dynamic.dart' as dynamic;
-import 'built_in_identifier_prefix_library_export.dart' as export;
-import 'built_in_identifier_prefix_library_external.dart' as external;
-import 'built_in_identifier_prefix_library_factory.dart' as factory;
-import 'built_in_identifier_prefix_library_get.dart' as get;
-import 'built_in_identifier_prefix_library_implements.dart' as implements;
-import 'built_in_identifier_prefix_library_import.dart' as import;
-import 'built_in_identifier_prefix_library_library.dart' as library;
-import 'built_in_identifier_prefix_library_operator.dart' as operator;
-import 'built_in_identifier_prefix_library_part.dart' as part;
-import 'built_in_identifier_prefix_library_set.dart' as set;
-import 'built_in_identifier_prefix_library_static.dart' as static;
-import 'built_in_identifier_prefix_library_typedef.dart' as typedef;
-
-abstract.A _abstract = new abstract.A();
-as.A _as = new as.A();
-dynamic.A _dynamic = new dynamic.A();
-export.A _export = new export.A();
-external.A _external = new external.A();
-factory.A _factory = new factory.A();
-get.A _get = new get.A();
-implements.A _implements = new implements.A();
-import.A _import = new import.A();
-library.A _library = new library.A();
-operator.A _operator = new operator.A();
-part.A _part = new part.A();
-set.A _set = new set.A();
-static.A _static = new static.A();
-typedef.A _typedef = new typedef.A();
-
-abstract<dynamic> generic_abstract = new abstract.A();
-as<dynamic> generic_as = new as.A();
-dynamic<dynamic> generic_dynamic = new dynamic.A();
-export<dynamic> generic_export = new export.A();
-external<dynamic> generic_external = new external.A();
-factory<dynamic> generic_factory = new factory.A();
-get<dynamic> generic_get = new get.A();
-implements<dynamic> generic_implements = new implements.A();
-import<dynamic> generic_import = new import.A();
-library<dynamic> generic_library = new library.A();
-operator<dynamic> generic_operator = new operator.A();
-part<dynamic> generic_part = new part.A();
-set<dynamic> generic_set = new set.A();
-static<dynamic> generic_static = new static.A();
-typedef<dynamic> generic_typedef = new typedef.A();
-
-abstract.B<dynamic> dynamic_B_abstract = new abstract.B();
-as.B<dynamic> dynamic_B_as = new as.B();
-dynamic.B<dynamic> dynamic_B_dynamic = new dynamic.B();
-export.B<dynamic> dynamic_B_export = new export.B();
-external.B<dynamic> dynamic_B_external = new external.B();
-factory.B<dynamic> dynamic_B_factory = new factory.B();
-get.B<dynamic> dynamic_B_get = new get.B();
-implements.B<dynamic> dynamic_B_implements = new implements.B();
-import.B<dynamic> dynamic_B_import = new import.B();
-library.B<dynamic> dynamic_B_library = new library.B();
-operator.B<dynamic> dynamic_B_operator = new operator.B();
-part.B<dynamic> dynamic_B_part = new part.B();
-set.B<dynamic> dynamic_B_set = new set.B();
-static.B<dynamic> dynamic_B_static = new static.B();
-typedef.B<dynamic> dynamic_B_typedef = new typedef.B();
-
-abstract.B<abstract<dynamic>> parameterized_B_abstract = new abstract.B();
-as.B<as<dynamic>> parameterized_B_as = new as.B();
-dynamic.B<dynamic<dynamic>> parameterized_B_dynamic = new dynamic.B();
-export.B<export<dynamic>> parameterized_B_export = new export.B();
-external.B<external<dynamic>> parameterized_B_external = new external.B();
-factory.B<factory<dynamic>> parameterized_B_factory = new factory.B();
-get.B<get<dynamic>> parameterized_B_get = new get.B();
-implements.B<implements<dynamic>> parameterized_B_implements =
-  new implements.B();
-import.B<import<dynamic>> parameterized_B_import = new import.B();
-library.B<library<dynamic>> parameterized_B_library = new library.B();
-operator.B<operator<dynamic>> parameterized_B_operator = new operator.B();
-part.B<part<dynamic>> parameterized_B_part = new part.B();
-set.B<set<dynamic>> parameterized_B_set = new set.B();
-static.B<static<dynamic>> parameterized_B_static = new static.B();
-typedef.B<typedef<dynamic>> parameterized_B_typedef = new typedef.B();
-
-class UseA {
-  abstract.A abstract = new abstract.A();
-  as.A as = new as.A();
-  dynamic.A dynamic = new dynamic.A();
-  export.A export = new export.A();
-  external.A external = new external.A();
-  factory.A factory = new factory.A();
-  get.A get = new get.A();
-  implements.A implements = new implements.A();
-  import.A import = new import.A();
-  library.A library = new library.A();
-  operator.A operator = new operator.A();
-  part.A part = new part.A();
-  set.A set = new set.A();
-  static.A static = new static.A();
-  typedef.A typedef = new typedef.A();
-}
-
-main() {
-  bool assertionsEnabled = false;
-  assert(assertionsEnabled = true);
-
-  Expect.isTrue(_abstract is abstract.A);
-  Expect.isTrue(_as is as.A);
-  Expect.isTrue(_dynamic is dynamic.A);
-  Expect.isTrue(_export is export.A);
-  Expect.isTrue(_external is external.A);
-  Expect.isTrue(_factory is factory.A);
-  Expect.isTrue(_get is get.A);
-  Expect.isTrue(_implements is implements.A);
-  Expect.isTrue(_import is import.A);
-  Expect.isTrue(_library is library.A);
-  Expect.isTrue(_operator is operator.A);
-  Expect.isTrue(_part is part.A);
-  Expect.isTrue(_set is set.A);
-  Expect.isTrue(_static is static.A);
-  Expect.isTrue(_typedef is typedef.A);
-
-  Expect.isTrue(dynamic_B_abstract is abstract.B);
-  Expect.isTrue(dynamic_B_as is as.B);
-  Expect.isTrue(dynamic_B_dynamic is dynamic.B);
-  Expect.isTrue(dynamic_B_export is export.B);
-  Expect.isTrue(dynamic_B_external is external.B);
-  Expect.isTrue(dynamic_B_factory is factory.B);
-  Expect.isTrue(dynamic_B_get is get.B);
-  Expect.isTrue(dynamic_B_implements is implements.B);
-  Expect.isTrue(dynamic_B_import is import.B);
-  Expect.isTrue(dynamic_B_library is library.B);
-  Expect.isTrue(dynamic_B_operator is operator.B);
-  Expect.isTrue(dynamic_B_part is part.B);
-  Expect.isTrue(dynamic_B_set is set.B);
-  Expect.isTrue(dynamic_B_static is static.B);
-  Expect.isTrue(dynamic_B_typedef is typedef.B);
-
-  var x = new UseA();
-  Expect.isTrue(x.abstract is abstract.A);
-  Expect.isTrue(x.as is as.A);
-  Expect.isTrue(x.dynamic is dynamic.A);
-  Expect.isTrue(x.export is export.A);
-  Expect.isTrue(x.external is external.A);
-  Expect.isTrue(x.factory is factory.A);
-  Expect.isTrue(x.get is get.A);
-  Expect.isTrue(x.implements is implements.A);
-  Expect.isTrue(x.import is import.A);
-  Expect.isTrue(x.library is library.A);
-  Expect.isTrue(x.operator is operator.A);
-  Expect.isTrue(x.part is part.A);
-  Expect.isTrue(x.set is set.A);
-  Expect.isTrue(x.static is static.A);
-  Expect.isTrue(x.typedef is typedef.A);
-
-  // Most of the following variables have malformed type annotations.
-  if (assertionsEnabled) return;
-
-  Expect.isTrue(generic_abstract is abstract.A);
-  Expect.isTrue(generic_as is as.A);
-  Expect.isTrue(generic_dynamic is dynamic.A);
-  Expect.isTrue(generic_export is export.A);
-  Expect.isTrue(generic_external is external.A);
-  Expect.isTrue(generic_factory is factory.A);
-  Expect.isTrue(generic_get is get.A);
-  Expect.isTrue(generic_implements is implements.A);
-  Expect.isTrue(generic_import is import.A);
-  Expect.isTrue(generic_library is library.A);
-  Expect.isTrue(generic_operator is operator.A);
-  Expect.isTrue(generic_part is part.A);
-  Expect.isTrue(generic_set is set.A);
-  Expect.isTrue(generic_static is static.A);
-  Expect.isTrue(generic_typedef is typedef.A);
-
-  Expect.isTrue(parameterized_B_abstract is abstract.B);
-  Expect.isTrue(parameterized_B_as is as.B);
-  Expect.isTrue(parameterized_B_dynamic is dynamic.B);
-  Expect.isTrue(parameterized_B_export is export.B);
-  Expect.isTrue(parameterized_B_external is external.B);
-  Expect.isTrue(parameterized_B_factory is factory.B);
-  Expect.isTrue(parameterized_B_get is get.B);
-  Expect.isTrue(parameterized_B_implements is implements.B);
-  Expect.isTrue(parameterized_B_import is import.B);
-  Expect.isTrue(parameterized_B_library is library.B);
-  Expect.isTrue(parameterized_B_operator is operator.B);
-  Expect.isTrue(parameterized_B_part is part.B);
-  Expect.isTrue(parameterized_B_set is set.B);
-  Expect.isTrue(parameterized_B_static is static.B);
-  Expect.isTrue(parameterized_B_typedef is typedef.B);
-}
diff --git a/tests/language/conflicting_type_variable_and_setter_test.dart b/tests/language/conflicting_type_variable_and_setter_test.dart
new file mode 100644
index 0000000..2aca0c3
--- /dev/null
+++ b/tests/language/conflicting_type_variable_and_setter_test.dart
@@ -0,0 +1,19 @@
+// 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.
+
+import "package:expect/expect.dart";
+
+class C<D> {
+  void set D(int value) {
+    field = value;
+  }
+
+  int field;
+}
+
+main() {
+  C<int> c = new C<int>();
+  c.D = 1;
+  Expect.equals(c.field, 1);
+}
diff --git a/tests/language/deep_nesting1_negative_test.dart b/tests/language/deep_nesting1_negative_test.dart
new file mode 100644
index 0000000..e85c11c
--- /dev/null
+++ b/tests/language/deep_nesting1_negative_test.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// Deeply nested expression must not crash compiler due to stack overflow.
+
+main() {
+  var x =
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]];
+  print('okay');
+}
diff --git a/tests/language/deep_nesting2_negative_test.dart b/tests/language/deep_nesting2_negative_test.dart
new file mode 100644
index 0000000..cd49a07
--- /dev/null
+++ b/tests/language/deep_nesting2_negative_test.dart
@@ -0,0 +1,10012 @@
+// 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.
+
+// Deeply nested statements must not crash compiler due to stack overflow.
+
+var x = 0;
+
+main() {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  if (x == 0) {
+  }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+  print("survived!");
+}
diff --git a/tests/language/deferred_import_core_test.dart b/tests/language/deferred_import_core_test.dart
new file mode 100644
index 0000000..f3d6644
--- /dev/null
+++ b/tests/language/deferred_import_core_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Nothing in the language spec explicitly prohibits a deferred import of
+// 'dart:core'.  Make sure it doesn't lead to any strange behavior.
+
+import "dart:core" deferred as core;
+
+main() {
+  core.loadLibrary().then((_) => null);
+}
diff --git a/tests/language/export_not_shadowed_by_prefix_helper.dart b/tests/language/export_not_shadowed_by_prefix_helper.dart
new file mode 100644
index 0000000..3dcd016
--- /dev/null
+++ b/tests/language/export_not_shadowed_by_prefix_helper.dart
@@ -0,0 +1,6 @@
+// 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.
+
+export "export_not_shadowed_by_prefix_helper2.dart";
+import "dart:core" as f;
diff --git a/tests/language/export_not_shadowed_by_prefix_helper2.dart b/tests/language/export_not_shadowed_by_prefix_helper2.dart
new file mode 100644
index 0000000..ae2dca5
--- /dev/null
+++ b/tests/language/export_not_shadowed_by_prefix_helper2.dart
@@ -0,0 +1,9 @@
+// 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.
+
+void f() {
+  f_called = true;
+}
+
+bool f_called = false;
diff --git a/tests/language/export_not_shadowed_by_prefix_test.dart b/tests/language/export_not_shadowed_by_prefix_test.dart
new file mode 100644
index 0000000..3af1b48
--- /dev/null
+++ b/tests/language/export_not_shadowed_by_prefix_test.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// Verify that import prefixes within an imported library don't shadow
+// names re-exported by that library.
+
+import "package:expect/expect.dart";
+import "export_not_shadowed_by_prefix_helper.dart";
+
+main() {
+  f();
+  Expect.isTrue(f_called);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 65a750e..319fdb8 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -6,9 +6,13 @@
 # current state of the language.
 
 [ ($compiler == none || $compiler == precompiler) ]
-built_in_identifier_prefix_test: Fail # Issue 6970
 tearoff_constructor_basic_test: Skip # Crashes in checked mode -- hausner investigating
-const_qq_test: Fail
+
+# These tests are skipped in the VM because it has "--supermixin"
+# functionality enabled unconditionally.  The tests should be removed
+# once the same is true for analyzer (#24478) and dart2js (#23773)
+mixin_illegal_super_use_test: Skip # Issues 24478 and 23773
+mixin_illegal_superclass_test: Skip # Issues 24478 and 23773
 
 # These bugs refer currently ongoing language discussions.
 constructor5_test: Fail # Issue 6422
@@ -38,7 +42,10 @@
 async_star_cancel_while_paused_test: RuntimeError
 async_star_await_pauses_test: Skip # Times out. Issue 23996
 
+library_env_test: RuntimeError
+
 [ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) ]
+
 class_keyword_test/02: MissingCompileTimeError # Issue 13627
 unicode_bom_test: Fail # Issue 16067
 vm/debug_break_enabled_vm_test/01: Crash, OK # Expected to hit breakpoint.
@@ -101,7 +108,7 @@
 [ ($compiler == none || $compiler == precompiler) && $runtime == ContentShellOnAndroid ]
 gc_test: SkipSlow # Times out flakily. Issue 20956
 
-[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ( $arch == simarm || $arch == arm || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
+[ ($compiler == none || $compiler == precompiler) && ($runtime == vm || $runtime == dart_precompiled) && ( $arch == simarm || $arch == arm || $arch == simarmv6 || $arch == armv6 || $arch == simarmv5te || $arch == armv5te || $arch == simarm64 || $arch == arm64 || $arch == simmips || $arch == mips) ]
 vm/load_to_load_unaligned_forwarding_vm_test: Pass, Crash # Unaligned offset. Issue 22151
 
 [ ($compiler == none || $compiler == precompiler) && $runtime == dartium ]
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index 5ea3d0a..f549de2 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -7,9 +7,15 @@
 # Runtime negative test. No static errors or warnings.
 closure_call_wrong_argument_count_negative_test: skip
 
+deep_nesting1_negative_test: Crash # Issue 25558
+deep_nesting2_negative_test: Crash # Issue 25558
+
 enum_syntax_test/05: Fail # 21649
 enum_syntax_test/06: Fail # 21649
 
+mixin_illegal_constructor_test/20: MissingCompileTimeError # 25588
+mixin_illegal_constructor_test/21: MissingCompileTimeError # 25588
+
 tearoff_basic_test: Skip # Tear-off not supported
 tearoff_constructor_basic_test: Skip # Tear-off not supported
 
@@ -19,7 +25,6 @@
 getter_setter_in_lib_test: Fail # issue 23286
 
 # Test issue 12694 (was analyzer issue), (1) when "abstract" is import prefix using it as type is warning; (2) currently analyzer resolves prefix as field (don't ask)
-built_in_identifier_prefix_test: CompileTimeError # Issue 12694
 
 # TBF: we should check conflicts not only for methods, but for accessors too
 override_field_test/03: fail
@@ -305,11 +310,6 @@
 mixin_invalid_bound_test/none: StaticWarning # legitimate StaticWarning, cannot be annotated
 mixin_invalid_bound2_test/none: StaticWarning # legitimate StaticWarning, cannot be annotated
 mixin_super_bound_test: StaticWarning # legitimate StaticWarning, cannot be annotated
-mixin_super_bound2_test: CompileTimeError # Issue 24478
-mixin_super_test: CompileTimeError # Issue 24478
-mixin_super_2_test: CompileTimeError # Issue 24478
-mixin_super_use_test: CompileTimeError # Issue 24478
-mixin_superclass_test: CompileTimeError # Issue 24478
 named_constructor_test/01: StaticWarning
 named_constructor_test/03: StaticWarning
 named_parameters2_test: StaticWarning
@@ -483,4 +483,4 @@
 # intentionally referring to a variable that's not in scope.
 transitive_private_library_access_test: StaticWarning
 
-const_qq_test: Fail
+conflicting_type_variable_and_setter_test: CompileTimeError # Issue 25525
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 2dbad85..a1bb9e3 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -4,6 +4,7 @@
 
 [ $compiler == dart2js ]
 getter_setter_in_lib_test: Fail # Issue 23288
+method_name_test: Fail # issue 25574
 
 async_star_cancel_while_paused_test: RuntimeError # Issue 22853
 async_star_await_pauses_test: Fail, Timeout # Issue 22853
@@ -13,8 +14,21 @@
 try_catch_on_syntax_test/10: Fail # Issue 19823
 try_catch_on_syntax_test/11: Fail # Issue 19823
 
+mixin_illegal_constructor_test/20: MissingCompileTimeError # 25587
+mixin_illegal_constructor_test/21: MissingCompileTimeError # 25587
+
+deep_nesting1_negative_test: Crash # Issue 25557
+deep_nesting2_negative_test: Crash # Issue 25557
+
 call_function_apply_test: RuntimeError # Issue 23873
 
+# The following tests are supposed to fail.
+# When run for testing dart2js supports all dart:X libraries (because it
+# uses '--categories=all').
+library_env_test/has_no_html_support: RuntimeError, OK
+library_env_test/has_no_io_support: RuntimeError, OK
+library_env_test/has_no_mirror_support: RuntimeError, OK
+
 [ $compiler == dart2js && $runtime == jsshell ]
 await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
 async_star_test: RuntimeError # Jsshell does not provide non-zero timers, Issue 7728
@@ -138,7 +152,6 @@
 branch_canonicalization_test: RuntimeError # Issue 638.
 identical_closure2_test: RuntimeError # Issue 1533, Issue 12596
 integer_division_by_zero_test: RuntimeError # Issue 8301
-built_in_identifier_prefix_test: CompileTimeError # Issue 6972
 number_identity2_test: RuntimeError # Issue 12596
 double_int_to_string_test: RuntimeError # Issue 1533
 mint_arithmetic_test: RuntimeError # Issue 1533
@@ -241,9 +254,9 @@
 async_await_syntax_test/d06a: Crash # (await for(var o in st){}): await for
 async_await_syntax_test/d09a: Crash # (()async*{yield 0;}): cannot handle sync*/async* functions
 async_await_syntax_test/d10a: Crash # (()async*{yield* [] ;}): cannot handle sync*/async* functions
-async_await_test/02: Crash # (switch (v){label:ca...  continue to a labeled switch case
-async_await_test/03: Crash # (switch (v){label:ca...  continue to a labeled switch case
-async_await_test/none: Crash # (switch (v){label:ca...  continue to a labeled switch case
+async_await_test/02: Crash # bailout: (await for
+async_await_test/03: Crash # bailout: (await for
+async_await_test/none: Crash # bailout: (await for
 async_or_generator_return_type_stacktrace_test/02: Crash # (void badReturnTypeAsyncStar()async*{}): cannot handle sync*/async* functions
 async_return_types_test/nestedFuture: Crash #  cannot handle sync*/async* functions
 async_return_types_test/none: Crash # cannot handle sync*/async* functions
@@ -267,26 +280,12 @@
 await_for_test: Crash # (await for(var x in infiniteStream()){i++ ;if(i>10)break;t4.record(x);}): await for
 await_for_use_local_test: Crash # (await for(var v in s){accum+= v;}): await for
 call_closurization_test: RuntimeError # Bad type inference for ".call" tear-off.
-closure_in_constructor_test: RuntimeError # Please triage this failure.
-closures_initializer_test: RuntimeError # Please triage this failure.
-constructor12_test: RuntimeError # Please triage this failure.
 deferred_super_dependency_test/01: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 field3a_negative_test: Fail # Bogus result from type inference in case of invalid program.
-first_class_types_test: RuntimeError # Please triage this failure.
-generic2_test: RuntimeError # Please triage this failure.
-generic_instanceof_test: RuntimeError # Please triage this failure.
-generic_native_test: RuntimeError # Please triage this failure.
 gc_test: Crash # Internal Error: Pending statics (see above).
-infinite_switch_label_test: Crash # (switch (target){l0:...  continue to a labeled switch case
-instanceof2_test: RuntimeError # Please triage this failure.
-instanceof4_test/01: RuntimeError # Please triage this failure.
 invocation_mirror_test: Crash # (super[37]=42): visitUnresolvedSuperIndexSet
-list_is_test: RuntimeError # Please triage this failure.
-list_test: RuntimeError # Please triage this failure.
-many_generic_instanceof_test: RuntimeError # Please triage this failure.
-nested_switch_label_test: Crash # (switch (target){out...  continue to a labeled switch case
 regress_23500_test/01: Crash # (await for(var c in new Stream.fromIterable([] )){}): await for
-stack_trace_test: Fail # Stack trace not preserved when inlining?
+savannah_test: RuntimeError # Success depends on the variable hints.
 super_call4_test: RuntimeError # Please triage this failure.
 super_getter_setter_test: Crash # Class 'PartialMethodElement' has no instance getter 'initializer'.
 super_operator_index5_test: Crash # (super[0]=42): visitUnresolvedSuperIndexSet
@@ -294,14 +293,7 @@
 super_operator_index8_test: Crash # (super[f()]=g()): visitUnresolvedSuperIndexSet
 super_operator_index_test/03: Crash # (super[4]=42): visitUnresolvedSuperIndexSet
 super_operator_index_test/05: Crash # (super[4]=42): visitUnresolvedSuperIndexSet
-switch_label2_test: Crash # (switch (target){cas...  continue to a labeled switch case
-switch_label_test: Crash # (switch (animal){cas...  continue to a labeled switch case
-switch_try_catch_test: Crash # (switch (0){_0:case ...  continue to a labeled switch case
-type_variable_closure2_test: RuntimeError # Issue 25309: T lost in List<T>
-type_variable_closure4_test: RuntimeError # T lost in <T,T>{}
-type_variable_field_initializer_closure_test: RuntimeError # Issue 25309: T lost in List<T>
-type_variable_field_initializer_test: RuntimeError # Issue 25309: T lost in List<T>
-type_variable_nested_test: RuntimeError # Issue 25309: T lost in List<T>
+switch8_test: Crash # Pending statics: JSArray
 
 [ $compiler == dart2js && $cps_ir && $host_checked == false ]
 regress_21795_test: Pass, RuntimeError # Due to inlining?
diff --git a/tests/language/library_env_test.dart b/tests/language/library_env_test.dart
new file mode 100644
index 0000000..d076ede
--- /dev/null
+++ b/tests/language/library_env_test.dart
@@ -0,0 +1,87 @@
+// 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.
+
+import 'package:expect/expect.dart';
+
+main() {
+  const NOT_PRESENT = null;
+
+  Expect.isTrue(const bool.fromEnvironment("dart.library.async"));
+  Expect.isTrue(const bool.fromEnvironment("dart.library.collection"));
+  Expect.isTrue(const bool.fromEnvironment("dart.library.convert"));
+  Expect.isTrue(const bool.fromEnvironment("dart.library.core"));
+  Expect.isTrue(const bool.fromEnvironment("dart.library.typed_data"));
+
+
+  bool hasHtmlSupport;
+  hasHtmlSupport = true;   /// has_html_support: ok
+  hasHtmlSupport = false;  /// has_no_html_support: ok
+
+  if (hasHtmlSupport != null) {
+    bool expectedResult = hasHtmlSupport ? true : NOT_PRESENT;
+
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.html",
+            defaultValue: NOT_PRESENT));
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.indexed_db",
+            defaultValue: NOT_PRESENT));
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.svg",
+            defaultValue: NOT_PRESENT));
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.web_audio",
+            defaultValue: NOT_PRESENT));
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.web_gl",
+            defaultValue: NOT_PRESENT));
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.web_sql",
+            defaultValue: NOT_PRESENT));
+  }
+
+  bool hasIoSupport;
+  hasIoSupport = true;   /// has_io_support: ok
+  hasIoSupport = false;  /// has_no_io_support: ok
+
+  if (hasIoSupport != null) {
+    bool expectedResult = hasIoSupport ? true : NOT_PRESENT;
+
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.io",
+            defaultValue: NOT_PRESENT));
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.developer",
+            defaultValue: NOT_PRESENT));
+  }
+
+  bool hasMirrorSupport;
+  hasMirrorSupport = true;   /// has_mirror_support: ok
+  hasMirrorSupport = false;  /// has_no_mirror_support: ok
+
+  if (hasMirrorSupport != null) {
+    bool expectedResult = hasMirrorSupport ? true : NOT_PRESENT;
+
+    Expect.equals(expectedResult,
+        const bool.fromEnvironment("dart.library.mirrors",
+            defaultValue: NOT_PRESENT));
+  }
+
+  Expect.equals(NOT_PRESENT,
+      const bool.fromEnvironment("dart.library.XYZ",
+          defaultValue: NOT_PRESENT));
+  Expect.equals(NOT_PRESENT,
+      const bool.fromEnvironment("dart.library.Collection",
+          defaultValue: NOT_PRESENT));
+  Expect.equals(NOT_PRESENT,
+      const bool.fromEnvironment("dart.library.converT",
+          defaultValue: NOT_PRESENT));
+  Expect.equals(NOT_PRESENT,
+      const bool.fromEnvironment("dart.library.",
+          defaultValue: NOT_PRESENT));
+  Expect.equals(NOT_PRESENT,
+      const bool.fromEnvironment("dart.library.core ",
+          defaultValue: NOT_PRESENT));
+
+}
diff --git a/tests/language/method_name_test.dart b/tests/language/method_name_test.dart
index b0199cf..ea9c7d2 100644
--- a/tests/language/method_name_test.dart
+++ b/tests/language/method_name_test.dart
@@ -12,6 +12,7 @@
   int get() {return 1;}
   int set() {return 2;}
   int operator() {return 3;}
+  int factory() { return 4; }
 }
 
 // Without return types.
@@ -19,6 +20,7 @@
   get() {return 1;}
   set() {return 2;}
   operator() {return 3;}
+  factory() { return 4; }
 }
 
 main() {
@@ -27,11 +29,13 @@
     Expect.equals(1, a.get());
     Expect.equals(2, a.set());
     Expect.equals(3, a.operator());
+    Expect.equals(4, a.factory());
   }
   {
     B b = new B();
     Expect.equals(1, b.get());
     Expect.equals(2, b.set());
     Expect.equals(3, b.operator());
+    Expect.equals(4, b.factory());
   }
 }
diff --git a/tests/language/mixin_illegal_constructor_test.dart b/tests/language/mixin_illegal_constructor_test.dart
index d0a59fb..8884084 100644
--- a/tests/language/mixin_illegal_constructor_test.dart
+++ b/tests/language/mixin_illegal_constructor_test.dart
@@ -15,7 +15,7 @@
   M2.named();
 }
 
-class C0 = Object with M0;
+class C0 = Object with M0;      /// 20: compile-time error
 class C1 = Object with M1;      /// 01: compile-time error
 class C2 = Object with M2;      /// 02: compile-time error
 class C3 = Object with M0, M1;  /// 03: compile-time error
@@ -23,7 +23,7 @@
 class C5 = Object with M0, M2;  /// 05: compile-time error
 class C6 = Object with M2, M0;  /// 06: compile-time error
 
-class D0 extends Object with M0 { }
+class D0 extends Object with M0 { }      /// 21: compile-time error
 class D1 extends Object with M1 { }      /// 07: compile-time error
 class D2 extends Object with M2 { }      /// 08: compile-time error
 class D3 extends Object with M0, M1 { }  /// 09: compile-time error
@@ -32,7 +32,7 @@
 class D6 extends Object with M2, M0 { }  /// 12: compile-time error
 
 main() {
-  new C0();
+  new C0();  /// 20: continued
   new C1();  /// 01: continued
   new C2();  /// 02: continued
   new C3();  /// 03: continued
@@ -40,16 +40,11 @@
   new C5();  /// 05: continued
   new C6();  /// 06: continued
 
-  new D0();
+  new D0();  /// 21: continued
   new D1();  /// 07: continued
   new D2();  /// 08: continued
   new D3();  /// 09: continued
   new D4();  /// 10: continued
   new D5();  /// 11: continued
   new D6();  /// 12: continued
-
-  new C0(1,2,3);   /// 13: static type warning, runtime error
-  new C0.named();  /// 14: static type warning, runtime error
-  new D0(1,2,3);   /// 15: static type warning, runtime error
-  new D0.named();  /// 16: static type warning, runtime error
 }
diff --git a/tests/language/mixin_illegal_super_use_test.dart b/tests/language/mixin_illegal_super_use_test.dart
new file mode 100644
index 0000000..7f0d64a
--- /dev/null
+++ b/tests/language/mixin_illegal_super_use_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class M {
+}
+
+class P0 {
+  foo() {
+    super.toString();    /// 01: compile-time error
+    super.foo();         /// 02: compile-time error
+    super.bar = 100;     /// 03: compile-time error
+
+    void inner() {
+      super.toString();  /// 04: compile-time error
+      super.foo();       /// 05: compile-time error
+      super.bar = 100;   /// 06: compile-time error
+    }
+    inner();
+
+    (() {
+      super.toString();  /// 07: compile-time error
+      super.foo();       /// 08: compile-time error
+      super.bar = 100;   /// 09: compile-time error
+    })();
+
+    return 42;
+  }
+}
+
+class P1 {
+  bar() {
+    super.toString();    /// 10: compile-time error
+    return 87;
+  }
+
+  // The test method is strategically placed here to try to force the
+  // P1 class and its bar method to be resolved before resolving the
+  // mixin applications.
+  test() {
+    new C();
+    var d = new D();
+    var e = new E();
+    var f = new F();
+    Expect.equals(42, d.foo());
+    Expect.equals(87, e.bar());
+    Expect.equals(99, f.baz());
+  }
+}
+
+class P2 {
+  baz() {
+    super.toString();   /// 11: compile-time error
+    return 99;
+  }
+}
+
+class C = Object with M;
+class D = Object with P0;
+class E = Object with M, P1;
+class F = Object with P2, M;
+
+main() {
+  var p1 = new P1();
+  var p2 = new P2();
+  Expect.equals(87, p1.bar());
+  p1.test();
+  Expect.equals(99, p2.baz());
+}
diff --git a/tests/language/mixin_illegal_superclass_test.dart b/tests/language/mixin_illegal_superclass_test.dart
new file mode 100644
index 0000000..03d2e6a
--- /dev/null
+++ b/tests/language/mixin_illegal_superclass_test.dart
@@ -0,0 +1,121 @@
+// Copyright (c) 2013, 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.
+
+class S0 { }
+class S1 extends Object { }
+class S2 extends S0 { }
+
+class M0 { }
+class M1 extends Object { }
+class M2 extends M0 { }
+
+class C00 = S0 with M0;
+class C01 = S0 with M1;
+class C02 = S0 with M2;      /// 01: compile-time error
+class C03 = S0 with M0, M1;
+class C04 = S0 with M0, M2;  /// 02: compile-time error
+class C05 = S0 with M2, M0;  /// 03: compile-time error
+class C06 = S0 with M1, M2;  /// 04: compile-time error
+class C07 = S0 with M2, M1;  /// 05: compile-time error
+
+class C10 = S1 with M0;
+class C11 = S1 with M1;
+class C12 = S1 with M2;      /// 06: compile-time error
+class C13 = S1 with M0, M1;
+class C14 = S1 with M0, M2;  /// 07: compile-time error
+class C15 = S1 with M2, M0;  /// 08: compile-time error
+class C16 = S1 with M1, M2;  /// 09: compile-time error
+class C17 = S1 with M2, M1;  /// 10: compile-time error
+
+class C20 = S2 with M0;
+class C21 = S2 with M1;
+class C22 = S2 with M2;      /// 11: compile-time error
+class C23 = S2 with M0, M1;
+class C24 = S2 with M0, M2;  /// 12: compile-time error
+class C25 = S2 with M2, M0;  /// 13: compile-time error
+class C26 = S2 with M1, M2;  /// 14: compile-time error
+class C27 = S2 with M2, M1;  /// 15: compile-time error
+
+class D00 extends S0 with M0 { }
+class D01 extends S0 with M1 { }
+class D02 extends S0 with M2 { }      /// 16: compile-time error
+class D03 extends S0 with M0, M1 { }
+class D04 extends S0 with M0, M2 { }  /// 17: compile-time error
+class D05 extends S0 with M2, M0 { }  /// 18: compile-time error
+class D06 extends S0 with M1, M2 { }  /// 19: compile-time error
+class D07 extends S0 with M2, M1 { }  /// 20: compile-time error
+
+class D10 extends S1 with M0 { }
+class D11 extends S1 with M1 { }
+class D12 extends S1 with M2 { }      /// 21: compile-time error
+class D13 extends S1 with M0, M1 { }
+class D14 extends S1 with M0, M2 { }  /// 22: compile-time error
+class D15 extends S1 with M2, M0 { }  /// 23: compile-time error
+class D16 extends S1 with M1, M2 { }  /// 24: compile-time error
+class D17 extends S1 with M2, M1 { }  /// 25: compile-time error
+
+class D20 extends S2 with M0 { }
+class D21 extends S2 with M1 { }
+class D22 extends S2 with M2 { }      /// 26: compile-time error
+class D23 extends S2 with M0, M1 { }
+class D24 extends S2 with M0, M2 { }  /// 27: compile-time error
+class D25 extends S2 with M2, M0 { }  /// 28: compile-time error
+class D26 extends S2 with M1, M2 { }  /// 29: compile-time error
+class D27 extends S2 with M2, M1 { }  /// 30: compile-time error
+
+main() {
+  new C00();
+  new C01();
+  new C02();  /// 01: continued
+  new C03();
+  new C04();  /// 02: continued
+  new C05();  /// 03: continued
+  new C06();  /// 04: continued
+  new C07();  /// 05: continued
+
+  new C10();
+  new C11();
+  new C12();  /// 06: continued
+  new C13();
+  new C14();  /// 07: continued
+  new C15();  /// 08: continued
+  new C16();  /// 09: continued
+  new C17();  /// 10: continued
+
+  new C20();
+  new C21();
+  new C22();  /// 11: continued
+  new C23();
+  new C24();  /// 12: continued
+  new C25();  /// 13: continued
+  new C26();  /// 14: continued
+  new C27();  /// 15: continued
+
+  new D00();
+  new D01();
+  new D02();  /// 16: continued
+  new D03();
+  new D04();  /// 17: continued
+  new D05();  /// 18: continued
+  new D06();  /// 19: continued
+  new D07();  /// 20: continued
+
+  new D10();
+  new D11();
+  new D12();  /// 21: continued
+  new D13();
+  new D14();  /// 22: continued
+  new D15();  /// 23: continued
+  new D16();  /// 24: continued
+  new D17();  /// 25: continued
+
+  new D20();
+  new D21();
+  new D22();  /// 26: continued
+  new D23();
+  new D24();  /// 27: continued
+  new D25();  /// 28: continued
+  new D26();  /// 29: continued
+  new D27();  /// 30: continued
+}
diff --git a/tests/language/mixin_super_2_test.dart b/tests/language/mixin_super_2_test.dart
index ad86c08..91d68c6 100644
--- a/tests/language/mixin_super_2_test.dart
+++ b/tests/language/mixin_super_2_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// SharedOptions=--supermixin
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/mixin_super_bound2_test.dart b/tests/language/mixin_super_bound2_test.dart
index c6fcd7a..87e8b7a 100644
--- a/tests/language/mixin_super_bound2_test.dart
+++ b/tests/language/mixin_super_bound2_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// SharedOptions=--supermixin
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/mixin_super_test.dart b/tests/language/mixin_super_test.dart
index 6a5d5a3..8a4ee98 100644
--- a/tests/language/mixin_super_test.dart
+++ b/tests/language/mixin_super_test.dart
@@ -1,6 +1,7 @@
 // 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.
+// SharedOptions=--supermixin
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/mixin_super_use_test.dart b/tests/language/mixin_super_use_test.dart
index cd95846..614bb632c 100644
--- a/tests/language/mixin_super_use_test.dart
+++ b/tests/language/mixin_super_use_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2013, 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.
+// SharedOptions=--supermixin
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/mixin_superclass_test.dart b/tests/language/mixin_superclass_test.dart
index ade41da..1e658e8 100644
--- a/tests/language/mixin_superclass_test.dart
+++ b/tests/language/mixin_superclass_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2013, 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.
+// SharedOptions=--supermixin
 
 class S0 { }
 class S1 extends Object { }
diff --git a/tests/language/proxy4_test.dart b/tests/language/proxy4_test.dart
new file mode 100644
index 0000000..a7d44b5
--- /dev/null
+++ b/tests/language/proxy4_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// Test for static warnings for member access on classes that inherit a
+// user defined noSuchMethod.
+
+class Mock {
+  noSuchMethod(i) => 42;
+}
+
+abstract class Foo { int foo(); }
+
+class DontWarnMe extends Mock implements Foo {}
+
+main() {
+  print(new DontWarnMe().foo());
+}
\ No newline at end of file
diff --git a/tests/language/proxy5_test.dart b/tests/language/proxy5_test.dart
new file mode 100644
index 0000000..41e63e6
--- /dev/null
+++ b/tests/language/proxy5_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Test for static warnings for member access on classes that inherit a
+// user defined noSuchMethod, even if it is abstract.
+
+import 'package:expect/expect.dart';
+
+abstract class Mock {
+  noSuchMethod(i);
+}
+
+abstract class Foo { int foo(); }
+
+class DontWarnMe extends Mock implements Foo {}
+
+main() {
+  Expect.throws(() => new DontWarnMe().foo());
+}
\ No newline at end of file
diff --git a/tests/language/regress_24567_test.dart b/tests/language/regress_24567_test.dart
new file mode 100644
index 0000000..e72750a
--- /dev/null
+++ b/tests/language/regress_24567_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+import "package:expect/expect.dart";
+import 'dart:math' as math;
+
+class Random { }
+
+typedef F(Random r);
+
+main() {
+  f(Random r) { }
+  g(math.Random r) { }
+  Expect.isTrue(f is F);
+  Expect.isFalse(g is F);
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index 4016986..3288d18 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -24,5 +24,5 @@
 lib/indexed_db/dartium/indexed_db_dartium: CompileTimeError # Issue 21647
 lib/web_audio/dartium/web_audio_dartium: CompileTimeError # Issue 21647
 lib/svg/dartium/svg_dartium: CompileTimeError # Issue 21647
-lib/_blink/dartium/_blink_dartium: CompileTimeError # Dartium JsInterop roll (js.JsObjectImpl)
-lib/js/dartium/js_dartium: CompileTimeError # Dartium JsInterop roll (js.JsObjectImpl)
+lib/_blink/dartium/_blink_dartium: CompileTimeError # Undefined Creates and Returns classes
+lib/js/dartium/js_dartium: CompileTimeError # Undefined Creates and Returns classes
\ No newline at end of file
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index d4cdafe..f5d5af2 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -170,7 +170,6 @@
 
 [ $compiler == dart2js && $checked ]
 convert/utf85_test: Pass, Slow # Issue 12029.
-mirrors/list_constructor_test/01: RuntimeError # Issue 19635.
 
 [ $compiler == dart2js ]
 convert/chunked_conversion_utf88_test: Slow, Pass
@@ -292,9 +291,6 @@
 profiler/metrics_test: Fail # Issue 20309
 profiler/metrics_num_test: Fail # Issue 20309
 
-[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
-mirrors/metadata_allowed_values_test/29: Crash # Issue 25287
-
 [ ($compiler == dartanalyzer || $compiler == dart2analyzer) && $checked ]
 mirrors/regress_16321_test/01: MissingCompileTimeError # Issue 16391
 
@@ -308,7 +304,7 @@
 [ ($compiler == none || $compiler == precompiler) && $arch == mips ]
 async/timer_regress22626_test: Pass, RuntimeError # Issue 22626
 
-[ $arch == simarm || $arch == simarmv5te ]
+[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te ]
 convert/chunked_conversion_utf88_test: Skip  # Pass, Slow Issue 12644.
 convert/utf85_test: Skip  # Pass, Slow Issue 12644.
 
@@ -331,7 +327,7 @@
 [ ($runtime == vm || $runtime == dart_precompiled) && $mode == release && $arch == ia32 && $system == windows ]
 convert/json_test: RuntimeError # Issue 24908
 
-[ $mode == debug && $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv5te ]
+[ $mode == debug && $arch != ia32 && $arch != x64 && $arch != simarm && $arch != simarmv6 && $arch != simarmv5te ]
 convert/streamed_conversion_json_utf8_decode_test: Skip  # Verification not yet implemented.
 
 [ ($runtime == vm || $runtime == dart_precompiled) && $mode == debug && $builder_tag == asan ]
@@ -341,6 +337,7 @@
 [ $compiler == dart2js && $cps_ir ]
 async/async_await_zones_test: Crash # (await for(var x in bar().take(100)){sum+= x;}): await for
 async/stream_iterator_test: Crash # (Stream createCancel...  cannot handle sync*/async* functions
+mirrors/parameter_annotation_mirror_test: Pass, Fail # Issue 25501.  Depends on inlining.
 mirrors/symbol_validation_test/none: RuntimeError # Please triage this failure.
 
 [ $compiler == dart2js && $cps_ir && $host_checked ]
diff --git a/tests/lib/mirrors/constructor_optional_args_test.dart b/tests/lib/mirrors/constructor_optional_args_test.dart
new file mode 100644
index 0000000..f9d9657
--- /dev/null
+++ b/tests/lib/mirrors/constructor_optional_args_test.dart
@@ -0,0 +1,58 @@
+// 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 test.constructor_test;
+
+@MirrorsUsed(targets: const [A])
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+class A {
+  factory A([x, y]) = B;
+  factory A.more([x, y]) = B.more;
+  factory A.oneMore(x, [y]) = B.more;
+}
+
+class B implements A {
+  final _x, _y, _z;
+
+  B([x = 'x', y = 'y']) : _x = x, _y = y, _z = null;
+
+  B.more([x = 'x', y = 'y', z = 'z']) : _x = x, _y = y, _z = z;
+
+  toString() => 'B(x=$_x, y=$_y, z=$_z)';
+}
+
+
+main() {
+  var d1 = new A(1);
+  Expect.equals('B(x=1, y=y, z=null)', '$d1', 'direct 1');
+
+  var d2 = new A.more(1);
+  Expect.equals('B(x=1, y=y, z=z)', '$d2', 'direct 2');
+
+  ClassMirror cm = reflectClass(A);
+
+  var v1 = cm.newInstance(const Symbol(''), []).reflectee;
+  var v2 = cm.newInstance(const Symbol(''), [1]).reflectee;
+  var v3 = cm.newInstance(const Symbol(''), [2, 3]).reflectee;
+
+  Expect.equals('B(x=x, y=y, z=null)', '$v1', 'unnamed 1');
+  Expect.equals('B(x=1, y=y, z=null)', '$v2', 'unnamed 2');
+  Expect.equals('B(x=2, y=3, z=null)', '$v3', 'unnamed 3');
+
+  var m1 = cm.newInstance(const Symbol('more'), []).reflectee;
+  var m2 = cm.newInstance(const Symbol('more'), [1]).reflectee;
+  var m3 = cm.newInstance(const Symbol('more'), [2, 3]).reflectee;
+
+  Expect.equals('B(x=x, y=y, z=z)', '$m1', 'more 1');
+  Expect.equals('B(x=1, y=y, z=z)', '$m2', 'more 2');
+  Expect.equals('B(x=2, y=3, z=z)', '$m3', 'more 3');
+
+  var o1 = cm.newInstance(const Symbol('oneMore'), [1]).reflectee;
+  var o2 = cm.newInstance(const Symbol('oneMore'), [2, 3]).reflectee;
+
+  Expect.equals('B(x=1, y=y, z=z)', '$o1', 'oneMore one arg');
+  Expect.equals('B(x=2, y=3, z=z)', '$o2', 'oneMore two args');
+}
diff --git a/tests/standalone/io/web_socket_compression_test.dart b/tests/standalone/io/web_socket_compression_test.dart
index 912b855..e25bc1b 100644
--- a/tests/standalone/io/web_socket_compression_test.dart
+++ b/tests/standalone/io/web_socket_compression_test.dart
@@ -130,6 +130,43 @@
     });
   }
 
+  void testContextSupport({CompressionOptions serverOpts,
+    CompressionOptions clientOpts,
+    int messages}) {
+    asyncStart();
+
+    createServer().then((server) {
+      server.listen((request) {
+        Expect.isTrue(WebSocketTransformer.isUpgradeRequest(request));
+        WebSocketTransformer.upgrade(request, compression: serverOpts)
+                            .then((webSocket) {
+            webSocket.listen((message) {
+              Expect.equals("Hello World", message);
+              webSocket.add(message);
+            });
+        });
+      });
+
+      var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
+      WebSocket.connect(url, compression: clientOpts).then((websocket) {
+        var i = 1;
+        websocket.listen((message) {
+          Expect.equals("Hello World", message);
+          if (i == messages) {
+            websocket.close();
+            return;
+          }
+          websocket.add("Hello World");
+          i++;
+        }, onDone: () {
+          server.close();
+          asyncEnd();
+        });
+        websocket.add("Hello World");
+      });
+    });
+  }
+
   void testCompressionHeaders() {
     asyncStart();
     createServer().then((server) {
@@ -271,6 +308,31 @@
     // Compression on server but not client.
     testCompressionSupport(server: true);
 
+    // Test Multiple messages with various context takeover configurations.
+    // no context takeover on the server.
+    var serverComp = new CompressionOptions(serverNoContextTakeover: true);
+    testContextSupport(serverOpts: serverComp,
+      clientOpts: serverComp,
+      messages: 5);
+    // no contexttakeover on the client.
+    var clientComp = new CompressionOptions(clientNoContextTakeover: true);
+    testContextSupport(serverOpts: clientComp,
+      clientOpts: clientComp,
+      messages: 5);
+    // no context takeover enabled for both.
+    var compression = new CompressionOptions(serverNoContextTakeover: true,
+                      clientNoContextTakeover: true);
+    testContextSupport(serverOpts: compression,
+      clientOpts: compression,
+      messages: 5);
+    // no context take over for opposing configurations.
+    testContextSupport(serverOpts: serverComp,
+      clientOpts: clientComp,
+      messages: 5);
+    testContextSupport(serverOpts: clientComp,
+      clientOpts: serverComp,
+      messages: 5);
+
     testCompressionHeaders();
     // Chrome headers
     testReturnHeaders('permessage-deflate; client_max_window_bits',
@@ -289,7 +351,7 @@
                       'client_no_context_takeover',
                       'permessage-deflate; client_max_window_bits=15');
     // Enable context Takeover and provide if requested.
-    var compression = new CompressionOptions(clientNoContextTakeover: true,
+    compression = new CompressionOptions(clientNoContextTakeover: true,
         serverNoContextTakeover: true);
     testReturnHeaders('permessage-deflate; client_max_window_bits; '
                       'client_no_context_takeover',
diff --git a/tests/standalone/precompilation_dart2js_test.dart b/tests/standalone/precompilation_dart2js_test.dart
index 5d3900e..d7a8b71 100644
--- a/tests/standalone/precompilation_dart2js_test.dart
+++ b/tests/standalone/precompilation_dart2js_test.dart
@@ -87,7 +87,7 @@
 
     var ld_library_path = new String.fromEnvironment("LD_LIBRARY_PATH");
     ld_library_path = "${ld_library_path}:${tmp.path}";
-    exec = "${dart_executable}_precompiled";
+    exec = "${dart_executable}_precompiled_runtime";
     args = ["--run-precompiled-snapshot", "ignored_script", "--version"];
     print("LD_LIBRARY_PATH=$ld_library_path $exec ${args.join(' ')}");
     result = Process.runSync(exec, args,
diff --git a/tests/standalone/precompilation_test.dart b/tests/standalone/precompilation_test.dart
index 751682e..e58c5fe 100644
--- a/tests/standalone/precompilation_test.dart
+++ b/tests/standalone/precompilation_test.dart
@@ -86,7 +86,7 @@
     ld_library_path = "${ld_library_path}:${tmp.path}";
 
     result = Process.runSync(
-       "${dart_executable}_precompiled",
+       "${dart_executable}_precompiled_runtime",
        ["--run-precompiled-snapshot", "ignored_script", "--hello"],
        workingDirectory: tmp.path,
        environment: {"LD_LIBRARY_PATH": ld_library_path});
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 590489e..8b09928 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -140,7 +140,7 @@
 [ $compiler == dart2js && $browser ]
 *: Skip
 
-[ $arch == simarm || $arch == simarmv5te || $arch == simmips ]
+[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simmips ]
 out_of_memory_test: Skip # passes on Mac, crashes on Linux
 oom_error_stacktrace_test: Skip # Fails on Linux
 
@@ -268,4 +268,4 @@
 io/test_extension_test: RuntimeError # Platform.executable
 io/regress_7679_test: RuntimeError # Platform.executable
 
-io/process_*: Skip # Most use Platform.executable
\ No newline at end of file
+io/process_*: Skip # Most use Platform.executable
diff --git a/tests/utils/utils.status b/tests/utils/utils.status
index bf69360..e81c804 100644
--- a/tests/utils/utils.status
+++ b/tests/utils/utils.status
@@ -5,8 +5,10 @@
 [ $compiler == dart2js && $host_checked ]
 dummy_compiler_test: Crash # Issue 22809
 
-[ $compiler == dart2js ]
+[ $compiler == dart2js && $host_checked == false ]
 dummy_compiler_test: Slow, Pass
+
+[ $compiler == dart2js ]
 recursive_import_test: Slow, Pass
 source_mirrors_test: Slow, Pass
 
@@ -25,10 +27,5 @@
 recursive_import_test: Pass, RuntimeError # Issue 17662
 source_mirrors_test: Pass, RuntimeError # Issue 17662
 
-[ $compiler == dart2js && $cps_ir ]
-dummy_compiler_test: Crash # (switch (function.na...  continue to a labeled switch case
-recursive_import_test: Crash # (switch (function.na...  continue to a labeled switch case
-source_mirrors_test: Crash, Slow # (switch (function.na...  continue to a labeled switch case
-
 [ ($noopt || $compiler == precompiler) ]
 source_mirrors_test: SkipByDesign # Imports dart:mirrors
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 3f481f1..074f02f 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -11,4 +11,5 @@
 !7zip.tar.gz.sha1
 !firefox_jsshell
 !gsutil.tar.gz.sha1
-!clang.tar.gz.sha1
\ No newline at end of file
+!clang.tar.gz.sha1
+!unittest.tar.gz.sha1
diff --git a/third_party/boringssl/boringssl_configurations.gypi b/third_party/boringssl/boringssl_configurations.gypi
index 91c76c1..0a82431 100644
--- a/third_party/boringssl/boringssl_configurations.gypi
+++ b/third_party/boringssl/boringssl_configurations.gypi
@@ -66,6 +66,27 @@
           'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO', # -Werror off
         },
       },
+      # Disable hand-coded assembly routines on ARMv6 and ARMv5TE.
+      'Dart_armv6_Base': {
+        'abstract': 1,
+        'defines': [
+          'OPENSSL_NO_ASM',
+        ],
+      },
+      'Dart_armv5te_Base': {
+        'abstract': 1,
+        'defines': [
+          'OPENSSL_NO_ASM',
+        ],
+      },
+      # TODO(24321): Also disable temporarily on arm64. Reenable after the next
+      # roll.
+      'Dart_arm64_Base': {
+        'abstract': 1,
+        'defines': [
+          'OPENSSL_NO_ASM',
+        ],
+      },
       # When being built for Android nss expects __linux__ to be defined.
       'Dart_Android_Base': {
         'target_conditions': [
@@ -96,4 +117,4 @@
       },
     },
   },
-}
\ No newline at end of file
+}
diff --git a/third_party/pkg/unittest.tar.gz.sha1 b/third_party/pkg/unittest.tar.gz.sha1
new file mode 100644
index 0000000..2a8a5c2
--- /dev/null
+++ b/third_party/pkg/unittest.tar.gz.sha1
@@ -0,0 +1 @@
+fc9b8ccbfbecf20257255d69693d5a50f8692757
\ No newline at end of file
diff --git a/third_party/pkg_tested/pkg_tested.status b/third_party/pkg_tested/pkg_tested.status
index 031b82b..9a58476 100644
--- a/third_party/pkg_tested/pkg_tested.status
+++ b/third_party/pkg_tested/pkg_tested.status
@@ -23,7 +23,7 @@
 pub/test/run/app_can_read_from_stdin_test: Fail # Issue 19448
 pub/test/run/forwards_signal_posix_test: SkipByDesign
 
-[ $runtime == vm && ($mode == debug || $arch == mips || $arch == simmips || $arch == simarm || $arch == simarmv5te || $arch == simarm64 || $builder_tag == asan) ]
+[ $runtime == vm && ($mode == debug || $arch == mips || $arch == simmips || $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simarm64 || $builder_tag == asan) ]
 dart_style/test/command_line_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators/mips.
 dart_style/test/formatter_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators/mips.
 
diff --git a/tools/VERSION b/tools/VERSION
index 4c7a8a0..a14f088 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL dev
 MAJOR 1
-MINOR 14
+MINOR 15
 PATCH 0
-PRERELEASE 7
-PRERELEASE_PATCH 2
+PRERELEASE 0
+PRERELEASE_PATCH 0
diff --git a/tools/build.py b/tools/build.py
index dac178f..91d6864 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -55,8 +55,8 @@
       default=False, action="store_true")
   result.add_option("-a", "--arch",
       help='Target architectures (comma-separated).',
-      metavar='[all,ia32,x64,simarm,arm,simarmv5te,armv5te,simmips,mips'
-              ',simarm64,arm64,]',
+      metavar='[all,ia32,x64,simarm,arm,simarmv6,armv6,simarmv5te,armv5te,'
+              'simmips,mips,simarm64,arm64,]',
       default=utils.GuessArchitecture())
   result.add_option("--os",
     help='Target OSs (comma-separated).',
@@ -101,8 +101,8 @@
       print "Unknown mode %s" % mode
       return False
   for arch in options.arch:
-    archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv5te', 'armv5te', 'simmips',
-             'mips', 'simarm64', 'arm64',]
+    archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
+             'simarmv5te', 'armv5te', 'simmips', 'mips', 'simarm64', 'arm64',]
     if not arch in archs:
       print "Unknown arch %s" % arch
       return False
@@ -119,7 +119,7 @@
         print ("Cross-compilation to %s is not supported on host os %s."
                % (os_name, HOST_OS))
         return False
-      if not arch in ['ia32', 'arm', 'armv5te', 'arm64', 'mips']:
+      if not arch in ['ia32', 'arm', 'armv6', 'armv5te', 'arm64', 'mips']:
         print ("Cross-compilation to %s is not supported for architecture %s."
                % (os_name, arch))
         return False
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index fbb0e6b..accf568 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -14,7 +14,7 @@
   "dartium_chromium_commit": "62a7524d4f71c9e0858d24b0aa1bbff3a2d09bff",
   "chromium_base_revision": "297060",
   "dartium_webkit_branch": "/blink/branches/dart/dartium",
-  "dartium_webkit_revision": "202748",
+  "dartium_webkit_revision": "202760",
 
   # We use mirrors of all github repos to guarantee reproducibility and
   # consistency between what users see and what the bots see.
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 92a5ed0..6d235b81 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -546,14 +546,10 @@
         if (wrap_unwrap_type_blink(type_id, type_registry)):
           type_is_callback = self.isCallback(type_registry, type_id)
           if (dart_js_interop and type_id == 'EventListener' and
-              (self.name == 'addEventListener')):
+              self.name in ['addEventListener', 'removeEventListener']):
               # Events fired need use a JsFunction not a anonymous closure to
               # insure the event can really be removed.
-              parameters.append('wrap_event_listener(this, %s)' % p.name)
-          elif (dart_js_interop and type_id == 'EventListener' and
-              (self.name == 'removeEventListener')):
-              # Find the JsFunction that corresponds to this Dart function.
-              parameters.append('_knownListeners[this.hashCode][identityHashCode(%s)]' % p.name)
+              parameters.append('unwrap_jso(js.allowInterop(%s))' % p.name)
           elif dart_js_interop and type_id == 'FontFaceSetForEachCallback':
               # forEach is supported in the DOM for FontFaceSet as it iterates
               # over the Javascript Object the callback parameters are also
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 24ecbb8..09c242d 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -614,9 +614,7 @@
     return new {0}._internalWrap();
   }}
 
-  factory {0}._internalWrap() {{
-    return new {0}.internal_();
-  }}
+  external factory {0}._internalWrap();
 
   @Deprecated("Internal Use Only")
   {0}.internal_() : super.internal_();
diff --git a/tools/dom/src/dartium_CustomElementSupport.dart b/tools/dom/src/dartium_CustomElementSupport.dart
index aec7b4a..e769e88 100644
--- a/tools/dom/src/dartium_CustomElementSupport.dart
+++ b/tools/dom/src/dartium_CustomElementSupport.dart
@@ -44,7 +44,7 @@
         throw new UnsupportedError('$tag is not registered.');
       }
       jsObject = unwrap_jso(element);
-    } else if (element.runtimeType == js.JsObjectImpl) {
+    } else if (element.runtimeType == js.JsObject) {
       // It's a Polymer core element (written in JS).
       jsObject = element;
     } else if (isNativeElementExtension) {
@@ -56,7 +56,7 @@
     } else if (tag != null && element.localName != tag) {
       throw new UnsupportedError('Element is incorrect type. Got ${element.runtimeType}, expected native Html or Svg element to extend.');
     } else if (tag == null) {
-      throw new UnsupportedError('Element is incorrect type. Got ${element.runtimeType}, expected HtmlElement/JsObjectImpl.');
+      throw new UnsupportedError('Element is incorrect type. Got ${element.runtimeType}, expected HtmlElement/JsObject.');
     }
 
     // Remember Dart class to tagName for any upgrading done in wrap_jso.
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index c82e9b5..66a18e0 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -158,9 +158,9 @@
   '_DOMWindowCrossFrame': () => _DOMWindowCrossFrame,
   // FIXME: Move these to better locations.
   'DateTime': () => DateTime,
-  'JsObject': () => js.JsObjectImpl,
-  'JsFunction': () => js.JsFunctionImpl,
-  'JsArray': () => js.JsArrayImpl,
+  'JsObject': () => js.JsObject,
+  'JsFunction': () => js.JsFunction,
+  'JsArray': () => js.JsArray,
 $!TYPE_MAP
 };
 
@@ -373,7 +373,7 @@
   } else if (runtimeType == TemplateElement) {
     // Data binding with a Dart class.
     tag = element.attributes['is'];
-  } else if (runtimeType == js.JsObjectImpl) {
+  } else if (runtimeType == js.JsObject) {
     // It's a Polymer core element (written in JS).
     // Make sure it's an element anything else we can ignore.
     if (element.hasProperty('nodeType') && element['nodeType'] == 1) {
@@ -386,7 +386,7 @@
       }
     }
   } else {
-    throw new UnsupportedError('Element is incorrect type. Got ${runtimeType}, expected HtmlElement/HtmlTemplate/JsObjectImpl.');
+    throw new UnsupportedError('Element is incorrect type. Got ${runtimeType}, expected HtmlElement/HtmlTemplate/JsObject.');
   }
 
   return tag;
@@ -394,15 +394,9 @@
 
 /// An abstract class for all DOM objects we wrap in dart:html and related
 ///  libraries.
-///
-/// ** Internal Use Only **
 @Deprecated("Internal Use Only")
-class DartHtmlDomObject {
-
-  /// The underlying JS DOM object.
-  @Deprecated("Internal Use Only")
-  js.JsObject blink_jsObject;
-
+class DartHtmlDomObject extends js.JSObject {
+  DartHtmlDomObject() : super.internal();
 }
 
 @Deprecated("Internal Use Only")
@@ -418,24 +412,6 @@
   }
 }
 
-// TODO(terry): Manage JS interop JsFunctions for each listener used for add/
-//              removeEventListener.  These JsFunctions will leak look at
-//              fixing with weak-refs in C++.  The key are the hashcodes of the
-//              user's this (this is needed for futures) and listener function.
-Map<int, Map<int, js.JsFunction>> _knownListeners = {};
-
-@Deprecated("Internal Use Only")
-js.JsFunction wrap_event_listener(theObject, Function listener) {
-  var thisHashCode = theObject.hashCode;
-  var listenerHashCode = identityHashCode(listener);
-
-  _knownListeners.putIfAbsent(thisHashCode, () => new Map<int, js.JsFunction>());
-  _knownListeners[thisHashCode].putIfAbsent(listenerHashCode, () =>
-    new js.JsFunction.withThis((theObject, event) => listener(wrap_jso(event))));
-
-  return _knownListeners[thisHashCode][listenerHashCode];
-}
-
 @Deprecated("Internal Use Only")
 Map<String, dynamic> convertNativeObjectToDartMap(js.JsObject jsObject) {
   var result = new Map();
diff --git a/tools/dom/templates/html/impl/impl_DOMException.darttemplate b/tools/dom/templates/html/impl/impl_DOMException.darttemplate
index 9bbae84..498349b 100644
--- a/tools/dom/templates/html/impl/impl_DOMException.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMException.darttemplate
@@ -52,12 +52,7 @@
     return new DomException._internalWrap();
   }
 
-  @Deprecated("Internal Use Only")
-  js.JsObject blink_jsObject;
-
-  factory DomException._internalWrap() {
-    return new DomException.internal_();
-  }
+  external factory DomException._internalWrap();
 
   @Deprecated("Internal Use Only")
   DomException.internal_() { }
diff --git a/tools/gyp/configurations.gypi b/tools/gyp/configurations.gypi
index 5b55362..ddf4647 100644
--- a/tools/gyp/configurations.gypi
+++ b/tools/gyp/configurations.gypi
@@ -17,9 +17,11 @@
       ['"<(target_arch)"=="ia32"', { 'dart_target_arch': 'IA32', }],
       ['"<(target_arch)"=="x64"', { 'dart_target_arch': 'X64', }],
       ['"<(target_arch)"=="arm"', { 'dart_target_arch': 'ARM', }],
+      ['"<(target_arch)"=="armv6"', { 'dart_target_arch': 'ARMV6', }],
       ['"<(target_arch)"=="armv5te"', { 'dart_target_arch': 'ARMV5TE', }],
       ['"<(target_arch)"=="arm64"', { 'dart_target_arch': 'ARM64', }],
       ['"<(target_arch)"=="simarm"', { 'dart_target_arch': 'SIMARM', }],
+      ['"<(target_arch)"=="simarmv6"', { 'dart_target_arch': 'SIMARMV6', }],
       ['"<(target_arch)"=="simarmv5te"', { 'dart_target_arch': 'SIMARMV5TE', }],
       ['"<(target_arch)"=="simarm64"', { 'dart_target_arch': 'SIMARM64', }],
       ['"<(target_arch)"=="mips"', { 'dart_target_arch': 'MIPS', }],
@@ -63,6 +65,14 @@
         ]
       },
 
+      'Dart_simarmv6_Base': {
+        'abstract': 1,
+        'defines': [
+          'TARGET_ARCH_ARM',
+          'TARGET_ARCH_ARM_6',
+        ]
+      },
+
       'Dart_simarmv5te_Base': {
         'abstract': 1,
         'defines': [
@@ -78,6 +88,14 @@
         ],
       },
 
+      'Dart_armv6_Base': {
+        'abstract': 1,
+        'defines': [
+          'TARGET_ARCH_ARM',
+          'TARGET_ARCH_ARM_6',
+        ],
+      },
+
       'Dart_armv5te_Base': {
         'abstract': 1,
         'defines': [
@@ -184,6 +202,27 @@
         ],
       },
 
+      'DebugSIMARMV6': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simarmv6_Base', 'Dart_Debug',
+          'Dart_<(dart_target_os)_Base',
+          'Dart_<(dart_target_os)_simarmv6_Base',
+          'Dart_<(dart_target_os)_Debug',
+        ],
+        'defines': [
+          'DEBUG',
+        ],
+      },
+
+      'ReleaseSIMARMV6': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_simarmv6_Base', 'Dart_Release',
+          'Dart_<(dart_target_os)_Base',
+          'Dart_<(dart_target_os)_simarmv6_Base',
+          'Dart_<(dart_target_os)_Release',
+        ],
+      },
+
       'DebugSIMARMV5TE': {
         'inherit_from': [
           'Dart_Base', 'Dart_simarmv5te_Base', 'Dart_Debug',
@@ -285,6 +324,42 @@
         ],
       },
 
+      'DebugXARMV6': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv6_Base', 'Dart_Debug',
+          'Dart_Linux_Base',
+          'Dart_Linux_xarmv6_Base',
+          'Dart_Linux_Debug',
+        ],
+      },
+
+      'ReleaseXARMV6': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv6_Base', 'Dart_Release',
+          'Dart_Linux_Base',
+          'Dart_Linux_xarmv6_Base',
+          'Dart_Linux_Release',
+        ],
+      },
+
+      'DebugARMV6': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv6_Base', 'Dart_Debug',
+          'Dart_Linux_Base',
+          'Dart_Linux_armv6_Base',
+          'Dart_Linux_Debug',
+        ],
+      },
+
+      'ReleaseARMV6': {
+        'inherit_from': [
+          'Dart_Base', 'Dart_armv6_Base', 'Dart_Release',
+          'Dart_Linux_Base',
+          'Dart_Linux_armv6_Base',
+          'Dart_Linux_Release',
+        ],
+      },
+
       'DebugXARMV5TE': {
         'inherit_from': [
           'Dart_Base', 'Dart_armv5te_Base', 'Dart_Debug',
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index ebaf935..307b1c2 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -76,6 +76,12 @@
         'ldflags': [ '-m32', ],
       },
 
+      'Dart_Linux_simarmv6_Base': {
+        'abstract': 1,
+        'cflags': [ '-O3', '-m32', '-msse2', '-mfpmath=sse' ],
+        'ldflags': [ '-m32', ],
+      },
+
       'Dart_Linux_simarmv5te_Base': {
         'abstract': 1,
         'cflags': [ '-O3', '-m32', '-msse2', '-mfpmath=sse' ],
@@ -117,6 +123,35 @@
         ],
       },
 
+      # ARMv6 cross-build
+      'Dart_Linux_xarmv6_Base': {
+        'abstract': 1,
+        'target_conditions': [
+        ['_toolset=="target"', {
+          'cflags': [
+            '-march=armv6',
+            '-mfpu=vfp',
+            '-Wno-psabi', # suppresses va_list warning
+            '-fno-strict-overflow',
+          ],
+        }],
+        ['_toolset=="host"', {
+          'cflags': ['-m32', '-msse2', '-mfpmath=sse' ],
+          'ldflags': ['-m32'],
+        }]]
+      },
+
+      # ARMv6 native build
+      'Dart_Linux_armv6_Base': {
+        'abstract': 1,
+        'cflags': [
+          '-march=armv6',
+          '-mfpu=vfp',
+          '-Wno-psabi', # suppresses va_list warning
+          '-fno-strict-overflow',
+        ],
+      },
+
       # ARMv5 cross-build
       'Dart_Linux_xarmv5te_Base': {
         'abstract': 1,
diff --git a/tools/gyp/configurations_msvs.gypi b/tools/gyp/configurations_msvs.gypi
index 3c859ce..c8b0fd3 100644
--- a/tools/gyp/configurations_msvs.gypi
+++ b/tools/gyp/configurations_msvs.gypi
@@ -24,6 +24,9 @@
       'Dart_Win_simarm_Base': {
         'abstract': 1,
       },
+      'Dart_Win_simarmv6_Base': {
+        'abstract': 1,
+      },
       'Dart_Win_simarmv5te_Base': {
         'abstract': 1,
       },
diff --git a/tools/gyp/configurations_xcode.gypi b/tools/gyp/configurations_xcode.gypi
index f709727..e3d04b6 100644
--- a/tools/gyp/configurations_xcode.gypi
+++ b/tools/gyp/configurations_xcode.gypi
@@ -78,6 +78,9 @@
       'Dart_Macos_simarm_Base': {
         'abstract': 1,
       },
+      'Dart_Macos_simarmv6_Base': {
+        'abstract': 1,
+      },
       'Dart_Macos_simarmv5te_Base': {
         'abstract': 1,
       },
diff --git a/tools/precompilation/test_linux.sh b/tools/precompilation/test_linux.sh
index 553dc18b..93de570 100755
--- a/tools/precompilation/test_linux.sh
+++ b/tools/precompilation/test_linux.sh
@@ -12,4 +12,4 @@
 
 gcc -m64 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
 
-LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugX64/dart_precompiled --run-precompiled-snapshot not_used.dart
+LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugX64/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_linux_simarm.sh b/tools/precompilation/test_linux_simarm.sh
index e61b58b..8a8f36c 100755
--- a/tools/precompilation/test_linux_simarm.sh
+++ b/tools/precompilation/test_linux_simarm.sh
@@ -12,4 +12,4 @@
 
 gcc -m32 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.S
 
-LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugSIMARM/dart_precompiled --run-precompiled-snapshot not_used.dart
+LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugSIMARM/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_macos.sh b/tools/precompilation/test_macos.sh
index 57e02dc..e853b1b 100755
--- a/tools/precompilation/test_macos.sh
+++ b/tools/precompilation/test_macos.sh
@@ -12,4 +12,4 @@
 
 clang -m64 -dynamiclib -o libprecompiled.dylib precompiled.S
 
-LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" lldb -- ./xcodebuild/DebugX64/dart_precompiled --run-precompiled-snapshot not_used.dart
+LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" lldb -- ./xcodebuild/DebugX64/dart_precompiled_runtime --run-precompiled-snapshot not_used.dart
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 55810eb..2978003 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -172,6 +172,8 @@
     switch (arch) {
       case 'simarm':
       case 'arm':
+      case 'simarmv6':
+      case 'armv6':
       case' simarmv5te':
       case 'armv5te':
       case 'simmips':
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 92514fe..852e86d 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -108,8 +108,8 @@
               'arch',
               'The architecture to run tests for',
               ['-a', '--arch'],
-              ['all', 'ia32', 'x64', 'arm', 'armv5te', 'arm64', 'mips',
-               'simarm', 'simarmv5te', 'simarm64', 'simmips'],
+              ['all', 'ia32', 'x64', 'arm', 'armv6', 'armv5te', 'arm64', 'mips',
+               'simarm', 'simarmv6', 'simarmv5te', 'simarm64', 'simmips'],
               'x64'),
           new _TestOptionSpecification(
               'system',
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 533c01c..fd67ebf 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -218,7 +218,7 @@
 
     if (dartExecutable == null || dartExecutable == '') {
       String suffix = executableBinarySuffix;
-      dartExecutable = '$buildDir/dart_precompiled$suffix';
+      dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
     }
 
     TestUtils.ensureExists(dartExecutable, configuration);
diff --git a/tools/utils.py b/tools/utils.py
index aaef94c..f2f0704 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -52,6 +52,8 @@
   os_id = platform.machine()
   if os_id.startswith('armv5te'):
     return 'armv5te'
+  elif os_id.startswith('armv6'):
+    return 'armv6'
   elif os_id.startswith('arm'):
     return 'arm'
   elif os_id.startswith('aarch64'):
@@ -228,10 +230,12 @@
   'ia32': 'ia32',
   'x64': 'ia32',
   'arm': 'arm',
+  'armv6': 'arm',
   'armv5te': 'arm',
   'arm64': 'arm',
   'mips': 'mips',
   'simarm': 'ia32',
+  'simarmv6': 'ia32',
   'simarmv5te': 'ia32',
   'simmips': 'ia32',
   'simarm64': 'ia32',
@@ -581,6 +585,9 @@
       # TODO(zra): This binary does not exist, yet. Check one in once we have
       # sufficient stability.
       return os.path.join(dart_binary_prefix, system, 'dart-armv5te')
+    elif arch == 'armv6':
+      # TODO(zra): Ditto.
+      return os.path.join(dart_binary_prefix, system, 'dart-armv6')
     elif arch == 'arm':
       return os.path.join(dart_binary_prefix, system, 'dart-arm')
     elif arch == 'arm64':