Version 2.2.1-dev.2.0

Merge commit '9d3988eb67b3c388fb8eb4425da3ba07182e08a2' into dev
diff --git a/.packages b/.packages
index a686ef2..87f497f 100644
--- a/.packages
+++ b/.packages
@@ -16,7 +16,6 @@
 args:third_party/pkg/args/lib
 async:third_party/pkg/async/lib
 async_helper:pkg/async_helper/lib
-barback:third_party/pkg/barback/lib
 bazel_worker:third_party/pkg/bazel_worker/lib
 boolean_selector:third_party/pkg/boolean_selector/lib
 build_integration:pkg/build_integration/lib
@@ -48,7 +47,6 @@
 http_retry:third_party/pkg/http_retry/lib
 http_throttle:third_party/pkg/http_throttle/lib
 intl:third_party/pkg/intl/lib
-isolate:third_party/pkg/isolate/lib
 js:pkg/js/lib
 js_ast:pkg/js_ast/lib
 js_runtime:sdk/lib/_internal/js_runtime/lib
@@ -67,9 +65,8 @@
 package_config:third_party/pkg_tested/package_config/lib
 package_resolver:third_party/pkg_tested/package_resolver/lib
 path:third_party/pkg/path/lib
-plugin:third_party/pkg/plugin/lib
 pool:third_party/pkg/pool/lib
-protobuf:third_party/pkg/protobuf/lib
+protobuf:third_party/pkg/protobuf/protobuf/lib
 pub:third_party/pkg/pub/lib
 pub_semver:third_party/pkg/pub_semver/lib
 quiver:third_party/pkg/quiver/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37704bb..110eaf0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+## 2.2.1-dev.2.0
+
 ## 2.2.1-dev.1.1
 
 * Cherry-pick 567d552de8ff93d704111467e7f3bf3b896ab684 to dev
@@ -5,6 +7,8 @@
 
 ## 2.2.1-dev.1.0
 
+* RegExp patterns can now use lookbehind assertions.
+
 ### Tool Changes
 
 #### Pub client
diff --git a/DEPS b/DEPS
index f1860721..c6f2c79 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   "chromium_git": "https://chromium.googlesource.com",
   "fuchsia_git": "https://fuchsia.googlesource.com",
 
-  "co19_2_rev": "b54821029f62b5b5873925cfef6c01f1100d1982",
+  "co19_2_rev": "2d157d6b9135f891ffd1d35b7a2d5dfa57611f63",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
   # should be kept up to date with the revisions pulled by the Flutter engine.
@@ -54,7 +54,7 @@
   # Revisions of /third_party/* dependencies.
   "args_tag": "1.4.4",
   "async_tag": "2.0.8",
-  "bazel_worker_tag": "0.1.14",
+  "bazel_worker_tag": "bazel_worker-v0.1.20",
   "boolean_selector_tag" : "1.0.4",
   "boringssl_gen_rev": "bbf52f18f425e29b1185f2f6753bec02ed8c5880",
   "boringssl_rev" : "702e2b6d3831486535e958f262a05c75a5cb312e",
@@ -108,10 +108,9 @@
   "package_config_tag": "1.0.5",
   "package_resolver_tag": "1.0.10",
   "path_tag": "1.6.2",
-  "plugin_tag": "f5b4b0e32d1406d62daccea030ba6457d14b1c47",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
-  "protobuf_tag": "0.9.0",
+  "protobuf_rev": "0c77167b16d00b561a6055bfe26690af7f26ae88",
   "pub_rev": "3c060aae47985e9a248b850f1d0450304a5c97e3",
   "pub_semver_tag": "1.4.2",
   "quiver_tag": "2.0.0+1",
@@ -157,7 +156,7 @@
   Var("dart_root") + "/tools/sdks": {
       "packages": [{
           "package": "dart/dart-sdk/${{platform}}",
-          "version": "version:2.2.1-dev.0.0",
+          "version": "version:2.2.1-dev.1.1",
       }],
       "dep_type": "cipd",
   },
@@ -303,12 +302,10 @@
       + "@" + Var("package_resolver_tag"),
   Var("dart_root") + "/third_party/pkg/path":
       Var("dart_git") + "path.git" + "@" + Var("path_tag"),
-  Var("dart_root") + "/third_party/pkg/plugin":
-      Var("dart_git") + "plugin.git" + "@" + Var("plugin_tag"),
   Var("dart_root") + "/third_party/pkg/pool":
       Var("dart_git") + "pool.git" + "@" + Var("pool_tag"),
   Var("dart_root") + "/third_party/pkg/protobuf":
-      Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_tag"),
+      Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_rev"),
   Var("dart_root") + "/third_party/pkg/pub_semver":
       Var("dart_git") + "pub_semver.git" + "@" + Var("pub_semver_tag"),
   Var("dart_root") + "/third_party/pkg/pub":
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index adf71a2..5ed9bcb 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -66,7 +66,7 @@
 
 [TODO: Link to an issue template for this]
 
-* Email `announce@dartlang.org, flutter-announce@googlegroups.com`,:
+* Email Dart Announce (`announce@dartlang.org`):
 
   * Subject: 'Breaking change [bug ID]: [short summary]'
 
@@ -77,6 +77,9 @@
   * A request that developers may leave comments in the linked issue, if this
     breaking change poses a severe problem.
 
+* Once you have sent the announce email, please let `aadilmaan@google.com` know
+as he will help drive the request through approval review process.
+
 ### Step 2: Approval
 
 If there is a general agreement that the benefit of the change outweighs the
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index d4f29d6..a08c3bc 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -196,7 +196,11 @@
       try {
         var analysisDriver = server.getAnalysisDriver(file);
         var session = analysisDriver.currentSession;
-        var resolvedLibrary = await session.getResolvedLibrary(file);
+
+        var fileElement = await session.getUnitElement(file);
+        var libraryPath = fileElement.element.librarySource.fullName;
+
+        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
         var requestedLibraryElement = await session.getLibraryByUri(
           library.uriStr,
         );
@@ -214,10 +218,10 @@
 
         var completion = params.label;
         var builder = DartChangeBuilder(session);
-        await builder.addFileEdit(file, (builder) {
+        await builder.addFileEdit(libraryPath, (builder) {
           var result = builder.importLibraryElement(
             targetLibrary: resolvedLibrary,
-            targetPath: file,
+            targetPath: libraryPath,
             targetOffset: params.offset,
             requestedLibrary: requestedLibraryElement,
             requestedElement: requestedElement,
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index c5ee92f..26a8028 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -43,6 +43,12 @@
   Expression get dotTarget;
 
   /**
+   * Return a list containing the names of the experiments that have been
+   * enabled.
+   */
+  List<String> get enabledExperiments;
+
+  /**
    * Return `true` if free standing identifiers should be suggested
    */
   bool get includeIdentifiers;
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 1d493ed..70f98dc 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -30,7 +30,6 @@
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:args/args.dart';
 import 'package:linter/src/rules.dart' as linter;
-import 'package:plugin/manager.dart';
 import 'package:telemetry/crash_reporting.dart';
 import 'package:telemetry/telemetry.dart' as telemetry;
 
@@ -440,10 +439,8 @@
     final serve_http = diagnosticServerPort != null;
 
     //
-    // Process all of the plugins so that extensions are registered.
+    // Register lint rules.
     //
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
     linter.registerLintRules();
 
     _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl();
@@ -701,6 +698,15 @@
     return sdk;
   }
 
+  /**
+   * Constructs a uuid combining the current date and a random integer.
+   */
+  String _generateUuidString() {
+    int millisecondsSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
+    int random = new Random().nextInt(0x3fffffff);
+    return '$millisecondsSinceEpoch$random';
+  }
+
   String _getSdkPath(ArgResults args) {
     if (args[SDK_OPTION] != null) {
       return args[SDK_OPTION];
@@ -768,15 +774,6 @@
   }
 
   /**
-   * Constructs a uuid combining the current date and a random integer.
-   */
-  String _generateUuidString() {
-    int millisecondsSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
-    int random = new Random().nextInt(0x3fffffff);
-    return '$millisecondsSinceEpoch$random';
-  }
-
-  /**
    * Perform log files rolling.
    *
    * Rename existing files with names `[path].(x)` to `[path].(x+1)`.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index a53579e..710ca2d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -326,6 +326,10 @@
   }
 
   @override
+  List<String> get enabledExperiments =>
+      result.session.analysisContext.analysisOptions.enabledExperiments;
+
+  @override
   bool get includeIdentifiers {
     return opType.includeIdentifiers;
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index ecc25d3..fb9885d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -327,6 +328,13 @@
   }
 
   @override
+  visitForElement(ForElement node) {
+    _addCollectionElementKeywords();
+    _addExpressionKeywords(node);
+    return super.visitForElement(node);
+  }
+
+  @override
   visitFormalParameterList(FormalParameterList node) {
     AstNode constructorDeclaration =
         node.thisOrAncestorOfType<ConstructorDeclaration>();
@@ -387,6 +395,13 @@
   }
 
   @override
+  visitIfElement(IfElement node) {
+    _addCollectionElementKeywords();
+    _addExpressionKeywords(node);
+    return super.visitIfElement(node);
+  }
+
+  @override
   visitIfStatement(IfStatement node) {
     if (_isPreviousTokenSynthetic(entity, TokenType.CLOSE_PAREN)) {
       // analyzer parser
@@ -449,6 +464,12 @@
   }
 
   @override
+  visitListLiteral(ListLiteral node) {
+    _addCollectionElementKeywords();
+    super.visitListLiteral(node);
+  }
+
+  @override
   visitMethodDeclaration(MethodDeclaration node) {
     if (entity == node.body) {
       if (isEmptyBody(node.body)) {
@@ -549,6 +570,18 @@
   }
 
   @override
+  visitSetOrMapLiteral(SetOrMapLiteral node) {
+    _addCollectionElementKeywords();
+    super.visitSetOrMapLiteral(node);
+  }
+
+  @override
+  visitSpreadElement(SpreadElement node) {
+    _addExpressionKeywords(node);
+    return super.visitSpreadElement(node);
+  }
+
+  @override
   visitStringLiteral(StringLiteral node) {
     // ignored
   }
@@ -627,6 +660,17 @@
     }
   }
 
+  void _addCollectionElementKeywords() {
+    List<String> enabledExperiments = request.enabledExperiments;
+    if (enabledExperiments.contains(EnableString.control_flow_collections) ||
+        enabledExperiments.contains(EnableString.spread_collections)) {
+      _addSuggestions([
+        Keyword.FOR,
+        Keyword.IF,
+      ]);
+    }
+  }
+
   void _addCompilationUnitKeywords() {
     _addSuggestions([
       Keyword.ABSTRACT,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 63faf71..50e4b46 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -76,9 +76,11 @@
     }
     String containingMethodName;
     List<InterfaceType> mixins;
+    List<InterfaceType> superclassConstraints;
     if (expression is SuperExpression && type is InterfaceType) {
       // Suggest members from superclass if target is "super"
       mixins = (type as InterfaceType).mixins;
+      superclassConstraints = (type as InterfaceType).superclassConstraints;
       type = (type as InterfaceType).superclass;
       // Determine the name of the containing method because
       // the most likely completion is a super expression with same name
@@ -99,7 +101,8 @@
     // Build the suggestions
     if (type is InterfaceType) {
       _SuggestionBuilder builder = new _SuggestionBuilder(containingLibrary);
-      builder.buildSuggestions(type, containingMethodName, mixins: mixins);
+      builder.buildSuggestions(type, containingMethodName,
+          mixins: mixins, superclassConstraints: superclassConstraints);
       return builder.suggestions.toList();
     }
     return const <CompletionSuggestion>[];
@@ -290,7 +293,7 @@
    * is the name of the method in which the completion is requested.
    */
   void buildSuggestions(InterfaceType type, String containingMethodName,
-      {List<InterfaceType> mixins}) {
+      {List<InterfaceType> mixins, List<InterfaceType> superclassConstraints}) {
     // Visit all of the types in the class hierarchy, collecting possible
     // completions.  If multiple elements are found that complete to the same
     // identifier, addSuggestion will discard all but the first (with a few
@@ -299,6 +302,9 @@
     if (mixins != null) {
       types.addAll(mixins);
     }
+    if (superclassConstraints != null) {
+      types.addAll(superclassConstraints);
+    }
     for (InterfaceType targetType in types) {
       for (MethodElement method in targetType.methods) {
         // Exclude static methods when completion on an instance
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 2b18345..4c4e5a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -60,6 +60,11 @@
   static const CONVERT_INTO_FINAL_FIELD = const AssistKind(
       'dart.assist.convert.getterToFinalField', 30, "Convert to final field",
       associatedErrorCodes: <String>['prefer_final_fields']);
+  static const CONVERT_INTO_ABSOLUTE_IMPORT = const AssistKind(
+      'dart.assist.convert.relativeToAbsoluteImport',
+      30,
+      "Convert to absolute import",
+      associatedErrorCodes: <String>['avoid_relative_lib_imports']);
   static const CONVERT_INTO_FOR_INDEX = const AssistKind(
       'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop");
   static const CONVERT_INTO_GENERIC_FUNCTION_SYNTAX = const AssistKind(
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 f092854..ee38d9c 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -104,6 +104,7 @@
     await _addProposal_convertMapConstructorToMapLiteral();
     await _addProposal_convertPartOfToUri();
     await _addProposal_convertSetConstructorToSetLiteral();
+    await _addProposal_convertToAbsoluteImport();
     await _addProposal_convertToAsyncFunctionBody();
     await _addProposal_convertToBlockFunctionBody();
     await _addProposal_convertToDoubleQuotedString();
@@ -1725,6 +1726,29 @@
         changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY);
   }
 
+  Future<void> _addProposal_convertToAbsoluteImport() async {
+    var node = this.node;
+    if (node is StringLiteral) {
+      node = node.parent;
+    }
+    if (node is ImportDirective) {
+      var importDirective = node;
+      var importUri = node.uriSource?.uri;
+      if (importUri?.scheme != 'package') {
+        return;
+      }
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (builder) {
+        builder.addSimpleReplacement(
+            range.node(importDirective.uri), "'$importUri'");
+      });
+      _addAssistFromBuilder(
+        changeBuilder,
+        DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT,
+      );
+    }
+  }
+
   Future<void> _addProposal_convertToMultilineString() async {
     var node = this.node;
     if (node is InterpolationElement) {
@@ -2516,7 +2540,10 @@
     await changeBuilder.addFileEdit(file, (builder) {
       builder.addReplacement(range.node(widgetExpr), (builder) {
         builder.writeType(streamBuilderElement.type);
-        builder.writeln('<Object>(');
+
+        builder.write('<');
+        builder.addSimpleLinkedEdit('type', 'Object');
+        builder.writeln('>(');
 
         String indentOld = utils.getLinePrefix(widgetExpr.offset);
         String indentNew1 = indentOld + utils.getIndent(1);
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index ec60587..3bb80d7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -73,15 +73,36 @@
     errorCode == StaticTypeWarningCode.UNDEFINED_SETTER ||
     errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER ||
     (errorCode is LintCode &&
-        (errorCode.name == LintNames.annotate_overrides ||
+        (errorCode.name == LintNames.always_require_non_null_named_parameters ||
+            errorCode.name == LintNames.annotate_overrides ||
+            errorCode.name == LintNames.avoid_annotating_with_dynamic ||
+            errorCode.name == LintNames.avoid_empty_else ||
             errorCode.name == LintNames.avoid_init_to_null ||
+            errorCode.name == LintNames.avoid_return_types_on_setters ||
+            errorCode.name == LintNames.avoid_types_on_closure_parameters ||
+            errorCode.name == LintNames.await_only_futures ||
+            errorCode.name == LintNames.empty_catches ||
+            errorCode.name == LintNames.empty_constructor_bodies ||
+            errorCode.name == LintNames.empty_statements ||
+            errorCode.name == LintNames.no_duplicate_case_values ||
+            errorCode.name == LintNames.non_constant_identifier_names ||
+            errorCode.name == LintNames.null_closures ||
             errorCode.name == LintNames.prefer_collection_literals ||
             errorCode.name == LintNames.prefer_conditional_assignment ||
             errorCode.name == LintNames.prefer_const_declarations ||
+            errorCode.name == LintNames.prefer_equal_for_default_values ||
+            errorCode.name == LintNames.prefer_final_fields ||
+            errorCode.name == LintNames.prefer_final_locals ||
+            errorCode.name == LintNames.prefer_is_not_empty ||
+            errorCode.name == LintNames.type_init_formals ||
+            errorCode.name == LintNames.unawaited_futures ||
             errorCode.name == LintNames.unnecessary_brace_in_string_interps ||
             errorCode.name == LintNames.unnecessary_const ||
             errorCode.name == LintNames.unnecessary_lambdas ||
-            errorCode.name == LintNames.unnecessary_this));
+            errorCode.name == LintNames.unnecessary_new ||
+            errorCode.name == LintNames.unnecessary_overrides ||
+            errorCode.name == LintNames.unnecessary_this ||
+            errorCode.name == LintNames.use_rethrow_when_possible));
 
 /**
  * The implementation of [DartFixContext].
@@ -105,6 +126,8 @@
 class DartFixKind {
   static const ADD_ASYNC =
       const FixKind('ADD_ASYNC', 50, "Add 'async' modifier");
+  static const ADD_AWAIT =
+      const FixKind('ADD_AWAIT', 50, "Add 'await' keyword");
   static const ADD_EXPLICIT_CAST = const FixKind(
       'ADD_EXPLICIT_CAST', 50, "Add cast",
       appliedTogetherMessage: "Add all casts in file");
@@ -262,8 +285,12 @@
   static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(
       'REPLACE_BOOLEAN_WITH_BOOL', 50, "Replace 'boolean' with 'bool'",
       appliedTogetherMessage: "Replace all 'boolean' with 'bool' in file");
+  static const REPLACE_COLON_WITH_EQUALS =
+      const FixKind('REPLACE_COLON_WITH_EQUALS', 50, "Replace ':' with '='");
   static const REPLACE_FINAL_WITH_CONST = const FixKind(
       'REPLACE_FINAL_WITH_CONST', 50, "Replace 'final' with 'const'");
+  static const REPLACE_NULL_WITH_CLOSURE = const FixKind(
+      'REPLACE_NULL_WITH_CLOSURE', 50, "Replace 'null' with a closure");
   static const REPLACE_RETURN_TYPE_FUTURE = const FixKind(
       'REPLACE_RETURN_TYPE_FUTURE',
       50,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 322e99a..adeb0f9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -592,12 +592,18 @@
       if (name == LintNames.non_constant_identifier_names) {
         await _addFix_renameToCamelCase();
       }
+      if (name == LintNames.null_closures) {
+        await _addFix_replaceNullWithClosure();
+      }
       if (name == LintNames.prefer_conditional_assignment) {
         await _addFix_replaceWithConditionalAssignment();
       }
       if (errorCode.name == LintNames.prefer_const_declarations) {
         await _addFix_replaceFinalWithConst();
       }
+      if (errorCode.name == LintNames.prefer_equal_for_default_values) {
+        await _addFix_replaceColonWithEquals();
+      }
       if (name == LintNames.prefer_final_fields) {
         await _addFix_makeVariableFinal();
       }
@@ -610,6 +616,9 @@
       if (name == LintNames.type_init_formals) {
         await _addFix_removeTypeAnnotation();
       }
+      if (name == LintNames.unawaited_futures) {
+        await _addFix_addAwait();
+      }
       if (name == LintNames.unnecessary_brace_in_string_interps) {
         await _addFix_removeInterpolationBraces();
       }
@@ -656,6 +665,14 @@
     }
   }
 
+  Future<void> _addFix_addAwait() async {
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleInsertion(node.offset, 'await ');
+    });
+    _addFixFromBuilder(changeBuilder, DartFixKind.ADD_AWAIT);
+  }
+
   Future<void> _addFix_addExplicitCast() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -3162,6 +3179,17 @@
         args: [newName]);
   }
 
+  Future<void> _addFix_replaceColonWithEquals() async {
+    if (node is DefaultFormalParameter) {
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addSimpleReplacement(
+            range.token((node as DefaultFormalParameter).separator), '=');
+      });
+      _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_COLON_WITH_EQUALS);
+    }
+  }
+
   Future<void> _addFix_replaceFinalWithConst() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -3185,6 +3213,39 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_VAR_WITH_DYNAMIC);
   }
 
+  Future<void> _addFix_replaceNullWithClosure() async {
+    var nodeToFix;
+    var parameters = const <ParameterElement>[];
+    if (coveredNode is NamedExpression) {
+      NamedExpression namedExpression = coveredNode;
+      var expression = namedExpression.expression;
+      if (expression is NullLiteral) {
+        var element = namedExpression.element;
+        if (element is ParameterElement) {
+          var type = element.type;
+          if (type is FunctionType) {
+            parameters = type.parameters;
+          }
+        }
+        nodeToFix = expression;
+      }
+    } else if (coveredNode is NullLiteral) {
+      nodeToFix = coveredNode;
+    }
+
+    if (nodeToFix != null) {
+      var changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addReplacement(range.node(nodeToFix),
+            (DartEditBuilder builder) {
+          builder.writeParameters(parameters);
+          builder.write(' => null');
+        });
+      });
+      _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_NULL_WITH_CLOSURE);
+    }
+  }
+
   Future<void> _addFix_replaceWithConditionalAssignment() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -4341,14 +4402,18 @@
   static const String no_duplicate_case_values = 'no_duplicate_case_values';
   static const String non_constant_identifier_names =
       'non_constant_identifier_names';
+  static const String null_closures = 'null_closures';
   static const String prefer_collection_literals = 'prefer_collection_literals';
   static const String prefer_conditional_assignment =
       'prefer_conditional_assignment';
   static const String prefer_const_declarations = 'prefer_const_declarations';
+  static const String prefer_equal_for_default_values =
+      'prefer_equal_for_default_values';
   static const String prefer_final_fields = 'prefer_final_fields';
   static const String prefer_final_locals = 'prefer_final_locals';
   static const String prefer_is_not_empty = 'prefer_is_not_empty';
   static const String type_init_formals = 'type_init_formals';
+  static const String unawaited_futures = 'unawaited_futures';
   static const String unnecessary_brace_in_string_interps =
       'unnecessary_brace_in_string_interps';
   static const String unnecessary_const = 'unnecessary_const';
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index 6135864..f4593b4 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -23,7 +23,6 @@
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
-import 'package:plugin/manager.dart';
 import 'package:test/test.dart';
 import 'package:watcher/watcher.dart';
 
@@ -108,11 +107,6 @@
 
   AnalysisServer createAnalysisServer() {
     //
-    // Process plugins
-    //
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
-    //
     // Create an SDK in the mock file system.
     //
     new MockSdk(
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 4a7e95d..88938f1 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
 import 'package:analyzer/src/generated/sdk.dart';
@@ -30,7 +31,6 @@
 import 'package:linter/src/rules.dart';
 import 'package:linter/src/rules/avoid_as.dart';
 import 'package:path/path.dart' as path;
-import 'package:plugin/manager.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:watcher/watcher.dart';
@@ -1722,9 +1722,6 @@
       .firstWhere((ErrorProcessor p) => p.appliesTo(error), orElse: () => null);
 
   void processRequiredPlugins() {
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(AnalysisEngine.instance.requiredPlugins);
-
     registerLintRules();
   }
 
@@ -1981,7 +1978,9 @@
     String sdkExtPath = '$projPath/sdk_ext';
     newFile('$projPath/test', content: 'test.dart');
     newFile('$sdkExtPath/entry.dart');
-    List<int> bytes = new SummaryBuilder([], null).build();
+    List<int> bytes = new SummaryBuilder(
+            [], RestrictedAnalysisContext(analysisOptions, null, null))
+        .build();
     newFileWithBytes('$projPath/sdk.ds', bytes);
     // Setup _embedder.yaml.
     newFile('$libPath/_embedder.yaml', content: r'''
@@ -2045,8 +2044,10 @@
 
     expect(
         lintNames,
-        unorderedEquals(
-            ['avoid_as' /* embedder */, 'camel_case_types' /* options */]));
+        unorderedEquals([
+          'avoid_as' /* embedder */,
+          'camel_case_types' /* options */
+        ]));
 
     // Sanity check embedder libs.
     var source = sourceFactory.forUri('dart:foobar');
@@ -2498,20 +2499,12 @@
 
     ContextBuilder builder =
         createContextBuilder(folder, options, useSummaries: true);
-    AnalysisContext context = builder.buildContext(folder.path);
-    SourceFactory sourceFactory = context.sourceFactory;
-    AnalysisOptions analysisOptions = context.analysisOptions;
-    context.dispose();
+    builder.analysisDriverScheduler = scheduler;
+    builder.byteStore = MemoryByteStore();
+    builder.performanceLog = logger;
+    builder.fileContentOverlay = FileContentOverlay();
+    currentDriver = builder.buildDriver(contextRoot);
 
-    currentDriver = new AnalysisDriver(
-        scheduler,
-        logger,
-        resourceProvider,
-        new MemoryByteStore(),
-        new FileContentOverlay(),
-        contextRoot,
-        sourceFactory,
-        analysisOptions);
     driverMap[path] = currentDriver;
     currentDriver.exceptions.listen((ExceptionResult result) {
       AnalysisEngine.instance.logger
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
index c9be4cd..1ea7f7c 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
@@ -44,6 +44,7 @@
 class int {}
 class num {}
 class Object {}
+class Iterable<E> {}
 class Map<K, V> {}
 class Null {}
 class String {}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 73f5b37..2955d79 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,6 +15,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(KeywordContributorTest);
+    defineReflectiveTests(KeywordContributorWithUiAsCodeTest);
   });
 }
 
@@ -1882,3 +1884,153 @@
     return true;
   }
 }
+
+@reflectiveTest
+class KeywordContributorWithUiAsCodeTest extends KeywordContributorTest {
+  static const List<Keyword> COLLECTION_ELEMENT_START = const [
+    Keyword.CONST,
+    Keyword.FALSE,
+    Keyword.FOR,
+    Keyword.IF,
+    Keyword.NEW,
+    Keyword.NULL,
+    Keyword.TRUE,
+  ];
+
+  @override
+  void setupResourceProvider() {
+    super.setupResourceProvider();
+    createAnalysisOptionsFile(experiments: [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections
+    ]);
+  }
+
+  test_ifOrForElement_forElement() async {
+    addTestSource('''
+f() => [for (var e in c) ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_ifElement_else() async {
+    addTestSource('''
+f() => [if (true) 1 else ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_ifElement_then() async {
+    addTestSource('''
+f() => [if (true) ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_empty() async {
+    addTestSource('''
+f() => [^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_first() async {
+    addTestSource('''
+f() => [^1, 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_last() async {
+    addTestSource('''
+f() => [1, 2, ^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_list_middle() async {
+    addTestSource('''
+f() => [1, ^, 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_empty() async {
+    addTestSource('''
+f() => <String, int>{^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_first() async {
+    addTestSource('''
+f() => <String, int>{^'a' : 1};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_last() async {
+    addTestSource('''
+f() => <String, int>{'a' : 1, 'b' : 2, ^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_map_middle() async {
+    addTestSource('''
+f() => <String, int>{'a' : 1, ^, 'b' : 2];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_empty() async {
+    addTestSource('''
+f() => <int>{^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_first() async {
+    addTestSource('''
+f() => <int>{^1, 2};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_last() async {
+    addTestSource('''
+f() => <int>{1, 2, ^};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_ifOrForElement_set_middle() async {
+    addTestSource('''
+f() => <int>{1, ^, 2};
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(COLLECTION_ELEMENT_START);
+  }
+
+  test_spreadElement() async {
+    addTestSource('''
+f() => [...^];
+''');
+    await computeSuggestions();
+    assertSuggestKeywords(KeywordContributorTest.EXPRESSION_START_NO_INSTANCE);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index c3712b1..11eb5eb 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -3659,6 +3659,19 @@
     assertNotSuggested('ms3');
   }
 
+  test_super_fromSuperclassConstraint() async {
+    addTestSource('''
+class C {
+  void c(x, int y) {}
+}
+mixin M on C {
+  m() {super.^}
+}
+''');
+    await computeSuggestions();
+    assertSuggestMethod('c', 'C', 'void');
+  }
+
   test_super_withMixin() async {
     addTestSource('''
 mixin M {
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
index 4dbfd3c..e99991e 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
@@ -134,6 +134,35 @@
 ''');
   }
 
+  test_newImport_part() async {
+    var partCode = r'''
+part of 'test.dart';
+
+main() {} // ref
+''';
+    var partPath = newFile('/home/test/lib/a.dart', content: partCode).path;
+    addTestFile(r'''
+part 'a.dart';
+''');
+
+    var mathSet = await waitForSetWithUri('dart:math');
+    var result = await _getSuggestionDetails(
+      _buildRequest(
+        file: partPath,
+        id: mathSet.id,
+        label: 'sin',
+        offset: partCode.indexOf('} // ref'),
+      ),
+    );
+
+    expect(result.completion, 'sin');
+    _assertTestFileChange(result.change, r'''
+import 'dart:math';
+
+part 'a.dart';
+''');
+  }
+
   void _assertEmptyChange(SourceChange change) {
     expect(change.edits, isEmpty);
   }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
new file mode 100644
index 0000000..36e3fab
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_absolute_import_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertIntoAbsoluteImportTest);
+  });
+}
+
+@reflectiveTest
+class ConvertIntoAbsoluteImportTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_INTO_ABSOLUTE_IMPORT;
+
+  test_fileName_onUri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'foo.dart';
+''');
+    await assertHasAssistAt('foo.dart', '''
+import 'package:test/foo.dart';
+''');
+  }
+
+  test_fileName_onImport() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'foo.dart';
+''');
+    // Validate assist is on import keyword too.
+    await assertHasAssistAt('import', '''
+import 'package:test/foo.dart';
+''');
+  }
+
+  test_nonPackage_Uri() async {
+    addSource('/home/test/lib/foo.dart', '');
+
+    await resolveTestUnit('''
+import 'dart:core';
+''');
+
+    await assertNoAssistAt('dart:core');
+    await assertNoAssistAt('import');
+  }
+
+  test_path() async {
+    addSource('/home/test/lib/foo/bar.dart', '');
+
+    testFile = convertPath('/home/test/lib/src/test.dart');
+
+    await resolveTestUnit('''
+import '../foo/bar.dart';
+''');
+    await assertHasAssistAt('bar.dart', '''
+import 'package:test/foo/bar.dart';
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index 1d75bb9..9bba973 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -11,6 +11,7 @@
     as convert_documentation_into_block;
 import 'convert_documentation_into_line_test.dart'
     as convert_documentation_into_line;
+import 'convert_into_absolute_import_test.dart' as convert_into_absolute_import;
 import 'convert_into_async_body_test.dart' as convert_into_async_body;
 import 'convert_into_block_body_test.dart' as convert_into_block_body;
 import 'convert_into_expression_body_test.dart' as convert_into_expression_body;
@@ -82,6 +83,7 @@
     convert_class_to_mixin.main();
     convert_documentation_into_block.main();
     convert_documentation_into_line.main();
+    convert_into_absolute_import.main();
     convert_into_async_body.main();
     convert_into_block_body.main();
     convert_into_expression_body.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart
new file mode 100644
index 0000000..1391007
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_await_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddAwaitTest);
+  });
+}
+
+@reflectiveTest
+class AddAwaitTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_AWAIT;
+
+  @override
+  String get lintCode => LintNames.unawaited_futures;
+
+  test_intLiteral() async {
+    await resolveTestUnit('''
+Future doSomething() => new Future();
+
+void main() async {
+  doSomething()/*LINT*/;
+}
+''');
+    await assertHasFix('''
+Future doSomething() => new Future();
+
+void main() async {
+  await doSomething()/*LINT*/;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
new file mode 100644
index 0000000..375a662
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceColonWithEqualsTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceColonWithEqualsTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_COLON_WITH_EQUALS;
+
+  @override
+  String get lintCode => LintNames.prefer_equal_for_default_values;
+
+  test_method() async {
+    await resolveTestUnit('''
+void f1({int a}) { }    
+
+f1({a/*LINT*/: 1}) => null;
+''');
+    await assertHasFix('''
+void f1({int a}) { }    
+
+f1({a/*LINT*/= 1}) => null;
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
new file mode 100644
index 0000000..4ada2dd
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_null_with_closure_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceNullWithClosureTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceNullWithClosureTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_NULL_WITH_CLOSURE;
+
+  @override
+  String get lintCode => LintNames.null_closures;
+
+  test_null_closure_named_expression() async {
+    await resolveTestUnit('''
+main() {
+  [1, 3, 5].firstWhere((e) => e.isOdd, orElse: /*LINT*/null);
+}
+''');
+    await assertHasFix('''
+main() {
+  [1, 3, 5].firstWhere((e) => e.isOdd, orElse: /*LINT*/() => null);
+}
+''');
+  }
+
+  test_null_closure_named_expression_with_args() async {
+    await resolveTestUnit('''
+void f({int closure(x, y)}) { }
+main() {
+  f(closure: /*LINT*/null);
+}
+''');
+    await assertHasFix('''
+void f({int closure(x, y)}) { }
+main() {
+  f(closure: /*LINT*/(x, y) => null);
+}
+''');
+  }
+
+  test_null_closure_named_expression_with_args_2() async {
+    await resolveTestUnit('''
+void f({int closure(x, y, {z})}) { }
+main() {
+  f(closure: /*LINT*/null);
+}
+''');
+    await assertHasFix('''
+void f({int closure(x, y, {z})}) { }
+main() {
+  f(closure: /*LINT*/(x, y, {z}) => null);
+}
+''');
+  }
+
+  /// Currently failing since the LINT annotation is tagging the ArgumentList
+  /// where the fix (and lint) expect a NullLiteral.
+  /// todo (pq): re-write FixProcessorLintTest to run the actual lints.
+  @failingTest
+  test_null_closure_literal() async {
+    await resolveTestUnit('''
+void f(dynamic x) { }
+main() {
+  f(null/*LINT*/);
+}
+''');
+    await assertHasFix('''
+void f(dynamic x) { }
+main() {
+  f(/*LINT*/() => null);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 07369fb..9e4fffb 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -5,6 +5,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'add_async_test.dart' as add_async;
+import 'add_await_test.dart' as add_await;
 import 'add_explicit_cast_test.dart' as add_explicit_cast;
 import 'add_field_formal_parameters_test.dart' as add_field_formal_parameters;
 import 'add_missing_parameter_named_test.dart' as add_missing_parameter_named;
@@ -57,6 +58,7 @@
 import 'remove_annotation_test.dart' as remove_annotation;
 import 'remove_await_test.dart' as remove_await;
 import 'remove_dead_code_test.dart' as remove_dead_code;
+import 'remove_duplicate_case_test.dart' as remove_duplicate_case;
 import 'remove_empty_catch_test.dart' as remove_empty_catch;
 import 'remove_empty_constructor_body_test.dart'
     as remove_empty_constructor_body;
@@ -81,7 +83,9 @@
 import 'remove_unused_import_test.dart' as remove_unused_import;
 import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
 import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
+import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
 import 'replace_final_with_const_test.dart' as replace_final_with_const;
+import 'replace_null_with_closure_test.dart' as replace_null_with_closure;
 import 'replace_return_type_future_test.dart' as replace_return_type_future;
 import 'replace_var_with_dynamic_test.dart' as replace_var_with_dynamic;
 import 'replace_with_brackets_test.dart' as replace_with_brackets;
@@ -97,10 +101,12 @@
 import 'use_eq_eq_null_test.dart' as use_eq_eq_null;
 import 'use_is_not_empty_test.dart' as use_is_not_empty;
 import 'use_not_eq_null_test.dart' as use_not_eq_null;
+import 'use_rethrow_test.dart' as use_rethrow;
 
 main() {
   defineReflectiveSuite(() {
     add_async.main();
+    add_await.main();
     add_explicit_cast.main();
     add_field_formal_parameters.main();
     add_missing_parameter_named.main();
@@ -147,6 +153,7 @@
     remove_annotation.main();
     remove_await.main();
     remove_dead_code.main();
+    remove_duplicate_case.main();
     remove_empty_catch.main();
     remove_empty_constructor_body.main();
     remove_empty_else.main();
@@ -168,7 +175,9 @@
     remove_unused_import.main();
     rename_to_camel_case.main();
     replace_boolean_with_bool.main();
+    replace_colon_with_equals.main();
     replace_final_with_const.main();
+    replace_null_with_closure.main();
     replace_return_type_future.main();
     replace_var_with_dynamic.main();
     replace_with_brackets.main();
@@ -182,5 +191,6 @@
     use_eq_eq_null.main();
     use_is_not_empty.main();
     use_not_eq_null.main();
+    use_rethrow.main();
   }, name: 'fix');
 }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 88eea40..e376b96 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,4 +1,4 @@
-##
+## 0.35.4
 * Deprecated AST structures that will no longer be used after the
   control_flow_collections and spread_collections experiments are enabled.  The
   following AST node types are deprecated:
@@ -13,6 +13,13 @@
   * `visitForStatement` (override `visitForStatement2` instead)
   * `visitMapLiteral` (override `visitSetOrMapLiteral` instead)
   * `visitSetLiteral` (override `visitSetOrMapLiteral` instead)
+* Deprecated ASTFactory methods that will no longer be available after the
+  control_flow_collections and spread_collections experiments are enabled.  The
+  following factory methods are deprecated:
+  * `mapLiteral` and `mapLiteral2` (use `setOrMapLiteral` instead)
+  * `setLiteral` and `setLiteral2` (use `setOrMapLiteral` instead)
+* Bug fixes: #33119, #33241, #35747, #35900, #36048, #36129
+* The analyzer no longer uses `package:html` (see #35802)
 
 ## 0.35.3
 * Further updates to the AST structure for the control_flow_collections and
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 271b921..b2ce8fa 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -4731,8 +4731,17 @@
   /// This getter will always return `false` if [isSet] returns `true`.
   ///
   /// However, this getter is _not_ the inverse of [isSet]. It is possible for
-  /// both getters to return `false` if the literal was either invalid or
-  /// ambiguous.
+  /// both getters to return `false` if
+  ///
+  /// - the AST has not been resolved (because determining the kind of the
+  ///   literal is done during resolution),
+  /// - the literal is ambiguous (contains one or more spread elements and none
+  ///   of those elements can be used to determine the kind of the literal), or
+  /// - the literal is invalid because it contains both expressions (for sets)
+  ///   and map entries (for maps).
+  ///
+  /// In both of the latter two cases there will be compilation errors
+  /// associated with the literal.
   bool get isMap;
 
   /// Return `true` if this literal represents a set literal.
@@ -4740,8 +4749,17 @@
   /// This getter will always return `false` if [isMap] returns `true`.
   ///
   /// However, this getter is _not_ the inverse of [isMap]. It is possible for
-  /// both getters to return `false` if the literal was either invalid or
-  /// ambiguous.
+  /// both getters to return `false` if
+  ///
+  /// - the AST has not been resolved (because determining the kind of the
+  ///   literal is done during resolution),
+  /// - the literal is ambiguous (contains one or more spread elements and none
+  ///   of those elements can be used to determine the kind of the literal), or
+  /// - the literal is invalid because it contains both expressions (for sets)
+  ///   and map entries (for maps).
+  ///
+  /// In both of the latter two cases there will be compilation errors
+  /// associated with the literal.
   bool get isSet;
 
   /// Return the left curly bracket.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index f4ce6d91..156688d 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// 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.
 
@@ -39,13 +39,13 @@
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/task/api/model.dart' show AnalysisTarget;
-import 'package:analyzer/src/task/dart.dart';
 
 /// An element that represents a class or a mixin. The class can be defined by
 /// either a class declaration (with a class body), a mixin application (without
@@ -727,10 +727,6 @@
   /// subclasses as being immutable.
   bool get isImmutable;
 
-  /// Return `true` if this annotation marks the associated constructor as
-  /// being literal.
-  bool get isLiteral;
-
   /// Return `true` if this annotation marks the associated member as running
   /// a single test.
   bool get isIsTest;
@@ -743,6 +739,10 @@
   /// `JS` annotation.
   bool get isJS;
 
+  /// Return `true` if this annotation marks the associated constructor as
+  /// being literal.
+  bool get isLiteral;
+
   /// Return `true` if this annotation marks the associated member as requiring
   /// overriding methods to call super.
   bool get isMustCallSuper;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 92894f9..a4ba3c5 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -67,6 +67,8 @@
   CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
   CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
   CompileTimeErrorCode.AMBIGUOUS_EXPORT,
+  CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+  CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER,
   CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
   CompileTimeErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
   CompileTimeErrorCode.ARGUMENT_DEFINITION_TEST_NON_PARAMETER,
@@ -110,6 +112,8 @@
   CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
   CompileTimeErrorCode.CONST_NOT_INITIALIZED,
   CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+  CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+  CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
   CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS,
   CompileTimeErrorCode.CONST_WITH_NON_CONST,
   CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT,
@@ -127,6 +131,7 @@
   CompileTimeErrorCode.DUPLICATE_PART,
   CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
   CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
+  CompileTimeErrorCode.EXPRESSION_IN_MAP,
   CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS,
   CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
   CompileTimeErrorCode.EXTENDS_NON_CLASS,
@@ -181,6 +186,7 @@
   CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
   CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
   CompileTimeErrorCode.LABEL_UNDEFINED,
+  CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP,
   CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME,
   CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL,
   CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL,
@@ -226,6 +232,8 @@
   CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR,
   CompileTimeErrorCode.NON_SYNC_FACTORY,
   CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS,
+  CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+  CompileTimeErrorCode.NOT_MAP_SPREAD,
   CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS,
   CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT,
   CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT,
@@ -390,6 +398,7 @@
   ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
   ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
   ParserErrorCode.EXPECTED_CLASS_MEMBER,
+  ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
   ParserErrorCode.EXPECTED_EXECUTABLE,
   ParserErrorCode.EXPECTED_INSTEAD,
   ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index b6fd429..95a75e7 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -3,57 +3,27 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/cancelable_future.dart';
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 import 'package:analyzer/src/context/cache.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/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
-import 'package:analyzer/src/plugin/task.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
 import 'package:analyzer/src/task/driver.dart';
-import 'package:analyzer/src/task/manager.dart';
-
-/**
- * Type of callback functions used by PendingFuture. Functions of this type
- * should perform a computation based on the data in [entry] and return it. If
- * the computation can't be performed yet because more analysis is needed,
- * `null` should be returned.
- *
- * The function may also throw an exception, in which case the corresponding
- * future will be completed with failure.
- *
- * Because this function is called while the state of analysis is being updated,
- * it should be free of side effects so that it doesn't cause reentrant changes
- * to the analysis state.
- */
-typedef T PendingFutureComputer<T>(CacheEntry entry);
 
 /**
  * An [AnalysisContext] in which analysis can be performed.
  */
 class AnalysisContextImpl implements InternalAnalysisContext {
   /**
-   * The flag that is `true` if the context is being analyzed.
-   */
-  bool _isActive = false;
-
-  /**
    * A client-provided name used to identify this context, or `null` if the
    * client has not provided a name.
    */
@@ -66,22 +36,6 @@
   AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
 
   /**
-   * The embedder yaml locator for this context.
-   */
-  @deprecated
-  EmbedderYamlLocator _embedderYamlLocator = new EmbedderYamlLocator(null);
-
-  /**
-   * A flag indicating whether this context is disposed.
-   */
-  bool _disposed = false;
-
-  /**
-   * A cache of content used to override the default content of a source.
-   */
-  ContentCache _contentCache = new ContentCache();
-
-  /**
    * The source factory used to create the sources that can be analyzed in this
    * context.
    */
@@ -92,18 +46,6 @@
    */
   DeclaredVariables _declaredVariables = new DeclaredVariables();
 
-  /**
-   * The partition that contains analysis results that are not shared with other
-   * contexts.
-   */
-  CachePartition _privatePartition;
-
-  /**
-   * The cache in which information about the results associated with targets
-   * are stored.
-   */
-  AnalysisCache _cache;
-
   @override
   final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
       new ReentrantSynchronousStream<InvalidatedResult>();
@@ -111,55 +53,17 @@
   ReentrantSynchronousStreamSubscription onResultInvalidatedSubscription = null;
 
   /**
-   * Configuration data associated with this context.
-   */
-  final HashMap<ResultDescriptor, Object> _configurationData =
-      new HashMap<ResultDescriptor, Object>();
-
-  /**
-   * The task manager used to manage the tasks used to analyze code.
-   */
-  TaskManager _taskManager;
-
-  /**
    * A list of all [WorkManager]s used by this context.
    */
   @override
   final List<WorkManager> workManagers = <WorkManager>[];
 
   /**
-   * The [DartWorkManager] instance that performs Dart specific scheduling.
-   */
-  DartWorkManager dartWorkManager;
-
-  /**
    * The analysis driver used to perform analysis.
    */
   AnalysisDriver driver;
 
   /**
-   * A list containing sources for which data should not be flushed.
-   */
-  List<Source> _priorityOrder = <Source>[];
-
-  CacheConsistencyValidatorImpl _cacheConsistencyValidator;
-
-  /**
-   * A map from all sources for which there are futures pending to a list of
-   * the corresponding PendingFuture objects.  These sources will be analyzed
-   * in the same way as priority sources, except with higher priority.
-   */
-  Map<AnalysisTarget, List<PendingFuture>> _pendingFutureTargets =
-      new HashMap<AnalysisTarget, List<PendingFuture>>();
-
-  /**
-   * A table mapping sources to the change notices that are waiting to be
-   * returned related to that source.
-   */
-  Map<Source, ChangeNoticeImpl> _pendingNotices =
-      new HashMap<Source, ChangeNoticeImpl>();
-
-  /**
    * The [TypeProvider] for this context, `null` if not yet created.
    */
   TypeProvider _typeProvider;
@@ -170,23 +74,6 @@
   TypeSystem _typeSystem;
 
   /**
-   * The controller for sending [SourcesChangedEvent]s.
-   */
-  StreamController<SourcesChangedEvent> _onSourcesChangedController;
-
-  /**
-   * A subscription for a stream of events indicating when files are (and are
-   * not) being implicitly analyzed.
-   */
-  StreamController<ImplicitAnalysisEvent> _implicitAnalysisEventsController;
-
-  /**
-   * The listeners that are to be notified when various analysis results are
-   * produced in this context.
-   */
-  List<AnalysisListener> _listeners = new List<AnalysisListener>();
-
-  /**
    * Determines whether this context should attempt to make use of the global
    * SDK cache partition. Note that if this context is responsible for
    * resynthesizing the SDK element model, this flag should be set to `false`,
@@ -199,13 +86,6 @@
   ResultProvider resultProvider;
 
   /**
-   * The map of [ResultChangedEvent] controllers.
-   */
-  final Map<ResultDescriptor, StreamController<ResultChangedEvent>>
-      _resultChangedControllers =
-      <ResultDescriptor, StreamController<ResultChangedEvent>>{};
-
-  /**
    * The most recently incrementally resolved source, or `null` when it was
    * already validated, or the most recent change was not incrementally resolved.
    */
@@ -230,30 +110,12 @@
   /**
    * Initialize a newly created analysis context.
    */
-  AnalysisContextImpl() {
-    AnalysisEngine.instance.processRequiredPlugins();
-    _privatePartition = new UniversalCachePartition(this);
-    _cache = createCacheFromSourceFactory(null);
-    _taskManager = AnalysisEngine.instance.taskManager;
-    for (WorkManagerFactory factory
-        in AnalysisEngine.instance.enginePlugin.workManagerFactories) {
-      WorkManager workManager = factory(this);
-      if (workManager != null) {
-        workManagers.add(workManager);
-        if (workManager is DartWorkManager) {
-          dartWorkManager = workManager;
-        }
-      }
-    }
-    driver = new AnalysisDriver(_taskManager, workManagers, this);
-    _onSourcesChangedController =
-        new StreamController<SourcesChangedEvent>.broadcast();
-    _implicitAnalysisEventsController =
-        new StreamController<ImplicitAnalysisEvent>.broadcast();
-  }
+  AnalysisContextImpl();
 
   @override
-  AnalysisCache get analysisCache => _cache;
+  AnalysisCache get analysisCache {
+    throw UnimplementedError();
+  }
 
   @override
   AnalysisOptions get analysisOptions => _options;
@@ -261,37 +123,20 @@
   @override
   void set analysisOptions(AnalysisOptions options) {
     this._options = options;
-    for (WorkManager workManager in workManagers) {
-      workManager.onAnalysisOptionsChanged();
-    }
   }
 
   @override
   void set analysisPriorityOrder(List<Source> sources) {
-    if (sources == null || sources.isEmpty) {
-      _priorityOrder = const <Source>[];
-    } else {
-      while (sources.remove(null)) {
-        // Nothing else to do.
-      }
-      if (sources.isEmpty) {
-        _priorityOrder = const <Source>[];
-      } else {
-        _priorityOrder = sources;
-      }
-    }
-    for (WorkManager workManager in workManagers) {
-      workManager.applyPriorityTargets(_priorityOrder);
-    }
-    driver.reset();
+    throw UnimplementedError();
   }
 
-  CacheConsistencyValidator get cacheConsistencyValidator =>
-      _cacheConsistencyValidator ??= new CacheConsistencyValidatorImpl(this);
+  CacheConsistencyValidator get cacheConsistencyValidator {
+    throw UnimplementedError();
+  }
 
   @override
   set contentCache(ContentCache value) {
-    _contentCache = value;
+    throw UnimplementedError();
   }
 
   @override
@@ -306,117 +151,86 @@
 
   @deprecated
   @override
-  EmbedderYamlLocator get embedderYamlLocator => _embedderYamlLocator;
+  EmbedderYamlLocator get embedderYamlLocator {
+    throw UnimplementedError();
+  }
 
   @override
   List<AnalysisTarget> get explicitTargets {
-    List<AnalysisTarget> targets = <AnalysisTarget>[];
-    MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
-    while (iterator.moveNext()) {
-      if (iterator.value.explicitlyAdded) {
-        targets.add(iterator.key);
-      }
-    }
-    return targets;
+    throw UnimplementedError();
   }
 
   @override
-  List<Source> get htmlSources => _getSources(SourceKind.HTML);
+  List<Source> get htmlSources {
+    throw UnimplementedError();
+  }
 
   @override
-  Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents =>
-      _implicitAnalysisEventsController.stream;
+  Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents {
+    throw UnimplementedError();
+  }
 
   @override
-  bool get isActive => _isActive;
+  bool get isActive {
+    throw UnimplementedError();
+  }
 
   @override
   set isActive(bool active) {
-    if (active != _isActive) {
-      _isActive = active;
-      _privatePartition.isActive = active;
-    }
+    throw UnimplementedError();
   }
 
   @override
-  bool get isDisposed => _disposed;
+  bool get isDisposed {
+    throw UnimplementedError();
+  }
 
   @override
   List<Source> get launchableClientLibrarySources {
-    List<Source> sources = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
-          !source.isInSystemLibrary &&
-          isClientLibrary(source)) {
-        sources.add(source);
-      }
-    }
-    return sources;
+    throw UnimplementedError();
   }
 
   @override
   List<Source> get launchableServerLibrarySources {
-    List<Source> sources = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY &&
-          !source.isInSystemLibrary &&
-          isServerLibrary(source)) {
-        sources.add(source);
-      }
-    }
-    return sources;
+    throw UnimplementedError();
   }
 
   @override
-  List<Source> get librarySources => _getSources(SourceKind.LIBRARY);
+  List<Source> get librarySources {
+    throw UnimplementedError();
+  }
 
   @override
-  Stream<SourcesChangedEvent> get onSourcesChanged =>
-      _onSourcesChangedController.stream;
-
-  /**
-   * Make _pendingFutureSources available to unit tests.
-   */
-  Map<AnalysisTarget, List<PendingFuture>>
-      get pendingFutureSources_forTesting => _pendingFutureTargets;
+  Stream<SourcesChangedEvent> get onSourcesChanged {
+    throw UnimplementedError();
+  }
 
   @override
-  List<Source> get prioritySources => _priorityOrder;
+  List<Source> get prioritySources {
+    throw UnimplementedError();
+  }
 
   @override
-  List<AnalysisTarget> get priorityTargets => prioritySources;
+  List<AnalysisTarget> get priorityTargets {
+    throw UnimplementedError();
+  }
 
   @override
-  CachePartition get privateAnalysisCachePartition => _privatePartition;
+  CachePartition get privateAnalysisCachePartition {
+    throw UnimplementedError();
+  }
 
   @override
   SourceFactory get sourceFactory => _sourceFactory;
 
   @override
   void set sourceFactory(SourceFactory factory) {
-    if (identical(_sourceFactory, factory)) {
-      return;
-    } else if (factory.context != null) {
-      throw new StateError(
-          "Source factories cannot be shared between contexts");
-    }
-    if (_sourceFactory != null) {
-      _sourceFactory.context = null;
-    }
-    factory.context = this;
     _sourceFactory = factory;
-    _cache?.dispose();
-    _cache = createCacheFromSourceFactory(factory);
-    for (WorkManager workManager in workManagers) {
-      workManager.onSourceFactoryChanged();
-    }
   }
 
   @override
   List<Source> get sources {
-    return _cache.sources.toList();
+    throw UnimplementedError();
   }
 
   /**
@@ -426,57 +240,15 @@
    * testing purposes only.
    */
   List<Source> get sourcesNeedingProcessing {
-    HashSet<Source> sources = new HashSet<Source>();
-    bool hintsEnabled = _options.hint;
-    bool lintsEnabled = _options.lint;
-
-    MapIterator<AnalysisTarget, CacheEntry> iterator =
-        _privatePartition.iterator();
-    while (iterator.moveNext()) {
-      AnalysisTarget target = iterator.key;
-      if (target is Source) {
-        _getSourcesNeedingProcessing(
-            target, iterator.value, false, hintsEnabled, lintsEnabled, sources);
-      }
-    }
-    return new List<Source>.from(sources);
+    throw UnimplementedError();
   }
 
-  List<Source> get test_priorityOrder => _priorityOrder;
+  List<Source> get test_priorityOrder {
+    throw UnimplementedError();
+  }
 
   @override
   TypeProvider get typeProvider {
-    // The `AnalysisContextTarget.request` results go into the SDK partition,
-    // and the TYPE_PROVIDER result is computed and put into the SDK partition
-    // only by the first non-SDK analysis context. So, in order to reuse it
-    // in other analysis contexts, we need to ask for it from the cache.
-    _typeProvider ??= getResult(AnalysisContextTarget.request, TYPE_PROVIDER);
-    if (_typeProvider != null) {
-      return _typeProvider;
-    }
-
-    // Make sure a task didn't accidentally try to call back into the context
-    // to retrieve the type provider.
-    assert(!driver.isTaskRunning);
-
-    Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
-    if (coreSource == null) {
-      throw new AnalysisException("Could not create a source for dart:core");
-    }
-    LibraryElement coreElement = computeLibraryElement(coreSource);
-    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");
-    }
-    _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
     return _typeProvider;
   }
 
@@ -490,411 +262,175 @@
 
   @override
   TypeSystem get typeSystem {
-    if (_typeSystem == null) {
-      _typeSystem = TypeSystem.create(this);
-    }
-    return _typeSystem;
+    return _typeSystem ??= Dart2TypeSystem(typeProvider);
   }
 
   @override
   bool aboutToComputeResult(CacheEntry entry, ResultDescriptor result) {
-    return PerformanceStatistics.summary.makeCurrentWhile(() {
-      // 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);
-        }
-      }
-      // Cannot provide the result.
-      return false;
-    });
+    throw UnimplementedError();
   }
 
   @override
   void addListener(AnalysisListener listener) {
-    if (!_listeners.contains(listener)) {
-      _listeners.add(listener);
-    }
+    throw UnimplementedError();
   }
 
   @override
   void applyAnalysisDelta(AnalysisDelta delta) {
-    ChangeSet changeSet = new ChangeSet();
-    delta.analysisLevels.forEach((Source source, AnalysisLevel level) {
-      if (level == AnalysisLevel.NONE) {
-        changeSet.removedSource(source);
-      } else {
-        changeSet.addedSource(source);
-      }
-    });
-    applyChanges(changeSet);
+    throw UnimplementedError();
   }
 
   @override
   void applyChanges(ChangeSet changeSet) {
-    if (changeSet.isEmpty) {
-      return;
-    }
-    //
-    // First, compute the list of sources that have been removed.
-    //
-    List<Source> removedSources = changeSet.removedSources.toList();
-    for (SourceContainer container in changeSet.removedContainers) {
-      _addSourcesInContainer(removedSources, container);
-    }
-    //
-    // Then determine which cached results are no longer valid.
-    //
-    for (Source source in changeSet.addedSources) {
-      _sourceAvailable(source);
-    }
-    // Exclude sources that are overridden in the content cache, so the change
-    // will have no effect. Just ignore it to avoid wasting time doing
-    // re-analysis.
-    List<Source> changedSources = changeSet.changedSources
-        .where((s) => _contentCache.getContents(s) == null)
-        .toList();
-    for (Source source in changedSources) {
-      _sourceChanged(source);
-    }
-    changeSet.changedContents.forEach((Source key, String value) {
-      _contentsChanged(key, value, false);
-    });
-    changeSet.changedRanges
-        .forEach((Source source, ChangeSet_ContentChange change) {
-      _contentRangeChanged(source, change.contents, change.offset,
-          change.oldLength, change.newLength);
-    });
-    for (Source source in removedSources) {
-      _sourceRemoved(source);
-    }
-    for (WorkManager workManager in workManagers) {
-      workManager.applyChange(
-          changeSet.addedSources, changedSources, removedSources);
-    }
-    _onSourcesChangedController.add(new SourcesChangedEvent(changeSet));
+    throw UnimplementedError();
   }
 
   @override
-  String computeDocumentationComment(Element element) =>
-      element?.documentationComment;
+  String computeDocumentationComment(Element element) {
+    throw UnimplementedError();
+  }
 
   @override
   List<AnalysisError> computeErrors(Source source) {
-    return computeResult(source, DART_ERRORS);
+    throw UnimplementedError();
   }
 
   @override
-  List<Source> computeExportedLibraries(Source source) =>
-      computeResult(source, EXPORTED_LIBRARIES);
+  List<Source> computeExportedLibraries(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
-  List<Source> computeImportedLibraries(Source source) =>
-      computeResult(source, EXPLICITLY_IMPORTED_LIBRARIES);
+  List<Source> computeImportedLibraries(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   SourceKind computeKindOf(Source source) {
-    String name = source.shortName;
-    if (AnalysisEngine.isDartFileName(name)) {
-      return computeResult(source, SOURCE_KIND);
-    }
-    return SourceKind.UNKNOWN;
+    throw UnimplementedError();
   }
 
   @override
   LibraryElement computeLibraryElement(Source source) {
-    //_computeResult(source, HtmlEntry.ELEMENT);
-    return computeResult(source, LIBRARY_ELEMENT);
+    throw UnimplementedError();
   }
 
   @override
-  LineInfo computeLineInfo(Source source) => computeResult(source, LINE_INFO);
+  LineInfo computeLineInfo(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
       Source unitSource, Source librarySource) {
-    if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
-        !AnalysisEngine.isDartFileName(librarySource.shortName)) {
-      return new CancelableFuture.error(new AnalysisNotScheduledError());
-    }
-    return new AnalysisFutureHelper<CompilationUnit>(this,
-            new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT)
-        .computeAsync();
+    throw UnimplementedError();
   }
 
   @override
   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);
-    CacheEntry entry = getCacheEntry(target);
-    CacheState state = entry.getState(descriptor);
-    if (state == CacheState.FLUSHED || state == CacheState.INVALID) {
-      // Check the result provider.
-      bool success = aboutToComputeResult(entry, descriptor);
-      if (success) {
-        return entry.getValue(descriptor);
-      }
-      // Compute the result.
-      driver.computeResult(target, descriptor);
-      entry = getCacheEntry(target);
-    }
-    state = entry.getState(descriptor);
-    if (state == CacheState.ERROR) {
-      throw new AnalysisException(
-          'Cannot compute $descriptor for $target', entry.exception);
-    }
-    return entry.getValue(descriptor);
+    throw UnimplementedError();
   }
 
   /**
    * Create an analysis cache based on the given source [factory].
    */
   AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    AnalysisCache createCache() {
-      if (factory == null) {
-        return new AnalysisCache(<CachePartition>[_privatePartition]);
-      }
-      if (!useSdkCachePartition) {
-        return new AnalysisCache(<CachePartition>[_privatePartition]);
-      }
-      DartSdk sdk = factory.dartSdk;
-      if (sdk == null) {
-        return new AnalysisCache(<CachePartition>[_privatePartition]);
-      }
-      return new AnalysisCache(<CachePartition>[
-        AnalysisEngine.instance.partitionManager.forSdk(sdk),
-        _privatePartition
-      ]);
-    }
-
-    AnalysisCache cache = createCache();
-    onResultInvalidatedSubscription?.cancel();
-    onResultInvalidatedSubscription =
-        cache.onResultInvalidated.listen((InvalidatedResult event) {
-      onResultInvalidated.add(event);
-      StreamController<ResultChangedEvent> controller =
-          _resultChangedControllers[event.descriptor];
-      if (controller != null) {
-        controller.add(new ResultChangedEvent(
-            this, event.entry.target, event.descriptor, event.value, false));
-      }
-    });
-    return cache;
+    throw UnimplementedError();
   }
 
   @override
-  void dispose() {
-    _disposed = true;
-    for (List<PendingFuture> pendingFutures in _pendingFutureTargets.values) {
-      for (PendingFuture pendingFuture in pendingFutures) {
-        pendingFuture.forciblyComplete();
-      }
-    }
-    _pendingFutureTargets.clear();
-    _privatePartition.dispose();
-    _cache.dispose();
-  }
+  void dispose() {}
 
   @override
   List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) {
-    // Check every library.
-    List<CompilationUnit> units = <CompilationUnit>[];
-    List<Source> containingLibraries = getLibrariesContaining(unitSource);
-    for (Source librarySource in containingLibraries) {
-      LibrarySpecificUnit target =
-          new LibrarySpecificUnit(librarySource, unitSource);
-      CompilationUnit unit = getResult(target, RESOLVED_UNIT);
-      if (unit == null) {
-        units = null;
-        break;
-      }
-      units.add(unit);
-    }
-    // If we have results, then we're done.
-    if (units != null) {
-      return units;
-    }
-    // Schedule computing of RESOLVED_UNIT results.
-    for (Source librarySource in containingLibraries) {
-      LibrarySpecificUnit target =
-          new LibrarySpecificUnit(librarySource, unitSource);
-      dartWorkManager.addPriorityResult(target, RESOLVED_UNIT);
-    }
-    return null;
+    throw UnimplementedError();
   }
 
   @override
   bool exists(Source source) {
-    if (source == null) {
-      return false;
-    }
-    bool overriddenExists = _contentCache.getExists(source);
-    if (overriddenExists != null) {
-      return overriddenExists;
-    }
-    return source.exists();
+    throw UnimplementedError();
   }
 
   @override
   CacheEntry getCacheEntry(AnalysisTarget target) {
-    CacheEntry entry = _cache.get(target);
-    if (entry == null) {
-      entry = new CacheEntry(target);
-      ImplicitAnalysisEvent event = null;
-      if (target is Source) {
-        entry.modificationTime = getModificationStamp(target);
-        event = new ImplicitAnalysisEvent(target, true);
-      }
-      _cache.put(entry);
-      if (event != null) {
-        _implicitAnalysisEventsController.add(event);
-      }
-    }
-    return entry;
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnitElement getCompilationUnitElement(
       Source unitSource, Source librarySource) {
-    AnalysisTarget target = new LibrarySpecificUnit(librarySource, unitSource);
-    return getResult(target, COMPILATION_UNIT_ELEMENT);
+    throw UnimplementedError();
   }
 
   @deprecated
   @override
-  V getConfigurationData<V>(ResultDescriptor<V> key) =>
-      (_configurationData[key] ?? key?.defaultValue) as V;
-
-  @override
-  TimestampedData<String> getContents(Source source) {
-    String contents = _contentCache.getContents(source);
-    if (contents != null) {
-      return new TimestampedData<String>(
-          _contentCache.getModificationStamp(source), contents);
-    }
-    return source.contents;
+  V getConfigurationData<V>(ResultDescriptor<V> key) {
+    throw UnimplementedError();
   }
 
   @override
-  InternalAnalysisContext getContextFor(Source source) =>
-      _cache.getContextFor(source) ?? this;
+  TimestampedData<String> getContents(Source source) {
+    throw UnimplementedError();
+  }
+
+  @override
+  InternalAnalysisContext getContextFor(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   Element getElement(ElementLocation location) {
-    // TODO(brianwilkerson) This should not be a "get" method.
-    try {
-      List<String> components = location.components;
-      Source source = _computeSourceFromEncoding(components[0]);
-      String sourceName = source.shortName;
-      if (AnalysisEngine.isDartFileName(sourceName)) {
-        ElementImpl element = computeLibraryElement(source) as ElementImpl;
-        for (int i = 1; i < components.length; i++) {
-          if (element == null) {
-            return null;
-          }
-          element = element.getChild(components[i]);
-        }
-        return element;
-      }
-    } catch (exception) {
-      // If the location cannot be decoded for some reason then the underlying
-      // cause should have been logged already and we can fall though to return
-      // null.
-    }
-    return null;
+    throw UnimplementedError();
   }
 
   @override
   AnalysisErrorInfo getErrors(Source source) {
-    List<AnalysisError> allErrors = <AnalysisError>[];
-    for (WorkManager workManager in workManagers) {
-      List<AnalysisError> errors = workManager.getErrors(source);
-      allErrors.addAll(errors);
-    }
-    LineInfo lineInfo = getLineInfo(source);
-    return new AnalysisErrorInfoImpl(allErrors, lineInfo);
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getHtmlFilesReferencing(Source source) {
-    return const <Source>[];
+    throw UnimplementedError();
   }
 
   @override
   SourceKind getKindOf(Source source) {
-    String name = source.shortName;
-    if (AnalysisEngine.isDartFileName(name)) {
-      return getResult(source, SOURCE_KIND);
-    }
-    return SourceKind.UNKNOWN;
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getLibrariesContaining(Source source) {
-    SourceKind kind = getKindOf(source);
-    if (kind == SourceKind.LIBRARY) {
-      return <Source>[source];
-    }
-    return dartWorkManager.getLibrariesContainingPart(source);
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getLibrariesDependingOn(Source librarySource) {
-    List<Source> dependentLibraries = <Source>[];
-    for (Source source in _cache.sources) {
-      CacheEntry entry = _cache.get(source);
-      if (entry.getValue(SOURCE_KIND) == SourceKind.LIBRARY) {
-        if (_contains(entry.getValue(EXPORTED_LIBRARIES), librarySource)) {
-          dependentLibraries.add(source);
-        }
-        if (_contains(entry.getValue(IMPORTED_LIBRARIES), librarySource)) {
-          dependentLibraries.add(source);
-        }
-      }
-    }
-    if (dependentLibraries.isEmpty) {
-      return const <Source>[];
-    }
-    return dependentLibraries;
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
-    return const <Source>[];
+    throw UnimplementedError();
   }
 
   @override
-  LibraryElement getLibraryElement(Source source) =>
-      getResult(source, LIBRARY_ELEMENT);
+  LibraryElement getLibraryElement(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
-  LineInfo getLineInfo(Source source) => getResult(source, LINE_INFO);
+  LineInfo getLineInfo(Source source) {
+    throw UnimplementedError();
+  }
 
   @override
   int getModificationStamp(Source source) {
-    int stamp = _contentCache.getModificationStamp(source);
-    if (stamp != null) {
-      return stamp;
-    }
-    return source.modificationStamp;
+    throw UnimplementedError();
   }
 
   @override
   ChangeNoticeImpl getNotice(Source source) {
-    ChangeNoticeImpl notice = _pendingNotices[source];
-    if (notice == null) {
-      notice = new ChangeNoticeImpl(source);
-      _pendingNotices[source] = notice;
-    }
-    return notice;
+    throw UnimplementedError();
   }
 
   @override
@@ -913,87 +449,29 @@
   @override
   CompilationUnit getResolvedCompilationUnit(
       Source unitSource, LibraryElement library) {
-    if (library == null ||
-        !AnalysisEngine.isDartFileName(unitSource.shortName)) {
-      return null;
-    }
-    return getResolvedCompilationUnit2(unitSource, library.source);
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit getResolvedCompilationUnit2(
       Source unitSource, Source librarySource) {
-    if (!AnalysisEngine.isDartFileName(unitSource.shortName) ||
-        !AnalysisEngine.isDartFileName(librarySource.shortName)) {
-      return null;
-    }
-    return getResult(
-        new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
+    throw UnimplementedError();
   }
 
   @override
   V getResult<V>(AnalysisTarget target, ResultDescriptor<V> result) {
-    return _cache.getValue(target, result);
+    throw UnimplementedError();
   }
 
   @override
   List<Source> getSourcesWithFullName(String path) {
-    return analysisCache.getSourcesWithFullName(path);
+    throw UnimplementedError();
   }
 
   @override
   bool handleContentsChanged(
       Source source, String originalContents, String newContents, bool notify) {
-    CacheEntry entry = _cache.get(source);
-    if (entry == null) {
-      return false;
-    }
-    // If there were no "originalContents" in the content cache,
-    // use the contents of the file instead.
-    if (originalContents == null) {
-      try {
-        TimestampedData<String> fileContents = source.contents;
-        if (fileContents.modificationTime == entry.modificationTime) {
-          originalContents = fileContents.data;
-        }
-      } catch (e) {}
-    }
-    bool changed = newContents != originalContents;
-    if (newContents != null) {
-      if (changed) {
-        entry.modificationTime = _contentCache.getModificationStamp(source);
-        // Don't compare with old contents because the cache has already been
-        // updated, and we know at this point that it changed.
-        _sourceChanged(source, compareWithOld: false);
-        entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
-      } else {
-        entry.modificationTime = _contentCache.getModificationStamp(source);
-      }
-    } else if (originalContents != null) {
-      // We are removing the overlay for the file, check if the file's
-      // contents is the same as it was in the overlay.
-      try {
-        TimestampedData<String> fileContents = getContents(source);
-        newContents = fileContents.data;
-        entry.modificationTime = fileContents.modificationTime;
-        if (newContents == originalContents) {
-          entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
-          changed = false;
-        }
-      } catch (e) {}
-      // If not the same content (e.g. the file is being closed without save),
-      // then force analysis.
-      if (changed) {
-        if (newContents == null) {
-          _sourceChanged(source);
-        }
-      }
-    }
-    if (notify && changed) {
-      _onSourcesChangedController
-          .add(new SourcesChangedEvent.changedContent(source, newContents));
-    }
-    return changed;
+    throw UnimplementedError();
   }
 
   /**
@@ -1001,797 +479,97 @@
    * to do.
    */
   void invalidateCachedResults() {
-    _cache?.dispose();
-    _cache = createCacheFromSourceFactory(_sourceFactory);
-    for (WorkManager workManager in workManagers) {
-      workManager.onAnalysisOptionsChanged();
-    }
+    throw UnimplementedError();
   }
 
   @override
   void invalidateLibraryHints(Source librarySource) {
-    List<Source> sources = getResult(librarySource, UNITS);
-    if (sources != null) {
-      for (Source source in sources) {
-        getCacheEntry(source).setState(HINTS, CacheState.INVALID);
-      }
-    }
+    throw UnimplementedError();
   }
 
   @override
   bool isClientLibrary(Source librarySource) {
-    CacheEntry entry = _cache.get(librarySource);
-    return entry != null &&
-        _referencesDartHtml(librarySource) &&
-        entry.getValue(IS_LAUNCHABLE);
+    throw UnimplementedError();
   }
 
   @override
   bool isServerLibrary(Source librarySource) {
-    CacheEntry entry = _cache.get(librarySource);
-    return entry != null &&
-        !_referencesDartHtml(librarySource) &&
-        entry.getValue(IS_LAUNCHABLE);
+    throw UnimplementedError();
   }
 
   @override
   Stream<ResultChangedEvent> onResultChanged(ResultDescriptor descriptor) {
-    driver.onResultComputed(descriptor).listen((ResultChangedEvent event) {
-      _resultChangedControllers[descriptor]?.add(event);
-    });
-    return _resultChangedControllers.putIfAbsent(descriptor, () {
-      return new StreamController<ResultChangedEvent>.broadcast(sync: true);
-    }).stream;
+    throw UnimplementedError();
   }
 
   @override
   @deprecated
   Stream<ComputedResult> onResultComputed(ResultDescriptor descriptor) {
-    return onResultChanged(descriptor)
-        .where((event) => event.wasComputed)
-        .map((event) {
-      return new ComputedResult(
-          event.context, event.descriptor, event.target, event.value);
-    });
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit parseCompilationUnit(Source source) {
-    if (!AnalysisEngine.isDartFileName(source.shortName)) {
-      return null;
-    }
-    try {
-      getContents(source);
-    } catch (exception, stackTrace) {
-      throw new AnalysisException('Could not get contents of $source',
-          new CaughtException(exception, stackTrace));
-    }
-    return computeResult(source, PARSED_UNIT);
+    throw UnimplementedError();
   }
 
   @override
   AnalysisResult performAnalysisTask() {
-    return PerformanceStatistics.analysis.makeCurrentWhile(() {
-      _evaluatePendingFutures();
-      bool done = !driver.performAnalysisTask();
-      List<ChangeNotice> notices = _getChangeNotices(done);
-      if (notices != null) {
-        int noticeCount = notices.length;
-        for (int i = 0; i < noticeCount; i++) {
-          ChangeNotice notice = notices[i];
-          _notifyErrors(notice.source, notice.errors, notice.lineInfo);
-        }
-      }
-      return new AnalysisResult(notices, -1, '', -1);
-    });
+    throw UnimplementedError();
   }
 
   @override
   void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
-    elementMap.forEach((Source librarySource, LibraryElement library) {
-      //
-      // Cache the element in the library's info.
-      //
-      CacheEntry entry = getCacheEntry(librarySource);
-      setValue(ResultDescriptor result, value) {
-        entry.setValue(result, value, const <TargetedResult>[]);
-      }
-
-      setValue(BUILD_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(BUILD_LIBRARY_ERRORS, AnalysisError.NO_ERRORS);
-      // CLASS_ELEMENTS
-      setValue(COMPILATION_UNIT_ELEMENT, library.definingCompilationUnit);
-      // CONSTRUCTORS
-      // CONSTRUCTORS_ERRORS
-      entry.setState(CONTENT, CacheState.FLUSHED);
-      setValue(EXPORTED_LIBRARIES, const <Source>[]);
-      // EXPORT_SOURCE_CLOSURE
-      setValue(IMPORTED_LIBRARIES, const <Source>[]);
-      // IMPORT_SOURCE_CLOSURE
-      setValue(INCLUDED_PARTS, const <Source>[]);
-      setValue(IS_LAUNCHABLE, false);
-      setValue(LIBRARY_ELEMENT, library);
-      setValue(LIBRARY_ELEMENT1, library);
-      setValue(LIBRARY_ELEMENT2, library);
-      setValue(LIBRARY_ELEMENT3, library);
-      setValue(LIBRARY_ELEMENT4, library);
-      setValue(LIBRARY_ELEMENT5, library);
-      setValue(LIBRARY_ELEMENT6, library);
-      setValue(LIBRARY_ELEMENT7, library);
-      setValue(LIBRARY_ELEMENT8, library);
-      setValue(LIBRARY_ELEMENT9, library);
-      setValue(LINE_INFO, new LineInfo(<int>[0]));
-      setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS);
-      entry.setState(PARSED_UNIT, CacheState.FLUSHED);
-      entry.setState(RESOLVE_TYPE_NAMES_ERRORS, CacheState.FLUSHED);
-      entry.setState(RESOLVE_TYPE_BOUNDS_ERRORS, CacheState.FLUSHED);
-      setValue(SCAN_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(SOURCE_KIND, SourceKind.LIBRARY);
-      entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
-      setValue(UNITS, <Source>[librarySource]);
-
-      LibrarySpecificUnit unit =
-          new LibrarySpecificUnit(librarySource, librarySource);
-      entry = getCacheEntry(unit);
-      setValue(HINTS, AnalysisError.NO_ERRORS);
-      setValue(LINTS, AnalysisError.NO_ERRORS);
-      setValue(LIBRARY_UNIT_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(RESOLVE_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(RESOLVE_TYPE_NAMES_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(RESOLVE_UNIT_ERRORS, AnalysisError.NO_ERRORS);
-      entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
-      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_UNIT12, CacheState.FLUSHED);
-      // USED_IMPORTED_ELEMENTS
-      // USED_LOCAL_ELEMENTS
-      setValue(STRONG_MODE_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(VARIABLE_REFERENCE_ERRORS, AnalysisError.NO_ERRORS);
-      setValue(VERIFY_ERRORS, AnalysisError.NO_ERRORS);
-    });
-
-    CacheEntry entry = getCacheEntry(AnalysisContextTarget.request);
-    entry.setValue(TYPE_PROVIDER, typeProvider, const <TargetedResult>[]);
+    throw UnimplementedError();
   }
 
   @override
   void removeListener(AnalysisListener listener) {
-    _listeners.remove(listener);
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit resolveCompilationUnit(
       Source unitSource, LibraryElement library) {
-    if (library == null) {
-      return null;
-    }
-    return resolveCompilationUnit2(unitSource, library.source);
+    throw UnimplementedError();
   }
 
   @override
   CompilationUnit resolveCompilationUnit2(
       Source unitSource, Source librarySource) {
-    return computeResult(
-        new LibrarySpecificUnit(librarySource, unitSource), RESOLVED_UNIT);
+    throw UnimplementedError();
   }
 
   @override
   void setChangedContents(Source source, String contents, int offset,
       int oldLength, int newLength) {
-    if (_contentRangeChanged(source, contents, offset, oldLength, newLength)) {
-      _onSourcesChangedController.add(new SourcesChangedEvent.changedRange(
-          source, contents, offset, oldLength, newLength));
-    }
+    throw UnimplementedError();
   }
 
   @deprecated
   @override
   void setConfigurationData(ResultDescriptor key, Object data) {
-    _configurationData[key] = data;
+    throw UnimplementedError();
   }
 
   @override
   void setContents(Source source, String contents) {
-    _contentsChanged(source, contents, true);
+    throw UnimplementedError();
   }
 
   @override
   bool shouldErrorsBeAnalyzed(Source source) {
-    CacheEntry entry = analysisCache.get(source);
-    if (source.isInSystemLibrary) {
-      return _options.generateSdkErrors;
-    } else if (!entry.explicitlyAdded) {
-      return _options.generateImplicitErrors;
-    } else {
-      return true;
-    }
+    throw UnimplementedError();
   }
 
   @override
   void test_flushAstStructures(Source source) {
-    CacheEntry entry = getCacheEntry(source);
-    entry.setState(PARSED_UNIT, CacheState.FLUSHED);
-    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_UNIT12, CacheState.FLUSHED);
-    entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
+    throw UnimplementedError();
   }
 
   @override
   void visitContentCache(ContentCacheVisitor visitor) {
-    _contentCache.accept(visitor);
-  }
-
-  /**
-   * Add all of the sources contained in the given source [container] to the
-   * given list of [sources].
-   */
-  void _addSourcesInContainer(List<Source> sources, SourceContainer container) {
-    for (Source source in _cache.sources) {
-      if (container.contains(source)) {
-        sources.add(source);
-      }
-    }
-  }
-
-  /**
-   * Remove the given [pendingFuture] from [_pendingFutureTargets], since the
-   * client has indicated its computation is not needed anymore.
-   */
-  void _cancelFuture(PendingFuture pendingFuture) {
-    List<PendingFuture> pendingFutures =
-        _pendingFutureTargets[pendingFuture.target];
-    if (pendingFutures != null) {
-      pendingFutures.remove(pendingFuture);
-      if (pendingFutures.isEmpty) {
-        _pendingFutureTargets.remove(pendingFuture.target);
-      }
-    }
-  }
-
-  /**
-   * Given the encoded form of a source ([encoding]), use the source factory to
-   * reconstitute the original source.
-   */
-  Source _computeSourceFromEncoding(String encoding) =>
-      _sourceFactory.fromEncoding(encoding);
-
-  /**
-   * Return `true` if the given list of [sources] contains the given
-   * [targetSource].
-   */
-  bool _contains(List<Source> sources, Source targetSource) {
-    for (Source source in sources) {
-      if (source == targetSource) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Set the contents of the given [source] to the given [contents] and mark the
-   * source as having changed. The additional [offset], [oldLength] and
-   * [newLength] information is used by the context to determine what reanalysis
-   * is necessary. The method [setChangedContents] triggers a source changed
-   * event where as this method does not.
-   */
-  bool _contentRangeChanged(Source source, String contents, int offset,
-      int oldLength, int newLength) {
-    bool changed = false;
-    String originalContents = _contentCache.setContents(source, contents);
-    if (contents != null) {
-      if (contents != originalContents) {
-        _sourceChanged(source);
-        changed = true;
-        CacheEntry entry = _cache.get(source);
-        if (entry != null) {
-          entry.modificationTime = _contentCache.getModificationStamp(source);
-          entry.setValue(CONTENT, contents, const <TargetedResult>[]);
-        }
-      }
-    } else if (originalContents != null) {
-      _sourceChanged(source);
-      changed = true;
-    }
-    return changed;
-  }
-
-  /**
-   * Set the contents of the given [source] to the given [contents] and mark the
-   * source as having changed. This has the effect of overriding the default
-   * contents of the source. If the contents are `null` the override is removed
-   * so that the default contents will be returned. If [notify] is true, a
-   * source changed event is triggered.
-   */
-  void _contentsChanged(Source source, String contents, bool notify) {
-    String originalContents = _contentCache.setContents(source, contents);
-    handleContentsChanged(source, originalContents, contents, notify);
-  }
-
-  /**
-   * Create a cache entry for the given [source]. The source was explicitly
-   * added to this context if [explicitlyAdded] is `true`. Return the cache
-   * entry that was created.
-   */
-  CacheEntry _createCacheEntry(Source source, bool explicitlyAdded) {
-    CacheEntry entry = new CacheEntry(source);
-    entry.modificationTime = getModificationStamp(source);
-    entry.explicitlyAdded = explicitlyAdded;
-    _cache.put(entry);
-    if (!explicitlyAdded) {
-      _implicitAnalysisEventsController
-          .add(new ImplicitAnalysisEvent(source, true));
-    }
-    return entry;
-  }
-
-  /**
-   * Return a list containing all of the cache entries for targets associated
-   * with the given [source].
-   */
-  List<CacheEntry> _entriesFor(Source source) {
-    List<CacheEntry> entries = <CacheEntry>[];
-    MapIterator<AnalysisTarget, CacheEntry> iterator = _cache.iterator();
-    while (iterator.moveNext()) {
-      if (iterator.key.source == source) {
-        entries.add(iterator.value);
-      }
-    }
-    return entries;
-  }
-
-  void _evaluatePendingFutures() {
-    for (AnalysisTarget target in _pendingFutureTargets.keys) {
-      CacheEntry cacheEntry = _cache.get(target);
-      List<PendingFuture> pendingFutures = _pendingFutureTargets[target];
-      for (int i = 0; i < pendingFutures.length;) {
-        if (cacheEntry == null) {
-          pendingFutures[i].forciblyComplete();
-          pendingFutures.removeAt(i);
-        } else if (pendingFutures[i].evaluate(cacheEntry)) {
-          pendingFutures.removeAt(i);
-        } else {
-          i++;
-        }
-      }
-    }
-  }
-
-  /**
-   * Return a list containing all of the change notices that are waiting to be
-   * returned. If there are no notices, then return either `null` or an empty
-   * list, depending on the value of [nullIfEmpty].
-   */
-  List<ChangeNotice> _getChangeNotices(bool nullIfEmpty) {
-    if (_pendingNotices.isEmpty) {
-      if (nullIfEmpty) {
-        return null;
-      }
-      return const <ChangeNoticeImpl>[];
-    }
-    List<ChangeNotice> notices = new List.from(_pendingNotices.values);
-    _pendingNotices.clear();
-    return notices;
-  }
-
-  /**
-   * Return a list containing all of the sources known to this context that have
-   * the given [kind].
-   */
-  List<Source> _getSources(SourceKind kind) {
-    List<Source> sources = <Source>[];
-    if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
-      for (Source source in _cache.sources) {
-        CacheEntry entry = _cache.get(source);
-        if (entry.getValue(SOURCE_KIND) == kind) {
-          sources.add(source);
-        }
-      }
-    }
-    if (sources.isEmpty) {
-      return const <Source>[];
-    }
-    return sources;
-  }
-
-  /**
-   * Look at the given [source] to see whether a task needs to be performed
-   * related to it. If so, add the source to the set of sources that need to be
-   * processed. This method is intended to be used for testing purposes only.
-   */
-  void _getSourcesNeedingProcessing(
-      Source source,
-      CacheEntry entry,
-      bool isPriority,
-      bool hintsEnabled,
-      bool lintsEnabled,
-      HashSet<Source> sources) {
-    CacheState state = entry.getState(CONTENT);
-    if (state == CacheState.INVALID ||
-        (isPriority && state == CacheState.FLUSHED)) {
-      sources.add(source);
-      return;
-    } else if (state == CacheState.ERROR) {
-      return;
-    }
-    state = entry.getState(SOURCE_KIND);
-    if (state == CacheState.INVALID ||
-        (isPriority && state == CacheState.FLUSHED)) {
-      sources.add(source);
-      return;
-    } else if (state == CacheState.ERROR) {
-      return;
-    }
-    SourceKind kind = entry.getValue(SOURCE_KIND);
-    if (kind == SourceKind.LIBRARY || kind == SourceKind.PART) {
-      state = entry.getState(SCAN_ERRORS);
-      if (state == CacheState.INVALID ||
-          (isPriority && state == CacheState.FLUSHED)) {
-        sources.add(source);
-        return;
-      } else if (state == CacheState.ERROR) {
-        return;
-      }
-      state = entry.getState(PARSE_ERRORS);
-      if (state == CacheState.INVALID ||
-          (isPriority && state == CacheState.FLUSHED)) {
-        sources.add(source);
-        return;
-      } else if (state == CacheState.ERROR) {
-        return;
-      }
-//      if (isPriority) {
-//        if (!entry.hasResolvableCompilationUnit) {
-//          sources.add(source);
-//          return;
-//        }
-//      }
-      for (Source librarySource in getLibrariesContaining(source)) {
-        CacheEntry libraryEntry = _cache.get(librarySource);
-        state = libraryEntry.getState(LIBRARY_ELEMENT);
-        if (state == CacheState.INVALID ||
-            (isPriority && state == CacheState.FLUSHED)) {
-          sources.add(source);
-          return;
-        } else if (state == CacheState.ERROR) {
-          return;
-        }
-        CacheEntry unitEntry =
-            _cache.get(new LibrarySpecificUnit(librarySource, source));
-        state = unitEntry.getState(RESOLVED_UNIT);
-        if (state == CacheState.INVALID ||
-            (isPriority && state == CacheState.FLUSHED)) {
-          sources.add(source);
-          return;
-        } else if (state == CacheState.ERROR) {
-          return;
-        }
-        if (shouldErrorsBeAnalyzed(source)) {
-          state = unitEntry.getState(VERIFY_ERRORS);
-          if (state == CacheState.INVALID ||
-              (isPriority && state == CacheState.FLUSHED)) {
-            sources.add(source);
-            return;
-          } else if (state == CacheState.ERROR) {
-            return;
-          }
-          if (hintsEnabled) {
-            state = unitEntry.getState(HINTS);
-            if (state == CacheState.INVALID ||
-                (isPriority && state == CacheState.FLUSHED)) {
-              sources.add(source);
-              return;
-            } else if (state == CacheState.ERROR) {
-              return;
-            }
-          }
-          if (lintsEnabled) {
-            state = unitEntry.getState(LINTS);
-            if (state == CacheState.INVALID ||
-                (isPriority && state == CacheState.FLUSHED)) {
-              sources.add(source);
-              return;
-            } else if (state == CacheState.ERROR) {
-              return;
-            }
-          }
-        }
-      }
-//    } else if (kind == SourceKind.HTML) {
-//      CacheState parsedUnitState = entry.getState(HtmlEntry.PARSED_UNIT);
-//      if (parsedUnitState == CacheState.INVALID ||
-//          (isPriority && parsedUnitState == CacheState.FLUSHED)) {
-//        sources.add(source);
-//        return;
-//      }
-//      CacheState resolvedUnitState =
-//          entry.getState(HtmlEntry.RESOLVED_UNIT);
-//      if (resolvedUnitState == CacheState.INVALID ||
-//          (isPriority && resolvedUnitState == CacheState.FLUSHED)) {
-//        sources.add(source);
-//        return;
-//      }
-    }
-  }
-
-  /**
-   * Log the given debugging [message].
-   */
-  void _logInformation(String message) {
-    AnalysisEngine.instance.logger.logInformation(message);
-  }
-
-  /**
-   * Notify all of the analysis listeners that the errors associated with the
-   * given [source] has been updated to the given [errors].
-   */
-  void _notifyErrors(
-      Source source, List<AnalysisError> errors, LineInfo lineInfo) {
-    int count = _listeners.length;
-    for (int i = 0; i < count; i++) {
-      _listeners[i].computedErrors(this, source, errors, lineInfo);
-    }
-  }
-
-  bool _referencesDartHtml(Source librarySource) {
-    Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML);
-    Set<Source> checkedSources = new Set<Source>();
-    bool _refHtml(Source source) {
-      if (!checkedSources.add(source)) {
-        return false;
-      }
-      if (source == htmlSource) {
-        return true;
-      }
-      LibraryElement library = _cache.getValue(source, LIBRARY_ELEMENT);
-      if (library != null) {
-        return library.importedLibraries.any((x) => _refHtml(x.source)) ||
-            library.exportedLibraries.any((x) => _refHtml(x.source));
-      }
-      return false;
-    }
-
-    return _refHtml(librarySource);
-  }
-
-  void _removeFromCache(Source source) {
-    CacheEntry entry = _cache.remove(source);
-    if (entry != null && !entry.explicitlyAdded) {
-      _implicitAnalysisEventsController
-          .add(new ImplicitAnalysisEvent(source, false));
-    }
-  }
-
-  /**
-   * Remove the given [source] from the priority order if it is in the list.
-   */
-  void _removeFromPriorityOrder(Source source) {
-    int count = _priorityOrder.length;
-    List<Source> newOrder = <Source>[];
-    for (int i = 0; i < count; i++) {
-      if (_priorityOrder[i] != source) {
-        newOrder.add(_priorityOrder[i]);
-      }
-    }
-    if (newOrder.length < count) {
-      analysisPriorityOrder = newOrder;
-    }
-  }
-
-  /**
-   * Create an entry for the newly added [source] and invalidate any sources
-   * that referenced the source before it existed.
-   */
-  void _sourceAvailable(Source source) {
-    driver.reset();
-    // TODO(brianwilkerson) This method needs to check whether the source was
-    // previously being implicitly analyzed. If so, the cache entry needs to be
-    // update to reflect the new status and an event needs to be generated to
-    // inform clients that it is no longer being implicitly analyzed.
-    CacheEntry entry = _cache.get(source);
-    if (entry == null) {
-      _createCacheEntry(source, true);
-    } else {
-      entry.explicitlyAdded = true;
-      entry.modificationTime = getModificationStamp(source);
-      entry.setState(CONTENT, CacheState.INVALID);
-      entry.setState(MODIFICATION_TIME, CacheState.INVALID);
-    }
-  }
-
-  /**
-   * Invalidate the [source] that was changed and any sources that referenced
-   * the source before it existed.
-   *
-   * Note: source may be considered "changed" if it was previously missing,
-   * but pointed to by an import or export directive.
-   */
-  void _sourceChanged(Source source, {bool compareWithOld: true}) {
-    CacheEntry entry = _cache.get(source);
-    // If the source has no cache entry, there is nothing to invalidate.
-    if (entry == null) {
-      return;
-    }
-
-    String oldContents = compareWithOld ? entry.getValue(CONTENT) : null;
-
-    // Flush so that from now on we will get new contents.
-    // (For example, in getLibrariesContaining.)
-    entry.setState(CONTENT, CacheState.FLUSHED);
-
-    // Prepare the new contents.
-    TimestampedData<String> fileContents;
-    try {
-      fileContents = getContents(source);
-    } catch (e) {}
-
-    // Update 'modificationTime' - we are going to update the entry.
-    {
-      int time = fileContents?.modificationTime ?? -1;
-      for (CacheEntry entry in _entriesFor(source)) {
-        entry.modificationTime = time;
-      }
-    }
-
-    // Fast path if the contents is the same as it was last time.
-    if (oldContents != null && fileContents?.data == oldContents) {
-      return;
-    }
-
-    // We're going to update the cache, so reset the driver.
-    driver.reset();
-
-    // We need to invalidate the cache.
-    {
-      entry.setState(CONTENT, CacheState.INVALID);
-      entry.setState(MODIFICATION_TIME, CacheState.INVALID);
-      entry.setState(SOURCE_KIND, CacheState.INVALID);
-    }
-    for (WorkManager workManager in workManagers) {
-      workManager
-          .applyChange(const <Source>[], <Source>[source], const <Source>[]);
-    }
-  }
-
-  /**
-   * Record that the given [source] has been removed.
-   */
-  void _sourceRemoved(Source source) {
-    driver.reset();
-    _removeFromCache(source);
-    _removeFromPriorityOrder(source);
-  }
-}
-
-/**
- * A helper class used to create futures for [AnalysisContextImpl].
- * Using a helper class allows us to preserve the generic parameter T.
- */
-class AnalysisFutureHelper<T> {
-  final AnalysisContextImpl _context;
-  final AnalysisTarget _target;
-  final ResultDescriptor<T> _descriptor;
-
-  AnalysisFutureHelper(this._context, this._target, this._descriptor);
-
-  /**
-   * Return a future that will be completed with the result specified
-   * in the constructor. If the result is cached, the future will be
-   * completed immediately with the resulting value. If not, then
-   * analysis is scheduled that will produce the required result.
-   * If the result cannot be generated, then the future will be completed with
-   * the error AnalysisNotScheduledError.
-   */
-  CancelableFuture<T> computeAsync() {
-    if (_context.isDisposed) {
-      // No further analysis is expected, so return a future that completes
-      // immediately with AnalysisNotScheduledError.
-      return new CancelableFuture.error(new AnalysisNotScheduledError());
-    }
-    CacheEntry entry = _context.getCacheEntry(_target);
-    PendingFuture<T> pendingFuture =
-        new PendingFuture<T>(_context, _target, (CacheEntry entry) {
-      CacheState state = entry.getState(_descriptor);
-      if (state == CacheState.ERROR) {
-        throw entry.exception;
-      } else if (state == CacheState.INVALID) {
-        return null;
-      }
-      return entry.getValue(_descriptor);
-    });
-    if (!pendingFuture.evaluate(entry)) {
-      _context._pendingFutureTargets
-          .putIfAbsent(_target, () => <PendingFuture>[])
-          .add(pendingFuture);
-      _context.dartWorkManager.addPriorityResult(_target, _descriptor);
-    }
-    return pendingFuture.future;
-  }
-}
-
-class CacheConsistencyValidatorImpl implements CacheConsistencyValidator {
-  final AnalysisContextImpl context;
-
-  CacheConsistencyValidatorImpl(this.context);
-
-  @override
-  List<Source> getSourcesToComputeModificationTimes() {
-    return context._privatePartition.sources.toList();
-  }
-
-  @override
-  bool sourceModificationTimesComputed(List<Source> sources, List<int> times) {
-    Stopwatch timer = new Stopwatch()..start();
-    HashSet<Source> changedSources = new HashSet<Source>();
-    HashSet<Source> removedSources = new HashSet<Source>();
-    for (int i = 0; i < sources.length; i++) {
-      Source source = sources[i];
-      // When a source is in the content cache,
-      // its modification time in the file system does not matter.
-      if (context._contentCache.getModificationStamp(source) != null) {
-        continue;
-      }
-      // When we were not able to compute the modification time in the
-      // file system, there is nothing to compare with, so skip the source.
-      int sourceTime = times[i];
-      if (sourceTime == null) {
-        continue;
-      }
-      // Compare with the modification time in the cache entry.
-      CacheEntry entry = context._privatePartition.get(source);
-      if (entry != null) {
-        if (entry.modificationTime != sourceTime) {
-          if (sourceTime == -1) {
-            removedSources.add(source);
-            PerformanceStatistics
-                .cacheConsistencyValidationStatistics.numOfRemoved++;
-          } else {
-            changedSources.add(source);
-            PerformanceStatistics
-                .cacheConsistencyValidationStatistics.numOfChanged++;
-          }
-        }
-      }
-    }
-    for (Source source in changedSources) {
-      context._sourceChanged(source);
-    }
-    for (Source source in removedSources) {
-      context._sourceRemoved(source);
-    }
-    if (changedSources.length > 0 || removedSources.length > 0) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("Consistency check took ");
-      buffer.write(timer.elapsedMilliseconds);
-      buffer.writeln(" ms and found");
-      buffer.write("  ");
-      buffer.write(changedSources.length);
-      buffer.writeln(" changed sources");
-      buffer.write("  ");
-      buffer.write(removedSources.length);
-      buffer.write(" removed sources.");
-      context._logInformation(buffer.toString());
-    }
-    return changedSources.isNotEmpty || removedSources.isNotEmpty;
+    throw UnimplementedError();
   }
 }
 
@@ -1801,117 +579,16 @@
  */
 class PartitionManager {
   /**
-   * A table mapping SDK's to the partitions used for those SDK's.
-   */
-  Map<DartSdk, SdkCachePartition> _sdkPartitions =
-      new HashMap<DartSdk, SdkCachePartition>();
-
-  /**
    * Clear any cached data being maintained by this manager.
    */
-  void clearCache() {
-    _sdkPartitions.clear();
-  }
+  void clearCache() {}
 
   /**
    * Return the partition being used for the given [sdk], creating the partition
    * if necessary.
    */
   SdkCachePartition forSdk(DartSdk sdk) {
-    // Call sdk.context now, because when it creates a new
-    // InternalAnalysisContext instance, it calls forSdk() again, so creates an
-    // SdkCachePartition instance.
-    // So, if we initialize context after "partition == null", we end up
-    // with two SdkCachePartition instances.
-    InternalAnalysisContext sdkContext = sdk.context;
-    // Check cache for an existing partition.
-    SdkCachePartition partition = _sdkPartitions[sdk];
-    if (partition == null) {
-      partition = new SdkCachePartition(sdkContext);
-      _sdkPartitions[sdk] = partition;
-    }
-    return partition;
-  }
-}
-
-/**
- * Representation of a pending computation which is based on the results of
- * analysis that may or may not have been completed.
- */
-class PendingFuture<T> {
-  /**
-   * The context in which this computation runs.
-   */
-  final AnalysisContextImpl _context;
-
-  /**
-   * The target used by this computation to compute its value.
-   */
-  final AnalysisTarget target;
-
-  /**
-   * The function which implements the computation.
-   */
-  final PendingFutureComputer<T> _computeValue;
-
-  /**
-   * The completer that should be completed once the computation has succeeded.
-   */
-  CancelableCompleter<T> _completer;
-
-  PendingFuture(this._context, this.target, this._computeValue) {
-    _completer = new CancelableCompleter<T>(_onCancel);
-  }
-
-  /**
-   * Retrieve the future which will be completed when this object is
-   * successfully evaluated.
-   */
-  CancelableFuture<T> get future => _completer.future;
-
-  /**
-   * Execute [_computeValue], passing it the given [entry], and complete
-   * the pending future if it's appropriate to do so.  If the pending future is
-   * completed by this call, true is returned; otherwise false is returned.
-   *
-   * Once this function has returned true, it should not be called again.
-   *
-   * Other than completing the future, this method is free of side effects.
-   * Note that any code the client has attached to the future will be executed
-   * in a microtask, so there is no danger of side effects occurring due to
-   * client callbacks.
-   */
-  bool evaluate(CacheEntry entry) {
-    assert(!_completer.isCompleted);
-    try {
-      T result = _computeValue(entry);
-      if (result == null) {
-        return false;
-      } else {
-        _completer.complete(result);
-        return true;
-      }
-    } catch (exception, stackTrace) {
-      _completer.completeError(exception, stackTrace);
-      return true;
-    }
-  }
-
-  /**
-   * No further analysis updates are expected which affect this future, so
-   * complete it with an AnalysisNotScheduledError in order to avoid
-   * deadlocking the client.
-   */
-  void forciblyComplete() {
-    try {
-      throw new AnalysisNotScheduledError();
-    } catch (exception, stackTrace) {
-      _completer.completeError(exception, stackTrace);
-    }
-  }
-
-  void _onCancel() {
-    _context._cancelFuture(this);
+    throw UnimplementedError();
   }
 }
 
@@ -1955,15 +632,6 @@
 
   @override
   AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    if (factory == null) {
-      return super.createCacheFromSourceFactory(factory);
-    }
-    DartSdk sdk = factory.dartSdk;
-    if (sdk == null) {
-      throw new ArgumentError(
-          "The source factory for an SDK analysis context must have a DartUriResolver");
-    }
-    return new AnalysisCache(
-        <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]);
+    throw UnimplementedError();
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 418b2ff..7a4b3d0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/constant/constant_verifier.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
@@ -27,10 +28,10 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/hint/sdk_constraint_verifier.dart';
+import 'package:analyzer/src/ignore_comments/ignore_info.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:pub_semver/pub_semver.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 44f61a4..2b3f303 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/element/element.dart'
     show CompilationUnitElement, LibraryElement;
-import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -43,7 +42,7 @@
   /// We use it as an approximation for the heap size of elements.
   int _linkedDataInBytes = 0;
 
-  AnalysisContextImpl analysisContext;
+  RestrictedAnalysisContext analysisContext;
   SummaryResynthesizer resynthesizer;
   InheritanceManager2 inheritanceManager;
 
@@ -63,18 +62,19 @@
       store.addStore(externalSummaries);
     }
 
-    // Fill the store with summaries required for the initial library.
-    load(targetLibrary);
-
     analysisContext = new RestrictedAnalysisContext(
       analysisOptions,
       declaredVariables,
       sourceFactory,
     );
 
-    var provider = new InputPackagesResultProvider(analysisContext, store,
-        session: session);
-    resynthesizer = provider.resynthesizer;
+    // Fill the store with summaries required for the initial library.
+    load(targetLibrary);
+
+    resynthesizer = new StoreBasedSummaryResynthesizer(
+        analysisContext, session, sourceFactory, true, store);
+    analysisContext.typeProvider = resynthesizer.typeProvider;
+    resynthesizer.finishCoreAsyncLibraries();
 
     inheritanceManager = new InheritanceManager2(analysisContext.typeSystem);
   }
@@ -173,7 +173,7 @@
       }, (String uri) {
         UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
         return unlinkedUnit;
-      }, (_) => null);
+      }, DeclaredVariables(), analysisContext.analysisOptions);
       logger.writeln('Linked ${linkedLibraries.length} libraries.');
     });
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 5144eeb..8dfa18b 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3042,6 +3042,9 @@
   }
 
   @override
+  ParameterElement get declaredElement => _parameter.declaredElement;
+
+  @override
   Token get beginToken => _parameter.beginToken;
 
   @override
@@ -8990,6 +8993,19 @@
   /// whether the kind has not or cannot be determined.
   _SetOrMapKind _resolvedKind;
 
+  /// The context type computed by
+  /// [ResolverVisitor._computeSetOrMapContextType].
+  ///
+  /// Note that this is not the same as the context pushed down by type
+  /// inference (which can be obtained via [InferenceContext.getContext]).  For
+  /// example, in the following code:
+  ///
+  ///     var m = {};
+  ///
+  /// The context pushed down by type inference is null, whereas the
+  /// `contextType` is `Map<dynamic, dynamic>`.
+  InterfaceType contextType;
+
   /// Initialize a newly created set or 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 [elements] can be `null` if the
diff --git a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
index b6b9169..a919a7f 100644
--- a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
@@ -344,29 +344,26 @@
 
   @override
   Object visitSetOrMapLiteral(SetOrMapLiteral node) {
-    if (node.isMap) {
-      Map<String, Object> map = new HashMap<String, Object>();
-      for (CollectionElement element in node.elements2) {
-        if (element is MapLiteralEntry) {
-          Object key = element.key.accept(this);
-          Object value = element.value.accept(this);
-          if (key is String && !identical(value, NOT_A_CONSTANT)) {
-            map[key] = value;
-          } else {
-            return NOT_A_CONSTANT;
-          }
+    // There are a lot of constants that this class does not support, so we
+    // didn't add support for set literals. As a result, this assumes that we're
+    // looking at a map literal until we prove otherwise.
+    Map<String, Object> map = new HashMap<String, Object>();
+    for (CollectionElement element in node.elements2) {
+      if (element is MapLiteralEntry) {
+        Object key = element.key.accept(this);
+        Object value = element.value.accept(this);
+        if (key is String && !identical(value, NOT_A_CONSTANT)) {
+          map[key] = value;
         } else {
-          // There are a lot of constants that this class does not support, so
-          // we didn't add support for the extended collection support.
           return NOT_A_CONSTANT;
         }
+      } else {
+        // There are a lot of constants that this class does not support, so
+        // we didn't add support for the extended collection support.
+        return NOT_A_CONSTANT;
       }
-      return map;
-    } else if (node.isSet) {
-      // There are a lot of constants that this class does not support, so
-      // we didn't add support for set literals.
     }
-    return NOT_A_CONSTANT;
+    return map;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 9588569..cb913fe 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -903,13 +903,20 @@
   }
 
   @override
-  SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) =>
-      astFactory.setOrMapLiteral(
-          constKeyword: cloneToken(node.constKeyword),
-          typeArguments: cloneNode(node.typeArguments),
-          leftBracket: cloneToken(node.leftBracket),
-          elements: cloneNodeList(node.elements2),
-          rightBracket: cloneToken(node.rightBracket));
+  SetOrMapLiteral visitSetOrMapLiteral(SetOrMapLiteral node) {
+    var result = astFactory.setOrMapLiteral(
+        constKeyword: cloneToken(node.constKeyword),
+        typeArguments: cloneNode(node.typeArguments),
+        leftBracket: cloneToken(node.leftBracket),
+        elements: cloneNodeList(node.elements2),
+        rightBracket: cloneToken(node.rightBracket));
+    if (node.isMap) {
+      (result as SetOrMapLiteralImpl).becomeMap();
+    } else if (node.isSet) {
+      (result as SetOrMapLiteralImpl).becomeSet();
+    }
+    return result;
+  }
 
   @override
   ShowCombinator visitShowCombinator(ShowCombinator node) => astFactory
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 4031e2f..712d4b6 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2018, 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.
 
@@ -10,7 +10,6 @@
     show TypeProvider, TypeSystem;
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
-import 'package:analyzer/src/task/dart.dart';
 
 /// Compute values of the given [constants] with correct ordering.
 void computeConstants(
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 3373f64..a8459c1 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -2,10 +2,9 @@
 // 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:collection';
-
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -14,6 +13,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/constant/potentially_constant.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -143,20 +143,17 @@
   void visitListLiteral(ListLiteral node) {
     super.visitListLiteral(node);
     if (node.isConst) {
-      // Dummy sets of keys to accommodate the fact that
-      // `_validateCollectionElement` handles map literals.
-      HashSet<DartObject> keys = new HashSet<DartObject>();
-      List<Expression> invalidKeys = new List<Expression>();
+      InterfaceType nodeType = node.staticType;
+      DartType elementType = nodeType.typeArguments[0];
+      var verifier = _ConstLiteralVerifier(
+        this,
+        isConst: true,
+        errorCode: CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT,
+        forList: true,
+        listElementType: elementType,
+      );
       for (CollectionElement element in node.elements2) {
-        bool isValid = _validateCollectionElement(element, true, keys,
-            invalidKeys, CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT);
-        if (isValid && element is Expression) {
-          // TODO(brianwilkerson) Handle the other kinds of elements.
-          _reportErrorIfFromDeferredLibrary(
-              element,
-              CompileTimeErrorCode
-                  .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY);
-        }
+        verifier.verify(element);
       }
     }
   }
@@ -171,69 +168,55 @@
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
     super.visitSetOrMapLiteral(node);
     bool isConst = node.isConst;
-    HashSet<DartObject> keys = new HashSet<DartObject>();
-    List<Expression> invalidKeys = new List<Expression>();
     if (node.isSet) {
-      HashSet<DartObject> elements = new HashSet<DartObject>();
-      List<Expression> invalidElements = new List<Expression>();
       if (isConst) {
+        InterfaceType nodeType = node.staticType;
+        var elementType = nodeType.typeArguments[0];
+        var duplicateElements = <Expression>[];
+        var verifier = _ConstLiteralVerifier(
+          this,
+          isConst: isConst,
+          errorCode: CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT,
+          forSet: true,
+          setElementType: elementType,
+          setUniqueValues: Set<DartObject>(),
+          setDuplicateElements: duplicateElements,
+        );
         for (CollectionElement element in node.elements2) {
-          if (element is Expression) {
-            // TODO(mfairhurst): unify this with _validateCollectionElemet
-            DartObject result = _validate(
-                element, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT);
-            if (result != null) {
-              _reportErrorIfFromDeferredLibrary(
-                  element,
-                  CompileTimeErrorCode
-                      .NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY);
-              if (!elements.add(result)) {
-                invalidElements.add(element);
-              }
-              DartType type = result.type;
-              if (_implementsEqualsWhenNotAllowed(type)) {
-                _errorReporter.reportErrorForNode(
-                    CompileTimeErrorCode
-                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
-                    element,
-                    [type.displayName]);
-              }
-            }
-          } else {
-            bool isValid = _validateCollectionElement(element, isConst, keys,
-                invalidKeys, CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT);
-            if (isValid) {
-              // TODO(mfairhurst) report deferred library error
-            }
-          }
+          verifier.verify(element);
         }
-        for (var invalidElement in invalidElements) {
+        for (var duplicateElement in duplicateElements) {
           _errorReporter.reportErrorForNode(
-              StaticWarningCode.EQUAL_VALUES_IN_CONST_SET, invalidElement);
+            StaticWarningCode.EQUAL_VALUES_IN_CONST_SET,
+            duplicateElement,
+          );
         }
       }
     } else if (node.isMap) {
+      InterfaceType nodeType = node.staticType;
+      var keyType = nodeType.typeArguments[0];
+      var valueType = nodeType.typeArguments[1];
       bool reportEqualKeys = true;
+      var duplicateKeyElements = <Expression>[];
+      var verifier = _ConstLiteralVerifier(
+        this,
+        isConst: isConst,
+        errorCode: CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT,
+        forMap: true,
+        mapKeyType: keyType,
+        mapValueType: valueType,
+        mapUniqueKeys: Set<DartObject>(),
+        mapDuplicateKeyElements: duplicateKeyElements,
+      );
       for (CollectionElement entry in node.elements2) {
-        if (entry is MapLiteralEntry) {
-          // TODO(mfairhurst): Change non-const error to a hint, and report
-          // duplicates in constant evaluator instead.
-          // TODO(mfairhurst): unify this with _validateCollectionElemet
-          if (!_validateMapLiteralEntry(entry, isConst, keys, invalidKeys)) {
-            reportEqualKeys = false;
-          }
-        } else {
-          bool isValid = _validateCollectionElement(entry, isConst, keys,
-              invalidKeys, CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT);
-          if (isValid) {
-            // TODO(mfarihurst): handle deferred library checks
-          }
-        }
+        verifier.verify(entry);
       }
       if (reportEqualKeys) {
-        for (int i = 0; i < invalidKeys.length; i++) {
+        for (var duplicateKeyElement in duplicateKeyElements) {
           _errorReporter.reportErrorForNode(
-              StaticWarningCode.EQUAL_KEYS_IN_MAP, invalidKeys[i]);
+            StaticWarningCode.EQUAL_KEYS_IN_MAP,
+            duplicateKeyElement,
+          );
         }
       }
     }
@@ -452,38 +435,6 @@
     return result;
   }
 
-  bool _validateCollectionElement(
-      CollectionElement element,
-      bool isConst,
-      HashSet<DartObject> keys,
-      List<Expression> invalidKeys,
-      ErrorCode errorCode) {
-    if (element is Expression) {
-      return !isConst || _validate(element, errorCode) != null;
-    } else if (element is ForElement) {
-      if (isConst) {
-        _errorReporter.reportErrorForNode(errorCode, element);
-        return false;
-      }
-      return true;
-    } else if (element is IfElement) {
-      bool validCondition =
-          !isConst || _validate(element.condition, errorCode) != null;
-      return validCondition &&
-          _validateCollectionElement(
-                  element.thenElement, isConst, keys, invalidKeys, errorCode) !=
-              null &&
-          _validateCollectionElement(
-                  element.elseElement, isConst, keys, invalidKeys, errorCode) !=
-              null;
-    } else if (element is MapLiteralEntry) {
-      return _validateMapLiteralEntry(element, isConst, keys, invalidKeys);
-    } else if (element is SpreadElement) {
-      return !isConst || _validate(element.expression, errorCode) != null;
-    }
-    return null;
-  }
-
   /// Validate that if the passed arguments are constant expressions.
   ///
   /// @param argumentList the argument list to evaluate
@@ -632,52 +583,6 @@
       _validateInitializerExpression(parameterElements, argument);
     }
   }
-
-  bool _validateMapLiteralEntry(MapLiteralEntry entry, bool isConst,
-      HashSet<DartObject> keys, List<Expression> invalidKeys) {
-    Expression key = entry.key;
-    if (isConst) {
-      DartObjectImpl keyResult =
-          _validate(key, CompileTimeErrorCode.NON_CONSTANT_MAP_KEY);
-      Expression valueExpression = entry.value;
-      DartObjectImpl valueResult = _validate(
-          valueExpression, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE);
-      if (valueResult != null) {
-        _reportErrorIfFromDeferredLibrary(valueExpression,
-            CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY);
-      }
-      if (keyResult != null) {
-        _reportErrorIfFromDeferredLibrary(key,
-            CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY);
-        if (!keys.add(keyResult)) {
-          invalidKeys.add(key);
-        }
-        DartType type = keyResult.type;
-        if (_implementsEqualsWhenNotAllowed(type)) {
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode
-                  .CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
-              key,
-              [type.displayName]);
-        }
-      }
-    } else {
-      // Note: we throw the errors away because this isn't actually a const.
-      AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
-      ErrorReporter subErrorReporter =
-          new ErrorReporter(errorListener, _errorReporter.source);
-      DartObjectImpl result =
-          key.accept(new ConstantVisitor(_evaluationEngine, subErrorReporter));
-      if (result != null) {
-        if (!keys.add(result)) {
-          invalidKeys.add(key);
-        }
-      } else {
-        return false;
-      }
-    }
-    return true;
-  }
 }
 
 class _ConstantVerifier_validateInitializerExpression extends ConstantVisitor {
@@ -739,3 +644,327 @@
     return super.visitSimpleIdentifier(node);
   }
 }
+
+class _ConstLiteralVerifier {
+  final ConstantVerifier verifier;
+  final bool isConst;
+  final Set<DartObject> mapUniqueKeys;
+  final List<Expression> mapDuplicateKeyElements;
+  final ErrorCode errorCode;
+  final DartType listElementType;
+  final DartType mapKeyType;
+  final DartType mapValueType;
+  final DartType setElementType;
+  final Set<DartObject> setUniqueValues;
+  final List<CollectionElement> setDuplicateElements;
+  final bool forList;
+  final bool forMap;
+  final bool forSet;
+
+  _ConstLiteralVerifier(
+    this.verifier, {
+    this.isConst,
+    this.mapUniqueKeys,
+    this.mapDuplicateKeyElements,
+    this.errorCode,
+    this.listElementType,
+    this.mapKeyType,
+    this.mapValueType,
+    this.setElementType,
+    this.setUniqueValues,
+    this.setDuplicateElements,
+    this.forList = false,
+    this.forMap = false,
+    this.forSet = false,
+  });
+
+  bool verify(CollectionElement element) {
+    if (element is Expression) {
+      if (!isConst) return true;
+
+      var value = verifier._validate(element, errorCode);
+      if (value == null) return false;
+
+      if (forList) {
+        return _validateListExpression(element, value);
+      }
+
+      if (forSet) {
+        return _validateSetExpression(element, value);
+      }
+
+      return true;
+    } else if (element is ForElement) {
+      if (!isConst) return true;
+
+      verifier._errorReporter.reportErrorForNode(errorCode, element);
+      return false;
+    } else if (element is IfElement) {
+      if (!isConst) return true;
+
+      var conditionValue = verifier._validate(element.condition, errorCode);
+      var conditionBool = conditionValue?.toBoolValue();
+
+      // The errors have already been reported.
+      if (conditionBool == null) return false;
+
+      var thenValid = true;
+      var elseValid = true;
+      if (conditionBool) {
+        thenValid = verify(element.thenElement);
+        if (element.elseElement != null) {
+          elseValid = _reportNotPotentialConstants(element.elseElement);
+        }
+      } else {
+        thenValid = _reportNotPotentialConstants(element.thenElement);
+        if (element.elseElement != null) {
+          elseValid = verify(element.elseElement);
+        }
+      }
+
+      return thenValid && elseValid;
+    } else if (element is MapLiteralEntry) {
+      return _validateMapLiteralEntry(element);
+    } else if (element is SpreadElement) {
+      if (!isConst) return true;
+
+      var value = verifier._validate(element.expression, errorCode);
+      if (value == null) return false;
+
+      if (forList || forSet) {
+        return _validateListOrSetSpread(element, value);
+      }
+
+      if (forMap) {
+        return _validateMapSpread(element, value);
+      }
+
+      return true;
+    }
+    throw new UnsupportedError(
+      'Unhandled type of collection element: ${element.runtimeType}',
+    );
+  }
+
+  /// Return `true` if the [node] is a potential constant.
+  bool _reportNotPotentialConstants(AstNode node) {
+    var notPotentiallyConstants = getNotPotentiallyConstants(node);
+    if (notPotentiallyConstants.isEmpty) return true;
+
+    for (var notConst in notPotentiallyConstants) {
+      CompileTimeErrorCode errorCode;
+      if (forList) {
+        errorCode = CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT;
+      } else if (forMap) {
+        errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT;
+        for (var parent = notConst; parent != null; parent = parent.parent) {
+          if (parent is MapLiteralEntry) {
+            if (parent.key == notConst) {
+              errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_KEY;
+            } else {
+              errorCode = CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE;
+            }
+            break;
+          }
+        }
+      } else if (forSet) {
+        errorCode = CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT;
+      }
+      verifier._errorReporter.reportErrorForNode(errorCode, notConst);
+    }
+
+    return false;
+  }
+
+  bool _validateListExpression(Expression expression, DartObjectImpl value) {
+    if (!verifier._evaluationEngine.runtimeTypeMatch(value, listElementType)) {
+      verifier._errorReporter.reportErrorForNode(
+        StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [value.type, listElementType],
+      );
+      return false;
+    }
+
+    verifier._reportErrorIfFromDeferredLibrary(
+      expression,
+      CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+    );
+
+    return true;
+  }
+
+  bool _validateListOrSetSpread(SpreadElement element, DartObjectImpl value) {
+    var listValue = value.toListValue();
+    var setValue = value.toSetValue();
+
+    if (listValue == null && setValue == null) {
+      if (value.isNull && _isNullableSpread(element)) {
+        return true;
+      }
+      verifier._errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
+        element.expression,
+      );
+      return false;
+    }
+
+    if (listValue != null) {
+      var elementType = value.type.typeArguments[0];
+      if (verifier._implementsEqualsWhenNotAllowed(elementType)) {
+        verifier._errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+          element,
+          [elementType],
+        );
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  bool _validateMapLiteralEntry(MapLiteralEntry entry) {
+    if (!forMap) return false;
+
+    var keyExpression = entry.key;
+    var valueExpression = entry.value;
+
+    if (isConst) {
+      var keyValue = verifier._validate(
+        keyExpression,
+        CompileTimeErrorCode.NON_CONSTANT_MAP_KEY,
+      );
+      var valueValue = verifier._validate(
+        valueExpression,
+        CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE,
+      );
+
+      if (keyValue != null) {
+        var keyType = keyValue.type;
+
+        if (!verifier._evaluationEngine
+            .runtimeTypeMatch(keyValue, mapKeyType)) {
+          verifier._errorReporter.reportErrorForNode(
+            StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+            keyExpression,
+            [keyType, mapKeyType],
+          );
+        }
+
+        if (verifier._implementsEqualsWhenNotAllowed(keyType)) {
+          verifier._errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS,
+            keyExpression,
+            [keyType],
+          );
+        }
+
+        verifier._reportErrorIfFromDeferredLibrary(
+          keyExpression,
+          CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY,
+        );
+
+        if (!mapUniqueKeys.add(keyValue)) {
+          mapDuplicateKeyElements.add(keyExpression);
+        }
+      }
+
+      if (valueValue != null) {
+        if (!verifier._evaluationEngine
+            .runtimeTypeMatch(valueValue, mapValueType)) {
+          verifier._errorReporter.reportErrorForNode(
+            StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+            valueExpression,
+            [valueValue.type, mapValueType],
+          );
+        }
+
+        verifier._reportErrorIfFromDeferredLibrary(
+          valueExpression,
+          CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+        );
+      }
+    } else {
+      // Note: we throw the errors away because this isn't actually a const.
+      var nullErrorReporter = new ErrorReporter(
+        AnalysisErrorListener.NULL_LISTENER,
+        verifier._errorReporter.source,
+      );
+      var keyValue = keyExpression.accept(
+        new ConstantVisitor(verifier._evaluationEngine, nullErrorReporter),
+      );
+
+      if (keyValue != null) {
+        if (!mapUniqueKeys.add(keyValue)) {
+          mapDuplicateKeyElements.add(keyExpression);
+        }
+      }
+    }
+    return true;
+  }
+
+  bool _validateMapSpread(SpreadElement element, DartObjectImpl value) {
+    if (value.isNull && _isNullableSpread(element)) {
+      return true;
+    }
+    Map<DartObject, DartObject> map = value.toMapValue();
+    if (map != null) {
+      // TODO(brianwilkerson) Figure out how to improve the error messages. They
+      //  currently point to the whole spread expression, but the key and/or
+      //  value being referenced might not be located there (if it's referenced
+      //  through a const variable).
+      for (var entry in map.entries) {
+        DartObjectImpl keyValue = entry.key;
+        if (keyValue != null) {
+          if (!mapUniqueKeys.add(keyValue)) {
+            mapDuplicateKeyElements.add(element.expression);
+          }
+        }
+      }
+      return true;
+    }
+    verifier._errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
+      element.expression,
+    );
+    return false;
+  }
+
+  bool _validateSetExpression(Expression expression, DartObjectImpl value) {
+    if (!verifier._evaluationEngine.runtimeTypeMatch(value, setElementType)) {
+      verifier._errorReporter.reportErrorForNode(
+        StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [value.type, setElementType],
+      );
+      return false;
+    }
+
+    if (verifier._implementsEqualsWhenNotAllowed(value.type)) {
+      verifier._errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
+        expression,
+        [value.type],
+      );
+      return false;
+    }
+
+    verifier._reportErrorIfFromDeferredLibrary(
+      expression,
+      CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT_FROM_DEFERRED_LIBRARY,
+    );
+
+    if (!setUniqueValues.add(value)) {
+      setDuplicateElements.add(expression);
+    }
+
+    return true;
+  }
+
+  static bool _isNullableSpread(SpreadElement element) {
+    return element.spreadOperator.type ==
+        TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 390eea8..c4416ee 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -26,7 +26,7 @@
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/type_system.dart'
     show Dart2TypeSystem, TypeSystem;
-import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/task/api/model.dart';
 
 /**
  * Helper class encapsulating the methods for evaluating constants and
@@ -930,6 +930,23 @@
 }
 
 /**
+ * Interface for [AnalysisTarget]s for which constant evaluation can be
+ * performed.
+ */
+abstract class ConstantEvaluationTarget extends AnalysisTarget {
+  /**
+   * Return the [AnalysisContext] which should be used to evaluate this
+   * constant.
+   */
+  AnalysisContext get context;
+
+  /**
+   * Return whether this constant is evaluated.
+   */
+  bool get isConstantEvaluated;
+}
+
+/**
  * Interface used by unit tests to verify correct dependency analysis during
  * constant evaluation.
  */
@@ -993,58 +1010,7 @@
 
 /**
  * A visitor used to evaluate constant expressions to produce their compile-time
- * value. According to the Dart Language Specification: <blockquote> A constant
- * expression is one of the following:
- *
- * * A literal number.
- * * A literal boolean.
- * * A literal string where any interpolated expression is a compile-time
- *   constant that evaluates to a numeric, string or boolean value or to
- *   <b>null</b>.
- * * A literal symbol.
- * * <b>null</b>.
- * * A qualified reference to a static constant variable.
- * * An identifier expression that denotes a constant variable, class or type
- *   alias.
- * * A constant constructor invocation.
- * * A constant list literal.
- * * A constant map literal.
- * * A simple or qualified identifier denoting a top-level function or a static
- *   method.
- * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
- *   expression.
- * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
- *   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- *   expressions and <i>identical()</i> is statically bound to the predefined
- *   dart function <i>identical()</i> discussed above.
- * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
- *   <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
- *   <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
- *   string or boolean value.
- * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
- *   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
- *   <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
- *   to a boolean value.
- * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
- *   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
- *   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
- *   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- *   expressions that evaluate to an integer value or to <b>null</b>.
- * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
- *   ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &gt; e<sub>2</sub></i>,
- *   <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
- *   e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or
- *   <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
- *   and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
- *   numeric value or to <b>null</b>.
- * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
- *   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
- *   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
- *   evaluates to a boolean value.
- * </blockquote>
+ * value.
  */
 class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
   /**
@@ -1467,7 +1433,14 @@
 
   @override
   DartObjectImpl visitSetOrMapLiteral(SetOrMapLiteral node) {
-    if (node.isMap) {
+    // Note: due to dartbug.com/33441, it's possible that a set/map literal
+    // resynthesized from a summary will have neither its `isSet` or `isMap`
+    // boolean set to `true`.  We work around the problem by assuming such
+    // literals are maps.
+    // TODO(paulberry): when dartbug.com/33441 is fixed, add an assertion here
+    // to verify that `node.isSet == !node.isMap`.
+    bool isMap = !node.isSet;
+    if (isMap) {
       if (!node.isConst) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
@@ -1494,7 +1467,7 @@
       InterfaceType mapType =
           _typeProvider.mapType.instantiate([keyType, valueType]);
       return new DartObjectImpl(mapType, new MapState(map));
-    } else if (node.isSet) {
+    } else {
       if (!node.isConst) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL, node);
@@ -1516,7 +1489,6 @@
       InterfaceType setType = _typeProvider.setType.instantiate([elementType]);
       return new DartObjectImpl(setType, new SetState(set));
     }
-    return null;
   }
 
   @override
@@ -1580,8 +1552,7 @@
    */
   bool _addElementsToList(List<DartObject> list, CollectionElement element) {
     if (element is IfElement) {
-      DartObjectImpl conditionResult = element.condition.accept(this);
-      bool conditionValue = conditionResult?.toBoolValue();
+      bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
       } else if (conditionValue) {
@@ -1618,8 +1589,7 @@
   bool _addElementsToMap(
       Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
     if (element is IfElement) {
-      DartObjectImpl conditionResult = element.condition.accept(this);
-      bool conditionValue = conditionResult?.toBoolValue();
+      bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
       } else if (conditionValue) {
@@ -1656,8 +1626,7 @@
    */
   bool _addElementsToSet(Set<DartObject> set, CollectionElement element) {
     if (element is IfElement) {
-      DartObjectImpl conditionResult = element.condition.accept(this);
-      bool conditionValue = conditionResult?.toBoolValue();
+      bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
       } else if (conditionValue) {
@@ -1707,6 +1676,27 @@
   }
 
   /**
+   * Evaluate the given [condition] with the assumption that it must be a
+   * `bool`.
+   */
+  bool _evaluateCondition(Expression condition) {
+    DartObjectImpl conditionResult = condition.accept(this);
+    bool conditionValue = conditionResult?.toBoolValue();
+    if (conditionValue == null) {
+      // TODO(brianwilkerson) Figure out why the static type is sometimes null.
+      DartType staticType = condition.staticType;
+      if (staticType == null ||
+          typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
+        // If the static type is not assignable, then we will have already
+        // reported this error.
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
+      }
+    }
+    return conditionValue;
+  }
+
+  /**
    * Return the constant value of the static constant represented by the given
    * [element]. The [node] is the node to be used if an error needs to be
    * reported.
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
new file mode 100644
index 0000000..5a48513
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -0,0 +1,330 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+
+/// Check if the [node] and all its sub-nodes are potentially constant.
+///
+/// Return the list of nodes that are not potentially constant.
+List<AstNode> getNotPotentiallyConstants(AstNode node) {
+  var collector = _Collector();
+  collector.collect(node);
+  return collector.nodes;
+}
+
+/// Return `true` if the [node] is a constant type expression.
+bool isConstantTypeExpression(TypeAnnotation node) {
+  if (node is TypeName) {
+    if (_isConstantTypeName(node.name)) {
+      var arguments = node.typeArguments?.arguments;
+      if (arguments != null) {
+        for (var argument in arguments) {
+          if (!isConstantTypeExpression(argument)) {
+            return false;
+          }
+        }
+      }
+      return true;
+    }
+    if (node.type is DynamicTypeImpl) {
+      return true;
+    }
+    if (node.type is VoidType) {
+      return true;
+    }
+    return false;
+  }
+
+  if (node is GenericFunctionType) {
+    var returnType = node.returnType;
+    if (returnType != null) {
+      if (!isConstantTypeExpression(returnType)) {
+        return false;
+      }
+    }
+
+    var typeParameters = node.typeParameters?.typeParameters;
+    if (typeParameters != null) {
+      for (var parameter in typeParameters) {
+        var bound = parameter.bound;
+        if (bound != null && !isConstantTypeExpression(bound)) {
+          return false;
+        }
+      }
+    }
+
+    var formalParameters = node.parameters?.parameters;
+    if (formalParameters != null) {
+      for (var parameter in formalParameters) {
+        if (parameter is SimpleFormalParameter) {
+          if (!isConstantTypeExpression(parameter.type)) {
+            return false;
+          }
+        }
+      }
+    }
+
+    return true;
+  }
+
+  return false;
+}
+
+bool _isConstantTypeName(Identifier name) {
+  var element = name.staticElement;
+  if (element is ClassElement || element is GenericTypeAliasElement) {
+    if (name is PrefixedIdentifier) {
+      if (name.isDeferred) {
+        return false;
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+class _Collector {
+  final List<AstNode> nodes = [];
+
+  void collect(AstNode node) {
+    if (node is BooleanLiteral ||
+        node is DoubleLiteral ||
+        node is IntegerLiteral ||
+        node is NullLiteral ||
+        node is SimpleStringLiteral ||
+        node is SymbolLiteral) {
+      return;
+    }
+
+    if (node is StringInterpolation) {
+      for (var component in node.elements) {
+        if (component is InterpolationExpression) {
+          collect(component.expression);
+        }
+      }
+      return;
+    }
+
+    if (node is Identifier) {
+      return _identifier(node);
+    }
+
+    if (node is InstanceCreationExpression) {
+      if (!node.isConst) {
+        nodes.add(node);
+      }
+      return;
+    }
+
+    if (node is TypedLiteral) {
+      return _typeLiteral(node);
+    }
+
+    if (node is ParenthesizedExpression) {
+      collect(node.expression);
+      return;
+    }
+
+    if (node is MethodInvocation) {
+      return _methodInvocation(node);
+    }
+
+    if (node is BinaryExpression) {
+      collect(node.leftOperand);
+      collect(node.rightOperand);
+      return;
+    }
+
+    if (node is PrefixExpression) {
+      var operator = node.operator.type;
+      if (operator == TokenType.BANG ||
+          operator == TokenType.MINUS ||
+          operator == TokenType.TILDE) {
+        collect(node.operand);
+        return;
+      }
+      nodes.add(node);
+      return;
+    }
+
+    if (node is ConditionalExpression) {
+      collect(node.condition);
+      collect(node.thenExpression);
+      collect(node.elseExpression);
+      return;
+    }
+
+    if (node is PropertyAccess) {
+      return _propertyAccess(node);
+    }
+
+    if (node is AsExpression) {
+      if (!isConstantTypeExpression(node.type)) {
+        nodes.add(node.type);
+      }
+      collect(node.expression);
+      return;
+    }
+
+    if (node is IsExpression) {
+      if (!isConstantTypeExpression(node.type)) {
+        nodes.add(node.type);
+      }
+      collect(node.expression);
+      return;
+    }
+
+    if (node is MapLiteralEntry) {
+      collect(node.key);
+      collect(node.value);
+      return;
+    }
+
+    if (node is SpreadElement) {
+      collect(node.expression);
+      return;
+    }
+
+    if (node is IfElement) {
+      collect(node.condition);
+      collect(node.thenElement);
+      if (node.elseElement != null) {
+        collect(node.elseElement);
+      }
+      return;
+    }
+
+    nodes.add(node);
+  }
+
+  void _identifier(Identifier node) {
+    var element = node.staticElement;
+
+    if (node is PrefixedIdentifier) {
+      if (node.isDeferred) {
+        nodes.add(node);
+        return;
+      }
+      if (node.identifier.name == 'length') {
+        collect(node.prefix);
+        return;
+      }
+      if (element is MethodElement && element.isStatic) {
+        if (_isConstantTypeName(node.prefix)) {
+          return;
+        }
+      }
+    }
+
+    if (element is VariableElement) {
+      if (!element.isConst) {
+        nodes.add(node);
+      }
+      return;
+    }
+    if (element is PropertyAccessorElement && element.isGetter) {
+      var variable = element.variable;
+      if (!variable.isConst) {
+        nodes.add(node);
+      }
+      return;
+    }
+    if (_isConstantTypeName(node)) {
+      return;
+    }
+    if (element is FunctionElement) {
+      return;
+    }
+    nodes.add(node);
+  }
+
+  void _methodInvocation(MethodInvocation node) {
+    var arguments = node.argumentList?.arguments;
+    if (arguments?.length == 2 && node.methodName.name == 'identical') {
+      var library = node.methodName?.staticElement?.library;
+      if (library?.isDartCore == true) {
+        collect(arguments[0]);
+        collect(arguments[1]);
+        return;
+      }
+    }
+    nodes.add(node);
+  }
+
+  void _propertyAccess(PropertyAccess node) {
+    if (node.propertyName.name == 'length') {
+      collect(node.target);
+      return;
+    }
+
+    var target = node.target;
+    if (target is PrefixedIdentifier) {
+      if (target.isDeferred) {
+        nodes.add(node);
+        return;
+      }
+
+      var element = node.propertyName.staticElement;
+      if (element is PropertyAccessorElement && element.isGetter) {
+        var variable = element.variable;
+        if (!variable.isConst) {
+          nodes.add(node.propertyName);
+        }
+        return;
+      }
+    }
+
+    nodes.add(node);
+  }
+
+  void _typeLiteral(TypedLiteral node) {
+    if (!node.isConst) {
+      nodes.add(node);
+      return;
+    }
+
+    if (node is ListLiteral) {
+      var typeArguments = node.typeArguments?.arguments;
+      if (typeArguments?.length == 1) {
+        var elementType = typeArguments[0];
+        if (!isConstantTypeExpression(elementType)) {
+          nodes.add(elementType);
+        }
+      }
+
+      for (var element in node.elements2) {
+        collect(element);
+      }
+      return;
+    }
+
+    if (node is SetOrMapLiteral) {
+      var typeArguments = node.typeArguments?.arguments;
+      if (typeArguments?.length == 1) {
+        var elementType = typeArguments[0];
+        if (!isConstantTypeExpression(elementType)) {
+          nodes.add(elementType);
+        }
+      }
+
+      if (typeArguments?.length == 2) {
+        var keyType = typeArguments[0];
+        var valueType = typeArguments[1];
+        if (!isConstantTypeExpression(keyType)) {
+          nodes.add(keyType);
+        }
+        if (!isConstantTypeExpression(valueType)) {
+          nodes.add(valueType);
+        }
+      }
+
+      for (var element in node.elements2) {
+        collect(element);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 3a9b8a7..6e5f535 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -12,11 +12,11 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart'
     show ConstructorElementHandle;
 import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
   while (constructor is ConstructorMember) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 1f9c4c1..5cf726d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/compute.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -31,7 +32,6 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /// Assert that the given [object] is null, which in the places where this
 /// function is called means that the element is not resynthesized.
@@ -60,6 +60,10 @@
   /// given [offset] in the file that contains the declaration of this element.
   AbstractClassElementImpl(String name, int offset) : super(name, offset);
 
+  AbstractClassElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created class element to have the given [name].
   AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -414,9 +418,6 @@
   /// The unlinked representation of the class in the summary.
   final UnlinkedClass _unlinkedClass;
 
-  final Reference reference;
-  final LinkedNode _linkedNode;
-
   /// If this class is resynthesized, whether it has a constant constructor.
   bool _hasConstConstructorCached;
 
@@ -455,31 +456,25 @@
   /// Initialize a newly created class element to have the given [name] at the
   /// given [offset] in the file that contains the declaration of this element.
   ClassElementImpl(String name, int offset)
-      : reference = null,
-        _linkedNode = null,
-        _unlinkedClass = null,
+      : _unlinkedClass = null,
         super(name, offset);
 
-  ClassElementImpl.forLinkedNode(this.reference, this._linkedNode,
-      CompilationUnitElementImpl enclosingUnit)
+  ClassElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+      Reference reference, LinkedNode linkedNode)
       : _unlinkedClass = null,
-        super.forSerialized(enclosingUnit) {
-    reference.element = this;
+        super.forLinkedNode(enclosing, reference, linkedNode) {
+    enclosing.linkedContext.loadClassMemberReferences(reference);
   }
 
   /// Initialize a newly created class element to have the given [name].
   ClassElementImpl.forNode(Identifier name)
-      : reference = null,
-        _linkedNode = null,
-        _unlinkedClass = null,
+      : _unlinkedClass = null,
         super.forNode(name);
 
   /// Initialize using the given serialized information.
   ClassElementImpl.forSerialized(
       this._unlinkedClass, CompilationUnitElementImpl enclosingUnit)
-      : reference = null,
-        _linkedNode = null,
-        super.forSerialized(enclosingUnit);
+      : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
   void set abstract(bool isAbstract) {
@@ -489,6 +484,18 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    if (linkedNode != null) {
+      if (_accessors != null) return _accessors;
+
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        _createPropertiesAndAccessors();
+        assert(_accessors != null);
+        return _accessors;
+      } else {
+        return _accessors = const [];
+      }
+    }
     if (_accessors == null) {
       if (_unlinkedClass != null) {
         _resynthesizeFieldsAndPropertyAccessors();
@@ -536,16 +543,18 @@
       return _constructors = _computeMixinAppConstructors();
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@constructor');
-      _constructors = _linkedNode.classOrMixinDeclaration_members
-          .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
-          .map((node) {
-        var name = context.getConstructorDeclarationName(node);
-        var reference = containerRef.getChild(name);
-        return ConstructorElementImpl.forLinkedNode(reference, node, this);
-      }).toList();
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        _constructors = linkedNode.classOrMixinDeclaration_members
+            .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
+            .map((node) {
+          var name = context.getConstructorDeclarationName(node);
+          var reference = containerRef.getChild(name);
+          return ConstructorElementImpl.forLinkedNode(reference, node, this);
+        }).toList();
+      }
     }
 
     if (_unlinkedClass != null) {
@@ -601,6 +610,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedClass != null) {
       return _unlinkedClass.documentationComment?.text;
     }
@@ -612,6 +626,18 @@
 
   @override
   List<FieldElement> get fields {
+    if (linkedNode != null) {
+      if (_fields != null) return _fields;
+
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        _createPropertiesAndAccessors();
+        assert(_fields != null);
+        return _fields;
+      } else {
+        _fields = const [];
+      }
+    }
     if (_fields == null) {
       if (_unlinkedClass != null) {
         _resynthesizeFieldsAndPropertyAccessors();
@@ -710,13 +736,13 @@
       return _interfaces;
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
-      var implementsClause =
-          _linkedNode.classOrMixinDeclaration_implementsClause;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var implementsClause = context.getImplementsClause(linkedNode);
       if (implementsClause != null) {
         return _interfaces = implementsClause.implementsClause_interfaces
             .map((node) => context.getInterfaceType(node.typeName_type))
+            .where((type) => type != null)
             .toList();
       }
     } else if (_unlinkedClass != null) {
@@ -757,8 +783,12 @@
 
   @override
   bool get isAbstract {
-    if (_linkedNode != null) {
-      return _linkedNode.classDeclaration_abstractKeyword != 0;
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        return linkedNode.classDeclaration_abstractKeyword != 0;
+      } else {
+        return linkedNode.classTypeAlias_abstractKeyword != 0;
+      }
     }
     if (_unlinkedClass != null) {
       return _unlinkedClass.isAbstract;
@@ -768,6 +798,9 @@
 
   @override
   bool get isMixinApplication {
+    if (linkedNode != null) {
+      return linkedNode.kind == LinkedNodeKind.classTypeAlias;
+    }
     if (_unlinkedClass != null) {
       return _unlinkedClass.isMixinApplication;
     }
@@ -819,6 +852,24 @@
       return _methods;
     }
 
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@method');
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        return _methods = linkedNode.classOrMixinDeclaration_members
+            .where((node) => node.kind == LinkedNodeKind.methodDeclaration)
+            .where((node) => node.methodDeclaration_propertyKeyword == 0)
+            .map((node) {
+          var name = context.getSimpleName(node.methodDeclaration_name);
+          var reference = containerRef.getChild(name);
+          return MethodElementImpl.forLinkedNode(reference, node, this);
+        }).toList();
+      } else {
+        return _methods = const <MethodElement>[];
+      }
+    }
+
     if (_unlinkedClass != null) {
       var unlinkedExecutables = _unlinkedClass.executables;
 
@@ -872,12 +923,18 @@
       return _mixins;
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
-      var withClause = _linkedNode.classDeclaration_withClause;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      LinkedNode withClause;
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        withClause = linkedNode.classDeclaration_withClause;
+      } else {
+        withClause = linkedNode.classTypeAlias_withClause;
+      }
       if (withClause != null) {
         return _mixins = withClause.withClause_mixinTypes
             .map((node) => context.getInterfaceType(node.typeName_type))
+            .where((type) => type != null)
             .toList();
       }
     } else if (_unlinkedClass != null) {
@@ -923,7 +980,7 @@
 
   @override
   String get name {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     if (_unlinkedClass != null) {
@@ -949,13 +1006,19 @@
   @override
   InterfaceType get supertype {
     if (_supertype == null) {
-      if (_linkedNode != null) {
-        var context = enclosingUnit._linkedContext;
-        var extendsClause = _linkedNode.classDeclaration_extendsClause;
-        if (extendsClause != null) {
-          _supertype = context.getInterfaceType(
-            extendsClause.extendsClause_superclass.typeName_type,
-          );
+      if (linkedNode != null) {
+        LinkedNode superclass;
+        if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+          superclass = linkedNode
+              .classDeclaration_extendsClause?.extendsClause_superclass;
+        } else {
+          superclass = linkedNode.classTypeAlias_superclass;
+        }
+        if (superclass != null) {
+          var context = enclosingUnit.linkedContext;
+          _supertype = context.getInterfaceType(superclass.typeName_type);
+        } else if (!linkedNode.classDeclaration_isDartObject) {
+          _supertype = context.typeProvider.objectType;
         }
       } else if (_unlinkedClass != null) {
         if (_unlinkedClass.supertype != null) {
@@ -991,6 +1054,27 @@
     return _type;
   }
 
+  @override
+  List<TypeParameterElement> get typeParameters {
+    if (_typeParameterElements != null) return _typeParameterElements;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeParameter');
+      var typeParameters = context.getTypeParameters(linkedNode);
+      if (typeParameters == null) {
+        return _typeParameterElements = const [];
+      }
+      return _typeParameterElements = typeParameters.map((node) {
+        var name = context.getSimpleName(node.typeParameter_name);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+    return super.typeParameters;
+  }
+
   /// Set the type parameters defined for this class to the given
   /// [typeParameters].
   void set typeParameters(List<TypeParameterElement> typeParameters) {
@@ -1208,6 +1292,75 @@
     }).toList(growable: false);
   }
 
+  void _createPropertiesAndAccessors() {
+    assert(_accessors == null);
+    assert(_fields == null);
+
+    var context = enclosingUnit.linkedContext;
+    var accessorList = <PropertyAccessorElementImpl>[];
+    var fieldList = <FieldElementImpl>[];
+
+    var fields = context.classFields(linkedNode);
+    for (var field in fields) {
+      var name = context.getVariableName(field);
+      var fieldElement = FieldElementImpl.forLinkedNodeFactory(
+        this,
+        reference.getChild('@field').getChild(name),
+        field,
+      );
+      fieldList.add(fieldElement);
+
+      accessorList.add(fieldElement.getter);
+      if (fieldElement.setter != null) {
+        accessorList.add(fieldElement.setter);
+      }
+    }
+
+    for (var node in linkedNode.classOrMixinDeclaration_members) {
+      if (node.kind == LinkedNodeKind.methodDeclaration) {
+        var isGetter = context.isGetterMethod(node);
+        var isSetter = context.isSetterMethod(node);
+        if (!isGetter && !isSetter) continue;
+
+        var name = context.getMethodName(node);
+        var containerRef = isGetter
+            ? reference.getChild('@getter')
+            : reference.getChild('@setter');
+
+        var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+          this,
+          containerRef.getChild(name),
+          node,
+        );
+        accessorList.add(accessorElement);
+
+        var fieldRef = reference.getChild('@field').getChild(name);
+        FieldElementImpl field = fieldRef.element;
+        if (field == null) {
+          field = new FieldElementImpl(name, -1);
+          fieldRef.element = field;
+          field.enclosingElement = this;
+          field.isSynthetic = true;
+          field.isFinal = isGetter;
+          field.isStatic = accessorElement.isStatic;
+          fieldList.add(field);
+        } else {
+          field.isFinal = false;
+        }
+
+        accessorElement.variable = field;
+        if (isGetter) {
+          field.getter = accessorElement;
+        } else {
+          field.setter = accessorElement;
+        }
+      }
+    }
+
+    _accessors = accessorList;
+    _fields = fieldList;
+  }
+
   /// Return `true` if the given [type] is an [InterfaceType] that can be used
   /// as a class.
   bool _isInterfaceTypeClass(DartType type) {
@@ -1412,9 +1565,7 @@
   /// The unlinked representation of the part in the summary.
   final UnlinkedPart _unlinkedPart;
 
-  final LinkedUnitContext _linkedContext;
-  final Reference reference;
-  final LinkedNode _linkedNode;
+  final LinkedUnitContext linkedContext;
 
   /// The source that corresponds to this compilation unit.
   @override
@@ -1477,27 +1628,20 @@
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        _linkedContext = null,
-        reference = null,
-        _linkedNode = null,
+        linkedContext = null,
         super(null, -1);
 
   CompilationUnitElementImpl.forLinkedNode(LibraryElementImpl enclosingLibrary,
-      this._linkedContext, this.reference, this._linkedNode)
+      this.linkedContext, Reference reference, LinkedNode linkedNode)
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        super.forSerialized(null) {
-    _enclosingElement = enclosingLibrary;
-    _nameOffset = -1;
-  }
+        super.forLinkedNode(enclosingLibrary, reference, linkedNode);
 
   /// Initialize using the given serialized information.
   CompilationUnitElementImpl.forSerialized(LibraryElementImpl enclosingLibrary,
       this.resynthesizerContext, this._unlinkedUnit, this._unlinkedPart)
-      : _linkedContext = null,
-        reference = null,
-        _linkedNode = null,
+      : linkedContext = null,
         super.forSerialized(null) {
     _enclosingElement = enclosingLibrary;
     _nameOffset = -1;
@@ -1505,6 +1649,12 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    if (linkedNode != null) {
+      if (_accessors != null) return _accessors;
+      _createPropertiesAndAccessors(this);
+      assert(_accessors != null);
+      return _accessors;
+    }
     if (_accessors == null) {
       if (_unlinkedUnit != null) {
         _explicitTopLevelAccessors ??=
@@ -1557,6 +1707,19 @@
 
   @override
   List<ClassElement> get enums {
+    if (linkedNode != null) {
+      if (_enums != null) return _enums;
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@enum');
+      _enums = linkedNode.compilationUnit_declarations
+          .where((node) => node.kind == LinkedNodeKind.enumDeclaration)
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return EnumElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
     if (_unlinkedUnit != null) {
       _enums ??= _unlinkedUnit.enums
           .map((e) => new EnumElementImpl.forSerialized(e, this))
@@ -1576,8 +1739,23 @@
 
   @override
   List<FunctionElement> get functions {
-    if (_unlinkedUnit != null) {
-      _functions ??= _unlinkedUnit.executables
+    if (_functions != null) return _functions;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@function');
+      _functions = linkedNode.compilationUnit_declarations
+          .where((node) =>
+              node.kind == LinkedNodeKind.functionDeclaration &&
+              !context.isGetterFunction(node) &&
+              !context.isSetterFunction(node))
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        return FunctionElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    } else if (_unlinkedUnit != null) {
+      _functions = _unlinkedUnit.executables
           .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
           .map((e) => new FunctionElementImpl.forSerialized(e, this))
           .toList(growable: false);
@@ -1596,8 +1774,22 @@
 
   @override
   List<FunctionTypeAliasElement> get functionTypeAliases {
+    if (_typeAliases != null) return _typeAliases;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeAlias');
+      _typeAliases = linkedNode.compilationUnit_declarations
+          .where((node) => node.kind == LinkedNodeKind.functionTypeAlias)
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        return GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+
     if (_unlinkedUnit != null) {
-      _typeAliases ??= _unlinkedUnit.typedefs.map((t) {
+      _typeAliases = _unlinkedUnit.typedefs.map((t) {
         return new GenericTypeAliasElementImpl.forSerialized(t, this);
       }).toList(growable: false);
     }
@@ -1657,6 +1849,12 @@
 
   @override
   List<TopLevelVariableElement> get topLevelVariables {
+    if (linkedNode != null) {
+      if (_variables != null) return _variables;
+      _createPropertiesAndAccessors(this);
+      assert(_variables != null);
+      return _variables;
+    }
     if (_variables == null) {
       if (_unlinkedUnit != null) {
         _explicitTopLevelAccessors ??=
@@ -1711,15 +1909,18 @@
 
   @override
   List<ClassElement> get types {
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@class');
-      _types = _linkedNode.compilationUnit_declarations
-          .where((node) => node.kind == LinkedNodeKind.classDeclaration)
+      _types = linkedNode.compilationUnit_declarations
+          .where((node) =>
+              node.kind == LinkedNodeKind.classDeclaration ||
+              node.kind == LinkedNodeKind.classTypeAlias)
           .map((node) {
         var name = context.getUnitMemberName(node);
         var reference = containerRef.getChild(name);
-        return ClassElementImpl.forLinkedNode(reference, node, this);
+        reference.node = node;
+        return ClassElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     } else if (_unlinkedUnit != null) {
       _types ??= _unlinkedUnit.classes
@@ -1880,6 +2081,89 @@
     }
     return null;
   }
+
+  static void _createPropertiesAndAccessors(CompilationUnitElementImpl unit) {
+    if (unit._variables != null) return;
+    assert(unit._accessors == null);
+
+    var accessorMap =
+        <CompilationUnitElementImpl, List<PropertyAccessorElementImpl>>{};
+    var variableMap =
+        <CompilationUnitElementImpl, List<TopLevelVariableElementImpl>>{};
+
+    var units = unit.library.units;
+    for (CompilationUnitElementImpl unit in units) {
+      var context = unit.linkedContext;
+
+      var accessorList = <PropertyAccessorElementImpl>[];
+      accessorMap[unit] = accessorList;
+
+      var variableList = <TopLevelVariableElementImpl>[];
+      variableMap[unit] = variableList;
+
+      var variables = context.topLevelVariables(unit.linkedNode);
+      for (var variable in variables) {
+        var name = context.getVariableName(variable);
+        var reference = unit.reference.getChild('@variable').getChild(name);
+        var variableElement = TopLevelVariableElementImpl.forLinkedNodeFactory(
+          unit,
+          reference,
+          variable,
+        );
+        variableList.add(variableElement);
+
+        accessorList.add(variableElement.getter);
+        if (variableElement.setter != null) {
+          accessorList.add(variableElement.setter);
+        }
+      }
+
+      for (var node in unit.linkedNode.compilationUnit_declarations) {
+        if (node.kind == LinkedNodeKind.functionDeclaration) {
+          var isGetter = context.isGetterFunction(node);
+          var isSetter = context.isSetterFunction(node);
+          if (!isGetter && !isSetter) continue;
+
+          var name = context.getUnitMemberName(node);
+          var containerRef = isGetter
+              ? unit.reference.getChild('@getter')
+              : unit.reference.getChild('@setter');
+
+          var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+            unit,
+            containerRef.getChild(name),
+            node,
+          );
+          accessorList.add(accessorElement);
+
+          var fieldRef = unit.reference.getChild('@field').getChild(name);
+          TopLevelVariableElementImpl field = fieldRef.element;
+          if (field == null) {
+            field = new TopLevelVariableElementImpl(name, -1);
+            fieldRef.element = field;
+            field.enclosingElement = unit;
+            field.isSynthetic = true;
+            field.isFinal = isGetter;
+            variableList.add(field);
+          } else {
+            field.isFinal = false;
+          }
+
+          accessorElement.variable = field;
+          if (isGetter) {
+            field.getter = accessorElement;
+          } else {
+            field.setter = accessorElement;
+          }
+        }
+      }
+    }
+
+    for (CompilationUnitElementImpl unit in units) {
+      unit._accessors = accessorMap[unit];
+      unit._variables = variableMap[unit];
+    }
+  }
 }
 
 /// A [FieldElement] for a 'const' or 'final' field that has an initializer.
@@ -1895,6 +2179,10 @@
   /// [name] and [offset].
   ConstFieldElementImpl(String name, int offset) : super(name, offset);
 
+  ConstFieldElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created field element to have the given [name].
   ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -1913,8 +2201,21 @@
       EnumElementImpl enumElement, this._unlinkedEnumValue, this._index)
       : super(enumElement);
 
+  ConstFieldElementImpl_EnumValue.forLinkedNode(EnumElementImpl enumElement,
+      Reference reference, LinkedNode linkedNode, this._index)
+      : _unlinkedEnumValue = null,
+        super.forLinkedNode(enumElement, reference, linkedNode);
+
+  @override
+  Expression get constantInitializer => null;
+
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedEnumValue != null) {
       return _unlinkedEnumValue.documentationComment?.text;
     }
@@ -1946,6 +2247,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedEnumValue != null) {
       return _unlinkedEnumValue.name;
     }
@@ -1954,9 +2258,16 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.enumConstantDeclaration_name,
+      );
+    }
     int offset = super.nameOffset;
-    if (offset == -1 && _unlinkedEnumValue != null) {
-      return _unlinkedEnumValue.nameOffset;
+    if (offset == -1) {
+      if (_unlinkedEnumValue != null) {
+        return _unlinkedEnumValue.nameOffset;
+      }
     }
     return offset;
   }
@@ -2008,6 +2319,10 @@
     enclosingElement = _enum;
   }
 
+  ConstFieldElementImpl_ofEnum.forLinkedNode(
+      this._enum, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(_enum, reference, linkedNode);
+
   @override
   void set evaluationResult(_) {
     assert(false);
@@ -2080,34 +2395,21 @@
   @override
   bool isConstantEvaluated = false;
 
-  final Reference reference;
-  final LinkedNode _linkedNode;
+  /// Initialize a newly created constructor element to have the given [name]
+  /// and [offset].
+  ConstructorElementImpl(String name, int offset) : super(name, offset);
 
-  /// Initialize a newly created constructor element to have the given [name
-  /// ] and[offset].
-  ConstructorElementImpl(String name, int offset)
-      : reference = null,
-        _linkedNode = null,
-        super(name, offset);
-
-  ConstructorElementImpl.forLinkedNode(
-      this.reference, this._linkedNode, ClassElementImpl enclosingClass)
-      : super.forLinkedNode(enclosingClass) {
-    reference.element = this;
-  }
+  ConstructorElementImpl.forLinkedNode(Reference reference,
+      LinkedNode linkedNode, ClassElementImpl enclosingClass)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode);
 
   /// Initialize a newly created constructor element to have the given [name].
-  ConstructorElementImpl.forNode(Identifier name)
-      : reference = null,
-        _linkedNode = null,
-        super.forNode(name);
+  ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
 
   /// Initialize using the given serialized information.
   ConstructorElementImpl.forSerialized(
       UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
-      : reference = null,
-        _linkedNode = null,
-        super.forSerialized(serializedExecutable, enclosingClass);
+      : super.forSerialized(serializedExecutable, enclosingClass);
 
   /// Return the constant initializers for this element, which will be empty if
   /// there are no initializers, or `null` if there was an error in the source.
@@ -2130,7 +2432,7 @@
 
   @override
   String get displayName {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     return super.displayName;
@@ -2152,8 +2454,8 @@
 
   @override
   bool get isConst {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_constKeyword != 0;
+    if (linkedNode != null) {
+      return linkedNode.constructorDeclaration_constKeyword != 0;
     }
     if (serializedExecutable != null) {
       return serializedExecutable.isConst;
@@ -2200,17 +2502,9 @@
   }
 
   @override
-  bool get isExternal {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_externalKeyword != 0;
-    }
-    return super.isExternal;
-  }
-
-  @override
   bool get isFactory {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_factoryKeyword != 0;
+    if (linkedNode != null) {
+      return linkedNode.constructorDeclaration_factoryKeyword != 0;
     }
     if (serializedExecutable != null) {
       return serializedExecutable.isFactory;
@@ -2222,19 +2516,11 @@
   bool get isStatic => false;
 
   @override
-  bool get isSynthetic {
-    if (_linkedNode != null) {
-      return _linkedNode.isSynthetic;
-    }
-    return super.isSynthetic;
-  }
-
-  @override
   ElementKind get kind => ElementKind.CONSTRUCTOR;
 
   @override
   String get name {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     return super.name;
@@ -2415,6 +2701,10 @@
   ConstTopLevelVariableElementImpl(String name, int offset)
       : super(name, offset);
 
+  ConstTopLevelVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created top-level variable element to have the given
   /// [name].
   ConstTopLevelVariableElementImpl.forNode(Identifier name)
@@ -2448,11 +2738,16 @@
   EvaluationResultImpl _evaluationResult;
 
   Expression get constantInitializer {
-    if (_constantInitializer == null) {
-      if (_unlinkedConst != null) {
-        _constantInitializer = enclosingUnit.resynthesizerContext
-            .buildExpression(this, _unlinkedConst);
-      }
+    if (_constantInitializer != null) return _constantInitializer;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      return _constantInitializer = context.readInitializer(linkedNode);
+    }
+
+    if (_unlinkedConst != null) {
+      _constantInitializer = enclosingUnit.resynthesizerContext
+          .buildExpression(this, _unlinkedConst);
     }
     return _constantInitializer;
   }
@@ -2515,6 +2810,10 @@
   DefaultParameterElementImpl(String name, int nameOffset)
       : super(name, nameOffset);
 
+  DefaultParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created parameter element to have the given [name].
   DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -2807,6 +3106,9 @@
   /// root of the element structure.
   ElementImpl _enclosingElement;
 
+  Reference reference;
+  final LinkedNode linkedNode;
+
   /// The name of this element.
   String _name;
 
@@ -2838,19 +3140,26 @@
 
   /// Initialize a newly created element to have the given [name] at the given
   /// [_nameOffset].
-  ElementImpl(String name, this._nameOffset) {
+  ElementImpl(String name, this._nameOffset, {this.reference})
+      : linkedNode = null {
     this._name = StringUtilities.intern(name);
+    this.reference?.element = this;
   }
 
   /// Initialize from linked node.
-  ElementImpl.forLinkedNode(this._enclosingElement);
+  ElementImpl.forLinkedNode(
+      this._enclosingElement, this.reference, this.linkedNode) {
+    reference?.element = this;
+  }
 
   /// Initialize a newly created element to have the given [name].
   ElementImpl.forNode(Identifier name)
       : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
 
   /// Initialize from serialized information.
-  ElementImpl.forSerialized(this._enclosingElement);
+  ElementImpl.forSerialized(this._enclosingElement)
+      : reference = null,
+        linkedNode = null;
 
   /// The length of the element's code, or `null` if the element is synthetic.
   int get codeLength => _codeLength;
@@ -3100,7 +3409,12 @@
   bool get isResynthesized => enclosingUnit?.resynthesizerContext != null;
 
   @override
-  bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
+  bool get isSynthetic {
+    if (linkedNode != null) {
+      return linkedNode.isSynthetic;
+    }
+    return hasModifier(Modifier.SYNTHETIC);
+  }
 
   /// Set whether this element is synthetic.
   void set isSynthetic(bool isSynthetic) {
@@ -3129,6 +3443,11 @@
   }
 
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     return _metadata ?? const <ElementAnnotation>[];
   }
 
@@ -3157,8 +3476,6 @@
     _nameOffset = offset;
   }
 
-  Reference get reference => null;
-
   @override
   AnalysisSession get session {
     return _enclosingElement?.session;
@@ -3340,6 +3657,23 @@
     }
   }
 
+  /// Return annotations for the given [nodeList] in the [unit].
+  List<ElementAnnotation> _buildAnnotations2(
+      CompilationUnitElementImpl unit, List<LinkedNode> nodeList) {
+    var length = nodeList.length;
+    if (length == 0) {
+      return const <ElementAnnotation>[];
+    }
+
+    var annotations = new List<ElementAnnotation>(length);
+    for (int i = 0; i < length; i++) {
+      var ast = unit.linkedContext.readNode(nodeList[i]);
+      annotations[i] = ElementAnnotationImpl(enclosingUnit)
+        ..annotationAst = ast;
+    }
+    return annotations;
+  }
+
   /// If the element associated with the given [type] is a generic function type
   /// element, then make it a child of this element. Return the [type] as a
   /// convenience.
@@ -3526,6 +3860,11 @@
       : _unlinkedEnum = null,
         super(name, offset);
 
+  EnumElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+      Reference reference, LinkedNode linkedNode)
+      : _unlinkedEnum = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created class element to have the given [name].
   EnumElementImpl.forNode(Identifier name)
       : _unlinkedEnum = null,
@@ -3544,6 +3883,9 @@
   @override
   List<PropertyAccessorElement> get accessors {
     if (_accessors == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3587,6 +3929,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedEnum != null) {
       return _unlinkedEnum.documentationComment?.text;
     }
@@ -3596,6 +3943,9 @@
   @override
   List<FieldElement> get fields {
     if (_fields == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3654,6 +4004,9 @@
   @override
   List<MethodElement> get methods {
     if (_methods == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3666,6 +4019,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedEnum != null) {
       return _unlinkedEnum.name;
     }
@@ -3716,11 +4072,14 @@
   void createToStringMethodElement() {
     var method = new MethodElementImpl('toString', -1);
     method.isSynthetic = true;
-    if (_unlinkedEnum != null) {
+    if (linkedNode != null || _unlinkedEnum != null) {
       method.returnType = context.typeProvider.stringType;
       method.type = new FunctionTypeImpl(method);
     }
     method.enclosingElement = this;
+    if (linkedNode != null) {
+      method.reference = reference.getChild('@method').getChild('toString');
+    }
     _methods = <MethodElement>[method];
   }
 
@@ -3755,6 +4114,51 @@
         .toList(growable: false);
     createToStringMethodElement();
   }
+
+  void _resynthesizeMembers2() {
+    var fields = <FieldElementImpl>[];
+    var getters = <PropertyAccessorElementImpl>[];
+
+    // Build the 'index' field.
+    {
+      var field = FieldElementImpl('index', -1)
+        ..enclosingElement = this
+        ..isSynthetic = true
+        ..isFinal = true
+        ..type = context.typeProvider.intType;
+      fields.add(field);
+      getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+          reference: reference.getChild('@getter').getChild('index'))
+        ..enclosingElement = this);
+    }
+
+    // Build the 'values' field.
+    {
+      var field = ConstFieldElementImpl_EnumValues(this);
+      fields.add(field);
+      getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+          reference: reference.getChild('@getter').getChild('values'))
+        ..enclosingElement = this);
+    }
+
+    // Build fields for all enum constants.
+    var constants = linkedNode.enumDeclaration_constants;
+    for (var i = 0; i < constants.length; ++i) {
+      var constant = constants[i];
+      var name = enclosingUnit.linkedContext.getSimpleName(
+        constant.enumConstantDeclaration_name,
+      );
+      var reference = this.reference.getChild('@constant').getChild(name);
+      var field = new ConstFieldElementImpl_EnumValue.forLinkedNode(
+          this, reference, constant, i);
+      fields.add(field);
+      getters.add(field.getter);
+    }
+
+    _fields = fields;
+    _accessors = getters;
+    createToStringMethodElement();
+  }
 }
 
 /// A base class for concrete implementations of an [ExecutableElement].
@@ -3779,14 +4183,17 @@
 
   /// Initialize a newly created executable element to have the given [name] and
   /// [offset].
-  ExecutableElementImpl(String name, int offset)
+  ExecutableElementImpl(String name, int offset, {Reference reference})
       : serializedExecutable = null,
-        super(name, offset);
+        super(name, offset, reference: reference);
 
   /// Initialize using the given linked node.
-  ExecutableElementImpl.forLinkedNode(ElementImpl enclosingElement)
+  ExecutableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
       : serializedExecutable = null,
-        super.forLinkedNode(enclosingElement);
+        super.forLinkedNode(enclosing, reference, linkedNode) {
+    reference.element = this;
+  }
 
   /// Initialize a newly created executable element to have the given [name].
   ExecutableElementImpl.forNode(Identifier name)
@@ -3827,6 +4234,9 @@
 
   @override
   String get displayName {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -3835,6 +4245,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.documentationComment?.text;
     }
@@ -3878,6 +4293,9 @@
 
   @override
   bool get isAsynchronous {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isAsynchronous(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isAsynchronous;
     }
@@ -3886,6 +4304,9 @@
 
   @override
   bool get isExternal {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isExternal(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isExternal;
     }
@@ -3894,6 +4315,9 @@
 
   @override
   bool get isGenerator {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isGenerator(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isGenerator;
     }
@@ -3917,6 +4341,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -3925,6 +4352,12 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.namedCompilationUnitMember_name,
+      );
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && serializedExecutable != null) {
       return serializedExecutable.nameOffset;
@@ -3935,6 +4368,37 @@
   @override
   List<ParameterElement> get parameters {
     if (_parameters == null) {
+      if (linkedNode != null) {
+        var context = enclosingUnit.linkedContext;
+        var containerRef = reference.getChild('@parameter');
+        var formalParameters = context.getFormalParameters(linkedNode);
+        if (formalParameters != null) {
+          _parameters = formalParameters.map((node) {
+            if (node.kind == LinkedNodeKind.defaultFormalParameter) {
+              var parameterNode = node.defaultFormalParameter_parameter;
+              var name = context.getFormalParameterName(parameterNode);
+              var reference = containerRef.getChild(name);
+              reference.node = node;
+              return DefaultParameterElementImpl.forLinkedNode(
+                this,
+                reference,
+                node,
+              );
+            } else {
+              var name = context.getFormalParameterName(node);
+              var reference = containerRef.getChild(name);
+              reference.node = node;
+              return ParameterElementImpl.forLinkedNodeFactory(
+                this,
+                reference,
+                node,
+              );
+            }
+          }).toList();
+        } else {
+          _parameters = const [];
+        }
+      }
       if (serializedExecutable != null) {
         _parameters = ParameterElementImpl.resynthesizeList(
             serializedExecutable.parameters, this);
@@ -3955,6 +4419,10 @@
 
   @override
   DartType get returnType {
+    if (linkedNode != null) {
+      return _returnType ??=
+          enclosingUnit.linkedContext.getReturnType(linkedNode);
+    }
     if (serializedExecutable != null &&
         _declaredReturnType == null &&
         _returnType == null) {
@@ -3976,8 +4444,11 @@
 
   @override
   FunctionType get type {
+    if (linkedNode != null) {
+      return _type ??= new FunctionTypeImpl(this);
+    }
     if (serializedExecutable != null) {
-      _type ??= new FunctionTypeImpl(this);
+      return _type ??= new FunctionTypeImpl(this);
     }
     return _type;
   }
@@ -4228,6 +4699,38 @@
   /// [name] at the given [offset].
   FieldElementImpl(String name, int offset) : super(name, offset);
 
+  FieldElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (!linkedNode.isSynthetic) {
+      var enclosingRef = enclosing.reference;
+
+      this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+        this,
+        reference: enclosingRef.getChild('@getter').getChild(name),
+      );
+
+      if (!isConst && !isFinal) {
+        this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+          this,
+          reference: enclosingRef.getChild('@setter').getChild(name),
+        );
+      }
+    }
+  }
+
+  factory FieldElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+      return ConstFieldElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    }
+    return FieldElementImpl.forLinkedNode(enclosing, reference, linkedNode);
+  }
+
   /// Initialize a newly created field element to have the given [name].
   FieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -4275,6 +4778,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isStatic(linkedNode);
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.isStatic;
     }
@@ -4320,6 +4826,10 @@
   FieldFormalParameterElementImpl(String name, int nameOffset)
       : super(name, nameOffset);
 
+  FieldFormalParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created parameter element to have the given [name].
   FieldFormalParameterElementImpl.forNode(Identifier name)
       : super.forNode(name);
@@ -4362,6 +4872,11 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      return _type ??= enclosingUnit.linkedContext.getType(
+        linkedNode.fieldFormalParameter_type2,
+      );
+    }
     if (unlinkedParam != null &&
         unlinkedParam.type == null &&
         !unlinkedParam.isFunctionTyped &&
@@ -4396,6 +4911,10 @@
   /// [offset].
   FunctionElementImpl(String name, int offset) : super(name, offset);
 
+  FunctionElementImpl.forLinkedNode(CompilationUnitElementImpl enclosingUnit,
+      Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
   /// Initialize a newly created function element to have the given [name].
   FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -4447,6 +4966,16 @@
   ElementKind get kind => ElementKind.FUNCTION;
 
   @override
+  DartType get returnType {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getType(
+        linkedNode.functionDeclaration_returnType2,
+      );
+    }
+    return super.returnType;
+  }
+
+  @override
   SourceRange get visibleRange {
     if (serializedExecutable != null) {
       if (serializedExecutable.visibleLength == 0) {
@@ -4768,6 +5297,13 @@
       : _unlinkedTypedef = null,
         super(name, offset);
 
+  GenericTypeAliasElementImpl.forLinkedNode(
+      CompilationUnitElementImpl enclosingUnit,
+      Reference reference,
+      LinkedNode linkedNode)
+      : _unlinkedTypedef = null,
+        super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
   /// Initialize a newly created type alias element to have the given [name].
   GenericTypeAliasElementImpl.forNode(Identifier name)
       : _unlinkedTypedef = null,
@@ -4799,6 +5335,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedTypedef != null) {
       return _unlinkedTypedef.documentationComment?.text;
     }
@@ -4818,31 +5359,53 @@
 
   @override
   GenericFunctionTypeElementImpl get function {
-    if (_function == null) {
-      if (_unlinkedTypedef != null) {
-        if (_unlinkedTypedef.style == TypedefStyle.genericFunctionType) {
-          DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
-              this, _unlinkedTypedef.returnType,
-              declaredType: true);
-          if (type is FunctionType) {
-            Element element = type.element;
-            if (element is GenericFunctionTypeElement) {
-              (element as GenericFunctionTypeElementImpl).enclosingElement =
-                  this;
-              _function = element;
-            }
+    if (_function != null) return _function;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      _function = new GenericFunctionTypeElementImpl.forOffset(-1);
+      _function.enclosingElement = this;
+      _function.returnType = context.getType(
+        linkedNode.functionTypeAlias_returnType2,
+      );
+      var containerRef = reference.getChild('@parameter');
+      var formalParameters = context.getFormalParameters(linkedNode);
+      _function.parameters = formalParameters.map((node) {
+        var name = context.getFormalParameterName(node);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return ParameterElementImpl.forLinkedNodeFactory(
+          this,
+          reference,
+          node,
+        );
+      }).toList();
+      return _function;
+    }
+
+    if (_unlinkedTypedef != null) {
+      if (_unlinkedTypedef.style == TypedefStyle.genericFunctionType) {
+        DartType type = enclosingUnit.resynthesizerContext.resolveTypeRef(
+            this, _unlinkedTypedef.returnType,
+            declaredType: true);
+        if (type is FunctionType) {
+          Element element = type.element;
+          if (element is GenericFunctionTypeElement) {
+            (element as GenericFunctionTypeElementImpl).enclosingElement = this;
+            _function = element;
           }
-        } else {
-          _function = new GenericFunctionTypeElementImpl.forOffset(-1);
-          _function.enclosingElement = this;
-          _function.returnType = enclosingUnit.resynthesizerContext
-              .resolveTypeRef(_function, _unlinkedTypedef.returnType,
-                  declaredType: true);
-          _function.parameters = ParameterElementImpl.resynthesizeList(
-              _unlinkedTypedef.parameters, _function);
         }
+      } else {
+        _function = new GenericFunctionTypeElementImpl.forOffset(-1);
+        _function.enclosingElement = this;
+        _function.returnType = enclosingUnit.resynthesizerContext
+            .resolveTypeRef(_function, _unlinkedTypedef.returnType,
+                declaredType: true);
+        _function.parameters = ParameterElementImpl.resynthesizeList(
+            _unlinkedTypedef.parameters, _function);
       }
     }
+
     return _function;
   }
 
@@ -4870,6 +5433,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedTypedef != null) {
       return _unlinkedTypedef.name;
     }
@@ -5087,6 +5653,12 @@
         _linkedDependency = null,
         super(null, offset);
 
+  ImportElementImpl.forLinkedNode(
+      LibraryElementImpl enclosing, LinkedNode linkedNode)
+      : _unlinkedImport = null,
+        _linkedDependency = null,
+        super.forLinkedNode(enclosing, null, linkedNode);
+
   /// Initialize using the given serialized information.
   ImportElementImpl.forSerialized(this._unlinkedImport, this._linkedDependency,
       LibraryElementImpl enclosingLibrary)
@@ -5114,10 +5686,28 @@
   }
 
   @override
+  CompilationUnitElementImpl get enclosingUnit {
+    LibraryElementImpl enclosingLibrary = enclosingElement;
+    return enclosingLibrary._definingCompilationUnit;
+  }
+
+  @override
   String get identifier => "${importedLibrary.identifier}@$nameOffset";
 
   @override
   LibraryElement get importedLibrary {
+    if (_importedLibrary != null) return _importedLibrary;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var relativeUriStr = context.getStringContent(
+        linkedNode.uriBasedDirective_uri,
+      );
+      var relativeUri = Uri.parse(relativeUriStr);
+      var uri = resolveRelativeUri(librarySource.uri, relativeUri);
+      var elementFactory = context.bundleContext.elementFactory;
+      return _importedLibrary = elementFactory.libraryOfUri('$uri');
+    }
     if (_linkedDependency != null) {
       if (_importedLibrary == null) {
         LibraryElementImpl library = enclosingElement as LibraryElementImpl;
@@ -5158,6 +5748,11 @@
 
   @override
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     if (_metadata == null) {
       if (_unlinkedImport != null) {
         return _metadata = _buildAnnotations(
@@ -5365,6 +5960,9 @@
 
   final UnlinkedUnit unlinkedDefiningUnit;
 
+  /// The context of the defining unit.
+  final LinkedUnitContext linkedContext;
+
   /// The compilation unit that defines this library.
   CompilationUnitElement _definingCompilationUnit;
 
@@ -5419,14 +6017,32 @@
       this.context, this.session, String name, int offset, this.nameLength)
       : resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        linkedContext = null,
         super(name, offset);
 
+  LibraryElementImpl.forLinkedNode(
+      this.context,
+      this.session,
+      String name,
+      int offset,
+      this.nameLength,
+      this.linkedContext,
+      Reference reference,
+      LinkedNode linkedNode)
+      : resynthesizerContext = null,
+        unlinkedDefiningUnit = null,
+        super.forLinkedNode(null, reference, linkedNode) {
+    _name = name;
+    _nameOffset = offset;
+  }
+
   /// Initialize a newly created library element in the given [context] to have
   /// the given [name].
   LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name)
       : nameLength = name != null ? name.length : 0,
         resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        linkedContext = null,
         super.forNode(name);
 
   /// Initialize using the given serialized information.
@@ -5438,7 +6054,8 @@
       this.nameLength,
       this.resynthesizerContext,
       this.unlinkedDefiningUnit)
-      : super.forSerialized(null) {
+      : linkedContext = null,
+        super.forSerialized(null) {
     _name = name;
     _nameOffset = offset;
     setResolutionCapability(
@@ -5612,6 +6229,13 @@
   @override
   List<ImportElement> get imports {
     if (_imports == null) {
+      if (linkedNode != null) {
+        return _imports = linkedNode.compilationUnit_directives
+            .where((node) => node.kind == LinkedNodeKind.importDirective)
+            .map((node) {
+          return ImportElementImpl.forLinkedNode(this, node);
+        }).toList();
+      }
       if (unlinkedDefiningUnit != null) {
         _imports = buildImportsFromSummary(this, unlinkedDefiningUnit.imports,
             resynthesizerContext.linkedLibrary.importDependencies);
@@ -5779,6 +6403,13 @@
 
   @override
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      CompilationUnitElementImpl enclosingUnit = _definingCompilationUnit;
+      var context = enclosingUnit.linkedContext;
+      var metadata = context.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     if (_metadata == null) {
       if (unlinkedDefiningUnit != null) {
         _metadata = _buildAnnotations(
@@ -6163,6 +6794,10 @@
   /// given [offset].
   MethodElementImpl(String name, int offset) : super(name, offset);
 
+  MethodElementImpl.forLinkedNode(Reference reference, LinkedNode linkedNode,
+      ClassElementImpl enclosingClass)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode);
+
   /// Initialize a newly created method element to have the given [name].
   MethodElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -6194,6 +6829,14 @@
       super.enclosingElement as ClassElementImpl;
 
   @override
+  bool get isAbstract {
+    if (linkedNode != null) {
+      return !isExternal && enclosingUnit.linkedContext.isAbstract(linkedNode);
+    }
+    return super.isAbstract;
+  }
+
+  @override
   bool get isOperator {
     String name = displayName;
     if (name.isEmpty) {
@@ -6208,6 +6851,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return linkedNode.methodDeclaration_modifierKeyword != 0;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isStatic;
     }
@@ -6233,6 +6879,16 @@
   }
 
   @override
+  DartType get returnType {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getType(
+        linkedNode.methodDeclaration_returnType2,
+      );
+    }
+    return super.returnType;
+  }
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
   @override
@@ -6772,6 +7428,11 @@
       : _unlinkedVariable = null,
         super(name, offset);
 
+  NonParameterVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : _unlinkedVariable = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created variable element to have the given [name].
   NonParameterVariableElementImpl.forNode(Identifier name)
       : _unlinkedVariable = null,
@@ -6800,6 +7461,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.variableDeclaration_declaration.comment,
+      );
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.documentationComment?.text;
     }
@@ -6883,6 +7549,11 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleName(
+        linkedNode.variableDeclaration_name,
+      );
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.name;
     }
@@ -6891,6 +7562,11 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.variableDeclaration_name,
+      );
+    }
     int offset = super.nameOffset;
     if (offset == 0) {
       if (_unlinkedVariable != null) {
@@ -6959,6 +7635,31 @@
       : unlinkedParam = null,
         super(name, nameOffset);
 
+  ParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : unlinkedParam = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
+  factory ParameterElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    var kind = linkedNode.kind;
+    if (kind == LinkedNodeKind.fieldFormalParameter) {
+      return FieldFormalParameterElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    } else if (kind == LinkedNodeKind.simpleFormalParameter) {
+      return ParameterElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   /// Initialize a newly created parameter element to have the given [name].
   ParameterElementImpl.forNode(Identifier name)
       : unlinkedParam = null,
@@ -7110,6 +7811,13 @@
 
   @override
   bool get isCovariant {
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameter = linkedNode.defaultFormalParameter_parameter;
+        return parameter.normalFormalParameter_isCovariant;
+      }
+      return linkedNode.normalFormalParameter_isCovariant;
+    }
     if (isExplicitlyCovariant || inheritsCovariant) {
       return true;
     }
@@ -7133,6 +7841,16 @@
 
   @override
   bool get isFinal {
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameter = linkedNode.defaultFormalParameter_parameter;
+        return parameter.simpleFormalParameter_keyword != 0;
+      }
+      if (linkedNode.kind == LinkedNodeKind.fieldFormalParameter) {
+        return false;
+      }
+      return linkedNode.simpleFormalParameter_keyword != 0;
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.isFinal;
     }
@@ -7168,6 +7886,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.name;
     }
@@ -7176,6 +7897,12 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.normalFormalParameter_identifier,
+      );
+    }
+
     int offset = super.nameOffset;
     if (offset == 0) {
       if (unlinkedParam != null) {
@@ -7193,7 +7920,19 @@
 
   @override
   ParameterKind get parameterKind {
-    if (unlinkedParam != null && _parameterKind == null) {
+    if (_parameterKind != null) return _parameterKind;
+
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        if (linkedNode.defaultFormalParameter_isNamed) {
+          return _parameterKind = ParameterKind.NAMED;
+        } else {
+          return _parameterKind = ParameterKind.POSITIONAL;
+        }
+      }
+      return _parameterKind = ParameterKind.REQUIRED;
+    }
+    if (unlinkedParam != null) {
       switch (unlinkedParam.kind) {
         case UnlinkedParamKind.named:
           _parameterKind = ParameterKind.NAMED;
@@ -7221,6 +7960,18 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      if (_type != null) return _type;
+      if (linkedNode.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameter = linkedNode.defaultFormalParameter_parameter;
+        return _type = enclosingUnit.linkedContext.getType(
+          parameter.simpleFormalParameter_type2,
+        );
+      }
+      return _type = enclosingUnit.linkedContext.getType(
+        linkedNode.simpleFormalParameter_type2,
+      );
+    }
     _resynthesizeTypeAndParameters();
     return super.type;
   }
@@ -7518,6 +8269,10 @@
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
 
+  PropertyAccessorElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created property accessor element to have the given
   /// [name].
   PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7529,8 +8284,9 @@
 
   /// Initialize a newly created synthetic property accessor element to be
   /// associated with the given [variable].
-  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
-      : super(variable.name, variable.nameOffset) {
+  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable,
+      {Reference reference})
+      : super(variable.name, variable.nameOffset, reference: reference) {
     this.variable = variable;
     isStatic = variable.isStatic;
     isSynthetic = true;
@@ -7587,7 +8343,18 @@
   }
 
   @override
+  bool get isAbstract {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isAbstract(linkedNode);
+    }
+    return super.isAbstract;
+  }
+
+  @override
   bool get isGetter {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isGetter(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.kind == UnlinkedExecutableKind.getter;
     }
@@ -7596,6 +8363,9 @@
 
   @override
   bool get isSetter {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isSetter(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.kind == UnlinkedExecutableKind.setter;
     }
@@ -7604,6 +8374,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isStatic(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isStatic ||
           variable is TopLevelVariableElement;
@@ -7627,6 +8400,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -7673,8 +8449,9 @@
     extends PropertyAccessorElementImpl {
   /// Create the implicit getter and bind it to the [property].
   PropertyAccessorElementImpl_ImplicitGetter(
-      PropertyInducingElementImpl property)
-      : super.forVariable(property) {
+      PropertyInducingElementImpl property,
+      {Reference reference})
+      : super.forVariable(property, reference: reference) {
     property.getter = this;
     enclosingElement = property.enclosingElement;
   }
@@ -7709,8 +8486,9 @@
     extends PropertyAccessorElementImpl {
   /// Create the implicit setter and bind it to the [property].
   PropertyAccessorElementImpl_ImplicitSetter(
-      PropertyInducingElementImpl property)
-      : super.forVariable(property) {
+      PropertyInducingElementImpl property,
+      {Reference reference})
+      : super.forVariable(property, reference: reference) {
     property.setter = this;
     enclosingElement = property.enclosingElement;
   }
@@ -7759,6 +8537,10 @@
   /// [offset].
   PropertyInducingElementImpl(String name, int offset) : super(name, offset);
 
+  PropertyInducingElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created element to have the given [name].
   PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -7779,6 +8561,12 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      if (_type != null) return _type;
+      return _type = enclosingUnit.linkedContext.getType(
+        linkedNode.variableDeclaration_type2,
+      );
+    }
     if (isSynthetic && _type == null) {
       if (getter != null) {
         _type = getter.returnType;
@@ -7950,6 +8738,42 @@
   /// the given [name] and [offset].
   TopLevelVariableElementImpl(String name, int offset) : super(name, offset);
 
+  TopLevelVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (!linkedNode.isSynthetic) {
+      var enclosingRef = enclosing.reference;
+
+      this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+        this,
+        reference: enclosingRef.getChild('@getter').getChild(name),
+      );
+
+      if (!isConst && !isFinal) {
+        this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+          this,
+          reference: enclosingRef.getChild('@setter').getChild(name),
+        );
+      }
+    }
+  }
+
+  factory TopLevelVariableElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+      return ConstTopLevelVariableElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    }
+    return TopLevelVariableElementImpl.forLinkedNode(
+      enclosing,
+      reference,
+      linkedNode,
+    );
+  }
+
   /// Initialize a newly created top-level variable element to have the given
   /// [name].
   TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7996,6 +8820,13 @@
       : _unlinkedTypeParam = null,
         super(name, offset);
 
+  TypeParameterElementImpl.forLinkedNode(
+      TypeParameterizedElementMixin enclosing,
+      Reference reference,
+      LinkedNode linkedNode)
+      : _unlinkedTypeParam = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created type parameter element to have the given
   /// [name].
   TypeParameterElementImpl.forNode(Identifier name)
@@ -8016,16 +8847,27 @@
   }
 
   DartType get bound {
-    if (_bound == null) {
-      if (_unlinkedTypeParam != null) {
-        if (_unlinkedTypeParam.bound == null) {
-          return null;
-        }
-        _bound = enclosingUnit.resynthesizerContext.resolveTypeRef(
-            this, _unlinkedTypeParam.bound,
-            instantiateToBoundsAllowed: false, declaredType: true);
+    if (_bound != null) return _bound;
+
+    if (linkedNode != null) {
+      var bound = linkedNode.typeParameter_bound;
+      if (bound != null) {
+        var context = enclosingUnit.linkedContext;
+        return _bound = context.getTypeAnnotationType(bound);
+      } else {
+        return null;
       }
     }
+
+    if (_unlinkedTypeParam != null) {
+      if (_unlinkedTypeParam.bound == null) {
+        return null;
+      }
+      return _bound = enclosingUnit.resynthesizerContext.resolveTypeRef(
+          this, _unlinkedTypeParam.bound,
+          instantiateToBoundsAllowed: false, declaredType: true);
+    }
+
     return _bound;
   }
 
@@ -8067,6 +8909,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedTypeParam != null) {
       return _unlinkedTypeParam.name;
     }
@@ -8083,6 +8928,9 @@
   }
 
   TypeParameterType get type {
+    if (linkedNode != null) {
+      _type ??= new TypeParameterTypeImpl(this);
+    }
     if (_unlinkedTypeParam != null) {
       _type ??= new TypeParameterTypeImpl(this);
     }
@@ -8133,19 +8981,34 @@
 
   @override
   List<TypeParameterElement> get typeParameters {
-    if (_typeParameterElements == null) {
-      List<UnlinkedTypeParam> unlinkedParams = unlinkedTypeParams;
-      if (unlinkedParams != null) {
-        int numTypeParameters = unlinkedParams.length;
-        _typeParameterElements =
-            new List<TypeParameterElement>(numTypeParameters);
-        for (int i = 0; i < numTypeParameters; i++) {
-          _typeParameterElements[i] =
-              new TypeParameterElementImpl.forSerialized(
-                  unlinkedParams[i], this);
-        }
+    if (_typeParameterElements != null) return _typeParameterElements;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeParameter');
+      var typeParameters = context.getTypeParameters(linkedNode);
+      if (typeParameters == null) {
+        return _typeParameterElements = const [];
+      }
+      return _typeParameterElements = typeParameters.map((node) {
+        var name = context.getSimpleName(node.typeParameter_name);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+
+    List<UnlinkedTypeParam> unlinkedParams = unlinkedTypeParams;
+    if (unlinkedParams != null) {
+      int numTypeParameters = unlinkedParams.length;
+      _typeParameterElements =
+          new List<TypeParameterElement>(numTypeParameters);
+      for (int i = 0; i < numTypeParameters; i++) {
+        _typeParameterElements[i] =
+            new TypeParameterElementImpl.forSerialized(unlinkedParams[i], this);
       }
     }
+
     return _typeParameterElements ?? const <TypeParameterElement>[];
   }
 
@@ -8243,6 +9106,10 @@
   /// [offset]. The offset may be `-1` if the element is synthetic.
   UriReferencedElementImpl(String name, int offset) : super(name, offset);
 
+  UriReferencedElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize using the given serialized information.
   UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
       : super.forSerialized(enclosingElement);
@@ -8303,6 +9170,10 @@
   /// [offset].
   VariableElementImpl(String name, int offset) : super(name, offset);
 
+  VariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created variable element to have the given [name].
   VariableElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -8366,6 +9237,9 @@
 
   @override
   bool get isConst {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isConst(linkedNode);
+    }
     return hasModifier(Modifier.CONST);
   }
 
@@ -8379,6 +9253,9 @@
 
   @override
   bool get isFinal {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isFinal(linkedNode);
+    }
     return hasModifier(Modifier.FINAL);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 1d45edd..62e8d17 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -163,6 +163,8 @@
       'EXPECTED_CLASS_MEMBER', "Expected a class member.",
       correction: "Try placing this code inside a class member.");
 
+  static const ParserErrorCode EXPECTED_ELSE_OR_COMMA = _EXPECTED_ELSE_OR_COMMA;
+
   static const ParserErrorCode EXPECTED_EXECUTABLE = const ParserErrorCode(
       'EXPECTED_EXECUTABLE',
       "Expected a method, getter, setter or operator declaration.",
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index c4a7f45..fd3008b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -101,6 +101,7 @@
   _STACK_OVERFLOW,
   _MISSING_CATCH_OR_FINALLY,
   _EXPERIMENT_NOT_ENABLED,
+  _EXPECTED_ELSE_OR_COMMA,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -239,6 +240,9 @@
     r"An equality expression can't be an operand of another equality expression.",
     correction: "Try re-writing the expression.");
 
+const ParserErrorCode _EXPECTED_ELSE_OR_COMMA = const ParserErrorCode(
+    'EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
+
 const ParserErrorCode _EXPECTED_INSTEAD = const ParserErrorCode(
     'EXPECTED_INSTEAD', r"Expected '#string' instead of this.");
 
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index adb3a99..b1161d4 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -213,6 +213,26 @@
           correction: "Try removing the export of one of the libraries, or "
               "explicitly hiding the name in one of the export directives.");
 
+  static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH =
+      const CompileTimeErrorCode(
+          'AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH',
+          "This literal must be both a map and a set, because some elements "
+          "spread a 'Map' and others spread an 'Iterable', but that isn't "
+          "allowed.",
+          correction:
+              "Try removing or changing some of the elements so that all of "
+              "the elements are consistent.");
+
+  static const CompileTimeErrorCode AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER =
+      const CompileTimeErrorCode(
+          'AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER',
+          "This literal must be either a map or a set, but none of the "
+          "elements have enough type information to know which, and that isn't "
+          "allowed.",
+          correction:
+              "Try adding type arguments to the literal (one for sets, two "
+              "for maps).");
+
   /**
    * 15 Metadata: The constant expression given in an annotation is type checked
    * and evaluated in the scope surrounding the declaration being annotated.
@@ -634,6 +654,14 @@
           correction:
               "Try declaring the field as final, or adding the keyword 'static'.");
 
+  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_LIST_OR_SET =
+      const CompileTimeErrorCode('CONST_SPREAD_EXPECTED_LIST_OR_SET',
+          "A list or a set is expected in this spread.");
+
+  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
+      const CompileTimeErrorCode(
+          'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
+
   /**
    * 12.8 Maps: It is a compile-time error if the key of an entry in a constant
    * map literal is an instance of a class that implements the operator
@@ -973,6 +1001,12 @@
           "The exported library '{0}' can't have a part-of directive.",
           correction: "Try exporting the library that the part is a part of.");
 
+  static const CompileTimeErrorCode EXPRESSION_IN_MAP =
+      const CompileTimeErrorCode(
+          'EXPRESSION_IN_MAP', "Expressions cannot be used in a map literal.",
+          correction:
+              "Try removing the expression or converting it to be a map entry.");
+
   /**
    * 7.9 Superclasses: It is a compile-time error if the extends clause of a
    * class <i>C</i> includes a type expression that does not denote a class
@@ -1691,6 +1725,12 @@
           correction: "Try defining the label, or "
               "correcting the name to match an existing label.");
 
+  static const CompileTimeErrorCode MAP_ENTRY_NOT_IN_MAP =
+      const CompileTimeErrorCode('MAP_ENTRY_NOT_IN_MAP',
+          "Map entries can only be used in a map literal.",
+          correction:
+              "Try converting the collection to a map or removing the map entry.");
+
   /**
    * 7 Classes: It is a compile time error if a class <i>C</i> declares a member
    * with the same name as <i>C</i>.
@@ -2239,6 +2279,14 @@
           "{0} required argument(s) expected, but {1} found.",
           correction: "Try adding the missing arguments.");
 
+  static const CompileTimeErrorCode NOT_ITERABLE_SPREAD =
+      const CompileTimeErrorCode('NOT_ITERABLE_SPREAD',
+          "Spread elements in list or set literals must implement 'Iterable'.");
+
+  static const CompileTimeErrorCode NOT_MAP_SPREAD = const CompileTimeErrorCode(
+      'NOT_MAP_SPREAD',
+      "Spread elements in map literals must implement 'Map'.");
+
   /**
    * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the
    * superinitializer appears and let <i>S</i> be the superclass of <i>C</i>.
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
new file mode 100644
index 0000000..29b65b9
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -0,0 +1,203 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// Verifier for [CollectionElement]s in list, set, or map literals.
+class LiteralElementVerifier {
+  final TypeProvider typeProvider;
+  final TypeSystem typeSystem;
+  final ErrorReporter errorReporter;
+  final bool Function(Expression) checkForUseOfVoidResult;
+
+  final bool forList;
+  final bool forSet;
+  final DartType elementType;
+
+  final bool forMap;
+  final DartType mapKeyType;
+  final DartType mapValueType;
+
+  LiteralElementVerifier(
+    this.typeProvider,
+    this.typeSystem,
+    this.errorReporter,
+    this.checkForUseOfVoidResult, {
+    this.forList = false,
+    this.forSet = false,
+    this.elementType,
+    this.forMap = false,
+    this.mapKeyType,
+    this.mapValueType,
+  });
+
+  void verify(CollectionElement element) {
+    _verifyElement(element);
+  }
+
+  /// Check that the given [type] is assignable to the [elementType], otherwise
+  /// report the list or set error on the [errorNode].
+  void _checkAssignableToElementType(DartType type, AstNode errorNode) {
+    if (!typeSystem.isAssignableTo(type, elementType)) {
+      var errorCode = forList
+          ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+          : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
+      errorReporter.reportTypeErrorForNode(
+        errorCode,
+        errorNode,
+        [type, elementType],
+      );
+    }
+  }
+
+  /// Verify that the given [element] can be assigned to the [elementType] of
+  /// the enclosing list, set, of map literal.
+  void _verifyElement(CollectionElement element) {
+    if (element is Expression) {
+      if (forList || forSet) {
+        if (!elementType.isVoid && checkForUseOfVoidResult(element)) {
+          return;
+        }
+        _checkAssignableToElementType(element.staticType, element);
+      } else {
+        errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.EXPRESSION_IN_MAP, element);
+      }
+    } else if (element is ForElement) {
+      _verifyElement(element.body);
+    } else if (element is IfElement) {
+      _verifyElement(element.thenElement);
+      _verifyElement(element.elseElement);
+    } else if (element is MapLiteralEntry) {
+      if (forMap) {
+        _verifyMapLiteralEntry(element);
+      } else {
+        errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, element);
+      }
+    } else if (element is SpreadElement) {
+      Expression expression = element.expression;
+      if (forList || forSet) {
+        _verifySpreadForListOrSet(expression);
+      } else if (forMap) {
+        _verifySpreadForMap(expression);
+      }
+    }
+  }
+
+  /// Verify that the [entry]'s key and value are assignable to [mapKeyType]
+  /// and [mapValueType].
+  void _verifyMapLiteralEntry(MapLiteralEntry entry) {
+    if (!mapKeyType.isVoid && checkForUseOfVoidResult(entry.key)) {
+      return;
+    }
+
+    if (!mapValueType.isVoid && checkForUseOfVoidResult(entry.value)) {
+      return;
+    }
+
+    var keyType = entry.key.staticType;
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+        entry.key,
+        [keyType, mapKeyType],
+      );
+    }
+
+    var valueType = entry.value.staticType;
+    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+        entry.value,
+        [valueType, mapValueType],
+      );
+    }
+  }
+
+  /// Verify that the type of the elements of the given [expression] can be
+  /// assigned to the [elementType] of the enclosing collection.
+  void _verifySpreadForListOrSet(Expression expression) {
+    var expressionType = expression.staticType;
+    if (expressionType.isDynamic) return;
+
+    // TODO(scheglov) Check for non-null-aware spread?
+    if (expressionType.isDartCoreNull) return;
+
+    InterfaceType iterableType;
+    var iterableObjectType = typeProvider.iterableObjectType;
+    if (expressionType is InterfaceTypeImpl &&
+        typeSystem.isSubtypeOf(expressionType, iterableObjectType)) {
+      iterableType = expressionType.asInstanceOf(
+        iterableObjectType.element,
+      );
+    }
+
+    if (iterableType == null) {
+      return errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+        expression,
+      );
+    }
+
+    var iterableElementType = iterableType.typeArguments[0];
+    if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+      var errorCode = forList
+          ? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
+          : StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
+      errorReporter.reportTypeErrorForNode(
+        errorCode,
+        expression,
+        [iterableElementType, elementType],
+      );
+    }
+  }
+
+  /// Verify that the [expression] is a subtype of `Map<Object, Object>`, and
+  /// its key and values are assignable to [mapKeyType] and [mapValueType].
+  void _verifySpreadForMap(Expression expression) {
+    var expressionType = expression.staticType;
+    if (expressionType.isDynamic) return;
+
+    // TODO(scheglov) Check for non-null-aware spread?
+    if (expressionType.isDartCoreNull) return;
+
+    InterfaceType mapType;
+    var mapObjectObjectType = typeProvider.mapObjectObjectType;
+    if (expressionType is InterfaceTypeImpl &&
+        typeSystem.isSubtypeOf(expressionType, mapObjectObjectType)) {
+      mapType = expressionType.asInstanceOf(mapObjectObjectType.element);
+    }
+
+    if (mapType == null) {
+      return errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.NOT_MAP_SPREAD,
+        expression,
+      );
+    }
+
+    var keyType = mapType.typeArguments[0];
+    if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [keyType, mapKeyType],
+      );
+    }
+
+    var valueType = mapType.typeArguments[1];
+    if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+      errorReporter.reportTypeErrorForNode(
+        StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
+        expression,
+        [valueType, mapValueType],
+      );
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 808478c..55671cc 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -25,7 +25,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/timestamped_data.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
@@ -34,8 +33,6 @@
 import 'package:analyzer/src/task/manager.dart';
 import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:path/path.dart' as pathos;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:pub_semver/pub_semver.dart';
 
 export 'package:analyzer/error/listener.dart' show RecordingErrorListener;
@@ -747,12 +744,6 @@
   Logger _logger = Logger.NULL;
 
   /**
-   * The plugin that defines the extension points and extensions that are
-   * inherently defined by the analysis engine.
-   */
-  final EnginePlugin enginePlugin = new EnginePlugin();
-
-  /**
    * The instrumentation service that is to be used by this analysis engine.
    */
   InstrumentationService _instrumentationService =
@@ -803,13 +794,6 @@
   }
 
   /**
-   * Return the list of plugins that clients are required to process, either by
-   * creating an [ExtensionManager] or by using the method
-   * [processRequiredPlugins].
-   */
-  List<Plugin> get requiredPlugins => <Plugin>[enginePlugin];
-
-  /**
    * Return the task manager used to manage the tasks used to analyze code.
    */
   TaskManager get taskManager {
@@ -841,12 +825,8 @@
    * plugins. This method can only be used by clients that do not need to
    * process any other plugins.
    */
-  void processRequiredPlugins() {
-    if (enginePlugin.workManagerFactoryExtensionPoint == null) {
-      ExtensionManager manager = new ExtensionManager();
-      manager.processPlugins(requiredPlugins);
-    }
-  }
+  @deprecated
+  void processRequiredPlugins() {}
 
   /**
    * Return `true` if the given [fileName] is an analysis options file.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 48f58c6..50697a0 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -15,11 +15,13 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/literal_element_verifier.dart';
 import 'package:analyzer/src/error/pending_error.dart';
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -28,7 +30,6 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /**
  * A visitor used to traverse an AST structure looking for additional errors and
@@ -740,13 +741,6 @@
   }
 
   @override
-  @deprecated
-  void visitForEachStatement(ForEachStatement node) {
-    _checkForInIterable(node);
-    super.visitForEachStatement(node);
-  }
-
-  @override
   void visitFormalParameterList(FormalParameterList node) {
     _checkDuplicateDefinitionInParameterList(node);
     _checkUseOfCovariantInParameters(node);
@@ -773,18 +767,6 @@
   }
 
   @override
-  @deprecated
-  void visitForStatement(ForStatement node) {
-    if (node.condition != null) {
-      _checkForNonBoolCondition(node.condition);
-    }
-    if (node.variables != null) {
-      _checkDuplicateVariables(node.variables);
-    }
-    super.visitForStatement(node);
-  }
-
-  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement functionElement = node.declaredElement;
     if (functionElement != null &&
@@ -913,6 +895,12 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    _checkForNonBoolCondition(node.condition);
+    super.visitIfElement(node);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     _checkForNonBoolCondition(node.condition);
     super.visitIfStatement(node);
@@ -1014,28 +1002,6 @@
   }
 
   @override
-  @deprecated
-  void visitMapLiteral(MapLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-    if (typeArguments != null) {
-      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-      if (arguments.isNotEmpty) {
-        if (node.isConst) {
-          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
-              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
-        }
-      }
-      _checkTypeArgumentCount(typeArguments, 2,
-          StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS);
-    }
-    _checkForRawTypedLiteral(node);
-    _checkForImplicitDynamicTypedLiteral(node);
-    _checkForMapTypeNotAssignable(node);
-    _checkForNonConstMapAsExpressionStatement(node);
-    super.visitMapLiteral(node);
-  }
-
-  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement previousFunction = _enclosingFunction;
     try {
@@ -1221,28 +1187,6 @@
   }
 
   @override
-  @deprecated
-  void visitSetLiteral(SetLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-    if (typeArguments != null) {
-      if (node.isConst) {
-        NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-        if (arguments.isNotEmpty) {
-          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
-              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET);
-        }
-      }
-      _checkTypeArgumentCount(typeArguments, 1,
-          StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS);
-    }
-    _checkForRawTypedLiteral(node);
-    _checkForImplicitDynamicTypedLiteral(node);
-    _checkForSetElementTypeNotAssignable(node);
-
-    super.visitSetLiteral(node);
-  }
-
-  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
     TypeArgumentList typeArguments = node.typeArguments;
     if (node.isMap) {
@@ -1259,7 +1203,7 @@
       }
       _checkForRawTypedLiteral(node);
       _checkForImplicitDynamicTypedLiteral(node);
-      _checkForMapTypeNotAssignable3(node);
+      _checkForMapTypeNotAssignable(node);
       _checkForNonConstMapAsExpressionStatement3(node);
     } else if (node.isSet) {
       if (typeArguments != null) {
@@ -2284,63 +2228,6 @@
   }
 
   /**
-   * Verify that the type of the elements of the given [spreadExpression] (the
-   * [spreadExpressionType]) can be assigned to the element type of the
-   * enclosing collection (the [elementType]). If not, report an error with the
-   * given [errorCode].
-   */
-  void _checkForArgumentTypeNotAssignableInSpread(
-      Expression spreadExpression,
-      DartType spreadExpressionType,
-      DartType elementType,
-      ErrorCode errorCode) {
-    if (spreadExpressionType != null && elementType != null) {
-      if (!elementType.isVoid && _checkForUseOfVoidResult(spreadExpression)) {
-        return;
-      }
-      if (spreadExpressionType is InterfaceType) {
-        if (_typeSystem.isSubtypeOf(
-            spreadExpressionType, _typeProvider.iterableObjectType)) {
-          InterfaceType iterableType =
-              (spreadExpressionType as InterfaceTypeImpl)
-                  .asInstanceOf(_typeProvider.iterableType.element);
-          if (iterableType != null) {
-            // The `iterableType` will be `null` when `spreadExpressionType` is
-            // `Null`. Fall through in that case to perform the default type
-            // check.
-            List<DartType> typeArguments = iterableType.typeArguments;
-            if (typeArguments.length == 1) {
-              _checkForAssignableExpressionAtType(
-                  spreadExpression, typeArguments[0], elementType, errorCode);
-              return;
-            }
-          }
-        } else if (_typeSystem.isSubtypeOf(
-            spreadExpressionType, _typeProvider.mapObjectObjectType)) {
-          // TODO(brianwilkerson) Handle spreads involving maps? This method
-          //  isn't currently called for maps, but might be if it's reworked as
-          //  expected.
-//          InterfaceType mapType =
-//              (spreadExpressionType as InterfaceTypeImpl)
-//                  .asInstanceOf(_typeProvider.mapType.element);
-//          if (mapType != null) {
-//            List<DartType> typeArguments = mapType.typeArguments;
-//            if (typeArguments.length == 2) {
-//              _checkForAssignableExpressionAtType(
-//                  spreadExpression, typeArguments[0], keyType, errorCode);
-//              _checkForAssignableExpressionAtType(
-//                  spreadExpression, typeArguments[1], valueType, errorCode);
-//              return;
-//            }
-//          }
-        }
-      }
-      _checkForAssignableExpressionAtType(
-          spreadExpression, spreadExpressionType, elementType, errorCode);
-    }
-  }
-
-  /**
    * Verify that the given [expression] can be assigned to its corresponding
    * parameters. The [expectedStaticType] is the expected static type.
    *
@@ -2599,34 +2486,6 @@
   }
 
   /**
-   * Verify that the given [element] can be assigned to the [elementType] of the
-   * enclosing list or set literal. Report an error with the given [errorCode]
-   * if not.
-   *
-   * This method corresponds to
-   * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
-   */
-  void _checkForCollectionElementTypeNotAssignableWithElementType(
-      CollectionElement element, DartType elementType, ErrorCode errorCode) {
-    if (element is ForElement) {
-      _checkForCollectionElementTypeNotAssignableWithElementType(
-          element.body, elementType, errorCode);
-    } else if (element is IfElement) {
-      _checkForCollectionElementTypeNotAssignableWithElementType(
-          element.thenElement, elementType, errorCode);
-      _checkForCollectionElementTypeNotAssignableWithElementType(
-          element.elseElement, elementType, errorCode);
-    } else if (element is Expression) {
-      _checkForArgumentTypeNotAssignable(
-          element, elementType, getStaticType(element), errorCode);
-    } else if (element is SpreadElement) {
-      Expression expression = element.expression;
-      _checkForArgumentTypeNotAssignableInSpread(
-          expression, getStaticType(expression), elementType, errorCode);
-    }
-  }
-
-  /**
    * Verify that the [_enclosingClass] does not have a method and getter pair
    * with the same name on, via inheritance.
    *
@@ -3808,84 +3667,6 @@
   }
 
   /**
-   * Check for a type mis-match between the iterable expression and the
-   * assigned variable in a for-in statement.
-   */
-  @deprecated
-  void _checkForInIterable(ForEachStatement node) {
-    DeclaredIdentifier loopVariable = node.loopVariable;
-
-    // Ignore malformed for statements.
-    if (node.identifier == null && loopVariable == null) {
-      return;
-    }
-
-    if (_checkForNullableDereference(node.iterable)) {
-      return;
-    }
-
-    if (_checkForUseOfVoidResult(node.iterable)) {
-      return;
-    }
-
-    DartType iterableType = getStaticType(node.iterable);
-    if (iterableType.isDynamic) {
-      return;
-    }
-
-    // The type of the loop variable.
-    SimpleIdentifier variable = node.identifier ?? loopVariable.identifier;
-    DartType variableType = getStaticType(variable);
-
-    DartType loopType = node.awaitKeyword != null
-        ? _typeProvider.streamType
-        : _typeProvider.iterableType;
-
-    // Use an explicit string instead of [loopType] to remove the "<E>".
-    String loopTypeName = node.awaitKeyword != null ? "Stream" : "Iterable";
-
-    // The object being iterated has to implement Iterable<T> for some T that
-    // is assignable to the variable's type.
-    // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
-    iterableType = iterableType.resolveToBound(_typeProvider.objectType);
-    DartType bestIterableType =
-        _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
-
-    // Allow it to be a supertype of Iterable<T> (basically just Object) and do
-    // an implicit downcast to Iterable<dynamic>.
-    if (bestIterableType == null) {
-      if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
-        bestIterableType = DynamicTypeImpl.instance;
-      }
-    }
-
-    if (loopVariable != null) {
-      if (loopVariable.isConst) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, loopVariable);
-      }
-    } else if (node.identifier != null) {
-      Element variableElement = node.identifier.staticElement;
-      if (variableElement is VariableElement && variableElement.isConst) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, node.identifier);
-      }
-    }
-
-    if (bestIterableType == null) {
-      _errorReporter.reportTypeErrorForNode(
-          StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
-          node.iterable,
-          [iterableType, loopTypeName]);
-    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
-      _errorReporter.reportTypeErrorForNode(
-          StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
-          node.iterable,
-          [iterableType, loopTypeName, variableType]);
-    }
-  }
-
-  /**
    * Check that the given [typeReference] is not a type reference and that then
    * the [name] is reference to an instance member.
    *
@@ -4082,131 +3863,20 @@
     DartType listElementType = typeArguments[0];
 
     // Check every list element.
-    bool isConst = literal.isConst;
+    var verifier = LiteralElementVerifier(
+      _typeProvider,
+      _typeSystem,
+      _errorReporter,
+      _checkForUseOfVoidResult,
+      forList: true,
+      elementType: listElementType,
+    );
     for (CollectionElement element in literal.elements2) {
-      if (isConst) {
-        // TODO(paulberry): this error should be based on the actual type of the
-        // list element, not the static type.  See dartbug.com/21119.
-        _checkForCollectionElementTypeNotAssignableWithElementType(
-            element,
-            listElementType,
-            CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
-      } else {
-        _checkForCollectionElementTypeNotAssignableWithElementType(
-            element,
-            listElementType,
-            StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
-      }
+      verifier.verify(element);
     }
   }
 
-  /**
-   * Verify that the given [element] can be assigned to the [elementType] of the
-   * enclosing list or set literal. Report an error with the given [errorCode]
-   * if not.
-   *
-   * This method corresponds to
-   * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
-   */
-  void _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-      CollectionElement element,
-      DartType keyType,
-      DartType valueType,
-      ErrorCode keyErrorCode,
-      ErrorCode valueErrorCode) {
-    if (element is ForElement) {
-      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-          element.body, keyType, valueType, keyErrorCode, valueErrorCode);
-    } else if (element is IfElement) {
-      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-          element.thenElement,
-          keyType,
-          valueType,
-          keyErrorCode,
-          valueErrorCode);
-      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-          element.elseElement,
-          keyType,
-          valueType,
-          keyErrorCode,
-          valueErrorCode);
-    } else if (element is MapLiteralEntry) {
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          element.key, keyType, keyErrorCode);
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          element.value, valueType, valueErrorCode);
-    } else if (element is SpreadElement) {
-      Expression expression = element.expression;
-      DartType expressionType = getStaticType(expression);
-      if (expressionType is ParameterizedType) {
-        List<DartType> typeArguments = expressionType.typeArguments;
-        if (typeArguments.length == 2) {
-          _checkForArgumentTypeNotAssignable(
-              expression, keyType, typeArguments[0], keyErrorCode);
-          _checkForArgumentTypeNotAssignable(
-              expression, valueType, typeArguments[1], valueErrorCode);
-        }
-      }
-    }
-  }
-
-  /**
-   * Verify that the key/value of entries of the given map [literal] are
-   * subtypes of the map's static type.
-   *
-   * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
-   * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
-   * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
-   * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
-   */
-  @deprecated
-  void _checkForMapTypeNotAssignable(MapLiteral literal) {
-    // Determine the map's key and value types. We base this on the static type
-    // and not the literal's type arguments because in strong mode, the type
-    // arguments may be inferred.
-    DartType mapType = literal.staticType;
-    if (mapType == null) {
-      // This is known to happen when the literal is the default value in an
-      // optional parameter in a generic function type alias.
-      return;
-    }
-    assert(mapType is InterfaceTypeImpl);
-
-    List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments;
-    assert(typeArguments.length == 2);
-    DartType keyType = typeArguments[0];
-    DartType valueType = typeArguments[1];
-
-    bool isConst = literal.isConst;
-    NodeList<MapLiteralEntry> entries = literal.entries;
-    for (MapLiteralEntry entry in entries) {
-      Expression key = entry.key;
-      Expression value = entry.value;
-      if (isConst) {
-        // TODO(paulberry): this error should be based on the actual type of the
-        // list element, not the static type.  See dartbug.com/21119.
-        _checkForArgumentTypeNotAssignableWithExpectedTypes(key, keyType,
-            CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
-        _checkForArgumentTypeNotAssignableWithExpectedTypes(value, valueType,
-            CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-      }
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          key, keyType, StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE);
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(
-          value, valueType, StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-    }
-  }
-
-  /**
-   * Verify that the key/value of entries of the given map [literal] are
-   * subtypes of the map's static type.
-   *
-   * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
-   * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
-   * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
-   * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
-   */
-  void _checkForMapTypeNotAssignable3(SetOrMapLiteral literal) {
+  void _checkForMapTypeNotAssignable(SetOrMapLiteral literal) {
     // Determine the map's key and value types. We base this on the static type
     // and not the literal's type arguments because in strong mode, the type
     // arguments may be inferred.
@@ -4227,26 +3897,17 @@
       DartType keyType = typeArguments[0];
       DartType valueType = typeArguments[1];
 
-      bool isConst = literal.isConst;
-      NodeList<CollectionElement> entries = literal.elements2;
-      for (CollectionElement entry in entries) {
-        if (isConst) {
-          // TODO(paulberry): this error should be based on the actual type of
-          //  the map entries, not the static type.  See dartbug.com/21119.
-          _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-              entry,
-              keyType,
-              valueType,
-              CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-              CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-        } else {
-          _checkForMapElementTypeNotAssignableWithKeyOrValueType(
-              entry,
-              keyType,
-              valueType,
-              StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
-              StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
-        }
+      var verifier = LiteralElementVerifier(
+        _typeProvider,
+        _typeSystem,
+        _errorReporter,
+        _checkForUseOfVoidResult,
+        forMap: true,
+        mapKeyType: keyType,
+        mapValueType: valueType,
+      );
+      for (CollectionElement element in literal.elements2) {
+        verifier.verify(element);
       }
     }
   }
@@ -4815,38 +4476,6 @@
    *
    * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
    */
-  @deprecated
-  void _checkForNonConstMapAsExpressionStatement(MapLiteral literal) {
-    // "const"
-    if (literal.constKeyword != null) {
-      return;
-    }
-    // has type arguments
-    if (literal.typeArguments != null) {
-      return;
-    }
-    // prepare statement
-    Statement statement = literal.thisOrAncestorOfType<ExpressionStatement>();
-    if (statement == null) {
-      return;
-    }
-    // OK, statement does not start with map
-    if (!identical(statement.beginToken, literal.beginToken)) {
-      return;
-    }
-
-    _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal);
-  }
-
-  /**
-   * Verify the given map [literal] either:
-   * * has `const modifier`
-   * * has explicit type arguments
-   * * is not start of the statement
-   *
-   * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
-   */
   void _checkForNonConstMapAsExpressionStatement3(SetOrMapLiteral literal) {
     // "const"
     if (literal.constKeyword != null) {
@@ -5475,42 +5104,6 @@
    * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
    * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
    */
-  @deprecated
-  void _checkForSetElementTypeNotAssignable(SetLiteral literal) {
-    // Determine the list's element type. We base this on the static type and
-    // not the literal's type arguments because in strong mode, the type
-    // arguments may be inferred.
-    DartType setType = literal.staticType;
-    assert(setType is InterfaceTypeImpl);
-
-    List<DartType> typeArguments = (setType as InterfaceTypeImpl).typeArguments;
-    assert(typeArguments.length == 1);
-
-    DartType setElementType = typeArguments[0];
-
-    // Check every set element.
-    bool isConst = literal.isConst;
-    for (Expression element in literal.elements) {
-      if (isConst) {
-        // TODO(paulberry): this error should be based on the actual type of the
-        // element, not the static type.  See dartbug.com/21119.
-        _checkForArgumentTypeNotAssignableWithExpectedTypes(
-            element,
-            setElementType,
-            CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-      }
-      _checkForArgumentTypeNotAssignableWithExpectedTypes(element,
-          setElementType, StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-    }
-  }
-
-  /**
-   * Verify that the elements in the given set [literal] are subtypes of the
-   * set's static type.
-   *
-   * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
-   * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
-   */
   void _checkForSetElementTypeNotAssignable3(SetOrMapLiteral literal) {
     // Determine the set's element type. We base this on the static type and
     // not the literal's type arguments because in strong mode, the type
@@ -5527,21 +5120,16 @@
       DartType setElementType = typeArguments[0];
 
       // Check every set element.
-      bool isConst = literal.isConst;
+      var verifier = LiteralElementVerifier(
+        _typeProvider,
+        _typeSystem,
+        _errorReporter,
+        _checkForUseOfVoidResult,
+        forSet: true,
+        elementType: setElementType,
+      );
       for (CollectionElement element in literal.elements2) {
-        if (isConst) {
-          // TODO(paulberry): this error should be based on the actual type of
-          //  the element, not the static type.  See dartbug.com/21119.
-          _checkForCollectionElementTypeNotAssignableWithElementType(
-              element,
-              setElementType,
-              CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-        } else {
-          _checkForCollectionElementTypeNotAssignableWithElementType(
-              element,
-              setElementType,
-              StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
-        }
+        verifier.verify(element);
       }
     }
   }
@@ -6918,6 +6506,7 @@
  */
 class _UninstantiatedBoundChecker extends RecursiveAstVisitor {
   final ErrorReporter _errorReporter;
+
   _UninstantiatedBoundChecker(this._errorReporter);
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 5ecd8d4..cd39326 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -3675,8 +3675,8 @@
   ///
   ///     mapLiteral ::=
   ///         'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
-  MapLiteral // ignore: deprecated_member_use_from_same_package
-      parseMapLiteral(Token modifier, TypeArgumentList typeArguments) {
+  SetOrMapLiteral parseMapLiteral(
+      Token modifier, TypeArgumentList typeArguments) {
     Token leftBracket = getAndAdvance();
     if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
       // ignore: deprecated_member_use_from_same_package
@@ -4032,8 +4032,7 @@
         _tokenMatchesKeyword(_peek(), Keyword.FOR)) {
       Token awaitToken = _currentToken;
       Statement statement = parseForStatement();
-      // ignore: deprecated_member_use_from_same_package
-      if (statement is! ForStatement) {
+      if (!(statement is ForStatement2 && statement.forLoopParts is ForParts)) {
         _reportErrorForToken(
             CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
       }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 7891289..88fce5b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1135,8 +1135,6 @@
     if (parent is IfStatement && parent.condition == childOfParent ||
         parent is ForPartsWithDeclarations &&
             parent.condition == childOfParent ||
-        // ignore: deprecated_member_use_from_same_package
-        parent is ForStatement && parent.condition == childOfParent ||
         parent is DoStatement && parent.condition == childOfParent ||
         parent is WhileStatement && parent.condition == childOfParent ||
         parent is ConditionalExpression && parent.condition == childOfParent ||
@@ -3540,11 +3538,6 @@
   }
 
   @override
-  void visitNode(AstNode node) {
-    super.visitNode(node);
-  }
-
-  @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
     _addStaticVariables(node.variables.variables);
     super.visitTopLevelVariableDeclaration(node);
@@ -3670,6 +3663,8 @@
    */
   final InheritanceManager2 inheritance;
 
+  final AnalysisOptionsImpl _analysisOptions;
+
   /// The object used to resolve the element associated with the current node.
   ElementResolver elementResolver;
 
@@ -3736,13 +3731,14 @@
       {Scope nameScope,
       bool propagateTypes: true,
       reportConstEvaluationErrors: true})
-      : super(definingLibrary, source, typeProvider, errorListener,
+      : _analysisOptions = definingLibrary.context.analysisOptions,
+        super(definingLibrary, source, typeProvider, errorListener,
             nameScope: nameScope) {
-    AnalysisOptions options = definingLibrary.context.analysisOptions;
     this.elementResolver = new ElementResolver(this,
         reportConstEvaluationErrors: reportConstEvaluationErrors);
     this.typeSystem = definingLibrary.context.typeSystem;
     bool strongModeHints = false;
+    AnalysisOptions options = _analysisOptions;
     if (options is AnalysisOptionsImpl) {
       strongModeHints = options.strongModeHints;
     }
@@ -4250,6 +4246,7 @@
         resolutionMap.elementDeclaredByFormalParameter(node.parameter)?.type);
     super.visitDefaultFormalParameter(node);
     ParameterElement element = node.declaredElement;
+
     if (element.initializer != null && node.defaultValue != null) {
       (element.initializer as FunctionElementImpl).returnType =
           node.defaultValue.staticType;
@@ -4328,52 +4325,7 @@
   }
 
   @override
-  @deprecated
-  void visitForEachStatementInScope(ForEachStatement node) {
-    Expression iterable = node.iterable;
-    DeclaredIdentifier loopVariable = node.loopVariable;
-    SimpleIdentifier identifier = node.identifier;
-
-    identifier?.accept(this);
-
-    DartType valueType;
-    if (loopVariable != null) {
-      TypeAnnotation typeAnnotation = loopVariable.type;
-      valueType = typeAnnotation?.type ?? UnknownInferredType.instance;
-    }
-    if (identifier != null) {
-      Element element = identifier.staticElement;
-      if (element is VariableElement) {
-        valueType = element.type;
-      } else if (element is PropertyAccessorElement) {
-        if (element.parameters.isNotEmpty) {
-          valueType = element.parameters[0].type;
-        }
-      }
-    }
-    if (valueType != null) {
-      InterfaceType targetType = (node.awaitKeyword == null)
-          ? typeProvider.iterableType
-          : typeProvider.streamType;
-      InferenceContext.setType(iterable, targetType.instantiate([valueType]));
-    }
-
-    //
-    // We visit the iterator before the loop variable because the loop variable
-    // cannot be in scope while visiting the iterator.
-    //
-    iterable?.accept(this);
-    loopVariable?.accept(this);
-    Statement body = node.body;
-    if (body != null) {
-      visitStatementInScope(body);
-    }
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-  }
-
-  @override
-  void visitForElement(ForElement node) {
+  void visitForElementInScope(ForElement node) {
     ForLoopParts forLoopParts = node.forLoopParts;
     if (forLoopParts is ForParts) {
       if (forLoopParts is ForPartsWithDeclarations) {
@@ -4485,17 +4437,6 @@
   }
 
   @override
-  @deprecated
-  void visitForStatementInScope(ForStatement node) {
-    node.variables?.accept(this);
-    node.initialization?.accept(this);
-    InferenceContext.setType(node.condition, typeProvider.boolType);
-    node.condition?.accept(this);
-    visitStatementInScope(node.body);
-    node.updaters.accept(this);
-  }
-
-  @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
     FunctionBody outerFunctionBody = _currentFunctionBody;
@@ -4573,9 +4514,6 @@
   }
 
   @override
-  void visitGenericFunctionType(GenericFunctionType node) {}
-
-  @override
   void visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) {
     super.visitGenericTypeAliasInFunctionScope(node);
     safelyVisitComment(node.documentationComment);
@@ -4695,40 +4633,6 @@
   }
 
   @override
-  @deprecated
-  void visitMapLiteral(MapLiteral node) {
-    InterfaceType mapT;
-    if (node.typeArguments != null) {
-      var targs = node.typeArguments.arguments.map((t) => t.type).toList();
-      if (targs.length == 2 && targs.any((t) => !t.isDynamic)) {
-        mapT = typeProvider.mapType.instantiate([targs[0], targs[1]]);
-      }
-    } else {
-      mapT = typeAnalyzer.inferMapType(node, downwards: true);
-      if (mapT != null &&
-          node.typeArguments == null &&
-          node.entries.isEmpty &&
-          typeSystem.isAssignableTo(typeProvider.iterableObjectType, mapT) &&
-          !typeSystem.isAssignableTo(typeProvider.mapObjectObjectType, mapT)) {
-        // The node is really an empty set literal with no type arguments, so
-        // don't try to visit the replaced map literal.
-        return;
-      }
-    }
-    if (mapT != null) {
-      DartType kType = mapT.typeArguments[0];
-      DartType vType = mapT.typeArguments[1];
-      for (MapLiteralEntry entry in node.entries) {
-        InferenceContext.setType(entry.key, kType);
-        InferenceContext.setType(entry.value, vType);
-      }
-      InferenceContext.setType(node, mapT);
-    } else {
-      InferenceContext.clearType(node);
-    }
-    visitNode(node);
-  }
-
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
@@ -4863,38 +4767,31 @@
   }
 
   @override
-  @deprecated
-  void visitSetLiteral(SetLiteral node) {
-    InterfaceType setT;
-
-    TypeArgumentList typeArguments = node.typeArguments;
-    if (typeArguments != null) {
-      if (typeArguments.length == 1) {
-        DartType elementType = typeArguments.arguments[0].type;
-        if (!elementType.isDynamic) {
-          setT = typeProvider.setType.instantiate([elementType]);
-        }
-      }
-    } else {
-      setT = typeAnalyzer.inferSetType(node, downwards: true);
-    }
-    if (setT != null) {
-      DartType eType = setT.typeArguments[0];
-      for (Expression child in node.elements) {
-        InferenceContext.setType(child, eType);
-      }
-      InferenceContext.setType(node, setT);
-    } else {
-      InferenceContext.clearType(node);
-    }
-    visitNode(node);
-  }
-
-  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    DartType literalType = _computeContextType(node);
-    // TODO(brianwilkerson) Determine whether we need special handling for type
-    // parameter types. (E-mail sent.)
+    var typeArguments = node.typeArguments?.arguments;
+    InterfaceType literalType;
+    var literalResolution = _computeSetOrMapResolution(node);
+    if (literalResolution.kind == _LiteralResolutionKind.set) {
+      if (typeArguments != null && typeArguments.length == 1) {
+        var elementType = typeArguments[0].type;
+        literalType = typeProvider.setType.instantiate([elementType]);
+      } else {
+        literalType = typeAnalyzer.inferSetTypeDownwards(
+            node, literalResolution.contextType);
+      }
+    } else if (literalResolution.kind == _LiteralResolutionKind.map) {
+      if (typeArguments != null && typeArguments.length == 2) {
+        var keyType = typeArguments[0].type;
+        var valueType = typeArguments[1].type;
+        literalType = typeProvider.mapType.instantiate([keyType, valueType]);
+      } else {
+        literalType = typeAnalyzer.inferMapTypeDownwards(
+            node, literalResolution.contextType);
+      }
+    } else {
+      assert(literalResolution.kind == _LiteralResolutionKind.ambiguous);
+      literalType = null;
+    }
     if (literalType is InterfaceType) {
       List<DartType> typeArguments = literalType.typeArguments;
       if (typeArguments.length == 1) {
@@ -4903,15 +4800,34 @@
             typeProvider.iterableType.instantiate([elementType]);
         _pushCollectionTypesDownToAll(node.elements2,
             elementType: elementType, iterableType: iterableType);
+        if (!_analysisOptions.experimentStatus.spread_collections &&
+            !_analysisOptions.experimentStatus.control_flow_collections &&
+            node.elements2.isEmpty &&
+            node.typeArguments == null &&
+            node.isMap) {
+          // The node is really an empty set literal with no type arguments.
+          // Rewrite the AST.
+          // ignore: deprecated_member_use_from_same_package
+          SetOrMapLiteral setLiteral = new AstFactoryImpl().setLiteral(
+              node.constKeyword,
+              null,
+              node.leftBracket,
+              null,
+              node.rightBracket);
+          InferenceContext.setType(
+              setLiteral, InferenceContext.getContext(node));
+          NodeReplacer.replace(node, setLiteral);
+          node = setLiteral;
+        }
       } else if (typeArguments.length == 2) {
         DartType keyType = typeArguments[0];
         DartType valueType = typeArguments[1];
         _pushCollectionTypesDownToAll(node.elements2,
             iterableType: literalType, keyType: keyType, valueType: valueType);
       }
-      InferenceContext.setType(node, literalType);
+      (node as SetOrMapLiteralImpl).contextType = literalType;
     } else {
-      InferenceContext.clearType(node);
+      (node as SetOrMapLiteralImpl).contextType = null;
     }
     super.visitSetOrMapLiteral(node);
   }
@@ -5076,59 +4992,6 @@
     }
   }
 
-  /// Compute the context type for the given set or map [literal].
-  DartType _computeContextType(SetOrMapLiteral literal) {
-    _LiteralResolution typeArgumentsResolution =
-        _fromTypeArguments(literal.typeArguments);
-    DartType contextType = InferenceContext.getContext(literal);
-    _LiteralResolution contextResolution = _fromContextType(contextType);
-    _LeafElements elementCounts = new _LeafElements(literal.elements2);
-    _LiteralResolution elementResolution = elementCounts.resolution;
-
-    List<_LiteralResolution> unambiguousResolutions = [];
-    Set<_LiteralResolutionKind> kinds = new Set<_LiteralResolutionKind>();
-    if (typeArgumentsResolution.kind != _LiteralResolutionKind.ambiguous) {
-      unambiguousResolutions.add(typeArgumentsResolution);
-      kinds.add(typeArgumentsResolution.kind);
-    }
-    if (contextResolution.kind != _LiteralResolutionKind.ambiguous) {
-      unambiguousResolutions.add(contextResolution);
-      kinds.add(contextResolution.kind);
-    }
-    if (elementResolution.kind != _LiteralResolutionKind.ambiguous) {
-      unambiguousResolutions.add(elementResolution);
-      kinds.add(elementResolution.kind);
-    }
-
-    if (kinds.length == 2) {
-      // It looks like it needs to be both a map and a set. Attempt to recover.
-      if (elementResolution.kind == _LiteralResolutionKind.ambiguous &&
-          elementResolution.contextType != null) {
-        return elementResolution.contextType;
-      } else if (typeArgumentsResolution.kind !=
-              _LiteralResolutionKind.ambiguous &&
-          typeArgumentsResolution.contextType != null) {
-        return typeArgumentsResolution.contextType;
-      } else if (contextResolution.kind != _LiteralResolutionKind.ambiguous &&
-          contextResolution.contextType != null) {
-        return contextResolution.contextType;
-      }
-    } else if (unambiguousResolutions.length >= 2) {
-      // If there are three resolutions, the last resolution is guaranteed to be
-      // from the elements, which always has a context type of `null` (when it
-      // is not ambiguous). So, whether there are 2 or 3 resolutions only the
-      // first two are potentially interesting.
-      return unambiguousResolutions[0].contextType ??
-          unambiguousResolutions[1].contextType;
-    } else if (unambiguousResolutions.length == 1) {
-      return unambiguousResolutions[0].contextType;
-    } else if (literal.elements2.isEmpty) {
-      return typeProvider.mapType
-          .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]);
-    }
-    return null;
-  }
-
   /// Given the declared return type of a function, compute the type of the
   /// values which should be returned or yielded as appropriate.  If a type
   /// cannot be computed from the declared return type, return null.
@@ -5160,6 +5023,62 @@
     return declaredType;
   }
 
+  /// Compute the context type for the given set or map [literal].
+  _LiteralResolution _computeSetOrMapResolution(SetOrMapLiteral literal) {
+    _LiteralResolution typeArgumentsResolution =
+        _fromTypeArguments(literal.typeArguments);
+    DartType contextType = InferenceContext.getContext(literal);
+    _LiteralResolution contextResolution = _fromContextType(contextType);
+    _LeafElements elementCounts = new _LeafElements(literal.elements2);
+    _LiteralResolution elementResolution = elementCounts.resolution;
+
+    List<_LiteralResolution> unambiguousResolutions = [];
+    Set<_LiteralResolutionKind> kinds = new Set<_LiteralResolutionKind>();
+    if (typeArgumentsResolution.kind != _LiteralResolutionKind.ambiguous) {
+      unambiguousResolutions.add(typeArgumentsResolution);
+      kinds.add(typeArgumentsResolution.kind);
+    }
+    if (contextResolution.kind != _LiteralResolutionKind.ambiguous) {
+      unambiguousResolutions.add(contextResolution);
+      kinds.add(contextResolution.kind);
+    }
+    if (elementResolution.kind != _LiteralResolutionKind.ambiguous) {
+      unambiguousResolutions.add(elementResolution);
+      kinds.add(elementResolution.kind);
+    }
+
+    if (kinds.length == 2) {
+      // It looks like it needs to be both a map and a set. Attempt to recover.
+      if (elementResolution.kind == _LiteralResolutionKind.ambiguous &&
+          elementResolution.contextType != null) {
+        return elementResolution;
+      } else if (typeArgumentsResolution.kind !=
+              _LiteralResolutionKind.ambiguous &&
+          typeArgumentsResolution.contextType != null) {
+        return typeArgumentsResolution;
+      } else if (contextResolution.kind != _LiteralResolutionKind.ambiguous &&
+          contextResolution.contextType != null) {
+        return contextResolution;
+      }
+    } else if (unambiguousResolutions.length >= 2) {
+      // If there are three resolutions, the last resolution is guaranteed to be
+      // from the elements, which always has a context type of `null` (when it
+      // is not ambiguous). So, whether there are 2 or 3 resolutions only the
+      // first two are potentially interesting.
+      return unambiguousResolutions[0].contextType == null
+          ? unambiguousResolutions[1]
+          : unambiguousResolutions[0];
+    } else if (unambiguousResolutions.length == 1) {
+      return unambiguousResolutions[0];
+    } else if (literal.elements2.isEmpty) {
+      return _LiteralResolution(
+          _LiteralResolutionKind.map,
+          typeProvider.mapType.instantiate(
+              [typeProvider.dynamicType, typeProvider.dynamicType]));
+    }
+    return _LiteralResolution(_LiteralResolutionKind.ambiguous, null);
+  }
+
   /// Return a newly created cloner that can be used to clone constant
   /// expressions.
   ConstantAstCloner _createCloner() {
@@ -5196,16 +5115,14 @@
       DartType unwrappedContextType = unwrap(contextType);
       // TODO(brianwilkerson) Find out what the "greatest closure" is and use that
       // where [unwrappedContextType] is used below.
-      if (typeSystem.isAssignableTo(
-              typeProvider.iterableObjectType, unwrappedContextType) &&
-          !typeSystem.isAssignableTo(
-              typeProvider.mapObjectObjectType, unwrappedContextType)) {
+      bool isIterable = typeSystem.isSubtypeOf(
+          unwrappedContextType, typeProvider.iterableObjectType);
+      bool isMap = typeSystem.isSubtypeOf(
+          unwrappedContextType, typeProvider.mapObjectObjectType);
+      if (isIterable && !isMap) {
         return _LiteralResolution(
             _LiteralResolutionKind.set, unwrappedContextType);
-      } else if (typeSystem.isAssignableTo(
-              typeProvider.mapObjectObjectType, unwrappedContextType) &&
-          !typeSystem.isAssignableTo(
-              typeProvider.iterableObjectType, unwrappedContextType)) {
+      } else if (isMap && !isIterable) {
         return _LiteralResolution(
             _LiteralResolutionKind.map, unwrappedContextType);
       }
@@ -5871,35 +5788,34 @@
   }
 
   @override
-  @deprecated
-  void visitForEachStatement(ForEachStatement node) {
-    Scope outerNameScope = nameScope;
-    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
-    try {
-      nameScope = new EnclosedScope(nameScope);
-      _implicitLabelScope = _implicitLabelScope.nest(node);
-      visitForEachStatementInScope(node);
-    } finally {
-      nameScope = outerNameScope;
-      _implicitLabelScope = outerImplicitScope;
-    }
-  }
-
-  /// Visit the given statement after it's scope has been created. This replaces
-  /// the normal call to the inherited visit method so that ResolverVisitor can
-  /// intervene when type propagation is enabled.
-  ///
-  /// @param node the statement to be visited
-  @deprecated
-  void visitForEachStatementInScope(ForEachStatement node) {
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
     //
     // We visit the iterator before the loop variable because the loop variable
     // cannot be in scope while visiting the iterator.
     //
-    node.identifier?.accept(this);
     node.iterable?.accept(this);
     node.loopVariable?.accept(this);
-    visitStatementInScope(node.body);
+  }
+
+  @override
+  void visitForElement(ForElement node) {
+    Scope outerNameScope = nameScope;
+    try {
+      nameScope = new EnclosedScope(nameScope);
+      visitForElementInScope(node);
+    } finally {
+      nameScope = outerNameScope;
+    }
+  }
+
+  /// Visit the given [node] after it's scope has been created. This replaces
+  /// the normal call to the inherited visit method so that ResolverVisitor can
+  /// intervene when type propagation is enabled.
+  void visitForElementInScope(ForElement node) {
+    // TODO(brianwilkerson) Investigate the possibility of removing the
+    //  visit...InScope methods now that type propagation is no longer done.
+    node.forLoopParts?.accept(this);
+    node.body?.accept(this);
   }
 
   @override
@@ -5919,21 +5835,6 @@
   }
 
   @override
-  @deprecated
-  void visitForStatement(ForStatement node) {
-    Scope outerNameScope = nameScope;
-    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
-    try {
-      nameScope = new EnclosedScope(nameScope);
-      _implicitLabelScope = _implicitLabelScope.nest(node);
-      visitForStatementInScope(node);
-    } finally {
-      nameScope = outerNameScope;
-      _implicitLabelScope = outerImplicitScope;
-    }
-  }
-
-  @override
   void visitForStatement2(ForStatement2 node) {
     Scope outerNameScope = nameScope;
     ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
@@ -5957,20 +5858,6 @@
     visitStatementInScope(node.body);
   }
 
-  /// Visit the given statement after it's scope has been created. This replaces
-  /// the normal call to the inherited visit method so that ResolverVisitor can
-  /// intervene when type propagation is enabled.
-  ///
-  /// @param node the statement to be visited
-  @deprecated
-  void visitForStatementInScope(ForStatement node) {
-    node.variables?.accept(this);
-    node.initialization?.accept(this);
-    node.condition?.accept(this);
-    node.updaters.accept(this);
-    visitStatementInScope(node.body);
-  }
-
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement functionElement = node.declaredElement;
@@ -9063,15 +8950,20 @@
   /// Return `true` if the given collection [element] does not contain any
   /// synthetic tokens.
   bool _isComplete(CollectionElement element) {
-    Token token = element.beginToken;
-    int endOffset = element.endToken.offset;
-    while (token != null && token.offset <= endOffset) {
-      if (token.isSynthetic) {
-        return false;
-      }
-      token = token.next;
-    }
+    // TODO(paulberry,brianwilkerson): the code below doesn't work because it
+    // assumes access to token offsets, which aren't available when working with
+    // expressions resynthesized from summaries.  For now we just assume the
+    // collection element is complete.
     return true;
+//    Token token = element.beginToken;
+//    int endOffset = element.endToken.offset;
+//    while (token != null && token.offset <= endOffset) {
+//      if (token.isSynthetic) {
+//        return false;
+//      }
+//      token = token.next;
+//    }
+//    return true;
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 66fe369..377affe 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -10,10 +10,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast_factory.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' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
@@ -55,11 +52,6 @@
   DartType _dynamicType;
 
   /**
-   * The status of the active experiments of the current context.
-   */
-  ExperimentStatus _experimentStatus;
-
-  /**
    * True if inference failures should be reported, otherwise false.
    */
   bool _strictInference;
@@ -87,7 +79,6 @@
     _promoteManager = _resolver.promoteManager;
     AnalysisOptionsImpl analysisOptions =
         _resolver.definingLibrary.context.analysisOptions;
-    _experimentStatus = analysisOptions.experimentStatus;
     _strictInference = analysisOptions.strictInference;
   }
 
@@ -189,101 +180,30 @@
     return inferred;
   }
 
-  @deprecated
-  ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) {
-    DartType contextType = InferenceContext.getContext(node);
-    if (contextType != null && _experimentStatus.set_literals) {
-      DartType unwrap(DartType type) {
-        if (type is InterfaceType &&
-            type.isDartAsyncFutureOr &&
-            type.typeArguments.length == 1) {
-          return unwrap(type.typeArguments[0]);
-        }
-        return type;
-      }
-
-      DartType unwrappedContextType = unwrap(contextType);
-      if (node.typeArguments == null &&
-          node.entries.isEmpty &&
-          _typeSystem.isAssignableTo(
-              _typeProvider.iterableObjectType, unwrappedContextType) &&
-          !_typeSystem.isAssignableTo(
-              _typeProvider.mapObjectObjectType, unwrappedContextType)) {
-        // The node is really an empty set literal with no type arguments.
-        // Rewrite the AST and infer the type of the set as appropriate.
-        SetLiteral setLiteral = new AstFactoryImpl().setLiteral(
-            node.constKeyword, null, node.leftBracket, null, node.rightBracket);
-        InferenceContext.setType(setLiteral, contextType);
-        NodeReplacer.replace(node, setLiteral);
-        DartType type = inferSetType(setLiteral, downwards: downwards);
-        setLiteral.staticType = type;
-        return type;
-      }
-    }
-    List<DartType> elementTypes;
-    List<ParameterElement> parameters;
-    if (downwards) {
-      if (contextType == null) {
-        return null;
-      }
-      elementTypes = [];
-      parameters = [];
-    } else {
-      var keyTypes =
-          node.entries.map((e) => e.key.staticType).where((t) => t != null);
-      var valueTypes =
-          node.entries.map((e) => e.value.staticType).where((t) => t != null);
-      var keyTypeParam = _typeProvider.mapType.typeParameters[0].type;
-      var valueTypeParam = _typeProvider.mapType.typeParameters[1].type;
-      var syntheticKeyParameter = new ParameterElementImpl.synthetic(
-          'key', keyTypeParam, ParameterKind.POSITIONAL);
-      var syntheticValueParameter = new ParameterElementImpl.synthetic(
-          'value', valueTypeParam, ParameterKind.POSITIONAL);
-      parameters = new List.filled(keyTypes.length, syntheticKeyParameter,
-          growable: true)
-        ..addAll(new List.filled(valueTypes.length, syntheticValueParameter));
-      elementTypes = new List<DartType>.from(keyTypes)..addAll(valueTypes);
+  ParameterizedType inferMapTypeDownwards(
+      SetOrMapLiteral node, DartType contextType) {
+    if (contextType == null) {
+      return null;
     }
 
-    // Use both downwards and upwards information to infer the type.
     var ts = _typeSystem as Dart2TypeSystem;
     ParameterizedType inferred = ts.inferGenericFunctionOrType(
-        _typeProvider.mapType, parameters, elementTypes, contextType,
-        downwards: downwards,
+        _typeProvider.mapType, [], [], contextType,
+        downwards: true,
         errorReporter: _resolver.errorReporter,
         errorNode: node);
     return inferred;
   }
 
-  @deprecated
-  DartType inferSetType(SetLiteral node, {bool downwards: false}) {
-    DartType contextType = InferenceContext.getContext(node);
+  DartType inferSetTypeDownwards(SetOrMapLiteral node, DartType contextType) {
+    if (contextType == null) {
+      return null;
+    }
 
     var ts = _typeSystem as Dart2TypeSystem;
-    List<DartType> elementTypes;
-    List<ParameterElement> parameters;
-
-    if (downwards) {
-      if (contextType == null) {
-        return null;
-      }
-
-      elementTypes = [];
-      parameters = [];
-    } else {
-      // Also use upwards information to infer the type.
-      elementTypes = node.elements
-          .map((e) => e.staticType)
-          .where((t) => t != null)
-          .toList();
-      var setTypeParam = _typeProvider.setType.typeParameters[0].type;
-      var syntheticParamElement = new ParameterElementImpl.synthetic(
-          'element', setTypeParam, ParameterKind.POSITIONAL);
-      parameters = new List.filled(elementTypes.length, syntheticParamElement);
-    }
     DartType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
-        _typeProvider.setType, parameters, elementTypes, contextType,
-        downwards: downwards,
+        _typeProvider.setType, [], [], contextType,
+        downwards: true,
         errorReporter: _resolver.errorReporter,
         errorNode: node);
     return inferred;
@@ -704,65 +624,6 @@
   }
 
   /**
-   * The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
-   * <i><b>const</b> &lt;K, V&gt; {k<sub>1</sub>:e<sub>1</sub>, &hellip;,
-   * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>&lt;K, V&gt; {k<sub>1</sub>:e<sub>1</sub>,
-   * &hellip;, k<sub>n</sub>:e<sub>n</sub>}</i> is `Map&lt;K, V&gt;`. The static type a map
-   * literal of the form <i><b>const</b> {k<sub>1</sub>:e<sub>1</sub>, &hellip;,
-   * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>{k<sub>1</sub>:e<sub>1</sub>, &hellip;,
-   * k<sub>n</sub>:e<sub>n</sub>}</i> is `Map&lt;dynamic, dynamic&gt;`.
-   *
-   * It is a compile-time error if the first type argument to a map literal is not
-   * <i>String</i>.</blockquote>
-   */
-  @override
-  @deprecated
-  void visitMapLiteral(MapLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-
-    // If we have type arguments, use them
-    if (typeArguments != null) {
-      DartType staticKeyType = _dynamicType;
-      DartType staticValueType = _dynamicType;
-      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-      if (arguments != null && arguments.length == 2) {
-        DartType entryKeyType = _getType(arguments[0]);
-        if (entryKeyType != null) {
-          staticKeyType = entryKeyType;
-        }
-        DartType entryValueType = _getType(arguments[1]);
-        if (entryValueType != null) {
-          staticValueType = entryValueType;
-        }
-      }
-      _recordStaticType(
-          node,
-          _typeProvider.mapType
-              .instantiate(<DartType>[staticKeyType, staticValueType]));
-      return;
-    }
-
-    DartType mapDynamicType = _typeProvider.mapType
-        .instantiate(<DartType>[_dynamicType, _dynamicType]);
-
-    // If we have no explicit type arguments, try to infer type arguments.
-    ParameterizedType inferred = inferMapType(node);
-
-    if (inferred != mapDynamicType) {
-      // TODO(jmesserly): this results in an "inferred" message even when we
-      // in fact had an error above, because it will still attempt to return
-      // a type. Perhaps we should record inference from TypeSystem if
-      // everything was successful?
-      _resolver.inferenceContext.recordInference(node, inferred);
-      _recordStaticType(node, inferred);
-      return;
-    }
-
-    // If no type arguments and no inference, use dynamic
-    _recordStaticType(node, mapDynamicType);
-  }
-
-  /**
    * The Dart Language Specification, 12.15.1: <blockquote>An ordinary method invocation <i>i</i>
    * has the form <i>o.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
    * &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
@@ -1010,66 +871,42 @@
   }
 
   @override
-  @deprecated
-  void visitSetLiteral(SetLiteral node) {
-    TypeArgumentList typeArguments = node.typeArguments;
-
-    // If we have type arguments, use them
-    if (typeArguments != null) {
-      DartType elementType = _dynamicType;
-      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
-      if (arguments != null && arguments.length == 1) {
-        DartType type = _getType(arguments[0]);
-        if (type != null) {
-          elementType = type;
-        }
-      }
-      _recordStaticType(
-          node, _typeProvider.setType.instantiate(<DartType>[elementType]));
-      return;
-    }
-
-    DartType setDynamicType =
-        _typeProvider.setType.instantiate(<DartType>[_dynamicType]);
-
-    // If we have no explicit type arguments, try to infer type arguments.
-    ParameterizedType inferred = inferSetType(node);
-
-    if (inferred != setDynamicType) {
-      // TODO(jmesserly): this results in an "inferred" message even when we
-      // in fact had an error above, because it will still attempt to return
-      // a type. Perhaps we should record inference from TypeSystem if
-      // everything was successful?
-      _resolver.inferenceContext.recordInference(node, inferred);
-      _recordStaticType(node, inferred);
-      return;
-    }
-
-    // If no type arguments and no inference, use dynamic
-    _recordStaticType(node, setDynamicType);
-  }
-
-  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    DartType staticType = node.staticType;
-    if (staticType == null) {
-      DartType literalType = _inferSetOrMapLiteralType(node);
-      if (literalType.element == _typeProvider.mapType.element) {
-        (node as SetOrMapLiteralImpl).becomeMap();
-      } else {
-        assert(literalType.element == _typeProvider.setType.element);
-        (node as SetOrMapLiteralImpl).becomeSet();
-      }
-      _resolver.inferenceContext.recordInference(node, literalType);
-      _recordStaticType(node, literalType);
-    } else if (staticType is InterfaceType) {
-      List<DartType> typeArguments = staticType.typeArguments;
+    var typeArguments = node.typeArguments?.arguments;
+
+    // If we have type arguments, use them.
+    // TODO(paulberry): this logic seems redundant with
+    //  ResolverVisitor._fromTypeArguments
+    if (typeArguments != null) {
       if (typeArguments.length == 1) {
         (node as SetOrMapLiteralImpl).becomeSet();
+        var elementType = _getType(typeArguments[0]) ?? _dynamicType;
+        _recordStaticType(
+            node, _typeProvider.setType.instantiate(<DartType>[elementType]));
+        return;
       } else if (typeArguments.length == 2) {
         (node as SetOrMapLiteralImpl).becomeMap();
+        var keyType = _getType(typeArguments[0]) ?? _dynamicType;
+        var valueType = _getType(typeArguments[1]) ?? _dynamicType;
+        _recordStaticType(node,
+            _typeProvider.mapType.instantiate(<DartType>[keyType, valueType]));
+        return;
       }
+      // If we get here, then a nonsense number of type arguments were provided,
+      // so treat it as though no type arguments were provided.
     }
+    DartType literalType = _inferSetOrMapLiteralType(node);
+    if (literalType.isDynamic) {
+      // The literal is ambiguous, and further analysis won't resolve the
+      // ambiguity.  Leave it as neither a set nor a map.
+    } else if (literalType.element == _typeProvider.mapType.element) {
+      (node as SetOrMapLiteralImpl).becomeMap();
+    } else {
+      assert(literalType.element == _typeProvider.setType.element);
+      (node as SetOrMapLiteralImpl).becomeSet();
+    }
+    _resolver.inferenceContext.recordInference(node, literalType);
+    _recordStaticType(node, literalType);
   }
 
   /**
@@ -1283,16 +1120,30 @@
       return _typeSystem.leastUpperBound(thenType, elseType);
     } else if (element is Expression) {
       return element.staticType;
+    } else if (element is MapLiteralEntry) {
+      // This error will be reported elsewhere.
+      return _typeProvider.dynamicType;
     } else if (element is SpreadElement) {
-      DartType collectionType = element.expression.staticType;
-      if (collectionType is ParameterizedType) {
-        List<DartType> typeArguments = collectionType.typeArguments;
-        if (typeArguments.length == 1) {
-          return typeArguments[0];
+      DartType expressionType = element.expression.staticType;
+      bool isNull = expressionType.isDartCoreNull;
+      if (!isNull && expressionType is InterfaceType) {
+        if (_typeSystem.isSubtypeOf(
+            expressionType, _typeProvider.iterableObjectType)) {
+          InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
+              .asInstanceOf(_typeProvider.iterableType.element);
+          return iterableType.typeArguments[0];
         }
+      } else if (expressionType.isDynamic) {
+        return expressionType;
+      } else if (isNull &&
+          element.spreadOperator.type ==
+              TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
+        return expressionType;
       }
+      // TODO(brianwilkerson) Report this as an error.
+      return _typeProvider.dynamicType;
     }
-    return null;
+    throw StateError('Unhandled element type ${element.runtimeType}');
   }
 
   /**
@@ -1551,7 +1402,7 @@
       }
       _InferredCollectionElementTypeInformation elseType =
           _inferCollectionElementType(element.elseElement);
-      return _InferredCollectionElementTypeInformation.leastUpperBound(
+      return _InferredCollectionElementTypeInformation.forIfElement(
           _typeSystem, thenType, elseType);
     } else if (element is Expression) {
       return _InferredCollectionElementTypeInformation(
@@ -1569,41 +1420,19 @@
             expressionType, _typeProvider.iterableObjectType)) {
           InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.iterableType.element);
-          if (iterableType != null) {
-            // The `iterableType` will be `null` when `expressionType` is
-            // `Null`. Fall through in that case to perform the default type
-            // check.
-            List<DartType> typeArguments = iterableType.typeArguments;
-            if (typeArguments.length == 1) {
-              return _InferredCollectionElementTypeInformation(
-                  elementType: typeArguments[0],
-                  keyType: null,
-                  valueType: null);
-            }
-          }
           return _InferredCollectionElementTypeInformation(
-              elementType: _typeProvider.dynamicType,
+              elementType: iterableType.typeArguments[0],
               keyType: null,
               valueType: null);
         } else if (_typeSystem.isSubtypeOf(
             expressionType, _typeProvider.mapObjectObjectType)) {
           InterfaceType mapType = (expressionType as InterfaceTypeImpl)
               .asInstanceOf(_typeProvider.mapType.element);
-          if (mapType != null) {
-            // The `iterableType` will be `null` when `expressionType` is
-            // `Null`. Fall through in that case to perform the default type
-            // check.
-            List<DartType> typeArguments = mapType.typeArguments;
-            if (typeArguments.length == 2) {
-              return _InferredCollectionElementTypeInformation(
-                  elementType: null,
-                  keyType: typeArguments[0],
-                  valueType: typeArguments[1]);
-            }
-          }
-          DartType dynamicType = _typeProvider.dynamicType;
+          List<DartType> typeArguments = mapType.typeArguments;
           return _InferredCollectionElementTypeInformation(
-              elementType: null, keyType: dynamicType, valueType: dynamicType);
+              elementType: null,
+              keyType: typeArguments[0],
+              valueType: typeArguments[1]);
         }
       } else if (expressionType.isDynamic) {
         return _InferredCollectionElementTypeInformation(
@@ -1636,11 +1465,7 @@
       AstNode parent = loopVariable.parent;
       Token awaitKeyword;
       Expression iterable;
-      // ignore: deprecated_member_use_from_same_package
-      if (parent is ForEachStatement) {
-        awaitKeyword = parent.awaitKeyword;
-        iterable = parent.iterable;
-      } else if (parent is ForEachPartsWithDeclaration) {
+      if (parent is ForEachPartsWithDeclaration) {
         AstNode parentParent = parent.parent;
         if (parentParent is ForStatement2Impl) {
           awaitKeyword = parentParent.awaitKeyword;
@@ -1952,11 +1777,10 @@
   }
 
   DartType _inferSetOrMapLiteralType(SetOrMapLiteral literal) {
-    DartType contextType = InferenceContext.getContext(literal);
+    var literalImpl = literal as SetOrMapLiteralImpl;
+    DartType contextType = literalImpl.contextType;
+    literalImpl.contextType = null; // Not needed anymore.
     NodeList<CollectionElement> elements = literal.elements2;
-    if (elements.length < 2 && contextType != null) {
-      return contextType;
-    }
     List<_InferredCollectionElementTypeInformation> inferredTypes = [];
     bool canBeAMap = true;
     bool mustBeAMap = false;
@@ -1976,11 +1800,36 @@
     } else if (canBeAMap && mustBeAMap) {
       return _toMapType(literal, contextType, inferredTypes);
     }
-    if (contextType == null) {
-      DartType dynamicType = _typeProvider.dynamicType;
-      return _typeProvider.mapType.instantiate([dynamicType, dynamicType]);
+    // Note: according to the spec, the following computations should be based
+    // on the greatest closure of the context type (unless the context type is
+    // `?`).  In practice, we can just use the context type directly, because
+    // the only way the greatest closure of the context type could possibly have
+    // a different subtype relationship to `Iterable<Object>` and
+    // `Map<Object, Object>` is if the context type is `?`.
+    bool contextProvidesAmbiguityResolutionClues =
+        contextType != null && contextType is! UnknownInferredType;
+    bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
+        _typeSystem.isSubtypeOf(contextType, _typeProvider.iterableObjectType);
+    bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
+        _typeSystem.isSubtypeOf(contextType, _typeProvider.mapObjectObjectType);
+    if (contextIsIterable && !contextIsMap) {
+      return _toSetType(literal, contextType, inferredTypes);
+    } else if ((contextIsMap && !contextIsIterable) || elements.isEmpty) {
+      return _toMapType(literal, contextType, inferredTypes);
+    } else {
+      // Ambiguous.  We're not going to get any more information to resolve the
+      // ambiguity.  We don't want to make an arbitrary decision at this point
+      // because it will interfere with future type inference (see
+      // dartbug.com/36210), so we return a type of `dynamic`.
+      if (mustBeAMap && mustBeASet) {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, literal);
+      } else {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER, literal);
+      }
+      return _typeProvider.dynamicType;
     }
-    return contextType;
   }
 
   /**
@@ -2106,22 +1955,44 @@
   _InferredCollectionElementTypeInformation(
       {this.elementType, this.keyType, this.valueType});
 
-  factory _InferredCollectionElementTypeInformation.leastUpperBound(
-          TypeSystem typeSystem,
-          _InferredCollectionElementTypeInformation first,
-          _InferredCollectionElementTypeInformation second) =>
-      _InferredCollectionElementTypeInformation(
-          elementType: _leastUpperBoundOfTypes(
-              typeSystem, first.elementType, second.elementType),
-          keyType: _leastUpperBoundOfTypes(
-              typeSystem, first.keyType, second.keyType),
-          valueType: _leastUpperBoundOfTypes(
-              typeSystem, first.valueType, second.valueType));
+  factory _InferredCollectionElementTypeInformation.forIfElement(
+      TypeSystem typeSystem,
+      _InferredCollectionElementTypeInformation thenInfo,
+      _InferredCollectionElementTypeInformation elseInfo) {
+    if (thenInfo.isDynamic) {
+      DartType dynamic = thenInfo.elementType;
+      return _InferredCollectionElementTypeInformation(
+          elementType: _dynamicOrNull(elseInfo.elementType, dynamic),
+          keyType: _dynamicOrNull(elseInfo.keyType, dynamic),
+          valueType: _dynamicOrNull(elseInfo.valueType, dynamic));
+    } else if (elseInfo.isDynamic) {
+      DartType dynamic = elseInfo.elementType;
+      return _InferredCollectionElementTypeInformation(
+          elementType: _dynamicOrNull(thenInfo.elementType, dynamic),
+          keyType: _dynamicOrNull(thenInfo.keyType, dynamic),
+          valueType: _dynamicOrNull(thenInfo.valueType, dynamic));
+    }
+    return _InferredCollectionElementTypeInformation(
+        elementType: _leastUpperBoundOfTypes(
+            typeSystem, thenInfo.elementType, elseInfo.elementType),
+        keyType: _leastUpperBoundOfTypes(
+            typeSystem, thenInfo.keyType, elseInfo.keyType),
+        valueType: _leastUpperBoundOfTypes(
+            typeSystem, thenInfo.valueType, elseInfo.valueType));
+  }
 
   bool get canBeAMap => keyType != null || valueType != null;
 
   bool get canBeASet => elementType != null;
 
+  bool get isDynamic =>
+      elementType != null &&
+      elementType.isDynamic &&
+      keyType != null &&
+      keyType.isDynamic &&
+      valueType != null &&
+      valueType.isDynamic;
+
   bool get mustBeAMap => canBeAMap && elementType == null;
 
   bool get mustBeASet => canBeASet && keyType == null && valueType == null;
@@ -2131,6 +2002,13 @@
     return '($elementType, $keyType, $valueType)';
   }
 
+  static DartType _dynamicOrNull(DartType type, DartType dynamic) {
+    if (type == null) {
+      return null;
+    }
+    return dynamic;
+  }
+
   static DartType _leastUpperBoundOfTypes(
       TypeSystem typeSystem, DartType first, DartType second) {
     if (first == null) {
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index 296457a..a2e6994 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -495,7 +495,7 @@
       fieldFormalParameter(null, null, identifier);
 
   @Deprecated('Use forStatement2')
-  static ForEachStatement forEachStatement(DeclaredIdentifier loopVariable,
+  static ForStatement2 forEachStatement(DeclaredIdentifier loopVariable,
           Expression iterator, Statement body) =>
       astFactory.forStatement2(
           forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -508,7 +508,7 @@
           body: body);
 
   @Deprecated('Use forStatement2')
-  static ForEachStatement forEachStatement2(
+  static ForStatement2 forEachStatement2(
           SimpleIdentifier identifier, Expression iterator, Statement body) =>
       astFactory.forStatement2(
           forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -530,7 +530,7 @@
           TokenFactory.tokenFromType(TokenType.CLOSE_PAREN));
 
   @Deprecated('Use forStatement2')
-  static ForStatement forStatement(Expression initialization,
+  static ForStatement2 forStatement(Expression initialization,
           Expression condition, List<Expression> updaters, Statement body) =>
       astFactory.forStatement2(
           forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
@@ -544,27 +544,19 @@
           rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
           body: body);
 
-  static
-      // ignore: deprecated_member_use_from_same_package
-      ForStatement forStatement2(
-              VariableDeclarationList variableList,
-              Expression condition,
-              List<Expression> updaters,
-              Statement body) =>
-          astFactory.forStatement2(
-              forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
-              leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-              forLoopParts: astFactory.forPartsWithDeclarations(
-                  variables: variableList,
-                  leftSeparator:
-                      TokenFactory.tokenFromType(TokenType.SEMICOLON),
-                  condition: condition,
-                  rightSeparator:
-                      TokenFactory.tokenFromType(TokenType.SEMICOLON),
-                  updaters: updaters),
-              rightParenthesis:
-                  TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-              body: body);
+  static ForStatement2 forStatement2(VariableDeclarationList variableList,
+          Expression condition, List<Expression> updaters, Statement body) =>
+      astFactory.forStatement2(
+          forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
+          leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+          forLoopParts: astFactory.forPartsWithDeclarations(
+              variables: variableList,
+              leftSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+              condition: condition,
+              rightSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+              updaters: updaters),
+          rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+          body: body);
 
   static FunctionDeclaration functionDeclaration(
           TypeAnnotation type,
@@ -678,6 +670,20 @@
         .toList();
   }
 
+  static IfElement ifElement(
+          Expression condition, CollectionElement thenElement,
+          [CollectionElement elseElement]) =>
+      astFactory.ifElement(
+          ifKeyword: TokenFactory.tokenFromKeyword(Keyword.IF),
+          leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+          condition: condition,
+          rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+          thenElement: thenElement,
+          elseKeyword: elseElement == null
+              ? null
+              : TokenFactory.tokenFromKeyword(Keyword.ELSE),
+          elseElement: elseElement);
+
   static IfStatement ifStatement(
           Expression condition, Statement thenStatement) =>
       ifStatement2(condition, thenStatement, null);
@@ -825,7 +831,7 @@
 
   static ListLiteral listLiteral2(
           Keyword keyword, TypeArgumentList typeArguments,
-          [List<Expression> elements]) =>
+          [List<CollectionElement> elements]) =>
       astFactory.listLiteral(
           keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
           typeArguments,
@@ -834,7 +840,8 @@
           TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET));
 
   @Deprecated('Use setOrMapLiteral')
-  static MapLiteral mapLiteral(Keyword keyword, TypeArgumentList typeArguments,
+  static SetOrMapLiteral mapLiteral(
+          Keyword keyword, TypeArgumentList typeArguments,
           [List<MapLiteralEntry> entries]) =>
       astFactory.mapLiteral(
           keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
@@ -844,7 +851,7 @@
           TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
 
   @Deprecated('Use setOrMapLiteral')
-  static MapLiteral mapLiteral2([List<MapLiteralEntry> entries]) =>
+  static SetOrMapLiteral mapLiteral2([List<MapLiteralEntry> entries]) =>
       mapLiteral(null, null, entries);
 
   static MapLiteralEntry mapLiteralEntry(String key, Expression value) =>
@@ -1087,8 +1094,8 @@
       astFactory.scriptTag(TokenFactory.tokenFromString(scriptTag));
 
   @Deprecated('Use setOrMapLiteral')
-  static SetLiteral setLiteral(Keyword keyword, TypeArgumentList typeArguments,
-          List<Expression> elements) =>
+  static SetOrMapLiteral setLiteral(Keyword keyword,
+          TypeArgumentList typeArguments, List<Expression> elements) =>
       astFactory.setLiteral(
           keyword == null ? null : TokenFactory.tokenFromKeyword(keyword),
           typeArguments,
@@ -1133,6 +1140,12 @@
           TypeAnnotation type, String parameterName) =>
       simpleFormalParameter2(null, type, parameterName);
 
+  static SpreadElement spreadElement(
+          TokenType operator, Expression expression) =>
+      astFactory.spreadElement(
+          spreadOperator: TokenFactory.tokenFromType(operator),
+          expression: expression);
+
   static StringInterpolation string([List<InterpolationElement> elements]) =>
       astFactory.stringInterpolation(elements);
 
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 30b2925..6e978a6 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -577,6 +577,9 @@
   ///
   /// In practice this will always replace `?` with either bottom or top
   /// (dynamic), depending on the position of `?`.
+  ///
+  /// This implements the operation the spec calls "least closure", or
+  /// sometimes "least closure with respect to `?`".
   DartType lowerBoundForType(DartType type) {
     return _substituteForUnknownType(type, lowerBound: true);
   }
@@ -641,6 +644,9 @@
   ///
   /// In practice this will always replace `?` with either bottom or top
   /// (dynamic), depending on the position of `?`.
+  ///
+  /// This implements the operation the spec calls "greatest closure", or
+  /// sometimes "greatest closure with respect to `?`".
   DartType upperBoundForType(DartType type) {
     return _substituteForUnknownType(type);
   }
diff --git a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
new file mode 100644
index 0000000..2596ac9
--- /dev/null
+++ b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
@@ -0,0 +1,105 @@
+// 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:collection';
+
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/// Information about analysis `//ignore:` and `//ignore_for_file` comments
+/// within a source file.
+class IgnoreInfo {
+  ///  Instance shared by all cases without matches.
+  static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
+
+  /// A regular expression for matching 'ignore' comments.  Produces matches
+  /// containing 2 groups.  For example:
+  ///
+  ///     * ['//ignore: error_code', 'error_code']
+  ///
+  /// Resulting codes may be in a list ('error_code_1,error_code2').
+  static final RegExp _IGNORE_MATCHER =
+      new RegExp(r'//+[ ]*ignore:(.*)$', multiLine: true);
+
+  /// A regular expression for matching 'ignore_for_file' comments.  Produces
+  /// matches containing 2 groups.  For example:
+  ///
+  ///     * ['//ignore_for_file: error_code', 'error_code']
+  ///
+  /// Resulting codes may be in a list ('error_code_1,error_code2').
+  static final RegExp _IGNORE_FOR_FILE_MATCHER =
+      new RegExp(r'//[ ]*ignore_for_file:(.*)$', multiLine: true);
+
+  final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
+
+  final Set<String> _ignoreForFileSet = new HashSet<String>();
+
+  /// Whether this info object defines any ignores.
+  bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
+
+  /// Iterable of error codes ignored for the whole file.
+  Iterable<String> get ignoreForFiles => _ignoreForFileSet;
+
+  /// Map of line numbers to associated ignored error codes.
+  Map<int, Iterable<String>> get ignores => _ignoreMap;
+
+  /// Ignore this [errorCode] at [line].
+  void add(int line, String errorCode) {
+    _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
+  }
+
+  /// Ignore these [errorCodes] at [line].
+  void addAll(int line, Iterable<String> errorCodes) {
+    _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
+  }
+
+  /// Ignore these [errorCodes] in the whole file.
+  void addAllForFile(Iterable<String> errorCodes) {
+    _ignoreForFileSet.addAll(errorCodes);
+  }
+
+  /// Test whether this [errorCode] is ignored at the given [line].
+  bool ignoredAt(String errorCode, int line) =>
+      _ignoreForFileSet.contains(errorCode) ||
+      _ignoreMap[line]?.contains(errorCode) == true;
+
+  /// Calculate ignores for the given [content] with line [info].
+  static IgnoreInfo calculateIgnores(String content, LineInfo info) {
+    Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
+    Iterable<Match> fileMatches = _IGNORE_FOR_FILE_MATCHER.allMatches(content);
+    if (matches.isEmpty && fileMatches.isEmpty) {
+      return _EMPTY_INFO;
+    }
+
+    IgnoreInfo ignoreInfo = new IgnoreInfo();
+    for (Match match in matches) {
+      // See _IGNORE_MATCHER for format --- note the possibility of error lists.
+      Iterable<String> codes = match
+          .group(1)
+          .split(',')
+          .map((String code) => code.trim().toLowerCase());
+      CharacterLocation location = info.getLocation(match.start);
+      int lineNumber = location.lineNumber;
+      String beforeMatch = content.substring(
+          info.getOffsetOfLine(lineNumber - 1),
+          info.getOffsetOfLine(lineNumber - 1) + location.columnNumber - 1);
+
+      if (beforeMatch.trim().isEmpty) {
+        // The comment is on its own line, so it refers to the next line.
+        ignoreInfo.addAll(lineNumber + 1, codes);
+      } else {
+        // The comment sits next to code, so it refers to its own line.
+        ignoreInfo.addAll(lineNumber, codes);
+      }
+    }
+    for (Match match in fileMatches) {
+      Iterable<String> codes = match
+          .group(1)
+          .split(',')
+          .map((String code) => code.trim().toLowerCase());
+      ignoreInfo.addAllForFile(codes);
+    }
+    return ignoreInfo;
+  }
+}
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index c9abd60..d62aaa0 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -34,8 +34,6 @@
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
 import 'package:package_config/src/packages_impl.dart' show MapPackages;
 import 'package:path/path.dart' as p;
-import 'package:plugin/manager.dart';
-import 'package:plugin/plugin.dart';
 import 'package:yaml/yaml.dart';
 
 AnalysisOptionsProvider _optionsProvider = new AnalysisOptionsProvider();
@@ -125,9 +123,7 @@
 
   final LinterOptions options;
 
-  LintDriver(this.options) {
-    _processPlugins();
-  }
+  LintDriver(this.options);
 
   /// Return the number of sources that have been analyzed so far.
   int get numSourcesAnalyzed => _sourcesAnalyzed.length;
@@ -252,13 +248,6 @@
     }
     return null;
   }
-
-  void _processPlugins() {
-    List<Plugin> plugins = <Plugin>[];
-    plugins.addAll(AnalysisEngine.instance.requiredPlugins);
-    ExtensionManager manager = new ExtensionManager();
-    manager.processPlugins(plugins);
-  }
 }
 
 /// Prints logging information comments to the [outSink] and error messages to
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
deleted file mode 100644
index 6f97315..0000000
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ /dev/null
@@ -1,176 +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 'package:analyzer/error/error.dart' show AnalysisError;
-import 'package:analyzer/src/generated/engine.dart'
-    show InternalAnalysisContext;
-import 'package:analyzer/src/plugin/task.dart';
-import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:analyzer/src/task/dart_work_manager.dart';
-import 'package:analyzer/src/task/options_work_manager.dart';
-import 'package:plugin/plugin.dart';
-
-/**
- * A plugin that defines the extension points and extensions that are inherently
- * defined by the analysis engine.
- */
-class EnginePlugin implements Plugin {
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new analysis error results to compute for a Dart source.
-   */
-  static const String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT =
-      'dartErrorsForSource';
-
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new analysis error results to compute for a Dart library
-   * specific unit.
-   */
-  static const String DART_ERRORS_FOR_UNIT_EXTENSION_POINT =
-      'dartErrorsForUnit';
-
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new analysis error results to compute for an HTML source.
-   */
-  static const String HTML_ERRORS_EXTENSION_POINT = 'htmlErrors';
-
-  /**
-   * The simple identifier of the extension point that allows plugins to
-   * register new work manager factories with the analysis engine.
-   */
-  static const String WORK_MANAGER_FACTORY_EXTENSION_POINT =
-      'workManagerFactory';
-
-  /**
-   * The unique identifier of this plugin.
-   */
-  static const String UNIQUE_IDENTIFIER = 'analysis_engine.core';
-
-  /**
-   * The extension point that allows plugins to register new analysis error
-   * results for a Dart source.
-   */
-  ExtensionPoint<ListResultDescriptor<AnalysisError>>
-      dartErrorsForSourceExtensionPoint;
-
-  /**
-   * The extension point that allows plugins to register new analysis error
-   * results for a Dart library specific unit.
-   */
-  ExtensionPoint<ListResultDescriptor<AnalysisError>>
-      dartErrorsForUnitExtensionPoint;
-
-  /**
-   * The extension point that allows plugins to register new analysis error
-   * results for an HTML source.
-   */
-  ExtensionPoint<ListResultDescriptor<AnalysisError>> htmlErrorsExtensionPoint;
-
-  /**
-   * The extension point that allows plugins to register new work manager
-   * factories with the analysis engine.
-   */
-  ExtensionPoint<WorkManagerFactory> workManagerFactoryExtensionPoint;
-
-  /**
-   * Initialize a newly created plugin.
-   */
-  EnginePlugin();
-
-  /**
-   * Return a list containing all of the contributed analysis error result
-   * descriptors for Dart sources.
-   */
-  @ExtensionPointId('DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID')
-  List<ListResultDescriptor<AnalysisError>> get dartErrorsForSource =>
-      dartErrorsForSourceExtensionPoint.extensions;
-
-  /**
-   * Return a list containing all of the contributed analysis error result
-   * descriptors for Dart library specific units.
-   */
-  @ExtensionPointId('DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID')
-  List<ListResultDescriptor<AnalysisError>> get dartErrorsForUnit =>
-      dartErrorsForUnitExtensionPoint.extensions;
-
-  /**
-   * Return a list containing all of the contributed analysis error result
-   * descriptors for HTML sources.
-   */
-  @ExtensionPointId('HTML_ERRORS_EXTENSION_POINT_ID')
-  List<ListResultDescriptor<AnalysisError>> get htmlErrors =>
-      htmlErrorsExtensionPoint.extensions;
-
-  @override
-  String get uniqueIdentifier => UNIQUE_IDENTIFIER;
-
-  /**
-   * Return a list containing all of the work manager factories that were
-   * contributed.
-   */
-  List<WorkManagerFactory> get workManagerFactories =>
-      workManagerFactoryExtensionPoint.extensions;
-
-  @override
-  void registerExtensionPoints(RegisterExtensionPoint registerExtensionPoint) {
-    dartErrorsForSourceExtensionPoint =
-        new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
-            this, DART_ERRORS_FOR_SOURCE_EXTENSION_POINT, null);
-    registerExtensionPoint(dartErrorsForSourceExtensionPoint);
-    dartErrorsForUnitExtensionPoint =
-        new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
-            this, DART_ERRORS_FOR_UNIT_EXTENSION_POINT, null);
-    registerExtensionPoint(dartErrorsForUnitExtensionPoint);
-    htmlErrorsExtensionPoint =
-        new ExtensionPoint<ListResultDescriptor<AnalysisError>>(
-            this, HTML_ERRORS_EXTENSION_POINT, null);
-    registerExtensionPoint(htmlErrorsExtensionPoint);
-    workManagerFactoryExtensionPoint = new ExtensionPoint<WorkManagerFactory>(
-        this, WORK_MANAGER_FACTORY_EXTENSION_POINT, null);
-    registerExtensionPoint(workManagerFactoryExtensionPoint);
-  }
-
-  @override
-  void registerExtensions(RegisterExtension registerExtension) {
-    _registerWorkManagerFactoryExtensions(registerExtension);
-    _registerDartErrorsForSource(registerExtension);
-    _registerDartErrorsForUnit(registerExtension);
-  }
-
-  void _registerDartErrorsForSource(RegisterExtension registerExtension) {
-    registerExtension(DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID, PARSE_ERRORS);
-    registerExtension(DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID, SCAN_ERRORS);
-  }
-
-  void _registerDartErrorsForUnit(RegisterExtension registerExtension) {
-    registerExtension(
-        DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID, LIBRARY_UNIT_ERRORS);
-  }
-
-  void _registerWorkManagerFactoryExtensions(
-      RegisterExtension registerExtension) {
-    String taskId = WORK_MANAGER_EXTENSION_POINT_ID;
-    registerExtension(taskId,
-        (InternalAnalysisContext context) => new DartWorkManager(context));
-    registerExtension(taskId,
-        (InternalAnalysisContext context) => new OptionsWorkManager(context));
-  }
-}
-
-/**
- * Annotation describing the relationship between a getter in [EnginePlugin]
- * and the associated identifier (in 'task.dart') which can be passed to the
- * extension manager to populate it.
- *
- * This annotation is not used at runtime; it is used to aid in static analysis
- * of the task model during development.
- */
-class ExtensionPointId {
-  final String extensionPointId;
-
-  const ExtensionPointId(this.extensionPointId);
-}
diff --git a/pkg/analyzer/lib/src/plugin/task.dart b/pkg/analyzer/lib/src/plugin/task.dart
index 8292485..fec6844 100644
--- a/pkg/analyzer/lib/src/plugin/task.dart
+++ b/pkg/analyzer/lib/src/plugin/task.dart
@@ -7,44 +7,7 @@
  * analysis tasks.
  */
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/plugin/engine_plugin.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:plugin/plugin.dart';
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for a Dart source. The object used as an
- * extension must be a [ResultDescriptor].
- */
-final String DART_ERRORS_FOR_SOURCE_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER,
-    EnginePlugin.DART_ERRORS_FOR_SOURCE_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for a Dart library specific unit. The
- * object used as an extension must be a [ResultDescriptor].
- */
-final String DART_ERRORS_FOR_UNIT_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER,
-    EnginePlugin.DART_ERRORS_FOR_UNIT_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * analysis error results to compute for an HTML source. The object used as an
- * extension must be a [ResultDescriptor].
- */
-final String HTML_ERRORS_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER, EnginePlugin.HTML_ERRORS_EXTENSION_POINT);
-
-/**
- * The identifier of the extension point that allows plugins to register new
- * work managers with the analysis engine. The object used as an extension must
- * be a [WorkManagerFactory].
- */
-final String WORK_MANAGER_EXTENSION_POINT_ID = Plugin.join(
-    EnginePlugin.UNIQUE_IDENTIFIER,
-    EnginePlugin.WORK_MANAGER_FACTORY_EXTENSION_POINT);
 
 /**
  * A function that will create a new [WorkManager] for the given [context].
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 4ec0123..aaed6fe 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -624,6 +624,7 @@
 
     var isLibrary = file.isLibrary;
     var library = isLibrary ? file : file.library;
+    if (library == null) return;
 
     if (isLibrary) {
       file.refresh(containingContext);
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index 3301d95..960e342 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -17,7 +17,7 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 
-bool _isSetOrMapEnabled(ExperimentStatus experimentStatus) =>
+bool _isSpreadOrControlFlowEnabled(ExperimentStatus experimentStatus) =>
     experimentStatus.spread_collections ||
     experimentStatus.control_flow_collections;
 
@@ -31,7 +31,8 @@
   final ElementImpl context;
   final UnlinkedExpr _uc;
   final bool requireValidConst;
-  final bool useSetOrMap;
+  final bool isSpreadOrControlFlowEnabled;
+  final bool becomeSetOrMap;
 
   int intPtr = 0;
   int doublePtr = 0;
@@ -47,15 +48,20 @@
 
   final Map<String, ParameterElement> parametersInScope;
 
-  ExprBuilder(this.resynthesizer, this.context, this._uc,
-      {this.requireValidConst: true,
-      this.localFunctions,
-      Map<String, ParameterElement> parametersInScope})
-      : this.parametersInScope =
+  ExprBuilder(
+    this.resynthesizer,
+    this.context,
+    this._uc, {
+    this.requireValidConst: true,
+    this.localFunctions,
+    Map<String, ParameterElement> parametersInScope,
+    this.becomeSetOrMap: true,
+  })  : this.parametersInScope =
             parametersInScope ?? _parametersInScope(context),
-        this.useSetOrMap = _isSetOrMapEnabled((resynthesizer
-                .library.context.analysisOptions as AnalysisOptionsImpl)
-            .experimentStatus);
+        this.isSpreadOrControlFlowEnabled = _isSpreadOrControlFlowEnabled(
+            (resynthesizer.library.context.analysisOptions
+                    as AnalysisOptionsImpl)
+                .experimentStatus);
 
   bool get hasNonEmptyExpr => _uc != null && _uc.operations.isNotEmpty;
 
@@ -234,7 +240,7 @@
           break;
         case UnlinkedExprOperation.makeTypedSet:
           TypeAnnotation itemType = _newTypeName();
-          if (useSetOrMap) {
+          if (isSpreadOrControlFlowEnabled) {
             _pushSetOrMap(
                 AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
           } else {
@@ -311,6 +317,18 @@
         case UnlinkedExprOperation.pushThis:
           _push(AstTestFactory.thisExpression());
           break;
+        case UnlinkedExprOperation.spreadElement:
+          _pushSpread(TokenType.PERIOD_PERIOD_PERIOD);
+          break;
+        case UnlinkedExprOperation.nullAwareSpreadElement:
+          _pushSpread(TokenType.PERIOD_PERIOD_PERIOD_QUESTION);
+          break;
+        case UnlinkedExprOperation.ifElement:
+          _pushIfElement(false);
+          break;
+        case UnlinkedExprOperation.ifElseElement:
+          _pushIfElement(true);
+          break;
         case UnlinkedExprOperation.cascadeSectionBegin:
         case UnlinkedExprOperation.cascadeSectionEnd:
         case UnlinkedExprOperation.pushLocalFunctionReference:
@@ -613,7 +631,7 @@
 
   CollectionElement _popCollectionElement() => stack.removeLast();
 
-  void _push(Expression expr) {
+  void _push(CollectionElement expr) {
     stack.add(expr);
   }
 
@@ -638,6 +656,13 @@
     _push(AstTestFactory.propertyAccess(target, propertyNode));
   }
 
+  void _pushIfElement(bool hasElse) {
+    CollectionElement elseElement = hasElse ? _popCollectionElement() : null;
+    CollectionElement thenElement = _popCollectionElement();
+    Expression condition = _pop();
+    _push(AstTestFactory.ifElement(condition, thenElement, elseElement));
+  }
+
   void _pushInstanceCreation() {
     EntityRef ref = _uc.references[refPtr++];
     ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
@@ -750,9 +775,10 @@
 
   void _pushList(TypeArgumentList typeArguments) {
     int count = _uc.ints[intPtr++];
-    List<Expression> elements = <Expression>[];
+    List<CollectionElement> elements =
+        isSpreadOrControlFlowEnabled ? <CollectionElement>[] : <Expression>[];
     for (int i = 0; i < count; i++) {
-      elements.insert(0, _pop());
+      elements.insert(0, _popCollectionElement());
     }
     var typeArg = typeArguments == null
         ? resynthesizer.typeProvider.dynamicType
@@ -825,7 +851,7 @@
         : typeArguments.arguments[1].type;
     var staticType =
         resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
-    if (useSetOrMap) {
+    if (isSpreadOrControlFlowEnabled) {
       _push(
           AstTestFactory.setOrMapLiteral(Keyword.CONST, typeArguments, entries)
             ..staticType = staticType);
@@ -865,27 +891,54 @@
     int count = _uc.ints[intPtr++];
     List<CollectionElement> elements = <CollectionElement>[];
     for (int i = 0; i < count; i++) {
-      elements.add(_popCollectionElement());
+      elements.insert(0, _popCollectionElement());
     }
+
+    bool isMap = true; // assume Map unless can prove otherwise
     DartType staticType;
-    if (typeArguments != null && typeArguments.arguments.length == 2) {
-      var keyType = typeArguments.arguments[0].type;
-      var valueType = typeArguments.arguments[1].type;
-      staticType =
-          resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
-    } else if (typeArguments != null && typeArguments.arguments.length == 1) {
-      var valueType = typeArguments == null
-          ? resynthesizer.typeProvider.dynamicType
-          : typeArguments.arguments[0].type;
-      staticType = resynthesizer.typeProvider.setType.instantiate([valueType]);
+    if (typeArguments != null) {
+      if (typeArguments.arguments.length == 2) {
+        var keyType = typeArguments.arguments[0].type;
+        var valueType = typeArguments.arguments[1].type;
+        staticType = resynthesizer.typeProvider.mapType
+            .instantiate([keyType, valueType]);
+      } else if (typeArguments.arguments.length == 1) {
+        isMap = false;
+        var valueType = typeArguments == null
+            ? resynthesizer.typeProvider.dynamicType
+            : typeArguments.arguments[0].type;
+        staticType =
+            resynthesizer.typeProvider.setType.instantiate([valueType]);
+      }
+    } else {
+      for (var i = 0; i < elements.length; ++i) {
+        var element = elements[i];
+        if (element is Expression) {
+          isMap = false;
+        }
+      }
     }
-    _push(astFactory.setOrMapLiteral(
-        constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-        typeArguments: typeArguments,
-        leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
-        elements: elements,
-        rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET))
-      ..staticType = staticType);
+
+    SetOrMapLiteral setOrMapLiteral = astFactory.setOrMapLiteral(
+      constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+      typeArguments: typeArguments,
+      leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
+      elements: elements,
+      rightBracket: TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET),
+    );
+    if (becomeSetOrMap) {
+      if (isMap) {
+        (setOrMapLiteral as SetOrMapLiteralImpl).becomeMap();
+      } else {
+        (setOrMapLiteral as SetOrMapLiteralImpl).becomeSet();
+      }
+    }
+    _push(setOrMapLiteral..staticType = staticType);
+  }
+
+  void _pushSpread(TokenType operator) {
+    Expression operand = _pop();
+    _push(AstTestFactory.spreadElement(operator, operand));
   }
 
   List<Expression> _removeTopExpressions(int count) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index f77a8b6..ca27841f 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4571,6 +4571,7 @@
   bool _variantField_31;
   String _variantField_20;
   String _variantField_22;
+  LinkedNodeVariablesDeclarationBuilder _variantField_32;
 
   @override
   List<LinkedNodeBuilder> get adjacentStrings_strings {
@@ -8781,6 +8782,12 @@
   }
 
   @override
+  int get methodDeclaration_actualProperty {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_19 ??= 0;
+  }
+
+  @override
   int get normalFormalParameter_covariantKeyword {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8862,6 +8869,12 @@
     _variantField_19 = value;
   }
 
+  void set methodDeclaration_actualProperty(int value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_19 = value;
+  }
+
   void set normalFormalParameter_covariantKeyword(int value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8906,6 +8919,30 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get fieldFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get functionDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get functionTypeAlias_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get genericFunctionType_returnType2 {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -8913,27 +8950,80 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get methodDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get simpleFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get typeName_type {
     assert(kind == idl.LinkedNodeKind.typeName);
     return _variantField_24;
   }
 
+  @override
+  LinkedNodeTypeBuilder get variableDeclaration_type2 {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_24;
+  }
+
   void set binaryExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
     _variantField_24 = value;
   }
 
+  void set fieldFormalParameter_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    _variantField_24 = value;
+  }
+
+  void set functionDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    _variantField_24 = value;
+  }
+
+  void set functionTypeAlias_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+    _variantField_24 = value;
+  }
+
+  void set genericFunctionType_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_24 = value;
+  }
+
   void set invocationExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
     _variantField_24 = value;
   }
 
+  void set methodDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_24 = value;
+  }
+
+  void set simpleFormalParameter_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_24 = value;
+  }
+
   void set typeName_type(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.typeName);
     _variantField_24 = value;
   }
 
+  void set variableDeclaration_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_24 = value;
+  }
+
   @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
@@ -8941,12 +9031,26 @@
   }
 
   @override
+  bool get classDeclaration_isDartObject {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    return _variantField_27 ??= false;
+  }
+
+  @override
   bool get defaultFormalParameter_isNamed {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     return _variantField_27 ??= false;
   }
 
   @override
+  bool get normalFormalParameter_isCovariant {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_27 ??= false;
+  }
+
+  @override
   bool get setOrMapLiteral_isMap {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     return _variantField_27 ??= false;
@@ -8957,11 +9061,23 @@
     _variantField_27 = value;
   }
 
+  void set classDeclaration_isDartObject(bool value) {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    _variantField_27 = value;
+  }
+
   void set defaultFormalParameter_isNamed(bool value) {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     _variantField_27 = value;
   }
 
+  void set normalFormalParameter_isCovariant(bool value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_27 = value;
+  }
+
   void set setOrMapLiteral_isMap(bool value) {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     _variantField_27 = value;
@@ -9454,6 +9570,18 @@
     _variantField_22 = value;
   }
 
+  @override
+  LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_32;
+  }
+
+  void set variableDeclaration_declaration(
+      LinkedNodeVariablesDeclarationBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 = value;
+  }
+
   LinkedNodeBuilder.adjacentStrings({
     List<LinkedNodeBuilder> adjacentStrings_strings,
     LinkedNodeTypeBuilder expression_type,
@@ -9775,6 +9903,7 @@
     int classDeclaration_classKeyword,
     int classOrMixinDeclaration_rightBracket,
     int classOrMixinDeclaration_leftBracket,
+    bool classDeclaration_isDartObject,
     LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
     List<LinkedNodeBuilder> classOrMixinDeclaration_members,
     LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
@@ -9788,6 +9917,7 @@
         _variantField_16 = classDeclaration_classKeyword,
         _variantField_18 = classOrMixinDeclaration_rightBracket,
         _variantField_19 = classOrMixinDeclaration_leftBracket,
+        _variantField_27 = classDeclaration_isDartObject,
         _variantField_12 = classOrMixinDeclaration_implementsClause,
         _variantField_5 = classOrMixinDeclaration_members,
         _variantField_13 = classOrMixinDeclaration_typeParameters,
@@ -9862,6 +9992,7 @@
     int functionDeclaration_externalKeyword,
     LinkedNodeBuilder functionDeclaration_returnType,
     int functionDeclaration_propertyKeyword,
+    LinkedNodeTypeBuilder functionDeclaration_returnType2,
     LinkedNodeBuilder namedCompilationUnitMember_name,
   })  : _kind = idl.LinkedNodeKind.functionDeclaration,
         _variantField_11 = annotatedNode_comment,
@@ -9870,6 +10001,7 @@
         _variantField_15 = functionDeclaration_externalKeyword,
         _variantField_7 = functionDeclaration_returnType,
         _variantField_16 = functionDeclaration_propertyKeyword,
+        _variantField_24 = functionDeclaration_returnType2,
         _variantField_14 = namedCompilationUnitMember_name;
 
   LinkedNodeBuilder.functionTypeAlias({
@@ -9880,6 +10012,7 @@
     LinkedNodeBuilder functionTypeAlias_typeParameters,
     int typeAlias_typedefKeyword,
     int typeAlias_semicolon,
+    LinkedNodeTypeBuilder functionTypeAlias_returnType2,
     LinkedNodeBuilder namedCompilationUnitMember_name,
   })  : _kind = idl.LinkedNodeKind.functionTypeAlias,
         _variantField_11 = annotatedNode_comment,
@@ -9889,6 +10022,7 @@
         _variantField_8 = functionTypeAlias_typeParameters,
         _variantField_18 = typeAlias_typedefKeyword,
         _variantField_19 = typeAlias_semicolon,
+        _variantField_24 = functionTypeAlias_returnType2,
         _variantField_14 = namedCompilationUnitMember_name;
 
   LinkedNodeBuilder.genericTypeAlias({
@@ -9933,6 +10067,8 @@
     int methodDeclaration_modifierKeyword,
     int methodDeclaration_operatorKeyword,
     int methodDeclaration_propertyKeyword,
+    int methodDeclaration_actualProperty,
+    LinkedNodeTypeBuilder methodDeclaration_returnType2,
     LinkedNodeBuilder methodDeclaration_typeParameters,
     LinkedNodeBuilder methodDeclaration_name,
   })  : _kind = idl.LinkedNodeKind.methodDeclaration,
@@ -9945,6 +10081,8 @@
         _variantField_16 = methodDeclaration_modifierKeyword,
         _variantField_17 = methodDeclaration_operatorKeyword,
         _variantField_18 = methodDeclaration_propertyKeyword,
+        _variantField_19 = methodDeclaration_actualProperty,
+        _variantField_24 = methodDeclaration_returnType2,
         _variantField_9 = methodDeclaration_typeParameters,
         _variantField_10 = methodDeclaration_name;
 
@@ -10039,12 +10177,16 @@
     LinkedNodeBuilder variableDeclaration_initializer,
     int variableDeclaration_equals,
     LinkedNodeBuilder variableDeclaration_name,
+    LinkedNodeTypeBuilder variableDeclaration_type2,
+    LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
   })  : _kind = idl.LinkedNodeKind.variableDeclaration,
         _variantField_11 = annotatedNode_comment,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = variableDeclaration_initializer,
         _variantField_15 = variableDeclaration_equals,
-        _variantField_7 = variableDeclaration_name;
+        _variantField_7 = variableDeclaration_name,
+        _variantField_24 = variableDeclaration_type2,
+        _variantField_32 = variableDeclaration_declaration;
 
   LinkedNodeBuilder.fieldFormalParameter({
     List<LinkedNodeBuilder> normalFormalParameter_metadata,
@@ -10055,6 +10197,8 @@
     int fieldFormalParameter_period,
     int fieldFormalParameter_thisKeyword,
     int normalFormalParameter_covariantKeyword,
+    LinkedNodeTypeBuilder fieldFormalParameter_type2,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10067,6 +10211,8 @@
         _variantField_16 = fieldFormalParameter_period,
         _variantField_17 = fieldFormalParameter_thisKeyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_24 = fieldFormalParameter_type2,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10077,6 +10223,7 @@
     LinkedNodeBuilder functionTypedFormalParameter_returnType,
     LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
     int normalFormalParameter_covariantKeyword,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10086,6 +10233,7 @@
         _variantField_7 = functionTypedFormalParameter_returnType,
         _variantField_8 = functionTypedFormalParameter_typeParameters,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10095,6 +10243,8 @@
     LinkedNodeBuilder simpleFormalParameter_type,
     int simpleFormalParameter_keyword,
     int normalFormalParameter_covariantKeyword,
+    LinkedNodeTypeBuilder simpleFormalParameter_type2,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10103,6 +10253,8 @@
         _variantField_6 = simpleFormalParameter_type,
         _variantField_15 = simpleFormalParameter_keyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_24 = simpleFormalParameter_type2,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10488,12 +10640,14 @@
     LinkedNodeBuilder genericFunctionType_returnType,
     LinkedNodeBuilder genericFunctionType_formalParameters,
     int genericFunctionType_question,
+    LinkedNodeTypeBuilder genericFunctionType_returnType2,
   })  : _kind = idl.LinkedNodeKind.genericFunctionType,
         _variantField_6 = genericFunctionType_typeParameters,
         _variantField_15 = genericFunctionType_functionKeyword,
         _variantField_7 = genericFunctionType_returnType,
         _variantField_8 = genericFunctionType_formalParameters,
-        _variantField_16 = genericFunctionType_question;
+        _variantField_16 = genericFunctionType_question,
+        _variantField_24 = genericFunctionType_returnType2;
 
   LinkedNodeBuilder.ifElement({
     LinkedNodeBuilder ifMixin_condition,
@@ -10899,6 +11053,7 @@
     _variantField_10?.flushInformative();
     _variantField_25?.flushInformative();
     _variantField_14?.flushInformative();
+    _variantField_32?.flushInformative();
   }
 
   /**
@@ -10985,6 +11140,8 @@
         this._variantField_29 == null ? 0 : this._variantField_29.index);
     signature.addString(this._variantField_30 ?? '');
     signature.addBool(this._variantField_31 == true);
+    signature.addBool(this._variantField_32 != null);
+    this._variantField_32?.collectApiSignature(signature);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -11008,6 +11165,7 @@
     fb.Offset offset_variantField_23;
     fb.Offset offset_variantField_20;
     fb.Offset offset_variantField_22;
+    fb.Offset offset_variantField_32;
     if (!(_variantField_2 == null || _variantField_2.isEmpty)) {
       offset_variantField_2 = fbBuilder
           .writeList(_variantField_2.map((b) => b.finish(fbBuilder)).toList());
@@ -11072,6 +11230,9 @@
     if (_variantField_22 != null) {
       offset_variantField_22 = fbBuilder.writeString(_variantField_22);
     }
+    if (_variantField_32 != null) {
+      offset_variantField_32 = _variantField_32.finish(fbBuilder);
+    }
     fbBuilder.startTable();
     if (offset_variantField_2 != null) {
       fbBuilder.addOffset(2, offset_variantField_2);
@@ -11171,6 +11332,9 @@
     if (offset_variantField_22 != null) {
       fbBuilder.addOffset(22, offset_variantField_22);
     }
+    if (offset_variantField_32 != null) {
+      fbBuilder.addOffset(32, offset_variantField_32);
+    }
     return fbBuilder.endTable();
   }
 }
@@ -11223,6 +11387,7 @@
   bool _variantField_31;
   String _variantField_20;
   String _variantField_22;
+  idl.LinkedNodeVariablesDeclaration _variantField_32;
 
   @override
   List<idl.LinkedNode> get adjacentStrings_strings {
@@ -14174,6 +14339,14 @@
   }
 
   @override
+  int get methodDeclaration_actualProperty {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_19 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+    return _variantField_19;
+  }
+
+  @override
   int get normalFormalParameter_covariantKeyword {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -14229,6 +14402,38 @@
   }
 
   @override
+  idl.LinkedNodeType get fieldFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get functionDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get functionTypeAlias_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get genericFunctionType_returnType2 {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -14238,6 +14443,22 @@
   }
 
   @override
+  idl.LinkedNodeType get methodDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get simpleFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get typeName_type {
     assert(kind == idl.LinkedNodeKind.typeName);
     _variantField_24 ??=
@@ -14246,6 +14467,14 @@
   }
 
   @override
+  idl.LinkedNodeType get variableDeclaration_type2 {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     _variantField_27 ??=
@@ -14254,6 +14483,14 @@
   }
 
   @override
+  bool get classDeclaration_isDartObject {
+    assert(kind == idl.LinkedNodeKind.classDeclaration);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
   bool get defaultFormalParameter_isNamed {
     assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
     _variantField_27 ??=
@@ -14262,6 +14499,16 @@
   }
 
   @override
+  bool get normalFormalParameter_isCovariant {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
   bool get setOrMapLiteral_isMap {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     _variantField_27 ??=
@@ -14601,6 +14848,14 @@
         const fb.StringReader().vTableGet(_bc, _bcOffset, 22, '');
     return _variantField_22;
   }
+
+  @override
+  idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
+        .vTableGet(_bc, _bcOffset, 32, null);
+    return _variantField_32;
+  }
 }
 
 abstract class _LinkedNodeMixin implements idl.LinkedNode {
@@ -15014,6 +15269,9 @@
       if (classOrMixinDeclaration_leftBracket != 0)
         _result["classOrMixinDeclaration_leftBracket"] =
             classOrMixinDeclaration_leftBracket;
+      if (classDeclaration_isDartObject != false)
+        _result["classDeclaration_isDartObject"] =
+            classDeclaration_isDartObject;
       if (classOrMixinDeclaration_implementsClause != null)
         _result["classOrMixinDeclaration_implementsClause"] =
             classOrMixinDeclaration_implementsClause.toJson();
@@ -15119,6 +15377,9 @@
       if (functionDeclaration_propertyKeyword != 0)
         _result["functionDeclaration_propertyKeyword"] =
             functionDeclaration_propertyKeyword;
+      if (functionDeclaration_returnType2 != null)
+        _result["functionDeclaration_returnType2"] =
+            functionDeclaration_returnType2.toJson();
       if (namedCompilationUnitMember_name != null)
         _result["namedCompilationUnitMember_name"] =
             namedCompilationUnitMember_name.toJson();
@@ -15142,6 +15403,9 @@
         _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
       if (typeAlias_semicolon != 0)
         _result["typeAlias_semicolon"] = typeAlias_semicolon;
+      if (functionTypeAlias_returnType2 != null)
+        _result["functionTypeAlias_returnType2"] =
+            functionTypeAlias_returnType2.toJson();
       if (namedCompilationUnitMember_name != null)
         _result["namedCompilationUnitMember_name"] =
             namedCompilationUnitMember_name.toJson();
@@ -15207,6 +15471,12 @@
       if (methodDeclaration_propertyKeyword != 0)
         _result["methodDeclaration_propertyKeyword"] =
             methodDeclaration_propertyKeyword;
+      if (methodDeclaration_actualProperty != 0)
+        _result["methodDeclaration_actualProperty"] =
+            methodDeclaration_actualProperty;
+      if (methodDeclaration_returnType2 != null)
+        _result["methodDeclaration_returnType2"] =
+            methodDeclaration_returnType2.toJson();
       if (methodDeclaration_typeParameters != null)
         _result["methodDeclaration_typeParameters"] =
             methodDeclaration_typeParameters.toJson();
@@ -15326,6 +15596,12 @@
         _result["variableDeclaration_equals"] = variableDeclaration_equals;
       if (variableDeclaration_name != null)
         _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+      if (variableDeclaration_type2 != null)
+        _result["variableDeclaration_type2"] =
+            variableDeclaration_type2.toJson();
+      if (variableDeclaration_declaration != null)
+        _result["variableDeclaration_declaration"] =
+            variableDeclaration_declaration.toJson();
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
       if (normalFormalParameter_metadata.isNotEmpty)
@@ -15352,6 +15628,12 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (fieldFormalParameter_type2 != null)
+        _result["fieldFormalParameter_type2"] =
+            fieldFormalParameter_type2.toJson();
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15380,6 +15662,9 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15405,6 +15690,12 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (simpleFormalParameter_type2 != null)
+        _result["simpleFormalParameter_type2"] =
+            simpleFormalParameter_type2.toJson();
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15832,6 +16123,9 @@
             genericFunctionType_formalParameters.toJson();
       if (genericFunctionType_question != 0)
         _result["genericFunctionType_question"] = genericFunctionType_question;
+      if (genericFunctionType_returnType2 != null)
+        _result["genericFunctionType_returnType2"] =
+            genericFunctionType_returnType2.toJson();
     }
     if (kind == idl.LinkedNodeKind.ifElement) {
       if (ifMixin_condition != null)
@@ -16519,6 +16813,7 @@
             classOrMixinDeclaration_rightBracket,
         "classOrMixinDeclaration_leftBracket":
             classOrMixinDeclaration_leftBracket,
+        "classDeclaration_isDartObject": classDeclaration_isDartObject,
         "classOrMixinDeclaration_implementsClause":
             classOrMixinDeclaration_implementsClause,
         "classOrMixinDeclaration_members": classOrMixinDeclaration_members,
@@ -16589,6 +16884,7 @@
         "functionDeclaration_returnType": functionDeclaration_returnType,
         "functionDeclaration_propertyKeyword":
             functionDeclaration_propertyKeyword,
+        "functionDeclaration_returnType2": functionDeclaration_returnType2,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -16604,6 +16900,7 @@
         "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
         "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
         "typeAlias_semicolon": typeAlias_semicolon,
+        "functionTypeAlias_returnType2": functionTypeAlias_returnType2,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -16646,6 +16943,8 @@
         "methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
         "methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
         "methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
+        "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
+        "methodDeclaration_returnType2": methodDeclaration_returnType2,
         "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
         "methodDeclaration_name": methodDeclaration_name,
         "isSynthetic": isSynthetic,
@@ -16732,8 +17031,10 @@
         "variableDeclaration_initializer": variableDeclaration_initializer,
         "variableDeclaration_equals": variableDeclaration_equals,
         "variableDeclaration_name": variableDeclaration_name,
+        "variableDeclaration_type2": variableDeclaration_type2,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "variableDeclaration_declaration": variableDeclaration_declaration,
       };
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
@@ -16749,6 +17050,8 @@
         "fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "fieldFormalParameter_type2": fieldFormalParameter_type2,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16767,6 +17070,7 @@
             functionTypedFormalParameter_typeParameters,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16781,6 +17085,8 @@
         "simpleFormalParameter_keyword": simpleFormalParameter_keyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "simpleFormalParameter_type2": simpleFormalParameter_type2,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -17143,6 +17449,7 @@
         "genericFunctionType_formalParameters":
             genericFunctionType_formalParameters,
         "genericFunctionType_question": genericFunctionType_question,
+        "genericFunctionType_returnType2": genericFunctionType_returnType2,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -17547,58 +17854,53 @@
 class LinkedNodeBundleBuilder extends Object
     with _LinkedNodeBundleMixin
     implements idl.LinkedNodeBundle {
-  LinkedNodeBuilder _node;
-  LinkedNodeReferenceBuilder _references;
-  UnlinkedTokensBuilder _tokens;
+  List<LinkedNodeLibraryBuilder> _libraries;
+  LinkedNodeReferencesBuilder _references;
 
   @override
-  LinkedNodeBuilder get node => _node;
+  List<LinkedNodeLibraryBuilder> get libraries =>
+      _libraries ??= <LinkedNodeLibraryBuilder>[];
 
-  void set node(LinkedNodeBuilder value) {
-    this._node = value;
+  void set libraries(List<LinkedNodeLibraryBuilder> value) {
+    this._libraries = value;
   }
 
   @override
-  LinkedNodeReferenceBuilder get references => _references;
+  LinkedNodeReferencesBuilder get references => _references;
 
-  void set references(LinkedNodeReferenceBuilder value) {
+  /// The shared list of references used in the [libraries].
+  void set references(LinkedNodeReferencesBuilder value) {
     this._references = value;
   }
 
-  @override
-  UnlinkedTokensBuilder get tokens => _tokens;
-
-  void set tokens(UnlinkedTokensBuilder value) {
-    this._tokens = value;
-  }
-
   LinkedNodeBundleBuilder(
-      {LinkedNodeBuilder node,
-      LinkedNodeReferenceBuilder references,
-      UnlinkedTokensBuilder tokens})
-      : _node = node,
-        _references = references,
-        _tokens = tokens;
+      {List<LinkedNodeLibraryBuilder> libraries,
+      LinkedNodeReferencesBuilder references})
+      : _libraries = libraries,
+        _references = references;
 
   /**
    * Flush [informative] data recursively.
    */
   void flushInformative() {
-    _node?.flushInformative();
+    _libraries?.forEach((b) => b.flushInformative());
     _references?.flushInformative();
-    _tokens?.flushInformative();
   }
 
   /**
    * Accumulate non-[informative] data into [signature].
    */
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addBool(this._tokens != null);
-    this._tokens?.collectApiSignature(signature);
     signature.addBool(this._references != null);
     this._references?.collectApiSignature(signature);
-    signature.addBool(this._node != null);
-    this._node?.collectApiSignature(signature);
+    if (this._libraries == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._libraries.length);
+      for (var x in this._libraries) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   List<int> toBuffer() {
@@ -17607,27 +17909,21 @@
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
-    fb.Offset offset_node;
+    fb.Offset offset_libraries;
     fb.Offset offset_references;
-    fb.Offset offset_tokens;
-    if (_node != null) {
-      offset_node = _node.finish(fbBuilder);
+    if (!(_libraries == null || _libraries.isEmpty)) {
+      offset_libraries = fbBuilder
+          .writeList(_libraries.map((b) => b.finish(fbBuilder)).toList());
     }
     if (_references != null) {
       offset_references = _references.finish(fbBuilder);
     }
-    if (_tokens != null) {
-      offset_tokens = _tokens.finish(fbBuilder);
-    }
     fbBuilder.startTable();
-    if (offset_node != null) {
-      fbBuilder.addOffset(2, offset_node);
+    if (offset_libraries != null) {
+      fbBuilder.addOffset(1, offset_libraries);
     }
     if (offset_references != null) {
-      fbBuilder.addOffset(1, offset_references);
-    }
-    if (offset_tokens != null) {
-      fbBuilder.addOffset(0, offset_tokens);
+      fbBuilder.addOffset(0, offset_references);
     }
     return fbBuilder.endTable();
   }
@@ -17654,55 +17950,283 @@
 
   _LinkedNodeBundleImpl(this._bc, this._bcOffset);
 
-  idl.LinkedNode _node;
-  idl.LinkedNodeReference _references;
-  idl.UnlinkedTokens _tokens;
+  List<idl.LinkedNodeLibrary> _libraries;
+  idl.LinkedNodeReferences _references;
 
   @override
-  idl.LinkedNode get node {
-    _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
-    return _node;
+  List<idl.LinkedNodeLibrary> get libraries {
+    _libraries ??= const fb.ListReader<idl.LinkedNodeLibrary>(
+            const _LinkedNodeLibraryReader())
+        .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeLibrary>[]);
+    return _libraries;
   }
 
   @override
-  idl.LinkedNodeReference get references {
+  idl.LinkedNodeReferences get references {
     _references ??=
-        const _LinkedNodeReferenceReader().vTableGet(_bc, _bcOffset, 1, null);
+        const _LinkedNodeReferencesReader().vTableGet(_bc, _bcOffset, 0, null);
     return _references;
   }
-
-  @override
-  idl.UnlinkedTokens get tokens {
-    _tokens ??=
-        const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 0, null);
-    return _tokens;
-  }
 }
 
 abstract class _LinkedNodeBundleMixin implements idl.LinkedNodeBundle {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
-    if (node != null) _result["node"] = node.toJson();
+    if (libraries.isNotEmpty)
+      _result["libraries"] =
+          libraries.map((_value) => _value.toJson()).toList();
     if (references != null) _result["references"] = references.toJson();
-    if (tokens != null) _result["tokens"] = tokens.toJson();
     return _result;
   }
 
   @override
   Map<String, Object> toMap() => {
-        "node": node,
+        "libraries": libraries,
         "references": references,
-        "tokens": tokens,
       };
 
   @override
   String toString() => convert.json.encode(toJson());
 }
 
-class LinkedNodeReferenceBuilder extends Object
-    with _LinkedNodeReferenceMixin
-    implements idl.LinkedNodeReference {
+class LinkedNodeLibraryBuilder extends Object
+    with _LinkedNodeLibraryMixin
+    implements idl.LinkedNodeLibrary {
+  List<int> _exports;
+  String _name;
+  int _nameLength;
+  int _nameOffset;
+  List<LinkedNodeUnitBuilder> _units;
+  String _uriStr;
+
+  @override
+  List<int> get exports => _exports ??= <int>[];
+
+  void set exports(List<int> value) {
+    assert(value == null || value.every((e) => e >= 0));
+    this._exports = value;
+  }
+
+  @override
+  String get name => _name ??= '';
+
+  void set name(String value) {
+    this._name = value;
+  }
+
+  @override
+  int get nameLength => _nameLength ??= 0;
+
+  void set nameLength(int value) {
+    assert(value == null || value >= 0);
+    this._nameLength = value;
+  }
+
+  @override
+  int get nameOffset => _nameOffset ??= 0;
+
+  void set nameOffset(int value) {
+    assert(value == null || value >= 0);
+    this._nameOffset = value;
+  }
+
+  @override
+  List<LinkedNodeUnitBuilder> get units => _units ??= <LinkedNodeUnitBuilder>[];
+
+  void set units(List<LinkedNodeUnitBuilder> value) {
+    this._units = value;
+  }
+
+  @override
+  String get uriStr => _uriStr ??= '';
+
+  void set uriStr(String value) {
+    this._uriStr = value;
+  }
+
+  LinkedNodeLibraryBuilder(
+      {List<int> exports,
+      String name,
+      int nameLength,
+      int nameOffset,
+      List<LinkedNodeUnitBuilder> units,
+      String uriStr})
+      : _exports = exports,
+        _name = name,
+        _nameLength = nameLength,
+        _nameOffset = nameOffset,
+        _units = units,
+        _uriStr = uriStr;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _units?.forEach((b) => b.flushInformative());
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._uriStr ?? '');
+    if (this._units == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._units.length);
+      for (var x in this._units) {
+        x?.collectApiSignature(signature);
+      }
+    }
+    if (this._exports == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._exports.length);
+      for (var x in this._exports) {
+        signature.addInt(x);
+      }
+    }
+    signature.addString(this._name ?? '');
+    signature.addInt(this._nameOffset ?? 0);
+    signature.addInt(this._nameLength ?? 0);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_exports;
+    fb.Offset offset_name;
+    fb.Offset offset_units;
+    fb.Offset offset_uriStr;
+    if (!(_exports == null || _exports.isEmpty)) {
+      offset_exports = fbBuilder.writeListUint32(_exports);
+    }
+    if (_name != null) {
+      offset_name = fbBuilder.writeString(_name);
+    }
+    if (!(_units == null || _units.isEmpty)) {
+      offset_units =
+          fbBuilder.writeList(_units.map((b) => b.finish(fbBuilder)).toList());
+    }
+    if (_uriStr != null) {
+      offset_uriStr = fbBuilder.writeString(_uriStr);
+    }
+    fbBuilder.startTable();
+    if (offset_exports != null) {
+      fbBuilder.addOffset(2, offset_exports);
+    }
+    if (offset_name != null) {
+      fbBuilder.addOffset(3, offset_name);
+    }
+    if (_nameLength != null && _nameLength != 0) {
+      fbBuilder.addUint32(5, _nameLength);
+    }
+    if (_nameOffset != null && _nameOffset != 0) {
+      fbBuilder.addUint32(4, _nameOffset);
+    }
+    if (offset_units != null) {
+      fbBuilder.addOffset(1, offset_units);
+    }
+    if (offset_uriStr != null) {
+      fbBuilder.addOffset(0, offset_uriStr);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeLibraryReader extends fb.TableReader<_LinkedNodeLibraryImpl> {
+  const _LinkedNodeLibraryReader();
+
+  @override
+  _LinkedNodeLibraryImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeLibraryImpl(bc, offset);
+}
+
+class _LinkedNodeLibraryImpl extends Object
+    with _LinkedNodeLibraryMixin
+    implements idl.LinkedNodeLibrary {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeLibraryImpl(this._bc, this._bcOffset);
+
+  List<int> _exports;
+  String _name;
+  int _nameLength;
+  int _nameOffset;
+  List<idl.LinkedNodeUnit> _units;
+  String _uriStr;
+
+  @override
+  List<int> get exports {
+    _exports ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 2, const <int>[]);
+    return _exports;
+  }
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
+    return _name;
+  }
+
+  @override
+  int get nameLength {
+    _nameLength ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 5, 0);
+    return _nameLength;
+  }
+
+  @override
+  int get nameOffset {
+    _nameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0);
+    return _nameOffset;
+  }
+
+  @override
+  List<idl.LinkedNodeUnit> get units {
+    _units ??=
+        const fb.ListReader<idl.LinkedNodeUnit>(const _LinkedNodeUnitReader())
+            .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeUnit>[]);
+    return _units;
+  }
+
+  @override
+  String get uriStr {
+    _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _uriStr;
+  }
+}
+
+abstract class _LinkedNodeLibraryMixin implements idl.LinkedNodeLibrary {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (exports.isNotEmpty) _result["exports"] = exports;
+    if (name != '') _result["name"] = name;
+    if (nameLength != 0) _result["nameLength"] = nameLength;
+    if (nameOffset != 0) _result["nameOffset"] = nameOffset;
+    if (units.isNotEmpty)
+      _result["units"] = units.map((_value) => _value.toJson()).toList();
+    if (uriStr != '') _result["uriStr"] = uriStr;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "exports": exports,
+        "name": name,
+        "nameLength": nameLength,
+        "nameOffset": nameOffset,
+        "units": units,
+        "uriStr": uriStr,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeReferencesBuilder extends Object
+    with _LinkedNodeReferencesMixin
+    implements idl.LinkedNodeReferences {
   List<String> _name;
   List<int> _parent;
 
@@ -17721,7 +18245,7 @@
     this._parent = value;
   }
 
-  LinkedNodeReferenceBuilder({List<String> name, List<int> parent})
+  LinkedNodeReferencesBuilder({List<String> name, List<int> parent})
       : _name = name,
         _parent = parent;
 
@@ -17773,22 +18297,22 @@
   }
 }
 
-class _LinkedNodeReferenceReader
-    extends fb.TableReader<_LinkedNodeReferenceImpl> {
-  const _LinkedNodeReferenceReader();
+class _LinkedNodeReferencesReader
+    extends fb.TableReader<_LinkedNodeReferencesImpl> {
+  const _LinkedNodeReferencesReader();
 
   @override
-  _LinkedNodeReferenceImpl createObject(fb.BufferContext bc, int offset) =>
-      new _LinkedNodeReferenceImpl(bc, offset);
+  _LinkedNodeReferencesImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeReferencesImpl(bc, offset);
 }
 
-class _LinkedNodeReferenceImpl extends Object
-    with _LinkedNodeReferenceMixin
-    implements idl.LinkedNodeReference {
+class _LinkedNodeReferencesImpl extends Object
+    with _LinkedNodeReferencesMixin
+    implements idl.LinkedNodeReferences {
   final fb.BufferContext _bc;
   final int _bcOffset;
 
-  _LinkedNodeReferenceImpl(this._bc, this._bcOffset);
+  _LinkedNodeReferencesImpl(this._bc, this._bcOffset);
 
   List<String> _name;
   List<int> _parent;
@@ -17808,7 +18332,7 @@
   }
 }
 
-abstract class _LinkedNodeReferenceMixin implements idl.LinkedNodeReference {
+abstract class _LinkedNodeReferencesMixin implements idl.LinkedNodeReferences {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
@@ -17842,7 +18366,7 @@
   List<int> get functionFormalParameters =>
       _functionFormalParameters ??= <int>[];
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   void set functionFormalParameters(List<int> value) {
     assert(value == null || value.every((e) => e >= 0));
     this._functionFormalParameters = value;
@@ -17858,7 +18382,7 @@
   @override
   List<int> get functionTypeParameters => _functionTypeParameters ??= <int>[];
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   void set functionTypeParameters(List<int> value) {
     assert(value == null || value.every((e) => e >= 0));
     this._functionTypeParameters = value;
@@ -17867,7 +18391,7 @@
   @override
   int get interfaceClass => _interfaceClass ??= 0;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   void set interfaceClass(int value) {
     assert(value == null || value >= 0);
     this._interfaceClass = value;
@@ -17891,7 +18415,7 @@
   @override
   int get typeParameterParameter => _typeParameterParameter ??= 0;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   void set typeParameterParameter(int value) {
     assert(value == null || value >= 0);
     this._typeParameterParameter = value;
@@ -18113,6 +18637,302 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class LinkedNodeUnitBuilder extends Object
+    with _LinkedNodeUnitMixin
+    implements idl.LinkedNodeUnit {
+  LinkedNodeBuilder _node;
+  UnlinkedTokensBuilder _tokens;
+  String _uriStr;
+
+  @override
+  LinkedNodeBuilder get node => _node;
+
+  void set node(LinkedNodeBuilder value) {
+    this._node = value;
+  }
+
+  @override
+  UnlinkedTokensBuilder get tokens => _tokens;
+
+  void set tokens(UnlinkedTokensBuilder value) {
+    this._tokens = value;
+  }
+
+  @override
+  String get uriStr => _uriStr ??= '';
+
+  void set uriStr(String value) {
+    this._uriStr = value;
+  }
+
+  LinkedNodeUnitBuilder(
+      {LinkedNodeBuilder node, UnlinkedTokensBuilder tokens, String uriStr})
+      : _node = node,
+        _tokens = tokens,
+        _uriStr = uriStr;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _node?.flushInformative();
+    _tokens?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._uriStr ?? '');
+    signature.addBool(this._tokens != null);
+    this._tokens?.collectApiSignature(signature);
+    signature.addBool(this._node != null);
+    this._node?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_node;
+    fb.Offset offset_tokens;
+    fb.Offset offset_uriStr;
+    if (_node != null) {
+      offset_node = _node.finish(fbBuilder);
+    }
+    if (_tokens != null) {
+      offset_tokens = _tokens.finish(fbBuilder);
+    }
+    if (_uriStr != null) {
+      offset_uriStr = fbBuilder.writeString(_uriStr);
+    }
+    fbBuilder.startTable();
+    if (offset_node != null) {
+      fbBuilder.addOffset(2, offset_node);
+    }
+    if (offset_tokens != null) {
+      fbBuilder.addOffset(1, offset_tokens);
+    }
+    if (offset_uriStr != null) {
+      fbBuilder.addOffset(0, offset_uriStr);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeUnitReader extends fb.TableReader<_LinkedNodeUnitImpl> {
+  const _LinkedNodeUnitReader();
+
+  @override
+  _LinkedNodeUnitImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeUnitImpl(bc, offset);
+}
+
+class _LinkedNodeUnitImpl extends Object
+    with _LinkedNodeUnitMixin
+    implements idl.LinkedNodeUnit {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeUnitImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNode _node;
+  idl.UnlinkedTokens _tokens;
+  String _uriStr;
+
+  @override
+  idl.LinkedNode get node {
+    _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
+    return _node;
+  }
+
+  @override
+  idl.UnlinkedTokens get tokens {
+    _tokens ??=
+        const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 1, null);
+    return _tokens;
+  }
+
+  @override
+  String get uriStr {
+    _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _uriStr;
+  }
+}
+
+abstract class _LinkedNodeUnitMixin implements idl.LinkedNodeUnit {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (node != null) _result["node"] = node.toJson();
+    if (tokens != null) _result["tokens"] = tokens.toJson();
+    if (uriStr != '') _result["uriStr"] = uriStr;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "node": node,
+        "tokens": tokens,
+        "uriStr": uriStr,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeVariablesDeclarationBuilder extends Object
+    with _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  LinkedNodeBuilder _comment;
+  bool _isConst;
+  bool _isFinal;
+  bool _isStatic;
+
+  @override
+  LinkedNodeBuilder get comment => _comment;
+
+  void set comment(LinkedNodeBuilder value) {
+    this._comment = value;
+  }
+
+  @override
+  bool get isConst => _isConst ??= false;
+
+  void set isConst(bool value) {
+    this._isConst = value;
+  }
+
+  @override
+  bool get isFinal => _isFinal ??= false;
+
+  void set isFinal(bool value) {
+    this._isFinal = value;
+  }
+
+  @override
+  bool get isStatic => _isStatic ??= false;
+
+  void set isStatic(bool value) {
+    this._isStatic = value;
+  }
+
+  LinkedNodeVariablesDeclarationBuilder(
+      {LinkedNodeBuilder comment, bool isConst, bool isFinal, bool isStatic})
+      : _comment = comment,
+        _isConst = isConst,
+        _isFinal = isFinal,
+        _isStatic = isStatic;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _comment?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addBool(this._isConst == true);
+    signature.addBool(this._isFinal == true);
+    signature.addBool(this._isStatic == true);
+    signature.addBool(this._comment != null);
+    this._comment?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_comment;
+    if (_comment != null) {
+      offset_comment = _comment.finish(fbBuilder);
+    }
+    fbBuilder.startTable();
+    if (offset_comment != null) {
+      fbBuilder.addOffset(3, offset_comment);
+    }
+    if (_isConst == true) {
+      fbBuilder.addBool(0, true);
+    }
+    if (_isFinal == true) {
+      fbBuilder.addBool(1, true);
+    }
+    if (_isStatic == true) {
+      fbBuilder.addBool(2, true);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeVariablesDeclarationReader
+    extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
+  const _LinkedNodeVariablesDeclarationReader();
+
+  @override
+  _LinkedNodeVariablesDeclarationImpl createObject(
+          fb.BufferContext bc, int offset) =>
+      new _LinkedNodeVariablesDeclarationImpl(bc, offset);
+}
+
+class _LinkedNodeVariablesDeclarationImpl extends Object
+    with _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNode _comment;
+  bool _isConst;
+  bool _isFinal;
+  bool _isStatic;
+
+  @override
+  idl.LinkedNode get comment {
+    _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 3, null);
+    return _comment;
+  }
+
+  @override
+  bool get isConst {
+    _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 0, false);
+    return _isConst;
+  }
+
+  @override
+  bool get isFinal {
+    _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
+    return _isFinal;
+  }
+
+  @override
+  bool get isStatic {
+    _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
+    return _isStatic;
+  }
+}
+
+abstract class _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (comment != null) _result["comment"] = comment.toJson();
+    if (isConst != false) _result["isConst"] = isConst;
+    if (isFinal != false) _result["isFinal"] = isFinal;
+    if (isStatic != false) _result["isStatic"] = isStatic;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "comment": comment,
+        "isConst": isConst,
+        "isFinal": isFinal,
+        "isStatic": isStatic,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class LinkedReferenceBuilder extends Object
     with _LinkedReferenceMixin
     implements idl.LinkedReference {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index bb8bc6b..6cd172f 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -398,6 +398,8 @@
 
   function,
 
+  genericTypeAlias,
+
   interface,
 
   typeParameter,
@@ -970,7 +972,26 @@
 
   /// Pop the top 2 values from the stack, place them in a [MapLiteralEntry],
   /// and push the result back onto the stack.
-  makeMapLiteralEntry
+  makeMapLiteralEntry,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...`, and push the result back onto the stack.
+  spreadElement,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...?`, and push the result back onto the stack.
+  nullAwareSpreadElement,
+
+  /// Pop the top two values from the stack.  The first is a condition
+  /// and the second is a collection element.  Push an "if" element having the
+  /// given condition, with the collection element as its "then" clause.
+  ifElement,
+
+  /// Pop the top three values from the stack.  The first is a condition and the
+  /// other two are collection elements.  Push an "if" element having the given
+  /// condition, with the two collection elements as its "then" and "else"
+  /// clauses, respectively.
+  ifElseElement
 }
 
 /// Enum used to indicate the kind of a parameter.
@@ -1791,19 +1812,36 @@
   variantField_20:string (id: 20);
 
   variantField_22:string (id: 22);
+
+  variantField_32:LinkedNodeVariablesDeclaration (id: 32);
 }
 
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
 table LinkedNodeBundle {
-  node:LinkedNode (id: 2);
+  libraries:[LinkedNodeLibrary] (id: 1);
 
-  references:LinkedNodeReference (id: 1);
+  /// The shared list of references used in the [libraries].
+  references:LinkedNodeReferences (id: 0);
+}
 
-  tokens:UnlinkedTokens (id: 0);
+/// Information about a single library in a [LinkedNodeBundle].
+table LinkedNodeLibrary {
+  exports:[uint] (id: 2);
+
+  name:string (id: 3);
+
+  nameLength:uint (id: 5);
+
+  nameOffset:uint (id: 4);
+
+  units:[LinkedNodeUnit] (id: 1);
+
+  uriStr:string (id: 0);
 }
 
 /// Flattened tree of declarations referenced from [LinkedNode]s.
-table LinkedNodeReference {
+table LinkedNodeReferences {
   name:[string] (id: 1);
 
   parent:[uint] (id: 0);
@@ -1811,25 +1849,46 @@
 
 /// Information about a Dart type.
 table LinkedNodeType {
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   functionFormalParameters:[uint] (id: 0);
 
   functionReturnType:LinkedNodeType (id: 1);
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   functionTypeParameters:[uint] (id: 2);
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   interfaceClass:uint (id: 3);
 
   interfaceTypeArguments:[LinkedNodeType] (id: 4);
 
   kind:LinkedNodeTypeKind (id: 5);
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   typeParameterParameter:uint (id: 6);
 }
 
+/// Information about a single library in a [LinkedNodeLibrary].
+table LinkedNodeUnit {
+  node:LinkedNode (id: 2);
+
+  tokens:UnlinkedTokens (id: 1);
+
+  uriStr:string (id: 0);
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+table LinkedNodeVariablesDeclaration {
+  comment:LinkedNode (id: 3);
+
+  isConst:bool (id: 0);
+
+  isFinal:bool (id: 1);
+
+  isStatic:bool (id: 2);
+}
+
 /// Information about the resolution of an [UnlinkedReference].
 table LinkedReference {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index b25b830..c9e84f8 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -987,6 +987,9 @@
   @VariantId(6, variant: LinkedNodeKind.classDeclaration)
   LinkedNode get classDeclaration_extendsClause;
 
+  @VariantId(27, variant: LinkedNodeKind.classDeclaration)
+  bool get classDeclaration_isDartObject;
+
   @VariantId(7, variant: LinkedNodeKind.classDeclaration)
   LinkedNode get classDeclaration_withClause;
 
@@ -1338,6 +1341,9 @@
   @VariantId(6, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_type;
 
+  @VariantId(24, variant: LinkedNodeKind.fieldFormalParameter)
+  LinkedNodeType get fieldFormalParameter_type2;
+
   @VariantId(7, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_typeParameters;
 
@@ -1459,6 +1465,9 @@
   @VariantId(7, variant: LinkedNodeKind.functionDeclaration)
   LinkedNode get functionDeclaration_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.functionDeclaration)
+  LinkedNodeType get functionDeclaration_returnType2;
+
   @VariantId(6, variant: LinkedNodeKind.functionDeclarationStatement)
   LinkedNode get functionDeclarationStatement_functionDeclaration;
 
@@ -1480,6 +1489,9 @@
   @VariantId(7, variant: LinkedNodeKind.functionTypeAlias)
   LinkedNode get functionTypeAlias_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.functionTypeAlias)
+  LinkedNodeType get functionTypeAlias_returnType2;
+
   @VariantId(8, variant: LinkedNodeKind.functionTypeAlias)
   LinkedNode get functionTypeAlias_typeParameters;
 
@@ -1504,6 +1516,9 @@
   @VariantId(7, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.genericFunctionType)
+  LinkedNodeType get genericFunctionType_returnType2;
+
   @VariantId(6, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_typeParameters;
 
@@ -1696,6 +1711,9 @@
   @VariantId(7, variant: LinkedNodeKind.mapLiteralEntry)
   LinkedNode get mapLiteralEntry_value;
 
+  @VariantId(19, variant: LinkedNodeKind.methodDeclaration)
+  int get methodDeclaration_actualProperty;
+
   @VariantId(6, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_body;
 
@@ -1720,6 +1738,9 @@
   @VariantId(8, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.methodDeclaration)
+  LinkedNodeType get methodDeclaration_returnType2;
+
   @VariantId(9, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_typeParameters;
 
@@ -1804,6 +1825,13 @@
   ])
   LinkedNode get normalFormalParameter_identifier;
 
+  @VariantId(27, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+  ])
+  bool get normalFormalParameter_isCovariant;
+
   @VariantId(4, variantList: [
     LinkedNodeKind.fieldFormalParameter,
     LinkedNodeKind.functionTypedFormalParameter,
@@ -1931,6 +1959,9 @@
   @VariantId(6, variant: LinkedNodeKind.simpleFormalParameter)
   LinkedNode get simpleFormalParameter_type;
 
+  @VariantId(24, variant: LinkedNodeKind.simpleFormalParameter)
+  LinkedNodeType get simpleFormalParameter_type2;
+
   @VariantId(15, variant: LinkedNodeKind.simpleIdentifier)
   int get simpleIdentifier_element;
 
@@ -2140,6 +2171,9 @@
   ])
   int get uriBasedDirective_uriElement;
 
+  @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
+
   @VariantId(15, variant: LinkedNodeKind.variableDeclaration)
   int get variableDeclaration_equals;
 
@@ -2149,6 +2183,9 @@
   @VariantId(7, variant: LinkedNodeKind.variableDeclaration)
   LinkedNode get variableDeclaration_name;
 
+  @VariantId(24, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNodeType get variableDeclaration_type2;
+
   @VariantId(15, variant: LinkedNodeKind.variableDeclarationList)
   int get variableDeclarationList_keyword;
 
@@ -2198,20 +2235,19 @@
   int get yieldStatement_yieldKeyword;
 }
 
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
 @TopLevel('LNBn')
 abstract class LinkedNodeBundle extends base.SummaryClass {
   factory LinkedNodeBundle.fromBuffer(List<int> buffer) =>
       generated.readLinkedNodeBundle(buffer);
 
-  @Id(2)
-  LinkedNode get node;
-
   @Id(1)
-  LinkedNodeReference get references;
+  List<LinkedNodeLibrary> get libraries;
 
+  /// The shared list of references used in the [libraries].
   @Id(0)
-  UnlinkedTokens get tokens;
+  LinkedNodeReferences get references;
 }
 
 /// Types of comments.
@@ -2344,8 +2380,29 @@
   yieldStatement,
 }
 
+/// Information about a single library in a [LinkedNodeBundle].
+abstract class LinkedNodeLibrary extends base.SummaryClass {
+  @Id(2)
+  List<int> get exports;
+
+  @Id(3)
+  String get name;
+
+  @Id(5)
+  int get nameLength;
+
+  @Id(4)
+  int get nameOffset;
+
+  @Id(1)
+  List<LinkedNodeUnit> get units;
+
+  @Id(0)
+  String get uriStr;
+}
+
 /// Flattened tree of declarations referenced from [LinkedNode]s.
-abstract class LinkedNodeReference extends base.SummaryClass {
+abstract class LinkedNodeReferences extends base.SummaryClass {
   @Id(1)
   List<String> get name;
 
@@ -2355,18 +2412,18 @@
 
 /// Information about a Dart type.
 abstract class LinkedNodeType extends base.SummaryClass {
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   @Id(0)
   List<int> get functionFormalParameters;
 
   @Id(1)
   LinkedNodeType get functionReturnType;
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   @Id(2)
   List<int> get functionTypeParameters;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   @Id(3)
   int get interfaceClass;
 
@@ -2376,7 +2433,7 @@
   @Id(5)
   LinkedNodeTypeKind get kind;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   @Id(6)
   int get typeParameterParameter;
 }
@@ -2386,11 +2443,40 @@
   bottom,
   dynamic_,
   function,
+  genericTypeAlias,
   interface,
   typeParameter,
   void_
 }
 
+/// Information about a single library in a [LinkedNodeLibrary].
+abstract class LinkedNodeUnit extends base.SummaryClass {
+  @Id(2)
+  LinkedNode get node;
+
+  @Id(1)
+  UnlinkedTokens get tokens;
+
+  @Id(0)
+  String get uriStr;
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
+  @Id(3)
+  LinkedNode get comment;
+
+  @Id(0)
+  bool get isConst;
+
+  @Id(1)
+  bool get isFinal;
+
+  @Id(2)
+  bool get isStatic;
+}
+
 /// Information about the resolution of an [UnlinkedReference].
 abstract class LinkedReference extends base.SummaryClass {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
@@ -3782,6 +3868,25 @@
   /// Pop the top 2 values from the stack, place them in a [MapLiteralEntry],
   /// and push the result back onto the stack.
   makeMapLiteralEntry,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...`, and push the result back onto the stack.
+  spreadElement,
+
+  /// Pop the top value from the stack, convert it to a spread element of type
+  /// `...?`, and push the result back onto the stack.
+  nullAwareSpreadElement,
+
+  /// Pop the top two values from the stack.  The first is a condition
+  /// and the second is a collection element.  Push an "if" element having the
+  /// given condition, with the collection element as its "then" clause.
+  ifElement,
+
+  /// Pop the top three values from the stack.  The first is a condition and the
+  /// other two are collection elements.  Push an "if" element having the given
+  /// condition, with the two collection elements as its "then" and "else"
+  /// clauses, respectively.
+  ifElseElement,
 }
 
 /// Unlinked summary information about an import declaration.
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 541cfe7..d38b602 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2,8 +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 'package:analyzer/dart/analysis/session.dart';
-
 /// This library is capable of producing linked summaries from unlinked
 /// ones (or prelinked ones).  It functions by building a miniature
 /// element model to represent the contents of the summaries, and then
@@ -57,12 +55,13 @@
 ///
 /// - Where possible, we favor method dispatch instead of "is" and "as"
 ///   checks.  E.g. see [ReferenceableElementForLink.asConstructor].
+import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/dart/element/builder.dart';
@@ -116,11 +115,12 @@
     Set<String> libraryUris,
     GetDependencyCallback getDependency,
     GetUnitCallback getUnit,
-    GetDeclaredVariable getDeclaredVariable,
+    DeclaredVariables declaredVariables,
+    AnalysisOptions analysisOptions,
     [GetAstCallback getAst]) {
   Map<String, LinkedLibraryBuilder> linkedLibraries =
-      setupForLink(libraryUris, getUnit, getDeclaredVariable);
-  _relink(linkedLibraries, getDependency, getUnit, getAst);
+      setupForLink(libraryUris, getUnit, declaredVariables);
+  _relink(linkedLibraries, getDependency, getUnit, getAst, analysisOptions);
   return linkedLibraries;
 }
 
@@ -132,7 +132,7 @@
 /// of the libraries in this build unit, and whose values are the corresponding
 /// [LinkedLibraryBuilder]s.
 Map<String, LinkedLibraryBuilder> setupForLink(Set<String> libraryUris,
-    GetUnitCallback getUnit, GetDeclaredVariable getDeclaredVariable) {
+    GetUnitCallback getUnit, DeclaredVariables declaredVariables) {
   Map<String, LinkedLibraryBuilder> linkedLibraries =
       <String, LinkedLibraryBuilder>{};
   for (String absoluteUri in libraryUris) {
@@ -141,7 +141,7 @@
         getUnit(absoluteUri),
         getUnit,
         (String absoluteUri) => getUnit(absoluteUri)?.publicNamespace,
-        getDeclaredVariable);
+        declaredVariables);
   }
   return linkedLibraries;
 }
@@ -301,8 +301,9 @@
     Map<String, LinkedLibraryBuilder> libraries,
     GetDependencyCallback getDependency,
     GetUnitCallback getUnit,
-    GetAstCallback getAst) {
-  new Linker(libraries, getDependency, getUnit, getAst).link();
+    GetAstCallback getAst,
+    AnalysisOptions analysisOptions) {
+  new Linker(libraries, getDependency, getUnit, getAst, analysisOptions).link();
 }
 
 /// Create an [UnlinkedParam] representing the given [parameter], which should
@@ -412,37 +413,7 @@
 /// [UnlinkedUnit] objects.
 typedef UnlinkedUnit GetUnitCallback(String absoluteUri);
 
-/// Stub implementation of [AnalysisOptions] used during linking.
-class AnalysisOptionsForLink implements AnalysisOptionsImpl {
-  final Linker _linker;
-
-  AnalysisOptionsForLink(this._linker);
-
-  @override
-  bool get hint => false;
-
-  @override
-  bool get implicitCasts => true;
-
-  @override
-  bool get strictInference => false;
-
-  @override
-  bool get strictRawTypes => false;
-
-  @deprecated
-  @override
-  bool get previewDart2 => true;
-
-  @override
-  bool get strongMode => true;
-
-  @override
-  bool get strongModeHints => false;
-
-  @override
-  ExperimentStatus get experimentStatus => new ExperimentStatus();
-
+class AnalysisSessionForLink implements AnalysisSession {
   @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
@@ -498,6 +469,9 @@
   Source get librarySource => library.source;
 
   @override
+  get linkedNode => null;
+
+  @override
   List<MethodElementForLink> get methods;
 
   @override
@@ -1931,6 +1905,7 @@
         case UnlinkedExprOperation.makeUntypedList:
         case UnlinkedExprOperation.makeUntypedMap:
         case UnlinkedExprOperation.makeUntypedSet:
+        case UnlinkedExprOperation.makeUntypedSetOrMap:
           intPtr++;
           break;
         case UnlinkedExprOperation.assignToRef:
@@ -1958,6 +1933,7 @@
           intPtr++;
           break;
         case UnlinkedExprOperation.makeTypedMap:
+        case UnlinkedExprOperation.makeTypedMap2:
           refPtr += 2;
           intPtr++;
           break;
@@ -2105,7 +2081,7 @@
   ContextForLink(this._linker);
 
   @override
-  AnalysisOptionsForLink get analysisOptions => _linker.analysisOptions;
+  AnalysisOptions get analysisOptions => _linker.analysisOptions;
 
   @override
   TypeProvider get typeProvider => _linker.typeProvider;
@@ -2344,6 +2320,9 @@
   LibraryElement get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name {
     if (_name == null) {
       _name = serializedExecutable.name;
@@ -2512,7 +2491,9 @@
       List<UnlinkedExecutable> localFunctions)
       : _builder = new ExprBuilder(
             unitResynthesizer, _functionElement, unlinkedConst,
-            requireValidConst: false, localFunctions: localFunctions);
+            requireValidConst: false,
+            localFunctions: localFunctions,
+            becomeSetOrMap: false);
 
   TopLevelInferenceErrorKind get errorKind {
     // TODO(paulberry): should we return TopLevelInferenceErrorKind.assignment
@@ -2854,6 +2835,9 @@
   bool get isAsynchronous => serializedExecutable.isAsynchronous;
 
   @override
+  get linkedNode => null;
+
+  @override
   DartType get returnType {
     // If this is a variable whose type needs inferring, infer it.
     if (_variable.hasImplicitType) {
@@ -3169,6 +3153,9 @@
   LibraryElementForLink get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name => _unlinkedTypedef.name;
 
   @override
@@ -3287,6 +3274,9 @@
   LibraryElementForLink get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name => '-';
 
   @override
@@ -3370,6 +3360,9 @@
   LibraryElementForLink get library => enclosingElement.library;
 
   @override
+  get linkedNode => null;
+
+  @override
   String get name => _unlinkedTypedef.name;
 
   @override
@@ -3651,6 +3644,9 @@
   LibraryResynthesizerContext get resynthesizerContext => this;
 
   @override
+  AnalysisSession get session => _linker.session;
+
+  @override
   Source get source => definingCompilationUnit.source;
 
   @override
@@ -3948,10 +3944,13 @@
   SpecialTypeElementForLink _bottomElement;
   InheritanceManager2 _inheritanceManager;
   ContextForLink _context;
-  AnalysisOptionsForLink _analysisOptions;
+  AnalysisSessionForLink _session;
+
+  /// Gets an instance of [AnalysisOptions] for use during linking.
+  final AnalysisOptions analysisOptions;
 
   Linker(Map<String, LinkedLibraryBuilder> linkedLibraries, this.getDependency,
-      this.getUnit, this.getAst) {
+      this.getUnit, this.getAst, this.analysisOptions) {
     // Create elements for the libraries to be linked.  The rest of
     // the element model will be created on demand.
     linkedLibraries
@@ -3962,10 +3961,6 @@
     });
   }
 
-  /// Get an instance of [AnalysisOptions] for use during linking.
-  AnalysisOptionsForLink get analysisOptions =>
-      _analysisOptions ??= new AnalysisOptionsForLink(this);
-
   /// Get the library element for `dart:async`.
   LibraryElementForLink get asyncLibrary =>
       _asyncLibrary ??= getLibrary(Uri.parse('dart:async'));
@@ -3990,6 +3985,10 @@
   InheritanceManager2 get inheritanceManager =>
       _inheritanceManager ??= new InheritanceManager2(typeSystem);
 
+  /// Get a stub implementation of [AnalysisContext] which can be used during
+  /// linking.
+  get session => _session ??= new AnalysisSessionForLink();
+
   /// Indicates whether type inference should use strong mode rules.
   @deprecated
   bool get strongMode => true;
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index dc9e818..91a51d2 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -1,23 +1,21 @@
+// 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' as io;
 import 'dart:math' show min;
 
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/api/general.dart';
 import 'package:analyzer/src/task/api/model.dart';
-import 'package:analyzer/src/task/dart.dart';
 
 /**
  * A [ConflictingSummaryException] indicates that two different summaries
@@ -187,130 +185,7 @@
 
   @override
   bool compute(CacheEntry entry, ResultDescriptor result) {
-    AnalysisTarget target = entry.target;
-
-    if (result == TYPE_PROVIDER) {
-      entry.setValue(result as ResultDescriptor<TypeProvider>,
-          _resynthesizer.typeProvider, const <TargetedResult>[]);
-      return true;
-    }
-
-    // LINE_INFO can be provided using just the UnlinkedUnit.
-    if (target is Source && result == LINE_INFO) {
-      String uriString = target.uri.toString();
-      UnlinkedUnit unlinkedUnit = _dataStore.unlinkedMap[uriString];
-      if (unlinkedUnit != null) {
-        List<int> lineStarts = unlinkedUnit.lineStarts;
-        if (lineStarts.isNotEmpty) {
-          LineInfo lineInfo = new LineInfo(lineStarts);
-          entry.setValue(result as ResultDescriptor<LineInfo>, lineInfo,
-              const <TargetedResult>[]);
-          return true;
-        }
-      }
-      return false;
-    }
-
-    // Check whether there are results for the source.
-    if (!hasResultsForSource(target.librarySource ?? target.source)) {
-      return false;
-    }
-    // Constant expressions are always resolved in summaries.
-    if (result == CONSTANT_EXPRESSION_RESOLVED &&
-        target is ConstantEvaluationTarget) {
-      entry.setValue(
-          result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
-      return true;
-    }
-    // Provide results for Source.
-    if (target is Source) {
-      String uriString = target.uri.toString();
-      // Provide known results.
-      if (result == LIBRARY_ELEMENT1 ||
-          result == LIBRARY_ELEMENT2 ||
-          result == LIBRARY_ELEMENT3 ||
-          result == LIBRARY_ELEMENT4 ||
-          result == LIBRARY_ELEMENT5 ||
-          result == LIBRARY_ELEMENT6 ||
-          result == LIBRARY_ELEMENT7 ||
-          result == LIBRARY_ELEMENT8 ||
-          result == LIBRARY_ELEMENT9 ||
-          result == LIBRARY_ELEMENT) {
-        LibraryElement libraryElement =
-            resynthesizer.getLibraryElement(uriString);
-        entry.setValue(result as ResultDescriptor<LibraryElement>,
-            libraryElement, const <TargetedResult>[]);
-        return true;
-      } else if (result == READY_LIBRARY_ELEMENT2 ||
-          result == READY_LIBRARY_ELEMENT6 ||
-          result == READY_LIBRARY_ELEMENT7) {
-        entry.setValue(
-            result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
-        return true;
-      } else if (result == MODIFICATION_TIME) {
-        entry.setValue(
-            result as ResultDescriptor<int>, 0, const <TargetedResult>[]);
-        return true;
-      } else if (result == SOURCE_KIND) {
-        UnlinkedUnit unlinked = _dataStore.unlinkedMap[uriString];
-        if (unlinked != null) {
-          entry.setValue(
-              result as ResultDescriptor<SourceKind>,
-              unlinked.isPartOf ? SourceKind.PART : SourceKind.LIBRARY,
-              const <TargetedResult>[]);
-          return true;
-        }
-        return false;
-      } else if (result == CONTAINING_LIBRARIES) {
-        List<String> libraryUriStrings =
-            _dataStore.getContainingLibraryUris(uriString);
-        if (libraryUriStrings != null) {
-          List<Source> librarySources = libraryUriStrings
-              .map((libraryUriString) =>
-                  context.sourceFactory.resolveUri(target, libraryUriString))
-              .toList(growable: false);
-          entry.setValue(result as ResultDescriptor<List<Source>>,
-              librarySources, const <TargetedResult>[]);
-          return true;
-        }
-        return false;
-      }
-    } else if (target is LibrarySpecificUnit) {
-      if (result == CREATED_RESOLVED_UNIT1 ||
-          result == CREATED_RESOLVED_UNIT2 ||
-          result == CREATED_RESOLVED_UNIT3 ||
-          result == CREATED_RESOLVED_UNIT4 ||
-          result == CREATED_RESOLVED_UNIT5 ||
-          result == CREATED_RESOLVED_UNIT6 ||
-          result == CREATED_RESOLVED_UNIT7 ||
-          result == CREATED_RESOLVED_UNIT8 ||
-          result == CREATED_RESOLVED_UNIT9 ||
-          result == CREATED_RESOLVED_UNIT10 ||
-          result == CREATED_RESOLVED_UNIT11) {
-        entry.setValue(
-            result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
-        return true;
-      }
-      if (result == COMPILATION_UNIT_ELEMENT) {
-        String libraryUri = target.library.uri.toString();
-        String unitUri = target.unit.uri.toString();
-        CompilationUnitElement unit = resynthesizer.getElement(
-            new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
-        if (unit != null) {
-          entry.setValue(result as ResultDescriptor<CompilationUnitElement>,
-              unit, const <TargetedResult>[]);
-          return true;
-        }
-      }
-    } else if (target is VariableElement) {
-      if (result == INFERRED_STATIC_VARIABLE) {
-        entry.setValue(result as ResultDescriptor<VariableElement>, target,
-            const <TargetedResult>[]);
-        return true;
-      }
-    }
-    // Unknown target.
-    return false;
+    throw UnimplementedError();
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index 6bda8fd..1785442 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -2,6 +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.
 
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -21,19 +22,13 @@
     UnlinkedUnit definingUnit,
     GetPartCallback getPart,
     GetImportCallback getImport,
-    GetDeclaredVariable getDeclaredVariable) {
-  return new _Prelinker(definingUnitUri, definingUnit, getPart, getImport,
-          getDeclaredVariable)
+    DeclaredVariables declaredVariables) {
+  return new _Prelinker(
+          definingUnitUri, definingUnit, getPart, getImport, declaredVariables)
       .prelink();
 }
 
 /**
- * Return the raw string value of the variable with the given [name],
- * or `null` of the variable is not defined.
- */
-typedef String GetDeclaredVariable(String name);
-
-/**
  * Type of the callback used by the prelinker to obtain public namespace
  * information about libraries with the given [absoluteUri] imported by the
  * library to be prelinked (and the transitive closure of parts and exports
@@ -219,7 +214,7 @@
   final UnlinkedUnit definingUnit;
   final GetPartCallback getPart;
   final GetImportCallback getImport;
-  final GetDeclaredVariable getDeclaredVariable;
+  final DeclaredVariables declaredVariables;
 
   /**
    * Cache of values returned by [getImport].
@@ -263,7 +258,7 @@
   final Map<String, _ExportNamespace> exportNamespaces = {};
 
   _Prelinker(this.definingUnitUri, this.definingUnit, this.getPart,
-      this.getImport, this.getDeclaredVariable) {
+      this.getImport, this.declaredVariables) {
     partCache[definingUnitUri] = definingUnit;
     importCache[definingUnitUri] = definingUnit.publicNamespace;
   }
@@ -719,7 +714,7 @@
   String _selectUri(
       String defaultUri, List<UnlinkedConfiguration> configurations) {
     for (UnlinkedConfiguration configuration in configurations) {
-      if (getDeclaredVariable(configuration.name) == configuration.value) {
+      if (declaredVariables.get(configuration.name) == configuration.value) {
         return configuration.uri;
       }
     }
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 5e93786..f367937 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -344,14 +344,6 @@
           typeName.typeArguments != null);
     } else if (expr is ListLiteral) {
       _serializeListLiteral(expr);
-      // ignore: deprecated_member_use_from_same_package
-    } else if (expr is MapLiteral) {
-      // ignore: deprecated_member_use_from_same_package
-      _serializeMapLiteral(expr);
-      // ignore: deprecated_member_use_from_same_package
-    } else if (expr is SetLiteral) {
-      // ignore: deprecated_member_use_from_same_package
-      _serializeSetLiteral(expr);
     } else if (expr is SetOrMapLiteral) {
       _serializeSetOrMapLiteral(expr);
     } else if (expr is MethodInvocation) {
@@ -549,6 +541,23 @@
       _serialize(element.key);
       _serialize(element.value);
       operations.add(UnlinkedExprOperation.makeMapLiteralEntry);
+    } else if (element is SpreadElement) {
+      _serialize(element.expression);
+      bool isNullAware = element.spreadOperator.type ==
+          TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
+      operations.add(isNullAware
+          ? UnlinkedExprOperation.nullAwareSpreadElement
+          : UnlinkedExprOperation.spreadElement);
+    } else if (element is IfElement) {
+      _serialize(element.condition);
+      _serializeCollectionElement(element.thenElement);
+      var elseElement = element.elseElement;
+      if (elseElement == null) {
+        operations.add(UnlinkedExprOperation.ifElement);
+      } else {
+        _serializeCollectionElement(elseElement);
+        operations.add(UnlinkedExprOperation.ifElseElement);
+      }
     } else {
       // TODO(paulberry): Implement serialization for spread and control flow
       //  elements.
@@ -573,27 +582,6 @@
     }
   }
 
-  @deprecated
-  void _serializeMapLiteral(MapLiteral expr) {
-    if (forConst || expr.typeArguments == null) {
-      for (MapLiteralEntry entry in expr.entries) {
-        _serialize(entry.key);
-        _serialize(entry.value);
-      }
-      ints.add(expr.entries.length);
-    } else {
-      ints.add(0);
-    }
-    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(UnlinkedExprOperation.makeTypedMap);
-    } else {
-      operations.add(UnlinkedExprOperation.makeUntypedMap);
-    }
-  }
-
   void _serializeMethodInvocation(MethodInvocation invocation) {
     Expression target = invocation.target;
     SimpleIdentifier methodName = invocation.methodName;
@@ -673,24 +661,6 @@
     }
   }
 
-  @deprecated
-  void _serializeSetLiteral(SetLiteral expr) {
-    if (forConst || expr.typeArguments == null) {
-      List<Expression> elements = expr.elements;
-      elements.forEach(_serialize);
-      ints.add(elements.length);
-    } else {
-      ints.add(0);
-    }
-    if (expr.typeArguments != null &&
-        expr.typeArguments.arguments.length == 1) {
-      references.add(serializeType(expr.typeArguments.arguments[0]));
-      operations.add(UnlinkedExprOperation.makeTypedSet);
-    } else {
-      operations.add(UnlinkedExprOperation.makeUntypedSet);
-    }
-  }
-
   void _serializeSetOrMapLiteral(SetOrMapLiteral expr) {
     if (forConst || expr.typeArguments == null) {
       for (CollectionElement element in expr.elements2) {
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 9d7b6ad..f774d2a 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
@@ -25,11 +26,9 @@
 class SummaryBuilder {
   final Iterable<Source> librarySources;
   final AnalysisContext context;
+
   /**
    * Create a summary builder for these [librarySources] and [context].
-   *
-   * TODO(paulberry): remove optional "strong" parameter once all callers have
-   * stopped passing it in.
    */
   SummaryBuilder(this.librarySources, this.context);
 
@@ -92,9 +91,7 @@
         throw new StateError('Unable to find unresolved unit $uri.');
       }
       return unlinked;
-    }, (String name) {
-      throw new StateError('Unexpected call to GetDeclaredVariable($name).');
-    });
+    }, DeclaredVariables(), context.analysisOptions);
     map.forEach(bundleAssembler.addLinkedLibrary);
 
     return bundleAssembler.assemble().toBuffer();
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index f8490e1..33f51e3 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -8,25 +8,17 @@
 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/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
 
 /// Deserializer of fully resolved ASTs from flat buffers.
 class AstBinaryReader {
-  final Reference _nameRoot;
-  final LinkedNodeReference _linkedReferences;
-  final List<Reference> _references;
+  final LinkedUnitContext _unitContext;
 
-  final UnlinkedTokens _tokensBinary;
-  final List<Token> _tokens;
-
-  AstBinaryReader(this._nameRoot, this._linkedReferences, this._tokensBinary)
-      : _references = List<Reference>(_linkedReferences.name.length),
-        _tokens = List<Token>(_tokensBinary.type.length);
+  AstBinaryReader(this._unitContext);
 
   AstNode readNode(LinkedNode data) {
     if (data == null) return null;
@@ -269,89 +261,18 @@
     }
   }
 
-  CommentToken _getCommentToken(int index) {
-    var result = _getToken(index);
-    var token = result;
-    while (true) {
-      index = _tokensBinary.next[index];
-      if (index == 0) return result;
-
-      var nextToken = _getToken(index);
-      token.next = nextToken;
-      token = nextToken;
-    }
-  }
-
   T _getElement<T extends Element>(int index) {
-    return _getReferenceByIndex(index)?.element;
+    var bundleContext = _unitContext.bundleContext;
+    return bundleContext.elementOfIndex(index);
   }
 
   List<T> _getElements<T extends Element>(List<int> indexList) {
-    var result = List<T>(indexList.length);
-    for (var i = 0; i < indexList.length; ++i) {
-      var index = indexList[i];
-      result[i] = _getElement(index);
-    }
-    return result;
-  }
-
-  Reference _getReferenceByIndex(int index) {
-    var reference = _references[index];
-    if (reference != null) return reference;
-
-    if (index == 0) {
-      _references[index] = _nameRoot;
-      return _nameRoot;
-    }
-
-    var parentIndex = _linkedReferences.parent[index];
-    var parent = _getReferenceByIndex(parentIndex);
-    if (parent == null) return null;
-
-    var name = _linkedReferences.name[index];
-    reference = parent[name];
-    _references[index] = reference;
-
-    return reference;
+    var bundleContext = _unitContext.bundleContext;
+    return bundleContext.elementsOfIndexes(indexList);
   }
 
   Token _getToken(int index) {
-    var token = _tokens[index];
-    if (token == null) {
-      var kind = _tokensBinary.kind[index];
-      switch (kind) {
-        case UnlinkedTokenKind.nothing:
-          return null;
-        case UnlinkedTokenKind.comment:
-          return CommentToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.lexeme[index],
-            _tokensBinary.offset[index],
-          );
-        case UnlinkedTokenKind.keyword:
-          return KeywordToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.offset[index],
-            _getCommentToken(_tokensBinary.precedingComment[index]),
-          );
-        case UnlinkedTokenKind.simple:
-          return SimpleToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.offset[index],
-            _getCommentToken(_tokensBinary.precedingComment[index]),
-          );
-        case UnlinkedTokenKind.string:
-          return StringToken(
-            _binaryToAstTokenType(_tokensBinary.type[index]),
-            _tokensBinary.lexeme[index],
-            _tokensBinary.offset[index],
-            _getCommentToken(_tokensBinary.precedingComment[index]),
-          );
-        default:
-          throw UnimplementedError('Token kind: $kind');
-      }
-    }
-    return token;
+    return _unitContext.tokensContext.tokenOfIndex(index);
   }
 
   List<Token> _getTokens(List<int> indexList) {
@@ -1236,7 +1157,7 @@
       leftBracket: _getToken(data.setOrMapLiteral_leftBracket),
       typeArguments: readNode(data.typedLiteral_typeArguments),
       rightBracket: _getToken(data.setOrMapLiteral_leftBracket),
-    );
+    )..staticType = _readType(data.expression_type);
     if (data.setOrMapLiteral_isMap) {
       node.becomeMap();
     } else if (data.setOrMapLiteral_isSet) {
@@ -1523,279 +1444,4 @@
     }
     return result;
   }
-
-  static TokenType _binaryToAstTokenType(UnlinkedTokenType type) {
-    switch (type) {
-      case UnlinkedTokenType.ABSTRACT:
-        return Keyword.ABSTRACT;
-      case UnlinkedTokenType.AMPERSAND:
-        return TokenType.AMPERSAND;
-      case UnlinkedTokenType.AMPERSAND_AMPERSAND:
-        return TokenType.AMPERSAND_AMPERSAND;
-      case UnlinkedTokenType.AMPERSAND_EQ:
-        return TokenType.AMPERSAND_EQ;
-      case UnlinkedTokenType.AS:
-        return TokenType.AS;
-      case UnlinkedTokenType.ASSERT:
-        return Keyword.ASSERT;
-      case UnlinkedTokenType.ASYNC:
-        return Keyword.ASYNC;
-      case UnlinkedTokenType.AT:
-        return TokenType.AT;
-      case UnlinkedTokenType.AWAIT:
-        return Keyword.AWAIT;
-      case UnlinkedTokenType.BACKPING:
-        return TokenType.BACKPING;
-      case UnlinkedTokenType.BACKSLASH:
-        return TokenType.BACKSLASH;
-      case UnlinkedTokenType.BANG:
-        return TokenType.BANG;
-      case UnlinkedTokenType.BANG_EQ:
-        return TokenType.BANG_EQ;
-      case UnlinkedTokenType.BAR:
-        return TokenType.BAR;
-      case UnlinkedTokenType.BAR_BAR:
-        return TokenType.BAR_BAR;
-      case UnlinkedTokenType.BAR_EQ:
-        return TokenType.BAR_EQ;
-      case UnlinkedTokenType.BREAK:
-        return Keyword.BREAK;
-      case UnlinkedTokenType.CARET:
-        return TokenType.CARET;
-      case UnlinkedTokenType.CARET_EQ:
-        return TokenType.CARET_EQ;
-      case UnlinkedTokenType.CASE:
-        return Keyword.CASE;
-      case UnlinkedTokenType.CATCH:
-        return Keyword.CATCH;
-      case UnlinkedTokenType.CLASS:
-        return Keyword.CLASS;
-      case UnlinkedTokenType.CLOSE_CURLY_BRACKET:
-        return TokenType.CLOSE_CURLY_BRACKET;
-      case UnlinkedTokenType.CLOSE_PAREN:
-        return TokenType.CLOSE_PAREN;
-      case UnlinkedTokenType.CLOSE_SQUARE_BRACKET:
-        return TokenType.CLOSE_SQUARE_BRACKET;
-      case UnlinkedTokenType.COLON:
-        return TokenType.COLON;
-      case UnlinkedTokenType.COMMA:
-        return TokenType.COMMA;
-      case UnlinkedTokenType.CONST:
-        return Keyword.CONST;
-      case UnlinkedTokenType.CONTINUE:
-        return Keyword.CONTINUE;
-      case UnlinkedTokenType.COVARIANT:
-        return Keyword.COVARIANT;
-      case UnlinkedTokenType.DEFAULT:
-        return Keyword.DEFAULT;
-      case UnlinkedTokenType.DEFERRED:
-        return Keyword.DEFERRED;
-      case UnlinkedTokenType.DO:
-        return Keyword.DO;
-      case UnlinkedTokenType.DOUBLE:
-        return TokenType.DOUBLE;
-      case UnlinkedTokenType.DYNAMIC:
-        return Keyword.DYNAMIC;
-      case UnlinkedTokenType.ELSE:
-        return Keyword.ELSE;
-      case UnlinkedTokenType.ENUM:
-        return Keyword.ENUM;
-      case UnlinkedTokenType.EOF:
-        return TokenType.EOF;
-      case UnlinkedTokenType.EQ:
-        return TokenType.EQ;
-      case UnlinkedTokenType.EQ_EQ:
-        return TokenType.EQ_EQ;
-      case UnlinkedTokenType.EXPORT:
-        return Keyword.EXPORT;
-      case UnlinkedTokenType.EXTENDS:
-        return Keyword.EXTENDS;
-      case UnlinkedTokenType.EXTERNAL:
-        return Keyword.EXTERNAL;
-      case UnlinkedTokenType.FACTORY:
-        return Keyword.FACTORY;
-      case UnlinkedTokenType.FALSE:
-        return Keyword.FALSE;
-      case UnlinkedTokenType.FINAL:
-        return Keyword.FINAL;
-      case UnlinkedTokenType.FINALLY:
-        return Keyword.FINALLY;
-      case UnlinkedTokenType.FOR:
-        return Keyword.FOR;
-      case UnlinkedTokenType.FUNCTION:
-        return TokenType.FUNCTION;
-      case UnlinkedTokenType.FUNCTION_KEYWORD:
-        return Keyword.FUNCTION;
-      case UnlinkedTokenType.GET:
-        return Keyword.GET;
-      case UnlinkedTokenType.GT:
-        return TokenType.GT;
-      case UnlinkedTokenType.GT_EQ:
-        return TokenType.GT_EQ;
-      case UnlinkedTokenType.GT_GT:
-        return TokenType.GT_GT;
-      case UnlinkedTokenType.GT_GT_EQ:
-        return TokenType.GT_GT_EQ;
-      case UnlinkedTokenType.HASH:
-        return TokenType.HASH;
-      case UnlinkedTokenType.HEXADECIMAL:
-        return TokenType.HEXADECIMAL;
-      case UnlinkedTokenType.HIDE:
-        return Keyword.HIDE;
-      case UnlinkedTokenType.IDENTIFIER:
-        return TokenType.IDENTIFIER;
-      case UnlinkedTokenType.IF:
-        return Keyword.IF;
-      case UnlinkedTokenType.IMPLEMENTS:
-        return Keyword.IMPLEMENTS;
-      case UnlinkedTokenType.IMPORT:
-        return Keyword.IMPORT;
-      case UnlinkedTokenType.IN:
-        return Keyword.IN;
-      case UnlinkedTokenType.INDEX:
-        return TokenType.INDEX;
-      case UnlinkedTokenType.INDEX_EQ:
-        return TokenType.INDEX_EQ;
-      case UnlinkedTokenType.INT:
-        return TokenType.INT;
-      case UnlinkedTokenType.INTERFACE:
-        return Keyword.INTERFACE;
-      case UnlinkedTokenType.IS:
-        return TokenType.IS;
-      case UnlinkedTokenType.LIBRARY:
-        return Keyword.LIBRARY;
-      case UnlinkedTokenType.LT:
-        return TokenType.LT;
-      case UnlinkedTokenType.LT_EQ:
-        return TokenType.LT_EQ;
-      case UnlinkedTokenType.LT_LT:
-        return TokenType.LT_LT;
-      case UnlinkedTokenType.LT_LT_EQ:
-        return TokenType.LT_LT_EQ;
-      case UnlinkedTokenType.MINUS:
-        return TokenType.MINUS;
-      case UnlinkedTokenType.MINUS_EQ:
-        return TokenType.MINUS_EQ;
-      case UnlinkedTokenType.MINUS_MINUS:
-        return TokenType.MINUS_MINUS;
-      case UnlinkedTokenType.MIXIN:
-        return Keyword.MIXIN;
-      case UnlinkedTokenType.MULTI_LINE_COMMENT:
-        return TokenType.MULTI_LINE_COMMENT;
-      case UnlinkedTokenType.NATIVE:
-        return Keyword.NATIVE;
-      case UnlinkedTokenType.NEW:
-        return Keyword.NEW;
-      case UnlinkedTokenType.NULL:
-        return Keyword.NULL;
-      case UnlinkedTokenType.OF:
-        return Keyword.OF;
-      case UnlinkedTokenType.ON:
-        return Keyword.ON;
-      case UnlinkedTokenType.OPEN_CURLY_BRACKET:
-        return TokenType.OPEN_CURLY_BRACKET;
-      case UnlinkedTokenType.OPEN_PAREN:
-        return TokenType.OPEN_PAREN;
-      case UnlinkedTokenType.OPEN_SQUARE_BRACKET:
-        return TokenType.OPEN_SQUARE_BRACKET;
-      case UnlinkedTokenType.OPERATOR:
-        return Keyword.OPERATOR;
-      case UnlinkedTokenType.PART:
-        return Keyword.PART;
-      case UnlinkedTokenType.PATCH:
-        return Keyword.PATCH;
-      case UnlinkedTokenType.PERCENT:
-        return TokenType.PERCENT;
-      case UnlinkedTokenType.PERCENT_EQ:
-        return TokenType.PERCENT_EQ;
-      case UnlinkedTokenType.PERIOD:
-        return TokenType.PERIOD;
-      case UnlinkedTokenType.PERIOD_PERIOD:
-        return TokenType.PERIOD_PERIOD;
-      case UnlinkedTokenType.PERIOD_PERIOD_PERIOD:
-        return TokenType.PERIOD_PERIOD_PERIOD;
-      case UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION:
-        return TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
-      case UnlinkedTokenType.PLUS:
-        return TokenType.PLUS;
-      case UnlinkedTokenType.PLUS_EQ:
-        return TokenType.PLUS_EQ;
-      case UnlinkedTokenType.PLUS_PLUS:
-        return TokenType.PLUS_PLUS;
-      case UnlinkedTokenType.QUESTION:
-        return TokenType.QUESTION;
-      case UnlinkedTokenType.QUESTION_PERIOD:
-        return TokenType.QUESTION_PERIOD;
-      case UnlinkedTokenType.QUESTION_QUESTION:
-        return TokenType.QUESTION_QUESTION;
-      case UnlinkedTokenType.QUESTION_QUESTION_EQ:
-        return TokenType.QUESTION_QUESTION_EQ;
-      case UnlinkedTokenType.RETHROW:
-        return Keyword.RETHROW;
-      case UnlinkedTokenType.RETURN:
-        return Keyword.RETURN;
-      case UnlinkedTokenType.SCRIPT_TAG:
-        return TokenType.SCRIPT_TAG;
-      case UnlinkedTokenType.SEMICOLON:
-        return TokenType.SEMICOLON;
-      case UnlinkedTokenType.SET:
-        return Keyword.SET;
-      case UnlinkedTokenType.SHOW:
-        return Keyword.SHOW;
-      case UnlinkedTokenType.SINGLE_LINE_COMMENT:
-        return TokenType.SINGLE_LINE_COMMENT;
-      case UnlinkedTokenType.SLASH:
-        return TokenType.SLASH;
-      case UnlinkedTokenType.SLASH_EQ:
-        return TokenType.SLASH_EQ;
-      case UnlinkedTokenType.SOURCE:
-        return Keyword.SOURCE;
-      case UnlinkedTokenType.STAR:
-        return TokenType.STAR;
-      case UnlinkedTokenType.STAR_EQ:
-        return TokenType.STAR_EQ;
-      case UnlinkedTokenType.STATIC:
-        return Keyword.STATIC;
-      case UnlinkedTokenType.STRING:
-        return TokenType.STRING;
-      case UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION:
-        return TokenType.STRING_INTERPOLATION_EXPRESSION;
-      case UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER:
-        return TokenType.STRING_INTERPOLATION_IDENTIFIER;
-      case UnlinkedTokenType.SUPER:
-        return Keyword.SUPER;
-      case UnlinkedTokenType.SWITCH:
-        return Keyword.SWITCH;
-      case UnlinkedTokenType.SYNC:
-        return Keyword.SYNC;
-      case UnlinkedTokenType.THIS:
-        return Keyword.THIS;
-      case UnlinkedTokenType.THROW:
-        return Keyword.THROW;
-      case UnlinkedTokenType.TILDE:
-        return TokenType.TILDE;
-      case UnlinkedTokenType.TILDE_SLASH:
-        return TokenType.TILDE_SLASH;
-      case UnlinkedTokenType.TILDE_SLASH_EQ:
-        return TokenType.TILDE_SLASH_EQ;
-      case UnlinkedTokenType.TRUE:
-        return Keyword.TRUE;
-      case UnlinkedTokenType.TRY:
-        return Keyword.TRY;
-      case UnlinkedTokenType.TYPEDEF:
-        return Keyword.TYPEDEF;
-      case UnlinkedTokenType.VAR:
-        return Keyword.VAR;
-      case UnlinkedTokenType.VOID:
-        return Keyword.VOID;
-      case UnlinkedTokenType.WHILE:
-        return Keyword.WHILE;
-      case UnlinkedTokenType.WITH:
-        return Keyword.WITH;
-      case UnlinkedTokenType.YIELD:
-        return Keyword.YIELD;
-      default:
-        throw StateError('Unexpected type: $type');
-    }
-  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 185370e..187dc7b 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -8,36 +8,24 @@
 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/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:meta/meta.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
 
 /// Serializer of fully resolved ASTs into flat buffers.
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
-  final referenceRoot = Reference.root();
-  final referenceBuilder = LinkedNodeReferenceBuilder();
-  final _references = <Reference>[];
+  final LinkingBundleContext _linkingBundleContext;
+  final TokensContext _tokensContext;
 
-  final UnlinkedTokensBuilder tokens = UnlinkedTokensBuilder();
-  final Map<Token, int> _tokenMap = Map.identity();
-  int _tokenIndex = 0;
+  /// This field is set temporary while visiting [FieldDeclaration] or
+  /// [TopLevelVariableDeclaration] to store data shared among all variables
+  /// in these declarations.
+  LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
 
-  AstBinaryWriter() {
-    _references.add(referenceRoot);
-    _addToken(
-      isSynthetic: true,
-      kind: UnlinkedTokenKind.nothing,
-      length: 0,
-      lexeme: '',
-      offset: 0,
-      precedingComment: 0,
-      type: UnlinkedTokenType.NOTHING,
-    );
-  }
+  AstBinaryWriter(this._linkingBundleContext, this._tokensContext);
 
   @override
   LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) {
@@ -105,7 +93,7 @@
   @override
   LinkedNodeBuilder visitAssignmentExpression(AssignmentExpression node) {
     return LinkedNodeBuilder.assignmentExpression(
-      assignmentExpression_element: _getReference(node.staticElement).index,
+      assignmentExpression_element: _getReferenceIndex(node.staticElement),
       assignmentExpression_leftHandSide: node.leftHandSide.accept(this),
       assignmentExpression_operator: _getToken(node.operator),
       assignmentExpression_rightHandSide: node.rightHandSide.accept(this),
@@ -125,7 +113,7 @@
   @override
   LinkedNodeBuilder visitBinaryExpression(BinaryExpression node) {
     return LinkedNodeBuilder.binaryExpression(
-      binaryExpression_element: _getReference(node.staticElement).index,
+      binaryExpression_element: _getReferenceIndex(node.staticElement),
       binaryExpression_leftOperand: node.leftOperand.accept(this),
       binaryExpression_operator: _getToken(node.operator),
       binaryExpression_rightOperand: node.rightOperand.accept(this),
@@ -312,7 +300,7 @@
   @override
   LinkedNodeBuilder visitConstructorName(ConstructorName node) {
     return LinkedNodeBuilder.constructorName(
-      constructorName_element: _getReference(node.staticElement).index,
+      constructorName_element: _getReferenceIndex(node.staticElement),
       constructorName_name: node.name?.accept(this),
       constructorName_period: _getToken(node.period),
       constructorName_type: node.type.accept(this),
@@ -452,6 +440,10 @@
 
   @override
   LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
+    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
+      isStatic: node.isStatic,
+    );
+
     var builder = LinkedNodeBuilder.fieldDeclaration(
       fieldDeclaration_covariantKeyword: _getToken(node.covariantKeyword),
       fieldDeclaration_fields: node.fields.accept(this),
@@ -459,6 +451,10 @@
       fieldDeclaration_staticKeyword: _getToken(node.staticKeyword),
     );
     _storeClassMember(builder, node);
+
+    _variablesDeclaration.comment = builder.annotatedNode_comment;
+    _variablesDeclaration = null;
+
     return builder;
   }
 
@@ -688,7 +684,7 @@
   @override
   LinkedNodeBuilder visitIndexExpression(IndexExpression node) {
     return LinkedNodeBuilder.indexExpression(
-      indexExpression_element: _getReference(node.staticElement).index,
+      indexExpression_element: _getReferenceIndex(node.staticElement),
       indexExpression_index: node.index.accept(this),
       indexExpression_leftBracket: _getToken(node.leftBracket),
       indexExpression_rightBracket: _getToken(node.rightBracket),
@@ -812,6 +808,7 @@
       methodDeclaration_operatorKeyword: _getToken(node.operatorKeyword),
       methodDeclaration_propertyKeyword: _getToken(node.propertyKeyword),
       methodDeclaration_returnType: node.returnType?.accept(this),
+      methodDeclaration_typeParameters: node.typeParameters?.accept(this),
     );
     _storeClassMember(builder, node);
     return builder;
@@ -899,7 +896,7 @@
   LinkedNodeBuilder visitPostfixExpression(PostfixExpression node) {
     return LinkedNodeBuilder.postfixExpression(
       expression_type: _writeType(node.staticType),
-      postfixExpression_element: _getReference(node.staticElement).index,
+      postfixExpression_element: _getReferenceIndex(node.staticElement),
       postfixExpression_operand: node.operand.accept(this),
       postfixExpression_operator: _getToken(node.operator),
     );
@@ -919,7 +916,7 @@
   LinkedNodeBuilder visitPrefixExpression(PrefixExpression node) {
     return LinkedNodeBuilder.prefixExpression(
       expression_type: _writeType(node.staticType),
-      prefixExpression_element: _getReference(node.staticElement).index,
+      prefixExpression_element: _getReferenceIndex(node.staticElement),
       prefixExpression_operand: node.operand.accept(this),
       prefixExpression_operator: _getToken(node.operator),
     );
@@ -945,7 +942,7 @@
       redirectingConstructorInvocation_constructorName:
           node.constructorName?.accept(this),
       redirectingConstructorInvocation_element:
-          _getReference(node.staticElement).index,
+          _getReferenceIndex(node.staticElement),
       redirectingConstructorInvocation_period: _getToken(node.period),
       redirectingConstructorInvocation_thisKeyword: _getToken(node.thisKeyword),
     );
@@ -1012,11 +1009,16 @@
 
   @override
   LinkedNodeBuilder visitSimpleIdentifier(SimpleIdentifier node) {
-    var isDeclared = node.inDeclarationContext();
+    Element element;
+    if (!node.inDeclarationContext()) {
+      element = node.staticElement;
+      if (element is MultiplyDefinedElement) {
+        element = null;
+      }
+    }
 
     return LinkedNodeBuilder.simpleIdentifier(
-      simpleIdentifier_element:
-          isDeclared ? null : _getReference(node.staticElement).index,
+      simpleIdentifier_element: _getReferenceIndex(element),
       simpleIdentifier_token: _getToken(node.token),
       expression_type: _writeType(node.staticType),
     );
@@ -1056,7 +1058,7 @@
       superConstructorInvocation_constructorName:
           node.constructorName?.accept(this),
       superConstructorInvocation_element:
-          _getReference(node.staticElement).index,
+          _getReferenceIndex(node.staticElement),
       superConstructorInvocation_period: _getToken(node.period),
       superConstructorInvocation_superKeyword: _getToken(node.superKeyword),
     );
@@ -1133,11 +1135,17 @@
   @override
   LinkedNodeBuilder visitTopLevelVariableDeclaration(
       TopLevelVariableDeclaration node) {
+    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
+
     var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
       topLevelVariableDeclaration_semicolon: _getToken(node.semicolon),
       topLevelVariableDeclaration_variableList: node.variables?.accept(this),
     );
     _storeCompilationUnitMember(builder, node);
+
+    _variablesDeclaration.comment = builder.annotatedNode_comment;
+    _variablesDeclaration = null;
+
     return builder;
   }
 
@@ -1196,11 +1204,17 @@
       variableDeclaration_equals: _getToken(node.equals),
       variableDeclaration_initializer: node.initializer?.accept(this),
       variableDeclaration_name: node.name.accept(this),
+      variableDeclaration_declaration: _variablesDeclaration,
     );
   }
 
   @override
   LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
+    if (_variablesDeclaration != null) {
+      _variablesDeclaration.isConst = node.isConst;
+      _variablesDeclaration.isFinal = node.isFinal;
+    }
+
     var builder = LinkedNodeBuilder.variableDeclarationList(
       variableDeclarationList_keyword: _getToken(node.keyword),
       variableDeclarationList_type: node.type?.accept(this),
@@ -1251,184 +1265,26 @@
   }
 
   LinkedNodeBuilder writeNode(AstNode node) {
-    _writeTokens(node.beginToken, node.endToken);
     return node.accept(this);
   }
 
-  /// Write [referenceRoot] and all its children into [referenceBuilder].
-  void writeReferences() {
-    for (var reference in _references) {
-      referenceBuilder.parent.add(reference.parent?.index ?? 0);
-      referenceBuilder.name.add(reference.name);
+  int _getReferenceIndex(Element element) {
+    if (element == null) return 0;
+
+    if (element is Member) {
+      element = (element as Member).baseElement;
     }
-  }
 
-  void _addToken({
-    @required bool isSynthetic,
-    @required UnlinkedTokenKind kind,
-    @required int length,
-    @required String lexeme,
-    @required int offset,
-    @required int precedingComment,
-    @required UnlinkedTokenType type,
-  }) {
-    tokens.endGroup.add(0);
-    tokens.isSynthetic.add(isSynthetic);
-    tokens.kind.add(kind);
-    tokens.length.add(length);
-    tokens.lexeme.add(lexeme);
-    tokens.next.add(0);
-    tokens.offset.add(offset);
-    tokens.precedingComment.add(precedingComment);
-    tokens.type.add(type);
-    _tokenIndex++;
-  }
-
-  void _ensureReferenceIndex(Reference reference) {
-    if (reference.index == null) {
-      reference.index = _references.length;
-      _references.add(reference);
+    var reference = (element as ElementImpl).reference;
+    if (identical(element, DynamicElementImpl.instance)) {
+      reference = _linkingBundleContext.dynamicReference;
     }
-  }
 
-  Reference _getReference(Element element) {
-    if (element == null) return referenceRoot;
-
-    // TODO(scheglov) handle Member elements
-
-    Reference result;
-    if (element is ClassElement) {
-      var containerRef = _getReference(element.library).getChild('@class');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is CompilationUnitElement) {
-      return _getReference(element.enclosingElement);
-    } else if (element is ConstructorElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@constructor');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is DynamicElementImpl) {
-      result = _getReference(element.library).getChild('@dynamic');
-    } else if (element is FieldElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@field');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is FunctionElement) {
-      var containerRef = _getReference(element.library).getChild('@function');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name ?? '');
-    } else if (element is FunctionTypeAliasElement) {
-      var libraryRef = _getReference(element.library);
-      var containerRef = libraryRef.getChild('@functionTypeAlias');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is GenericFunctionTypeElement) {
-      if (element.enclosingElement is GenericTypeAliasElement) {
-        return _getReference(element.enclosingElement);
-      } else {
-        var libraryRef = _getReference(element.library);
-        var containerRef = libraryRef.getChild('@functionType');
-        _ensureReferenceIndex(containerRef);
-
-        // TODO(scheglov) do we need to store these elements at all?
-        result = containerRef.getChild('<unnamed>');
-      }
-    } else if (element is GenericTypeAliasElement) {
-      var containerRef = _getReference(element.library).getChild('@typeAlias');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is GenericFunctionTypeElement &&
-        element.enclosingElement is ParameterElement) {
-      return _getReference(element.enclosingElement);
-    } else if (element is LibraryElement) {
-      var uriStr = element.source.uri.toString();
-      result = referenceRoot.getChild(uriStr);
-    } else if (element is LabelElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@label');
-      _ensureReferenceIndex(containerRef);
-
-      // TODO(scheglov) use index instead of offset
-      result = containerRef.getChild('${element.nameOffset}');
-    } else if (element is LocalVariableElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@localVariable');
-      _ensureReferenceIndex(containerRef);
-
-      // TODO(scheglov) use index instead of offset
-      result = containerRef.getChild('${element.nameOffset}');
-    } else if (element is MethodElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@method');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is MultiplyDefinedElement) {
-      return referenceRoot;
-    } else if (element is ParameterElement) {
-      var enclosing = element.enclosingElement;
-      var enclosingRef = _getReference(enclosing);
-      var containerRef = enclosingRef.getChild('@parameter');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is PrefixElement) {
-      var containerRef = _getReference(element.library).getChild('@prefix');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is PropertyAccessorElement) {
-      var enclosingRef = _getReference(element.library);
-      var containerRef = enclosingRef.getChild(
-        element.isGetter ? '@getter' : '@setter',
-      );
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.displayName);
-    } else if (element is TopLevelVariableElement) {
-      var enclosingRef = _getReference(element.library);
-      var containerRef = enclosingRef.getChild('@variable');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is TypeParameterElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@typeParameter');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else {
-      throw UnimplementedError('(${element.runtimeType}) $element');
-    }
-    _ensureReferenceIndex(result);
-    return result;
-  }
-
-  List<int> _getReferences(List<Element> elements) {
-    var result = List<int>(elements.length);
-    for (var i = 0; i < elements.length; ++i) {
-      var element = elements[i];
-      result[i] = _getReference(element).index;
-    }
-    return result;
+    return _linkingBundleContext.indexOfReference(reference);
   }
 
   int _getToken(Token token) {
-    if (token == null) return 0;
-
-    var index = _tokenMap[token];
-    if (index == null) {
-      throw StateError('Token must be written first: $token');
-    }
-    return index;
+    return _tokensContext.indexOfToken(token);
   }
 
   List<int> _getTokens(List<Token> tokenList) {
@@ -1602,36 +1458,7 @@
     builder
       ..uriBasedDirective_uri = node.uri.accept(this)
       ..uriBasedDirective_uriContent = node.uriContent
-      ..uriBasedDirective_uriElement = _getReference(node.uriElement).index;
-  }
-
-  int _writeCommentToken(CommentToken token) {
-    if (token == null) return 0;
-    var firstIndex = _tokenIndex;
-
-    var previousIndex = 0;
-    while (token != null) {
-      var index = _tokenIndex;
-      _tokenMap[token] = index;
-      _addToken(
-        isSynthetic: false,
-        kind: UnlinkedTokenKind.comment,
-        length: token.length,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        precedingComment: 0,
-        type: _astToBinaryTokenType(token.type),
-      );
-
-      if (previousIndex != 0) {
-        tokens.next[previousIndex] = index;
-      }
-      previousIndex = index;
-
-      token = token.next;
-    }
-
-    return firstIndex;
+      ..uriBasedDirective_uriElement = _getReferenceIndex(node.uriElement);
   }
 
   List<LinkedNodeBuilder> _writeNodeList(List<AstNode> nodeList) {
@@ -1646,389 +1473,7 @@
     return result;
   }
 
-  int _writeToken(Token token) {
-    assert(_tokenMap[token] == null);
-
-    var commentIndex = _writeCommentToken(token.precedingComments);
-
-    var index = _tokenIndex;
-    _tokenMap[token] = index;
-
-    if (token is KeywordToken) {
-      _addToken(
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.keyword,
-        lexeme: '',
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else if (token is StringToken) {
-      _addToken(
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.string,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else if (token is SimpleToken) {
-      _addToken(
-        isSynthetic: token.isSynthetic,
-        kind: UnlinkedTokenKind.simple,
-        lexeme: token.lexeme,
-        offset: token.offset,
-        length: token.length,
-        precedingComment: commentIndex,
-        type: _astToBinaryTokenType(token.type),
-      );
-    } else {
-      throw UnimplementedError('(${token.runtimeType}) $token');
-    }
-
-    return index;
-  }
-
-  /// Write all the tokens from the [first] to the [last] inclusively.
-  void _writeTokens(Token first, Token last) {
-    if (first is CommentToken) {
-      first = (first as CommentToken).parent;
-    }
-
-    var endGroupToBeginIndexMap = <Token, int>{};
-    var previousIndex = 0;
-    for (var token = first;; token = token.next) {
-      var index = _writeToken(token);
-
-      if (previousIndex != 0) {
-        tokens.next[previousIndex] = index;
-      }
-      previousIndex = index;
-
-      if (token.endGroup != null) {
-        endGroupToBeginIndexMap[token.endGroup] = index;
-      }
-
-      var beginIndex = endGroupToBeginIndexMap[token];
-      if (beginIndex != null) {
-        tokens.endGroup[beginIndex] = index;
-      }
-
-      if (token == last) break;
-    }
-  }
-
   LinkedNodeTypeBuilder _writeType(DartType type) {
-    if (type == null) return null;
-
-    if (type.isBottom) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.bottom,
-      );
-    } else if (type.isDynamic) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.dynamic_,
-      );
-    } else if (type is FunctionType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.function,
-        functionFormalParameters: _getReferences(type.parameters),
-        functionReturnType: _writeType(type.returnType),
-        functionTypeParameters: _getReferences(type.parameters),
-      );
-    } else if (type is InterfaceType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.interface,
-        interfaceClass: _getReference(type.element).index,
-        interfaceTypeArguments: type.typeArguments.map(_writeType).toList(),
-      );
-    } else if (type is TypeParameterType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.typeParameter,
-        typeParameterParameter: _getReference(type.element).index,
-      );
-    } else if (type is VoidType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.void_,
-      );
-    } else {
-      throw UnimplementedError('(${type.runtimeType}) $type');
-    }
-  }
-
-  static UnlinkedTokenType _astToBinaryTokenType(TokenType type) {
-    if (type == Keyword.ABSTRACT) {
-      return UnlinkedTokenType.ABSTRACT;
-    } else if (type == TokenType.AMPERSAND) {
-      return UnlinkedTokenType.AMPERSAND;
-    } else if (type == TokenType.AMPERSAND_AMPERSAND) {
-      return UnlinkedTokenType.AMPERSAND_AMPERSAND;
-    } else if (type == TokenType.AMPERSAND_EQ) {
-      return UnlinkedTokenType.AMPERSAND_EQ;
-    } else if (type == TokenType.AS) {
-      return UnlinkedTokenType.AS;
-    } else if (type == Keyword.ASSERT) {
-      return UnlinkedTokenType.ASSERT;
-    } else if (type == Keyword.ASYNC) {
-      return UnlinkedTokenType.ASYNC;
-    } else if (type == TokenType.AT) {
-      return UnlinkedTokenType.AT;
-    } else if (type == Keyword.AWAIT) {
-      return UnlinkedTokenType.AWAIT;
-    } else if (type == TokenType.BACKPING) {
-      return UnlinkedTokenType.BACKPING;
-    } else if (type == TokenType.BACKSLASH) {
-      return UnlinkedTokenType.BACKSLASH;
-    } else if (type == TokenType.BANG) {
-      return UnlinkedTokenType.BANG;
-    } else if (type == TokenType.BANG_EQ) {
-      return UnlinkedTokenType.BANG_EQ;
-    } else if (type == TokenType.BAR) {
-      return UnlinkedTokenType.BAR;
-    } else if (type == TokenType.BAR_BAR) {
-      return UnlinkedTokenType.BAR_BAR;
-    } else if (type == TokenType.BAR_EQ) {
-      return UnlinkedTokenType.BAR_EQ;
-    } else if (type == Keyword.BREAK) {
-      return UnlinkedTokenType.BREAK;
-    } else if (type == TokenType.CARET) {
-      return UnlinkedTokenType.CARET;
-    } else if (type == TokenType.CARET_EQ) {
-      return UnlinkedTokenType.CARET_EQ;
-    } else if (type == Keyword.CASE) {
-      return UnlinkedTokenType.CASE;
-    } else if (type == Keyword.CATCH) {
-      return UnlinkedTokenType.CATCH;
-    } else if (type == Keyword.CLASS) {
-      return UnlinkedTokenType.CLASS;
-    } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-      return UnlinkedTokenType.CLOSE_CURLY_BRACKET;
-    } else if (type == TokenType.CLOSE_PAREN) {
-      return UnlinkedTokenType.CLOSE_PAREN;
-    } else if (type == TokenType.CLOSE_SQUARE_BRACKET) {
-      return UnlinkedTokenType.CLOSE_SQUARE_BRACKET;
-    } else if (type == TokenType.COLON) {
-      return UnlinkedTokenType.COLON;
-    } else if (type == TokenType.COMMA) {
-      return UnlinkedTokenType.COMMA;
-    } else if (type == Keyword.CONST) {
-      return UnlinkedTokenType.CONST;
-    } else if (type == Keyword.CONTINUE) {
-      return UnlinkedTokenType.CONTINUE;
-    } else if (type == Keyword.COVARIANT) {
-      return UnlinkedTokenType.COVARIANT;
-    } else if (type == Keyword.DEFAULT) {
-      return UnlinkedTokenType.DEFAULT;
-    } else if (type == Keyword.DEFERRED) {
-      return UnlinkedTokenType.DEFERRED;
-    } else if (type == Keyword.DO) {
-      return UnlinkedTokenType.DO;
-    } else if (type == TokenType.DOUBLE) {
-      return UnlinkedTokenType.DOUBLE;
-    } else if (type == Keyword.DYNAMIC) {
-      return UnlinkedTokenType.DYNAMIC;
-    } else if (type == Keyword.ELSE) {
-      return UnlinkedTokenType.ELSE;
-    } else if (type == Keyword.ENUM) {
-      return UnlinkedTokenType.ENUM;
-    } else if (type == TokenType.EOF) {
-      return UnlinkedTokenType.EOF;
-    } else if (type == TokenType.EQ) {
-      return UnlinkedTokenType.EQ;
-    } else if (type == TokenType.EQ_EQ) {
-      return UnlinkedTokenType.EQ_EQ;
-    } else if (type == Keyword.EXPORT) {
-      return UnlinkedTokenType.EXPORT;
-    } else if (type == Keyword.EXTENDS) {
-      return UnlinkedTokenType.EXTENDS;
-    } else if (type == Keyword.EXTERNAL) {
-      return UnlinkedTokenType.EXTERNAL;
-    } else if (type == Keyword.FACTORY) {
-      return UnlinkedTokenType.FACTORY;
-    } else if (type == Keyword.FALSE) {
-      return UnlinkedTokenType.FALSE;
-    } else if (type == Keyword.FINAL) {
-      return UnlinkedTokenType.FINAL;
-    } else if (type == Keyword.FINALLY) {
-      return UnlinkedTokenType.FINALLY;
-    } else if (type == Keyword.FOR) {
-      return UnlinkedTokenType.FOR;
-    } else if (type == Keyword.FUNCTION) {
-      return UnlinkedTokenType.FUNCTION_KEYWORD;
-    } else if (type == TokenType.FUNCTION) {
-      return UnlinkedTokenType.FUNCTION;
-    } else if (type == Keyword.GET) {
-      return UnlinkedTokenType.GET;
-    } else if (type == TokenType.GT) {
-      return UnlinkedTokenType.GT;
-    } else if (type == TokenType.GT_EQ) {
-      return UnlinkedTokenType.GT_EQ;
-    } else if (type == TokenType.GT_GT) {
-      return UnlinkedTokenType.GT_GT;
-    } else if (type == TokenType.GT_GT_EQ) {
-      return UnlinkedTokenType.GT_GT_EQ;
-    } else if (type == TokenType.HASH) {
-      return UnlinkedTokenType.HASH;
-    } else if (type == TokenType.HEXADECIMAL) {
-      return UnlinkedTokenType.HEXADECIMAL;
-    } else if (type == Keyword.HIDE) {
-      return UnlinkedTokenType.HIDE;
-    } else if (type == TokenType.IDENTIFIER) {
-      return UnlinkedTokenType.IDENTIFIER;
-    } else if (type == Keyword.IF) {
-      return UnlinkedTokenType.IF;
-    } else if (type == Keyword.IMPLEMENTS) {
-      return UnlinkedTokenType.IMPLEMENTS;
-    } else if (type == Keyword.IMPORT) {
-      return UnlinkedTokenType.IMPORT;
-    } else if (type == Keyword.IN) {
-      return UnlinkedTokenType.IN;
-    } else if (type == TokenType.INDEX) {
-      return UnlinkedTokenType.INDEX;
-    } else if (type == TokenType.INDEX_EQ) {
-      return UnlinkedTokenType.INDEX_EQ;
-    } else if (type == TokenType.INT) {
-      return UnlinkedTokenType.INT;
-    } else if (type == Keyword.INTERFACE) {
-      return UnlinkedTokenType.INTERFACE;
-    } else if (type == TokenType.IS) {
-      return UnlinkedTokenType.IS;
-    } else if (type == Keyword.LIBRARY) {
-      return UnlinkedTokenType.LIBRARY;
-    } else if (type == TokenType.LT) {
-      return UnlinkedTokenType.LT;
-    } else if (type == TokenType.LT_EQ) {
-      return UnlinkedTokenType.LT_EQ;
-    } else if (type == TokenType.LT_LT) {
-      return UnlinkedTokenType.LT_LT;
-    } else if (type == TokenType.LT_LT_EQ) {
-      return UnlinkedTokenType.LT_LT_EQ;
-    } else if (type == TokenType.MINUS) {
-      return UnlinkedTokenType.MINUS;
-    } else if (type == TokenType.MINUS_EQ) {
-      return UnlinkedTokenType.MINUS_EQ;
-    } else if (type == TokenType.MINUS_MINUS) {
-      return UnlinkedTokenType.MINUS_MINUS;
-    } else if (type == Keyword.MIXIN) {
-      return UnlinkedTokenType.MIXIN;
-    } else if (type == TokenType.MULTI_LINE_COMMENT) {
-      return UnlinkedTokenType.MULTI_LINE_COMMENT;
-    } else if (type == Keyword.NATIVE) {
-      return UnlinkedTokenType.NATIVE;
-    } else if (type == Keyword.NEW) {
-      return UnlinkedTokenType.NEW;
-    } else if (type == Keyword.NULL) {
-      return UnlinkedTokenType.NULL;
-    } else if (type == Keyword.OF) {
-      return UnlinkedTokenType.OF;
-    } else if (type == Keyword.ON) {
-      return UnlinkedTokenType.ON;
-    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-      return UnlinkedTokenType.OPEN_CURLY_BRACKET;
-    } else if (type == TokenType.OPEN_PAREN) {
-      return UnlinkedTokenType.OPEN_PAREN;
-    } else if (type == TokenType.OPEN_SQUARE_BRACKET) {
-      return UnlinkedTokenType.OPEN_SQUARE_BRACKET;
-    } else if (type == Keyword.OPERATOR) {
-      return UnlinkedTokenType.OPERATOR;
-    } else if (type == Keyword.PART) {
-      return UnlinkedTokenType.PART;
-    } else if (type == Keyword.PATCH) {
-      return UnlinkedTokenType.PATCH;
-    } else if (type == TokenType.PERCENT) {
-      return UnlinkedTokenType.PERCENT;
-    } else if (type == TokenType.PERCENT_EQ) {
-      return UnlinkedTokenType.PERCENT_EQ;
-    } else if (type == TokenType.PERIOD) {
-      return UnlinkedTokenType.PERIOD;
-    } else if (type == TokenType.PERIOD_PERIOD) {
-      return UnlinkedTokenType.PERIOD_PERIOD;
-    } else if (type == TokenType.PERIOD_PERIOD_PERIOD) {
-      return UnlinkedTokenType.PERIOD_PERIOD_PERIOD;
-    } else if (type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
-      return UnlinkedTokenType.PERIOD_PERIOD_PERIOD_QUESTION;
-    } else if (type == TokenType.PLUS) {
-      return UnlinkedTokenType.PLUS;
-    } else if (type == TokenType.PLUS_EQ) {
-      return UnlinkedTokenType.PLUS_EQ;
-    } else if (type == TokenType.PLUS_PLUS) {
-      return UnlinkedTokenType.PLUS_PLUS;
-    } else if (type == TokenType.QUESTION) {
-      return UnlinkedTokenType.QUESTION;
-    } else if (type == TokenType.QUESTION_PERIOD) {
-      return UnlinkedTokenType.QUESTION_PERIOD;
-    } else if (type == TokenType.QUESTION_QUESTION) {
-      return UnlinkedTokenType.QUESTION_QUESTION;
-    } else if (type == TokenType.QUESTION_QUESTION_EQ) {
-      return UnlinkedTokenType.QUESTION_QUESTION_EQ;
-    } else if (type == Keyword.RETHROW) {
-      return UnlinkedTokenType.RETHROW;
-    } else if (type == Keyword.RETURN) {
-      return UnlinkedTokenType.RETURN;
-    } else if (type == TokenType.SCRIPT_TAG) {
-      return UnlinkedTokenType.SCRIPT_TAG;
-    } else if (type == TokenType.SEMICOLON) {
-      return UnlinkedTokenType.SEMICOLON;
-    } else if (type == Keyword.SET) {
-      return UnlinkedTokenType.SET;
-    } else if (type == Keyword.SHOW) {
-      return UnlinkedTokenType.SHOW;
-    } else if (type == TokenType.SINGLE_LINE_COMMENT) {
-      return UnlinkedTokenType.SINGLE_LINE_COMMENT;
-    } else if (type == TokenType.SLASH) {
-      return UnlinkedTokenType.SLASH;
-    } else if (type == TokenType.SLASH_EQ) {
-      return UnlinkedTokenType.SLASH_EQ;
-    } else if (type == Keyword.SOURCE) {
-      return UnlinkedTokenType.SOURCE;
-    } else if (type == TokenType.STAR) {
-      return UnlinkedTokenType.STAR;
-    } else if (type == TokenType.STAR_EQ) {
-      return UnlinkedTokenType.STAR_EQ;
-    } else if (type == Keyword.STATIC) {
-      return UnlinkedTokenType.STATIC;
-    } else if (type == TokenType.STRING) {
-      return UnlinkedTokenType.STRING;
-    } else if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
-      return UnlinkedTokenType.STRING_INTERPOLATION_EXPRESSION;
-    } else if (type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-      return UnlinkedTokenType.STRING_INTERPOLATION_IDENTIFIER;
-    } else if (type == Keyword.SUPER) {
-      return UnlinkedTokenType.SUPER;
-    } else if (type == Keyword.SWITCH) {
-      return UnlinkedTokenType.SWITCH;
-    } else if (type == Keyword.SYNC) {
-      return UnlinkedTokenType.SYNC;
-    } else if (type == Keyword.THIS) {
-      return UnlinkedTokenType.THIS;
-    } else if (type == Keyword.THROW) {
-      return UnlinkedTokenType.THROW;
-    } else if (type == TokenType.TILDE) {
-      return UnlinkedTokenType.TILDE;
-    } else if (type == TokenType.TILDE_SLASH) {
-      return UnlinkedTokenType.TILDE_SLASH;
-    } else if (type == TokenType.TILDE_SLASH_EQ) {
-      return UnlinkedTokenType.TILDE_SLASH_EQ;
-    } else if (type == Keyword.TRUE) {
-      return UnlinkedTokenType.TRUE;
-    } else if (type == Keyword.TRY) {
-      return UnlinkedTokenType.TRY;
-    } else if (type == Keyword.TYPEDEF) {
-      return UnlinkedTokenType.TYPEDEF;
-    } else if (type == Keyword.VAR) {
-      return UnlinkedTokenType.VAR;
-    } else if (type == Keyword.VOID) {
-      return UnlinkedTokenType.VOID;
-    } else if (type == Keyword.WHILE) {
-      return UnlinkedTokenType.WHILE;
-    } else if (type == Keyword.WITH) {
-      return UnlinkedTokenType.WITH;
-    } else if (type == Keyword.YIELD) {
-      return UnlinkedTokenType.YIELD;
-    } else {
-      throw StateError('Unexpected type: $type');
-    }
+    return _linkingBundleContext.writeType(type);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
new file mode 100644
index 0000000..c3dcf81
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+/// Used to resolve some AST nodes - variable initializers, and annotations.
+class AstResolver {
+  final Linker _linker;
+
+  LibraryElement _library;
+  Scope _nameScope;
+
+  AstResolver(this._linker, Reference libraryRef) {
+    _library = _linker.elementFactory.elementOfReference(libraryRef);
+    _nameScope = LibraryScope(_library);
+  }
+
+  LinkedNode resolve(UnitBuilder unit, AstNode node) {
+    var source = _FakeSource();
+    var errorListener = AnalysisErrorListener.NULL_LISTENER;
+
+    var typeResolverVisitor = new TypeResolverVisitor(
+        _library, source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope);
+    node.accept(typeResolverVisitor);
+
+//    expression.accept(_astRewriteVisitor);
+//    expression.accept(_variableResolverVisitor);
+//    if (_linker.getAst != null) {
+//      expression.accept(_partialResolverVisitor);
+//    }
+
+    var resolverVisitor = new ResolverVisitor(_linker.inheritance, _library,
+        source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope,
+        propagateTypes: false,
+        reportConstEvaluationErrors: false);
+    node.accept(resolverVisitor);
+
+    var writer = AstBinaryWriter(
+      _linker.linkingBundleContext,
+      unit.context.tokensContext,
+    );
+    return writer.writeNode(node);
+  }
+}
+
+class _FakeSource implements Source {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
deleted file mode 100644
index a816247..0000000
--- a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2019, 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:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
-import 'package:analyzer/src/summary2/declaration.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/scope.dart';
-
-class LibraryBuilder {
-  final Uri uri;
-  final Reference reference;
-  final List<UnitBuilder> units = [];
-
-  /// The import scope of the library.
-  final Scope importScope;
-
-  /// Local declarations, enclosed by [importScope].
-  final Scope scope;
-
-  /// The export scope of the library.
-  final Scope exportScope = Scope.top();
-
-  LibraryBuilder(Uri uri, Reference reference)
-      : this._(uri, reference, Scope.top());
-
-  LibraryBuilder._(this.uri, this.reference, this.importScope)
-      : scope = Scope(importScope, <String, Declaration>{});
-
-  /// Add top-level declaration of the library units to the local scope.
-  void addLocalDeclarations() {
-    for (var unit in units) {
-      for (var node in unit.node.compilationUnit_declarations) {
-        if (node.kind == LinkedNodeKind.classDeclaration) {
-          var name = unit.context.getUnitMemberName(node);
-          var reference = this.reference.getChild('@class').getChild(name);
-          reference.node = node;
-          var declaration = Declaration(name, reference);
-          scope.declare(name, declaration);
-        } else {
-          // TODO(scheglov) implement
-          throw UnimplementedError();
-        }
-      }
-    }
-  }
-
-  /// Return `true` if the export scope was modified.
-  bool addToExportScope(String name, Declaration declaration) {
-    if (name.startsWith('_')) return false;
-    if (declaration is PrefixBuilder) return false;
-
-    var existing = exportScope.map[name];
-    if (existing == declaration) return false;
-
-    // Ambiguous declaration detected.
-    if (existing != null) return false;
-
-    exportScope.map[name] = declaration;
-    return true;
-  }
-
-  void addUnit(LinkedUnitContext context, LinkedNode node) {
-    units.add(UnitBuilder(context, node));
-  }
-
-  void buildInitialExportScope() {
-    // TODO(scheglov) Maybe store export scopes in summaries?
-    scope.forEach((name, declaration) {
-      addToExportScope(name, declaration);
-    });
-  }
-}
-
-class UnitBuilder {
-  final LinkedUnitContext context;
-  final LinkedNode node;
-
-  UnitBuilder(this.context, this.node);
-}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index c676b9b..f029ec9 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -2,27 +2,170 @@
 // 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:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
+import 'package:analyzer/src/summary2/declaration.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/metadata_resolver.dart';
 import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/reference_resolver.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+import 'package:analyzer/src/summary2/tokens_writer.dart';
+import 'package:analyzer/src/summary2/top_level_inference.dart';
 
-class SourceLibraryBuilder extends LibraryBuilder {
+class SourceLibraryBuilder {
   final Linker linker;
-  final LinkedBundleContext bundleContext;
+  final Uri uri;
   final Reference reference;
+  final LinkedNodeLibraryBuilder node;
+  final List<UnitBuilder> units = [];
 
-  SourceLibraryBuilder(this.linker, this.bundleContext, Uri uri, this.reference)
-      : super(uri, reference);
+  /// The import scope of the library.
+  final Scope importScope;
+
+  /// Local declarations, enclosed by [importScope].
+  final Scope scope;
+
+  /// The export scope of the library.
+  final Scope exportScope = Scope.top();
+
+  SourceLibraryBuilder(Linker linker, Uri uri, Reference reference,
+      LinkedNodeLibraryBuilder node)
+      : this._(linker, uri, reference, node, Scope.top());
+
+  SourceLibraryBuilder._(
+      this.linker, this.uri, this.reference, this.node, this.importScope)
+      : scope = Scope(importScope, <String, Declaration>{});
+
+  void addImportsToScope() {
+    // TODO
+    var hasDartCore = false;
+    var unitContext = units[0].context;
+    for (var directive in units[0].node.compilationUnit_directives) {
+      if (directive.kind == LinkedNodeKind.importDirective) {
+        var relativeUriStr = unitContext.getStringContent(
+          directive.uriBasedDirective_uri,
+        );
+        var relativeUri = Uri.parse(relativeUriStr);
+        var uri = resolveRelativeUri(this.uri, relativeUri);
+        var builder = linker.builders[uri];
+        if (builder != null) {
+          builder.exportScope.forEach((name, declaration) {
+            importScope.declare(name, declaration);
+          });
+        } else {
+          var references = linker.elementFactory.exportsOfLibrary('$uri');
+          _importExportedReferences(references);
+        }
+        // TODO(scheglov) prefix
+        // TODO(scheglov) combinators
+      }
+    }
+    if (!hasDartCore) {
+      var importDartCore = LinkedNodeBuilder.importDirective(
+        uriBasedDirective_uri: LinkedNodeBuilder.simpleStringLiteral(
+          simpleStringLiteral_value: 'dart:core',
+        ),
+      )..isSynthetic = true;
+      units[0].node.compilationUnit_directives.add(importDartCore);
+
+      // TODO(scheglov) This works only when dart:core is linked
+      var references = linker.elementFactory.exportsOfLibrary('dart:core');
+      _importExportedReferences(references);
+    }
+  }
+
+  /// Add top-level declaration of the library units to the local scope.
+  void addLocalDeclarations() {
+    for (var unit in units) {
+      var unitRef = reference.getChild('@unit').getChild('${unit.uri}');
+      var classRef = unitRef.getChild('@class');
+      var enumRef = unitRef.getChild('@enum');
+      var functionRef = unitRef.getChild('@function');
+      var typeAliasRef = unitRef.getChild('@typeAlias');
+      var getterRef = unitRef.getChild('@getter');
+      var setterRef = unitRef.getChild('@setter');
+      var variableRef = unitRef.getChild('@variable');
+      for (var node in unit.node.compilationUnit_declarations) {
+        if (node.kind == LinkedNodeKind.classDeclaration ||
+            node.kind == LinkedNodeKind.classTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = classRef.getChild(name);
+          reference.node = node;
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = enumRef.getChild(name);
+          reference.node = node;
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+          var name = unit.context.getUnitMemberName(node);
+
+          Reference containerRef;
+          if (unit.context.isGetterFunction(node)) {
+            containerRef = getterRef;
+          } else if (unit.context.isSetterFunction(node)) {
+            containerRef = setterRef;
+          } else {
+            containerRef = functionRef;
+          }
+
+          var reference = containerRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.functionTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = typeAliasRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = typeAliasRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+          var variableList = node.topLevelVariableDeclaration_variableList;
+          for (var variable in variableList.variableDeclarationList_variables) {
+            var name = unit.context.getVariableName(variable);
+
+            var reference = variableRef.getChild(name);
+            reference.node = node;
+
+            var getter = getterRef.getChild(name);
+            scope.declare(name, Declaration(name, getter));
+
+            if (!unit.context.isFinal(variable)) {
+              var setter = setterRef.getChild(name);
+              scope.declare('$name=', Declaration(name, setter));
+            }
+          }
+        } else {
+          // TODO(scheglov) implement
+          throw UnimplementedError('${node.kind}');
+        }
+      }
+    }
+  }
 
   void addSyntheticConstructors() {
     for (var declaration in scope.map.values) {
       var reference = declaration.reference;
       var node = reference.node;
-
+      if (node == null) continue;
       if (node.kind != LinkedNodeKind.classDeclaration) continue;
 
       // Skip the class if it already has a constructor.
@@ -35,75 +178,154 @@
         LinkedNodeBuilder.constructorDeclaration(
           constructorDeclaration_parameters:
               LinkedNodeBuilder.formalParameterList(),
+          constructorDeclaration_body: LinkedNodeBuilder.emptyFunctionBody(),
         )..isSynthetic = true,
       );
     }
   }
 
+  /// Return `true` if the export scope was modified.
+  bool addToExportScope(String name, Declaration declaration) {
+    if (name.startsWith('_')) return false;
+    if (declaration is PrefixBuilder) return false;
+
+    var existing = exportScope.map[name];
+    if (existing == declaration) return false;
+
+    // Ambiguous declaration detected.
+    if (existing != null) return false;
+
+    exportScope.map[name] = declaration;
+    return true;
+  }
+
+  void buildInitialExportScope() {
+    scope.forEach((name, declaration) {
+      addToExportScope(name, declaration);
+    });
+  }
+
+  void performTopLevelInference() {
+    for (var unit in units) {
+      TopLevelInference(linker, reference, unit).infer();
+    }
+  }
+
+  void resolveMetadata() {
+    var metadataResolver = MetadataResolver(linker, reference);
+    for (var unit in units) {
+      metadataResolver.resolve(unit);
+    }
+  }
+
   void resolveTypes() {
     for (var unit in units) {
-      for (var node in unit.node.compilationUnit_declarations) {
-        if (node.kind == LinkedNodeKind.classDeclaration) {
-          var extendsClause = node.classDeclaration_extendsClause;
-          if (extendsClause != null) {
-            _resolveTypeName(
-              unit.context,
-              extendsClause.extendsClause_superclass,
-            );
-          }
+      var unitReference = reference.getChild('@unit').getChild('${unit.uri}');
+      ReferenceResolver(
+        linker.linkingBundleContext,
+        unit,
+        scope,
+        unitReference,
+      ).resolve();
+    }
+  }
 
-          var withClause = node.classDeclaration_withClause;
-          if (withClause != null) {
-            for (var typeName in withClause.withClause_mixinTypes) {
-              _resolveTypeName(unit.context, typeName);
+  void storeExportScope() {
+    var linkingBundleContext = linker.linkingBundleContext;
+    for (var declaration in exportScope.map.values) {
+      var reference = declaration.reference;
+      var index = linkingBundleContext.indexOfReference(reference);
+      node.exports.add(index);
+    }
+  }
+
+  void _importExportedReferences(List<Reference> exportedReferences) {
+    for (var reference in exportedReferences) {
+      var name = reference.name;
+      importScope.declare(name, Declaration(name, reference));
+    }
+  }
+
+  static void build(Linker linker, Source librarySource,
+      Map<Source, ast.CompilationUnit> libraryUnits) {
+    var libraryUriStr = librarySource.uri.toString();
+    var libraryReference = linker.rootReference.getChild(libraryUriStr);
+
+    var unitNodeList = <LinkedNodeUnitBuilder>[];
+    var libraryNode = LinkedNodeLibraryBuilder(
+      units: unitNodeList,
+      uriStr: libraryUriStr,
+    );
+
+    var builder = SourceLibraryBuilder(
+      linker,
+      librarySource.uri,
+      libraryReference,
+      libraryNode,
+    );
+
+    ast.CompilationUnit definingUnit;
+    for (var unitSource in libraryUnits.keys) {
+      var unit = libraryUnits[unitSource];
+      definingUnit ??= unit;
+
+      var tokensResult = TokensWriter().writeTokens(
+        unit.beginToken,
+        unit.endToken,
+      );
+      var tokensContext = tokensResult.toContext();
+
+      var unitContext = LinkedUnitContext(
+        linker.bundleContext,
+        tokensContext,
+      );
+
+      var writer = AstBinaryWriter(linker.linkingBundleContext, tokensContext);
+      var unitNode = writer.writeNode(unit);
+
+      builder.units.add(
+        UnitBuilder(unitSource.uri, unitContext, unitNode),
+      );
+
+      libraryNode.units.add(
+        LinkedNodeUnitBuilder(
+          uriStr: '${unitSource.uri}',
+          tokens: tokensResult.tokens,
+          node: unitNode,
+        ),
+      );
+
+      if (libraryUriStr == 'dart:core') {
+        for (var declaration in unitNode.compilationUnit_declarations) {
+          if (declaration.kind == LinkedNodeKind.classDeclaration) {
+            var nameNode = declaration.namedCompilationUnitMember_name;
+            if (unitContext.getSimpleName(nameNode) == 'Object') {
+              declaration.classDeclaration_isDartObject = true;
             }
           }
-
-          var implementsClause = node.classOrMixinDeclaration_implementsClause;
-          if (implementsClause != null) {
-            for (var typeName in implementsClause.implementsClause_interfaces) {
-              _resolveTypeName(unit.context, typeName);
-            }
-          }
-
-          // TODO(scheglov) type parameters
-          assert(node.classOrMixinDeclaration_typeParameters == null);
-        } else {
-          // TODO(scheglov) implement
-          throw UnimplementedError();
         }
       }
     }
-  }
 
-  int _referenceIndex(Reference reference) {
-    if (reference.index == null) {
-      reference.index = linker.references.length;
-      linker.references.add(reference);
-    }
-    return reference.index;
-  }
-
-  void _resolveTypeName(LinkedUnitContext context, LinkedNodeBuilder typeName) {
-    var identifier = typeName.typeName_name;
-    if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
-      var name = context.getSimpleName(identifier);
-      var reference = exportScope.lookup(name).reference;
-      var referenceIndex = _referenceIndex(reference);
-      identifier.simpleIdentifier_element = referenceIndex;
-      if (reference.isClass) {
-        typeName.typeName_type = LinkedNodeTypeBuilder(
-          kind: LinkedNodeTypeKind.interface,
-          interfaceClass: referenceIndex,
-        );
-        // TODO(scheglov) type arguments
-      } else {
-        // TODO(scheglov) set Object? keep unresolved?
-        throw UnimplementedError();
+    for (var directive in definingUnit.directives) {
+      if (directive is ast.LibraryDirective) {
+        var name = directive.name;
+        libraryNode.name = name.components.map((id) => id.name).join('.');
+        libraryNode.nameOffset = name.offset;
+        libraryNode.nameLength = name.length;
+        break;
       }
-    } else {
-      // TODO(scheglov) implement
-      throw UnimplementedError();
     }
+
+    linker.linkingLibraries.add(libraryNode);
+    linker.builders[builder.uri] = builder;
   }
 }
+
+class UnitBuilder {
+  final Uri uri;
+  final LinkedUnitContext context;
+  final LinkedNode node;
+
+  UnitBuilder(this.uri, this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e24fc84..aec825a 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -2,140 +2,193 @@
 // 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:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/ast_binary_writer.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 LinkResult link(
-  Reference rootReference,
+  AnalysisOptions analysisOptions,
+  SourceFactory sourceFactory,
+  List<LinkedNodeBundle> inputs,
   Map<Source, Map<Source, CompilationUnit>> unitMap,
 ) {
-  var linker = Linker(rootReference);
-  linker.link(unitMap);
-  return LinkResult(linker.references, linker.libraryResults);
-}
-
-class LibraryLinkResult {
-  final Source source;
-  final Map<Source, UnitLinkResult> units;
-
-  LibraryLinkResult(this.source, this.units);
+  var linker = Linker(analysisOptions, sourceFactory);
+  linker.link(inputs, unitMap);
+  return LinkResult(linker.linkingBundle);
 }
 
 class Linker {
-  final Reference rootReference;
+  final Reference rootReference = Reference.root();
+  LinkedElementFactory elementFactory;
 
-  /// References used in all libraries being linked.
-  /// Element references in [LinkedNode]s are indexes in this list.
-  final List<Reference> references = [null];
+  LinkingBundleContext linkingBundleContext;
+  List<LinkedNodeLibraryBuilder> linkingLibraries = [];
+  LinkedNodeBundleBuilder linkingBundle;
+  LinkedBundleContext bundleContext;
 
-  /// The output results.
-  var libraryResults = <Source, LibraryLinkResult>{};
+  /// Libraries that are being linked.
+  final Map<Uri, SourceLibraryBuilder> builders = {};
 
-  /// Libraries that are being linked, or are already linked.
-  final Map<Uri, LibraryBuilder> builders = {};
+  _AnalysisContextForLinking analysisContext;
+  TypeProvider typeProvider;
+  Dart2TypeSystem typeSystem;
+  InheritanceManager2 inheritance;
 
-  Linker(this.rootReference);
+  Linker(AnalysisOptions analysisOptions, SourceFactory sourceFactory) {
+    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
+    dynamicRef.element = DynamicElementImpl.instance;
 
-  void addBuilder(LibraryBuilder builder) {
-    builders[builder.uri] = builder;
+    linkingBundleContext = LinkingBundleContext(dynamicRef);
+
+    analysisContext = _AnalysisContextForLinking(
+      analysisOptions,
+      sourceFactory,
+    );
+
+    elementFactory = LinkedElementFactory(
+      analysisContext,
+      _AnalysisSessionForLinking(),
+      rootReference,
+    );
+
+    linkingBundle = LinkedNodeBundleBuilder(
+      references: linkingBundleContext.referencesBuilder,
+      libraries: linkingLibraries,
+    );
+
+    bundleContext = LinkedBundleContext(
+      elementFactory,
+      linkingBundle.references,
+    );
   }
 
-  void addSyntheticConstructors() {
+  void link(List<LinkedNodeBundle> inputs,
+      Map<Source, Map<Source, CompilationUnit>> unitMap) {
+    for (var input in inputs) {
+      elementFactory.addBundle(input);
+    }
+
+    for (var librarySource in unitMap.keys) {
+      SourceLibraryBuilder.build(this, librarySource, unitMap[librarySource]);
+    }
+
+    // Add libraries being linked, so we can ask for their elements as well.
+    elementFactory.addBundle(linkingBundle, context: bundleContext);
+
+    _buildOutlines();
+  }
+
+  void _addSyntheticConstructors() {
     for (var library in builders.values) {
-      if (library is SourceLibraryBuilder) {
-        library.addSyntheticConstructors();
-      }
+      library.addSyntheticConstructors();
     }
   }
 
-  void buildOutlines() {
-    computeLibraryScopes();
-    resolveTypes();
-    addSyntheticConstructors();
+  void _buildOutlines() {
+    _computeLibraryScopes();
+    _addSyntheticConstructors();
+    _createTypeSystem();
+    _resolveTypes();
+    _performTopLevelInference();
+    _resolveMetadata();
   }
 
-  void computeLibraryScopes() {
-    for (var uri in builders.keys) {
-      var library = builders[uri];
+  void _computeLibraryScopes() {
+    for (var library in builders.values) {
+      library.addLocalDeclarations();
+    }
+
+    for (var library in builders.values) {
       library.buildInitialExportScope();
     }
 
+    for (var library in builders.values) {
+      library.addImportsToScope();
+    }
+
+    for (var library in builders.values) {
+      library.storeExportScope();
+    }
+
     // TODO(scheglov) process imports and exports
   }
 
-  void link(Map<Source, Map<Source, CompilationUnit>> unitMap) {
-    var linkedBundleContext = LinkedBundleContext(references);
-    for (var librarySource in unitMap.keys) {
-      var libraryUriStr = librarySource.uri.toString();
-      var libraryReference = rootReference.getChild(libraryUriStr);
+  void _createTypeSystem() {
+    var coreRef = rootReference.getChild('dart:core');
+    var coreLib = elementFactory.elementOfReference(coreRef);
+    typeProvider = SummaryTypeProvider()..initializeCore(coreLib);
+    analysisContext.typeProvider = typeProvider;
 
-      var unitResults = <Source, UnitLinkResult>{};
-      libraryResults[librarySource] = LibraryLinkResult(
-        librarySource,
-        unitResults,
-      );
+    typeSystem = Dart2TypeSystem(typeProvider);
+    analysisContext.typeSystem = typeSystem;
 
-      var libraryBuilder = SourceLibraryBuilder(
-        this,
-        linkedBundleContext,
-        librarySource.uri,
-        libraryReference,
-      );
-      addBuilder(libraryBuilder);
-
-      var libraryUnits = unitMap[librarySource];
-      for (var unitSource in libraryUnits.keys) {
-        var unit = libraryUnits[unitSource];
-
-        var writer = AstBinaryWriter();
-        var unitData = writer.writeNode(unit);
-
-        var unitLinkResult = UnitLinkResult(writer.tokens, unitData);
-        unitResults[unitSource] = unitLinkResult;
-
-        var linkedUnitContext = LinkedUnitContext(
-          linkedBundleContext,
-          writer.tokens,
-        );
-        libraryBuilder.addUnit(linkedUnitContext, unitData);
-      }
-
-      libraryBuilder.addLocalDeclarations();
-    }
-
-    buildOutlines();
+    inheritance = InheritanceManager2(typeSystem);
   }
 
-  void resolveTypes() {
-    for (var uri in builders.keys) {
-      var library = builders[uri];
-      if (library is SourceLibraryBuilder) {
-        library.resolveTypes();
-      }
+  void _performTopLevelInference() {
+    for (var library in builders.values) {
+      library.performTopLevelInference();
+    }
+  }
+
+  void _resolveMetadata() {
+    for (var library in builders.values) {
+      library.resolveMetadata();
+    }
+  }
+
+  void _resolveTypes() {
+    for (var library in builders.values) {
+      library.resolveTypes();
     }
   }
 }
 
 class LinkResult {
-  /// Element references in [LinkedNode]s are indexes in this list.
-  final List<Reference> references;
+  final LinkedNodeBundleBuilder bundle;
 
-  final Map<Source, LibraryLinkResult> libraries;
-
-  LinkResult(this.references, this.libraries);
+  LinkResult(this.bundle);
 }
 
-class UnitLinkResult {
-  final UnlinkedTokensBuilder tokens;
-  final LinkedNodeBuilder node;
+class _AnalysisContextForLinking implements InternalAnalysisContext {
+  @override
+  final AnalysisOptions analysisOptions;
 
-  UnitLinkResult(this.tokens, this.node);
+  @override
+  final SourceFactory sourceFactory;
+
+  @override
+  TypeProvider typeProvider;
+
+  @override
+  TypeSystem typeSystem;
+
+  _AnalysisContextForLinking(this.analysisOptions, this.sourceFactory);
+
+  @override
+  Namespace getPublicNamespace(LibraryElement library) {
+    // TODO(scheglov) Not sure if this method of AnalysisContext is useful.
+    var builder = new NamespaceBuilder();
+    return builder.createPublicNamespaceForLibrary(library);
+  }
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class _AnalysisSessionForLinking implements AnalysisSession {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index 2b1d0ed..fbaf454 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -2,24 +2,107 @@
 // 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: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/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 /// The context of a linked bundle, with shared references.
 class LinkedBundleContext {
-  final List<Reference> references;
+  final LinkedElementFactory elementFactory;
+  final LinkedNodeReferences referencesData;
+  final List<Reference> _references;
 
-  LinkedBundleContext(this.references);
+  LinkedBundleContext(this.elementFactory, this.referencesData)
+      : _references = List<Reference>.filled(referencesData.name.length, null,
+            growable: true);
+
+  T elementOfIndex<T extends Element>(int index) {
+    var reference = referenceOfIndex(index);
+    return elementFactory.elementOfReference(reference);
+  }
+
+  List<T> elementsOfIndexes<T extends Element>(List<int> indexList) {
+    var result = List<T>(indexList.length);
+    for (var i = 0; i < indexList.length; ++i) {
+      var index = indexList[i];
+      result[i] = elementOfIndex(index);
+    }
+    return result;
+  }
 
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
-    if (linkedType.kind == LinkedNodeTypeKind.interface) {
-      var element = references[linkedType.interfaceClass].element;
-      // TODO(scheglov) type arguments
-      assert(linkedType.interfaceTypeArguments.isEmpty);
-      return InterfaceTypeImpl.explicit(element, []);
+    var type = getType(linkedType);
+    if (type is InterfaceType && !type.element.isEnum) {
+      return type;
     }
     return null;
   }
+
+  DartType getType(LinkedNodeType linkedType) {
+    var kind = linkedType.kind;
+    if (kind == LinkedNodeTypeKind.dynamic_) {
+      return DynamicTypeImpl.instance;
+    } else if (kind == LinkedNodeTypeKind.function) {
+      var returnType = getType(linkedType.functionReturnType);
+      var typeParameters = linkedType.functionTypeParameters
+          .map(referenceOfIndex)
+          .map(elementFactory.elementOfReference)
+          .cast<TypeParameterElement>()
+          .toList();
+      var formalParameters = linkedType.functionFormalParameters
+          .map(referenceOfIndex)
+          .map(elementFactory.elementOfReference)
+          .cast<ParameterElement>()
+          .toList();
+      // TODO(scheglov) Rework this to purely synthetic types.
+      return FunctionElementImpl.synthetic(formalParameters, returnType).type;
+    } else if (kind == LinkedNodeTypeKind.interface) {
+      var reference = referenceOfIndex(linkedType.interfaceClass);
+      Element element = elementFactory.elementOfReference(reference);
+      return InterfaceTypeImpl.explicit(
+        element,
+        linkedType.interfaceTypeArguments.map(getType).toList(),
+      );
+    } else if (kind == LinkedNodeTypeKind.typeParameter) {
+      var reference = referenceOfIndex(linkedType.typeParameterParameter);
+      Element element = elementFactory.elementOfReference(reference);
+      return TypeParameterTypeImpl(element);
+    } else if (kind == LinkedNodeTypeKind.void_) {
+      return VoidTypeImpl.instance;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  Reference referenceOfIndex(int index) {
+    // When we are linking a bundle, we add new references.
+    // So, grow the list of references when we have data for them.
+    if (index >= _references.length) {
+      if (referencesData.name.length > _references.length) {
+        _references.length = referencesData.name.length;
+      }
+    }
+
+    var reference = _references[index];
+    if (reference != null) return reference;
+
+    if (index == 0) {
+      reference = elementFactory.rootReference;
+      _references[index] = reference;
+      return reference;
+    }
+
+    var parentIndex = referencesData.parent[index];
+    var parent = referenceOfIndex(parentIndex);
+
+    var name = referencesData.name[index];
+    reference = parent.getChild(name);
+    _references[index] = reference;
+
+    return reference;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
new file mode 100644
index 0000000..7653ed6
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -0,0 +1,299 @@
+// Copyright (c) 2019, 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:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/tokens_context.dart';
+
+class LinkedElementFactory {
+  final AnalysisContext analysisContext;
+  final AnalysisSession analysisSession;
+  final Reference rootReference;
+  final Map<String, _Library> libraryMap = {};
+
+  LinkedElementFactory(
+      this.analysisContext, this.analysisSession, this.rootReference);
+
+  void addBundle(LinkedNodeBundle bundle, {LinkedBundleContext context}) {
+    context ??= LinkedBundleContext(this, bundle.references);
+    for (var library in bundle.libraries) {
+      libraryMap[library.uriStr] = _Library(context, library);
+    }
+  }
+
+  Element elementOfReference(Reference reference) {
+    if (reference.element != null) {
+      return reference.element;
+    }
+    if (reference.parent == null) {
+      return null;
+    }
+
+    return _ElementRequest(this, reference).elementOfReference(reference);
+  }
+
+  List<Reference> exportsOfLibrary(String uriStr) {
+    var library = libraryMap[uriStr];
+    var exportIndexList = library.node.exports;
+    var exportReferences = List<Reference>(exportIndexList.length);
+    for (var i = 0; i < exportIndexList.length; ++i) {
+      var index = exportIndexList[i];
+      var reference = library.context.referenceOfIndex(index);
+      exportReferences[i] = reference;
+    }
+    return exportReferences;
+  }
+
+  LibraryElementImpl libraryOfUri(String uriStr) {
+    var reference = rootReference.getChild(uriStr);
+    return elementOfReference(reference);
+  }
+}
+
+class _ElementRequest {
+  final LinkedElementFactory elementFactory;
+  final Reference input;
+
+  _ElementRequest(this.elementFactory, this.input);
+
+  ElementImpl elementOfReference(Reference reference) {
+    if (reference.element != null) {
+      return reference.element;
+    }
+
+    var parent2 = reference.parent.parent;
+    if (parent2 == null) {
+      return _createLibraryElement(reference);
+    }
+
+    var parentName = reference.parent.name;
+
+    if (parentName == '@class') {
+      var unit = elementOfReference(parent2);
+      return _class(unit, reference);
+    }
+
+    if (parentName == '@constructor') {
+      var class_ = elementOfReference(parent2);
+      return _constructor(class_, reference);
+    }
+
+    if (parentName == '@function') {
+      CompilationUnitElementImpl enclosing = elementOfReference(parent2);
+      return _function(enclosing, reference);
+    }
+
+    if (parentName == '@getter') {
+      var enclosing = elementOfReference(parent2);
+      return _getter(enclosing, reference);
+    }
+
+    if (parentName == '@method') {
+      var enclosing = elementOfReference(parent2);
+      return _method(enclosing, reference);
+    }
+
+    if (parentName == '@parameter') {
+      ExecutableElementImpl enclosing = elementOfReference(parent2);
+      return _parameter(enclosing, reference);
+    }
+
+    if (parentName == '@typeAlias') {
+      var unit = elementOfReference(parent2);
+      return _typeAlias(unit, reference);
+    }
+