diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
index ef991be..c17d7f8 100644
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ b/pkg/analyzer/test/src/summary/expr_builder_test.dart
@@ -11,9 +11,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../abstract_single_unit.dart';
-import 'resynthesize_ast_test.dart';
 import 'resynthesize_common.dart';
+import 'test_strategies.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -22,100 +21,13 @@
 }
 
 @reflectiveTest
-class ExprBuilderTest extends AbstractSingleUnitTest
-    with AstSerializeTestMixin {
-  @override
-  bool get allowMissingFiles => false;
+class ExprBuilderTest extends ResynthesizeTestStrategyTwoPhase
+    with ExprBuilderTestCases, ExprBuilderTestHelpers {}
 
-  Expression buildConstructorInitializer(String sourceText,
-      {String className: 'C',
-      String initializerName: 'x',
-      bool requireValidConst: false}) {
-    var resynthesizer = encodeSource(sourceText);
-    var library = resynthesizer.getLibraryElement(testSource.uri.toString());
-    var c = library.getType(className);
-    var constructor = c.unnamedConstructor as ConstructorElementImpl;
-    var serializedExecutable = constructor.serializedExecutable;
-    var x = serializedExecutable.constantInitializers
-        .singleWhere((i) => i.name == initializerName);
-    return buildExpression(resynthesizer, constructor, x.expression,
-        serializedExecutable.localFunctions,
-        requireValidConst: requireValidConst);
-  }
-
-  Expression buildExpression(
-      TestSummaryResynthesizer resynthesizer,
-      ElementImpl context,
-      UnlinkedExpr unlinkedExpr,
-      List<UnlinkedExecutable> localFunctions,
-      {bool requireValidConst: false}) {
-    var library = resynthesizer.getLibraryElement(testSource.uri.toString());
-    var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
-    var unitResynthesizerContext =
-        unit.resynthesizerContext as SummaryResynthesizerContext;
-    var unitResynthesizer = unitResynthesizerContext.unitResynthesizer;
-    var exprBuilder = new ExprBuilder(unitResynthesizer, context, unlinkedExpr,
-        requireValidConst: requireValidConst, localFunctions: localFunctions);
-    return exprBuilder.build();
-  }
-
-  Expression buildTopLevelVariable(String sourceText,
-      {String variableName: 'x', bool requireValidConst: false}) {
-    var resynthesizer = encodeSource(sourceText);
-    var library = resynthesizer.getLibraryElement(testSource.uri.toString());
-    var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
-    TopLevelVariableElementImpl x =
-        unit.topLevelVariables.singleWhere((e) => e.name == variableName);
-    return buildExpression(
-        resynthesizer,
-        x,
-        x.unlinkedVariableForTesting.initializer.bodyExpr,
-        x.unlinkedVariableForTesting.initializer.localFunctions,
-        requireValidConst: requireValidConst);
-  }
-
-  void checkCompoundAssignment(String exprText) {
-    checkSimpleExpression(exprText, extraDeclarations: 'var y;');
-  }
-
-  void checkConstructorInitializer(String sourceText, String expectedText,
-      {String className: 'C',
-      String initializerName: 'x',
-      bool requireValidConst: false}) {
-    Expression expr = buildConstructorInitializer(sourceText,
-        className: className,
-        initializerName: initializerName,
-        requireValidConst: requireValidConst);
-    expect(expr.toString(), expectedText);
-  }
-
-  void checkInvalidConst(String expressionText) {
-    checkTopLevelVariable('var x = $expressionText;', 'null',
-        requireValidConst: true);
-  }
-
-  Expression checkSimpleExpression(String expressionText,
-      {String expectedText,
-      String extraDeclarations: '',
-      bool requireValidConst: false}) {
-    return checkTopLevelVariable('var x = $expressionText;\n$extraDeclarations',
-        expectedText ?? expressionText,
-        requireValidConst: requireValidConst);
-  }
-
-  Expression checkTopLevelVariable(String sourceText, String expectedText,
-      {String variableName: 'x', bool requireValidConst: false}) {
-    Expression expr = buildTopLevelVariable(sourceText,
-        variableName: variableName, requireValidConst: requireValidConst);
-    expect(expr.toString(), expectedText);
-    return expr;
-  }
-
-  TestSummaryResynthesizer encodeSource(String text) {
-    var source = addTestSource(text);
-    return encodeLibrary(source);
-  }
-
+/// Mixin containing test cases exercising the [ExprBuilder].  Intended to be
+/// applied to a class implementing [ResynthesizeTestStrategy], along with the
+/// mixin [ExprBuilderTestHelpers].
+abstract class ExprBuilderTestCases implements ExprBuilderTestHelpers {
   void test_add() {
     checkSimpleExpression('0 + 1');
   }
@@ -565,3 +477,96 @@
     checkSimpleExpression('0 is! num', expectedText: '!(0 is num)');
   }
 }
+
+/// Mixin containing helper methods for testing the [ExprBuilder].  Intended to
+/// be applied to a class implementing [ResynthesizeTestStrategy].
+abstract class ExprBuilderTestHelpers implements ResynthesizeTestStrategy {
+  Expression buildConstructorInitializer(String sourceText,
+      {String className: 'C',
+      String initializerName: 'x',
+      bool requireValidConst: false}) {
+    var resynthesizer = encodeSource(sourceText);
+    var library = resynthesizer.getLibraryElement(testSource.uri.toString());
+    var c = library.getType(className);
+    var constructor = c.unnamedConstructor as ConstructorElementImpl;
+    var serializedExecutable = constructor.serializedExecutable;
+    var x = serializedExecutable.constantInitializers
+        .singleWhere((i) => i.name == initializerName);
+    return buildExpression(resynthesizer, constructor, x.expression,
+        serializedExecutable.localFunctions,
+        requireValidConst: requireValidConst);
+  }
+
+  Expression buildExpression(
+      TestSummaryResynthesizer resynthesizer,
+      ElementImpl context,
+      UnlinkedExpr unlinkedExpr,
+      List<UnlinkedExecutable> localFunctions,
+      {bool requireValidConst: false}) {
+    var library = resynthesizer.getLibraryElement(testSource.uri.toString());
+    var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
+    var unitResynthesizerContext =
+        unit.resynthesizerContext as SummaryResynthesizerContext;
+    var unitResynthesizer = unitResynthesizerContext.unitResynthesizer;
+    var exprBuilder = new ExprBuilder(unitResynthesizer, context, unlinkedExpr,
+        requireValidConst: requireValidConst, localFunctions: localFunctions);
+    return exprBuilder.build();
+  }
+
+  Expression buildTopLevelVariable(String sourceText,
+      {String variableName: 'x', bool requireValidConst: false}) {
+    var resynthesizer = encodeSource(sourceText);
+    var library = resynthesizer.getLibraryElement(testSource.uri.toString());
+    var unit = library.definingCompilationUnit as CompilationUnitElementImpl;
+    TopLevelVariableElementImpl x =
+        unit.topLevelVariables.singleWhere((e) => e.name == variableName);
+    return buildExpression(
+        resynthesizer,
+        x,
+        x.unlinkedVariableForTesting.initializer.bodyExpr,
+        x.unlinkedVariableForTesting.initializer.localFunctions,
+        requireValidConst: requireValidConst);
+  }
+
+  void checkCompoundAssignment(String exprText) {
+    checkSimpleExpression(exprText, extraDeclarations: 'var y;');
+  }
+
+  void checkConstructorInitializer(String sourceText, String expectedText,
+      {String className: 'C',
+      String initializerName: 'x',
+      bool requireValidConst: false}) {
+    Expression expr = buildConstructorInitializer(sourceText,
+        className: className,
+        initializerName: initializerName,
+        requireValidConst: requireValidConst);
+    expect(expr.toString(), expectedText);
+  }
+
+  void checkInvalidConst(String expressionText) {
+    checkTopLevelVariable('var x = $expressionText;', 'null',
+        requireValidConst: true);
+  }
+
+  Expression checkSimpleExpression(String expressionText,
+      {String expectedText,
+      String extraDeclarations: '',
+      bool requireValidConst: false}) {
+    return checkTopLevelVariable('var x = $expressionText;\n$extraDeclarations',
+        expectedText ?? expressionText,
+        requireValidConst: requireValidConst);
+  }
+
+  Expression checkTopLevelVariable(String sourceText, String expectedText,
+      {String variableName: 'x', bool requireValidConst: false}) {
+    Expression expr = buildTopLevelVariable(sourceText,
+        variableName: variableName, requireValidConst: requireValidConst);
+    expect(expr.toString(), expectedText);
+    return expr;
+  }
+
+  TestSummaryResynthesizer encodeSource(String text) {
+    var source = addTestSource(text);
+    return encodeLibrary(source);
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index f49374a..c15af1e 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -2,30 +2,8 @@
 // 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:async';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisContext, AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary/link.dart';
-import 'package:analyzer/src/summary/prelink.dart';
-import 'package:analyzer/src/summary/resynthesize.dart';
-import 'package:analyzer/src/summary/summarize_ast.dart';
-import 'package:analyzer/src/summary/summarize_elements.dart'
-    show PackageBundleAssembler;
-import 'package:analyzer/src/task/api/dart.dart' show PARSED_UNIT;
-import 'package:analyzer/src/task/api/general.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../context/abstract_context.dart';
 import 'element_text.dart';
 import 'resynthesize_common.dart';
 import 'test_strategies.dart';
@@ -44,129 +22,9 @@
   }
 }
 
-/// Mixin for serializing ASTs during testing.
-abstract class AstSerializeTestMixin
-    implements _AstSerializeTestMixinInterface {
-  final Set<Source> serializedSources = new Set<Source>();
-  PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
-  final Map<String, UnlinkedUnitBuilder> uriToUnit =
-      <String, UnlinkedUnitBuilder>{};
-
-  AnalysisContext get context;
-
-  TestSummaryResynthesizer encodeLibrary(Source source) {
-    _serializeLibrary(source);
-
-    PackageBundle bundle =
-        new PackageBundle.fromBuffer(bundleAssembler.assemble().toBuffer());
-
-    Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
-    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
-      String uri = bundle.unlinkedUnitUris[i];
-      unlinkedSummaries[uri] = bundle.unlinkedUnits[i];
-    }
-
-    LinkedLibrary getDependency(String absoluteUri) {
-      Map<String, LinkedLibrary> sdkLibraries =
-          SerializedMockSdk.instance.uriToLinkedLibrary;
-      LinkedLibrary linkedLibrary = sdkLibraries[absoluteUri];
-      if (linkedLibrary == null && !allowMissingFiles) {
-        fail('Linker unexpectedly requested LinkedLibrary for "$absoluteUri".'
-            '  Libraries available: ${sdkLibraries.keys}');
-      }
-      return linkedLibrary;
-    }
-
-    UnlinkedUnit getUnit(String absoluteUri) {
-      UnlinkedUnit unit = uriToUnit[absoluteUri] ??
-          SerializedMockSdk.instance.uriToUnlinkedUnit[absoluteUri];
-      if (unit == null && !allowMissingFiles) {
-        fail('Linker unexpectedly requested unit for "$absoluteUri".');
-      }
-      return unit;
-    }
-
-    Set<String> nonSdkLibraryUris = serializedSources
-        .where((Source source) =>
-            !source.isInSystemLibrary &&
-            context.computeKindOf(source) == SourceKind.LIBRARY)
-        .map((Source source) => source.uri.toString())
-        .toSet();
-
-    Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
-        getDependency, getUnit, context.declaredVariables.get);
-
-    return new TestSummaryResynthesizer(
-        context,
-        new Map<String, UnlinkedUnit>()
-          ..addAll(SerializedMockSdk.instance.uriToUnlinkedUnit)
-          ..addAll(unlinkedSummaries),
-        new Map<String, LinkedLibrary>()
-          ..addAll(SerializedMockSdk.instance.uriToLinkedLibrary)
-          ..addAll(linkedSummaries),
-        allowMissingFiles);
-  }
-
-  UnlinkedUnit _getUnlinkedUnit(Source source) {
-    if (source == null) {
-      return new UnlinkedUnitBuilder();
-    }
-
-    String uriStr = source.uri.toString();
-    {
-      UnlinkedUnit unlinkedUnitInSdk =
-          SerializedMockSdk.instance.uriToUnlinkedUnit[uriStr];
-      if (unlinkedUnitInSdk != null) {
-        return unlinkedUnitInSdk;
-      }
-    }
-    return uriToUnit.putIfAbsent(uriStr, () {
-      int modificationTime = context.computeResult(source, MODIFICATION_TIME);
-      if (modificationTime < 0) {
-        // Source does not exist.
-        if (!allowMissingFiles) {
-          fail('Unexpectedly tried to get unlinked summary for $source');
-        }
-        return null;
-      }
-      CompilationUnit unit = context.computeResult(source, PARSED_UNIT);
-      UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
-      bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
-      return unlinkedUnit;
-    });
-  }
-
-  void _serializeLibrary(Source librarySource) {
-    if (librarySource == null || librarySource.isInSystemLibrary) {
-      return;
-    }
-    if (!serializedSources.add(librarySource)) {
-      return;
-    }
-
-    UnlinkedUnit getPart(String absoluteUri) {
-      Source source = context.sourceFactory.forUri(absoluteUri);
-      return _getUnlinkedUnit(source);
-    }
-
-    UnlinkedPublicNamespace getImport(String relativeUri) {
-      return getPart(relativeUri)?.publicNamespace;
-    }
-
-    UnlinkedUnit definingUnit = _getUnlinkedUnit(librarySource);
-    if (definingUnit != null) {
-      LinkedLibraryBuilder linkedLibrary = prelink(librarySource.uri.toString(),
-          definingUnit, getPart, getImport, context.declaredVariables.get);
-      linkedLibrary.dependencies.skip(1).forEach((LinkedDependency d) {
-        Source source = context.sourceFactory.forUri(d.uri);
-        _serializeLibrary(source);
-      });
-    }
-  }
-}
-
 @reflectiveTest
-class ResynthesizeAstStrongTest extends _ResynthesizeAstTest {
+class ResynthesizeAstStrongTest extends ResynthesizeTestStrategyTwoPhase
+    with ResynthesizeTestCases, ResynthesizeTestHelpers {
   @failingTest // See dartbug.com/32290
   test_const_constructor_inferred_args() =>
       super.test_const_constructor_inferred_args();
@@ -201,164 +59,3 @@
     await super.test_syntheticFunctionType_withArguments();
   }
 }
-
-/**
- * Abstract mixin for serializing ASTs and resynthesizing elements from it.
- */
-abstract class _AstResynthesizeTestMixin
-    implements _AstSerializeTestMixinInterface {
-  AnalysisContext get context;
-
-  TestSummaryResynthesizer encodeLibrary(Source source);
-
-  LibraryElementImpl _encodeDecodeLibraryElement(Source source) {
-    SummaryResynthesizer resynthesizer = encodeLibrary(source);
-    return resynthesizer.getLibraryElement(source.uri.toString());
-  }
-}
-
-/**
- * Interface that [_AstSerializeTestMixin] requires of classes it's mixed
- * into.  We can't place the getter below into [_AstSerializeTestMixin]
- * directly, because then it would be overriding a field at the site where the
- * mixin is instantiated.
- */
-abstract class _AstSerializeTestMixinInterface {
-  /**
-   * A test should return `true` to indicate that a missing file at the time of
-   * summary resynthesis shouldn't trigger an error.
-   */
-  bool get allowMissingFiles;
-}
-
-abstract class _ResynthesizeAstTest extends ResynthesizeTest
-    with _AstResynthesizeTestMixin, AstSerializeTestMixin {
-  bool get shouldCompareLibraryElements;
-
-  @override
-  Future<LibraryElementImpl> checkLibrary(String text,
-      {bool allowErrors: false, bool dumpSummaries: false}) async {
-    Source source = addTestSource(text);
-    LibraryElementImpl resynthesized = _encodeDecodeLibraryElement(source);
-    LibraryElementImpl original = context.computeLibraryElement(source);
-    if (!allowErrors) {
-      List<AnalysisError> errors = context.computeErrors(source);
-      if (errors.where((e) => e.message.startsWith('unused')).isNotEmpty) {
-        fail('Analysis errors: $errors');
-      }
-    }
-    if (shouldCompareLibraryElements) {
-      checkLibraryElements(original, resynthesized);
-    }
-    return resynthesized;
-  }
-
-  @override
-  DartSdk createDartSdk() => AbstractContextTest.SHARED_MOCK_SDK;
-
-  @override
-  AnalysisOptionsImpl createOptions() {
-    return super.createOptions()
-      ..previewDart2 = true
-      ..isMixinSupportEnabled = true;
-  }
-
-  test_getElement_constructor_named() async {
-    String text = 'class C { C.named(); }';
-    Source source = addLibrarySource('/test.dart', text);
-    ConstructorElement original = context
-        .computeLibraryElement(source)
-        .getType('C')
-        .getNamedConstructor('named');
-    expect(original, isNotNull);
-    ConstructorElement resynthesized = _validateGetElement(text, original);
-    compareConstructorElements(resynthesized, original, 'C.constructor named');
-  }
-
-  test_getElement_constructor_unnamed() async {
-    String text = 'class C { C(); }';
-    Source source = addLibrarySource('/test.dart', text);
-    ConstructorElement original =
-        context.computeLibraryElement(source).getType('C').unnamedConstructor;
-    expect(original, isNotNull);
-    ConstructorElement resynthesized = _validateGetElement(text, original);
-    compareConstructorElements(resynthesized, original, 'C.constructor');
-  }
-
-  test_getElement_field() async {
-    String text = 'class C { var f; }';
-    Source source = addLibrarySource('/test.dart', text);
-    FieldElement original =
-        context.computeLibraryElement(source).getType('C').getField('f');
-    expect(original, isNotNull);
-    FieldElement resynthesized = _validateGetElement(text, original);
-    compareFieldElements(resynthesized, original, 'C.field f');
-  }
-
-  test_getElement_getter() async {
-    String text = 'class C { get f => null; }';
-    Source source = addLibrarySource('/test.dart', text);
-    PropertyAccessorElement original =
-        context.computeLibraryElement(source).getType('C').getGetter('f');
-    expect(original, isNotNull);
-    PropertyAccessorElement resynthesized = _validateGetElement(text, original);
-    comparePropertyAccessorElements(resynthesized, original, 'C.getter f');
-  }
-
-  test_getElement_method() async {
-    String text = 'class C { f() {} }';
-    Source source = addLibrarySource('/test.dart', text);
-    MethodElement original =
-        context.computeLibraryElement(source).getType('C').getMethod('f');
-    expect(original, isNotNull);
-    MethodElement resynthesized = _validateGetElement(text, original);
-    compareMethodElements(resynthesized, original, 'C.method f');
-  }
-
-  test_getElement_operator() async {
-    String text = 'class C { operator+(x) => null; }';
-    Source source = addLibrarySource('/test.dart', text);
-    MethodElement original =
-        context.computeLibraryElement(source).getType('C').getMethod('+');
-    expect(original, isNotNull);
-    MethodElement resynthesized = _validateGetElement(text, original);
-    compareMethodElements(resynthesized, original, 'C.operator+');
-  }
-
-  test_getElement_setter() async {
-    String text = 'class C { void set f(value) {} }';
-    Source source = addLibrarySource('/test.dart', text);
-    PropertyAccessorElement original =
-        context.computeLibraryElement(source).getType('C').getSetter('f');
-    expect(original, isNotNull);
-    PropertyAccessorElement resynthesized = _validateGetElement(text, original);
-    comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
-  }
-
-  test_getElement_unit() async {
-    String text = 'class C { f() {} }';
-    Source source = addLibrarySource('/test.dart', text);
-    CompilationUnitElement original =
-        context.computeLibraryElement(source).definingCompilationUnit;
-    expect(original, isNotNull);
-    CompilationUnitElement resynthesized = _validateGetElement(text, original);
-    compareCompilationUnitElements(resynthesized, original);
-  }
-
-  /**
-   * Encode the library containing [original] into a summary and then use
-   * [TestSummaryResynthesizer.getElement] to retrieve just the original
-   * element from the resynthesized summary.
-   */
-  Element _validateGetElement(String text, Element original) {
-    SummaryResynthesizer resynthesizer = encodeLibrary(original.library.source);
-    ElementLocationImpl location = original.location;
-    Element result = resynthesizer.getElement(location);
-    checkMinimalResynthesisWork(resynthesizer, original.library);
-    // Check that no other summaries needed to be resynthesized to resynthesize
-    // the library element.
-    expect(resynthesizer.resynthesisCount, 3);
-    expect(result.location, location);
-    return result;
-  }
-}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3199bbd..ab472d5 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -34,6 +34,7 @@
 import '../abstract_single_unit.dart';
 import '../context/abstract_context.dart';
 import 'element_text.dart';
+import 'test_strategies.dart';
 
 /**
  * Abstract base class for resynthesizing and comparing elements.
@@ -44,28 +45,11 @@
   Set<Source> otherLibrarySources = new Set<Source>();
 
   /**
-   * Names of variables which have initializers that are not valid constants,
-   * so they are not resynthesized.
-   */
-  Set<String> variablesWithNotConstInitializers = new Set<String>();
-
-  /**
-   * Names that cannot be resolved, e.g. because of duplicate declaration.
-   */
-  Set<String> namesThatCannotBeResolved = new Set<String>();
-
-  /**
    * Tests may set this to `true` to indicate that a missing file at the time of
    * summary resynthesis shouldn't trigger an error.
    */
   bool allowMissingFiles = false;
 
-  /**
-   * Tests may set this to `false` to indicate that resynthesized elements
-   * should not be compare with elements created using AnalysisContext.
-   */
-  bool shouldCompareLibraryElements = true;
-
   void addLibrary(String uri) {
     otherLibrarySources.add(context.sourceFactory.forUri(uri));
   }
@@ -96,67 +80,6 @@
   }
 
   /**
-   * Verify that the given prefix is safe to elide from a resynthesized AST.
-   */
-  void checkElidablePrefix(SimpleIdentifier prefix) {
-    if (prefix.staticElement is! PrefixElement &&
-        prefix.staticElement is! ClassElement) {
-      fail('Prefix of type ${prefix.staticElement.runtimeType}'
-          ' should not have been elided');
-    }
-  }
-
-  void checkLibraryElements(
-      LibraryElementImpl original, LibraryElementImpl resynthesized) {
-    compareElements(resynthesized, original, '(library)');
-    expect(resynthesized.displayName, original.displayName);
-    expect(original.enclosingElement, isNull);
-    expect(resynthesized.enclosingElement, isNull);
-    expect(resynthesized.hasExtUri, original.hasExtUri);
-    compareCompilationUnitElements(resynthesized.definingCompilationUnit,
-        original.definingCompilationUnit);
-    expect(resynthesized.parts.length, original.parts.length, reason: 'parts');
-    for (int i = 0; i < resynthesized.parts.length; i++) {
-      compareCompilationUnitElements(resynthesized.parts[i], original.parts[i]);
-    }
-    expect(resynthesized.imports.length, original.imports.length,
-        reason: 'imports');
-    for (int i = 0; i < resynthesized.imports.length; i++) {
-      ImportElement originalImport = original.imports[i];
-      compareImportElements(
-          resynthesized.imports[i], originalImport, originalImport.toString());
-    }
-    expect(resynthesized.exports.length, original.exports.length,
-        reason: 'exports');
-    for (int i = 0; i < resynthesized.exports.length; i++) {
-      ExportElement originalExport = original.exports[i];
-      compareExportElements(
-          resynthesized.exports[i], originalExport, originalExport.toString());
-    }
-    expect(resynthesized.nameLength, original.nameLength);
-    compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
-        '(public namespace)');
-    compareNamespaces(resynthesized.exportNamespace, original.exportNamespace,
-        '(export namespace)');
-    if (original.entryPoint == null) {
-      expect(resynthesized.entryPoint, isNull);
-    } else {
-      expect(resynthesized.entryPoint, isNotNull);
-      compareFunctionElements(
-          resynthesized.entryPoint, original.entryPoint, '(entry point)');
-    }
-    // The libraries `dart:core` and `dart:async` cannot create their
-    // `loadLibrary` functions until after both are created.
-    if (original.name != 'dart.core' && original.name != 'dart.async') {
-      compareExecutableElements(
-          resynthesized.loadLibraryFunction as ExecutableElementImpl,
-          original.loadLibraryFunction as ExecutableElementImpl,
-          '(loadLibraryFunction)');
-    }
-    expect(resynthesized.libraryCycle.toSet(), original.libraryCycle.toSet());
-  }
-
-  /**
    * Verify that the [resynthesizer] didn't do any unnecessary work when
    * resynthesizing [library].
    */
@@ -179,1008 +102,6 @@
     }
   }
 
-  void checkPossibleLocalElements(Element resynthesized, Element original) {
-    if (original is! LocalElement && resynthesized is! LocalElement) {
-      return;
-    }
-    if (original is LocalElement && resynthesized is LocalElement) {
-      expect(resynthesized.visibleRange, original.visibleRange);
-    } else {
-      fail('Incompatible local elements '
-          '${resynthesized.runtimeType} vs. ${original.runtimeType}');
-    }
-  }
-
-  void checkPossibleMember(
-      Element resynthesized, Element original, String desc) {
-    Element resynthesizedNonHandle = resynthesized is ElementHandle
-        ? resynthesized.actualElement
-        : resynthesized;
-    if (original is Member) {
-      expect(resynthesizedNonHandle, new TypeMatcher<Member>(), reason: desc);
-      if (resynthesizedNonHandle is Member) {
-        List<DartType> resynthesizedTypeArguments =
-            resynthesizedNonHandle.definingType.typeArguments;
-        List<DartType> originalTypeArguments =
-            original.definingType.typeArguments;
-        expect(
-            resynthesizedTypeArguments, hasLength(originalTypeArguments.length),
-            reason: desc);
-        for (int i = 0; i < originalTypeArguments.length; i++) {
-          compareTypeImpls(resynthesizedTypeArguments[i],
-              originalTypeArguments[i], '$desc type argument $i');
-        }
-      }
-    } else {
-      expect(
-          resynthesizedNonHandle, isNot(new TypeMatcher<ConstructorMember>()),
-          reason: desc);
-    }
-  }
-
-  void compareClassElements(ClassElement r, ClassElement o, String desc) {
-    compareElements(r, o, desc);
-    expect(r.fields.length, o.fields.length, reason: '$desc fields.length');
-    for (int i = 0; i < r.fields.length; i++) {
-      String name = o.fields[i].name;
-      compareFieldElements(r.fields[i], o.fields[i], '$desc.field $name');
-    }
-    compareTypes(r.supertype, o.supertype, '$desc supertype');
-    expect(r.interfaces.length, o.interfaces.length,
-        reason: '$desc interfaces.length');
-    for (int i = 0; i < r.interfaces.length; i++) {
-      compareTypes(r.interfaces[i], o.interfaces[i],
-          '$desc interface ${o.interfaces[i].name}');
-    }
-    expect(r.mixins.length, o.mixins.length, reason: '$desc mixins.length');
-    for (int i = 0; i < r.mixins.length; i++) {
-      compareTypes(r.mixins[i], o.mixins[i], '$desc mixin ${o.mixins[i].name}');
-    }
-    expect(r.typeParameters.length, o.typeParameters.length,
-        reason: '$desc typeParameters.length');
-    for (int i = 0; i < r.typeParameters.length; i++) {
-      compareTypeParameterElements(r.typeParameters[i], o.typeParameters[i],
-          '$desc type parameter ${o.typeParameters[i].name}');
-    }
-    expect(r.constructors.length, o.constructors.length,
-        reason: '$desc constructors.length');
-    for (int i = 0; i < r.constructors.length; i++) {
-      compareConstructorElements(r.constructors[i], o.constructors[i],
-          '$desc constructor ${o.constructors[i].name}');
-    }
-    expect(r.accessors.length, o.accessors.length,
-        reason: '$desc accessors.length');
-    List<PropertyAccessorElement> rAccessors = _getSortedPropertyAccessors(r);
-    List<PropertyAccessorElement> oAccessors = _getSortedPropertyAccessors(o);
-    for (int i = 0; i < r.accessors.length; i++) {
-      comparePropertyAccessorElements(
-          rAccessors[i], oAccessors[i], '$desc accessor ${oAccessors[i].name}');
-    }
-    expect(r.methods.length, o.methods.length, reason: '$desc methods.length');
-    for (int i = 0; i < r.methods.length; i++) {
-      compareMethodElements(
-          r.methods[i], o.methods[i], '$desc.${o.methods[i].name}');
-    }
-    compareTypes(r.type, o.type, desc);
-    if (r is ClassElementImpl && o is ClassElementImpl) {
-      expect(r.hasBeenInferred, o.hasBeenInferred, reason: desc);
-    }
-  }
-
-  void compareCompilationUnitElements(CompilationUnitElementImpl resynthesized,
-      CompilationUnitElementImpl original) {
-    String desc = 'Compilation unit ${original.source.uri}';
-    expect(resynthesized.source, original.source);
-    expect(resynthesized.librarySource, original.librarySource);
-    compareLineInfo(resynthesized.lineInfo, original.lineInfo);
-
-    expect(resynthesized.types.length, original.types.length,
-        reason: '$desc.types.length');
-    for (int i = 0; i < resynthesized.types.length; i++) {
-      compareClassElements(
-          resynthesized.types[i], original.types[i], original.types[i].name);
-    }
-
-    // TODO(scheglov) Uncomment once the tasks based implementation is ready.
-//    expect(resynthesized.mixins.length, original.mixins.length,
-//        reason: '$desc.mixins.length');
-//    for (int i = 0; i < resynthesized.mixins.length; i++) {
-//      compareClassElements(
-//          resynthesized.mixins[i], original.mixins[i], original.mixins[i].name);
-//    }
-
-    expect(resynthesized.topLevelVariables.length,
-        original.topLevelVariables.length,
-        reason: '$desc.topLevelVariables.length');
-    for (int i = 0; i < resynthesized.topLevelVariables.length; i++) {
-      String name = resynthesized.topLevelVariables[i].name;
-      compareTopLevelVariableElements(
-          resynthesized.topLevelVariables[i],
-          original.topLevelVariables
-              .singleWhere((TopLevelVariableElement e) => e.name == name),
-          '$desc.topLevelVariables[$name]');
-    }
-    expect(resynthesized.functions.length, original.functions.length,
-        reason: '$desc.functions.length');
-    for (int i = 0; i < resynthesized.functions.length; i++) {
-      compareFunctionElements(resynthesized.functions[i], original.functions[i],
-          '$desc.functions[$i] /* ${original.functions[i].name} */');
-    }
-    expect(resynthesized.functionTypeAliases.length,
-        original.functionTypeAliases.length,
-        reason: '$desc.functionTypeAliases.length');
-    for (int i = 0; i < resynthesized.functionTypeAliases.length; i++) {
-      compareFunctionTypeAliasElements(
-          resynthesized.functionTypeAliases[i],
-          original.functionTypeAliases[i],
-          original.functionTypeAliases[i].name);
-    }
-    expect(resynthesized.enums.length, original.enums.length,
-        reason: '$desc.enums.length');
-    for (int i = 0; i < resynthesized.enums.length; i++) {
-      compareClassElements(
-          resynthesized.enums[i], original.enums[i], original.enums[i].name);
-    }
-    expect(resynthesized.accessors.length, original.accessors.length,
-        reason: '$desc.accessors.length');
-    for (int i = 0; i < resynthesized.accessors.length; i++) {
-      String name = resynthesized.accessors[i].name;
-      if (original.accessors[i].isGetter) {
-        comparePropertyAccessorElements(
-            resynthesized.accessors[i],
-            original.accessors
-                .singleWhere((PropertyAccessorElement e) => e.name == name),
-            '$desc.accessors[$i] /* getter $name */');
-      } else {
-        comparePropertyAccessorElements(
-            resynthesized.accessors[i],
-            original.accessors
-                .singleWhere((PropertyAccessorElement e) => e.name == name),
-            '$desc.accessors[$i] /* setter $name */');
-      }
-    }
-    // Note: no need to test CompilationUnitElementImpl._offsetToElementMap
-    // since it is built on demand when needed (see
-    // CompilationUnitElementImpl.getElementAt])
-  }
-
-  void compareConstAstLists(
-      List<Object> rItems, List<Object> oItems, String desc) {
-    if (rItems == null && oItems == null) {
-      return;
-    }
-    expect(rItems != null && oItems != null, isTrue);
-    expect(rItems, hasLength(oItems.length));
-    for (int i = 0; i < oItems.length; i++) {
-      Object rItem = rItems[i];
-      Object oItem = oItems[i];
-      if (rItem is Expression && oItem is Expression) {
-        compareConstAsts(rItem, oItem, desc);
-      } else if (rItem is TypeName && oItem is TypeName) {
-        compareConstAsts(rItem.name, oItem.name, desc);
-      } else if (rItem is InterpolationString && oItem is InterpolationString) {
-        expect(rItem.value, oItem.value);
-      } else if (rItem is InterpolationExpression &&
-          oItem is InterpolationExpression) {
-        compareConstAsts(rItem.expression, oItem.expression, desc);
-      } else if (rItem is MapLiteralEntry && oItem is MapLiteralEntry) {
-        compareConstAsts(rItem.key, oItem.key, desc);
-        compareConstAsts(rItem.value, oItem.value, desc);
-      } else if (oItem is ConstructorFieldInitializer &&
-          rItem is ConstructorFieldInitializer) {
-        compareConstAsts(rItem.fieldName, oItem.fieldName, desc);
-        if (variablesWithNotConstInitializers.contains(rItem.fieldName.name)) {
-          expect(rItem.expression, isNull, reason: desc);
-        } else {
-          compareConstAsts(rItem.expression, oItem.expression, desc);
-        }
-      } else if (oItem is AssertInitializer && rItem is AssertInitializer) {
-        compareConstAsts(rItem.condition, oItem.condition, '$desc condition');
-        compareConstAsts(rItem.message, oItem.message, '$desc message');
-      } else if (oItem is SuperConstructorInvocation &&
-          rItem is SuperConstructorInvocation) {
-        compareElements(rItem.staticElement, oItem.staticElement, desc);
-        compareConstAsts(rItem.constructorName, oItem.constructorName, desc);
-        compareConstAstLists(
-            rItem.argumentList.arguments, oItem.argumentList.arguments, desc);
-      } else if (oItem is RedirectingConstructorInvocation &&
-          rItem is RedirectingConstructorInvocation) {
-        compareElements(rItem.staticElement, oItem.staticElement, desc);
-        compareConstAsts(rItem.constructorName, oItem.constructorName, desc);
-        compareConstAstLists(
-            rItem.argumentList.arguments, oItem.argumentList.arguments, desc);
-      } else {
-        fail('$desc Incompatible item types: '
-            '${rItem.runtimeType} vs. ${oItem.runtimeType}');
-      }
-    }
-  }
-
-  void compareConstAsts(AstNode r, AstNode o, String desc) {
-    if (o == null) {
-      expect(r, isNull, reason: desc);
-    } else {
-      expect(r, isNotNull, reason: desc);
-      // ConstantAstCloner does not copy static types, and constant values
-      // computer does not use static types. So, we don't set them during
-      // resynthesis and should not check them here.
-      if (o is ParenthesizedExpression) {
-        // We don't resynthesize parenthesis, so just ignore it.
-        compareConstAsts(r, o.expression, desc);
-      } else if (o is SimpleIdentifier && r is SimpleIdentifier) {
-        expect(r.name, o.name, reason: desc);
-        if (namesThatCannotBeResolved.contains(r.name)) {
-          expect(r.staticElement, isNull);
-        } else {
-          compareElements(r.staticElement, o.staticElement, desc);
-        }
-      } else if (o is PrefixedIdentifier && r is SimpleIdentifier) {
-        // We don't resynthesize prefixed identifiers when the prefix refers to
-        // a PrefixElement or a ClassElement.  We use simple identifiers with
-        // correct elements.
-        if (o.prefix.staticElement is PrefixElement ||
-            o.prefix.staticElement is ClassElement) {
-          compareConstAsts(r, o.identifier, desc);
-        } else {
-          fail('Prefix of type ${o.prefix.staticElement.runtimeType} should not'
-              ' have been elided');
-        }
-      } else if (o is SimpleIdentifier && r is PrefixedIdentifier) {
-        // In 'class C {static const a = 0; static const b = a;}' the reference
-        // to 'a' in 'b' is serialized as a fully qualified 'C.a' reference.
-        if (r.prefix.staticElement is ClassElement) {
-          Element oElement = resolutionMap.staticElementForIdentifier(o);
-          compareElements(
-              r.prefix.staticElement, oElement?.enclosingElement, desc);
-          compareConstAsts(r.identifier, o, desc);
-        } else {
-          fail('Prefix of type ${r.prefix.staticElement.runtimeType} should not'
-              ' have been elided');
-        }
-      } else if (o is PropertyAccess &&
-          o.target is PrefixedIdentifier &&
-          r is PrefixedIdentifier) {
-        // We don't resynthesize prefixed identifiers when the prefix refers to
-        // a PrefixElement or a ClassElement.  Which means that if the original
-        // expression was e.g. `prefix.topLevelVariableName.length`, it will get
-        // resynthesized as `topLevelVariableName.length`
-        PrefixedIdentifier oTarget = o.target;
-        checkElidablePrefix(oTarget.prefix);
-        compareConstAsts(
-            r,
-            AstTestFactory.identifier(oTarget.identifier, o.propertyName),
-            desc);
-      } else if (o is PrefixedIdentifier && r is PrefixedIdentifier) {
-        compareConstAsts(r.prefix, o.prefix, desc);
-        compareConstAsts(r.identifier, o.identifier, desc);
-      } else if (o is PropertyAccess && r is PropertyAccess) {
-        compareConstAsts(r.target, o.target, desc);
-        String oName = o.propertyName.name;
-        String rName = r.propertyName.name;
-        expect(rName, oName, reason: desc);
-        if (oName == 'length') {
-          compareElements(
-              r.propertyName.staticElement, o.propertyName.staticElement, desc);
-        }
-      } else if (o is PropertyAccess &&
-          o.target is PrefixedIdentifier &&
-          r is SimpleIdentifier) {
-        // We don't resynthesize property access when it takes the form
-        // `prefixName.className.staticMember`.  We just resynthesize a
-        // SimpleIdentifier correctly resolved to the static member.
-        PrefixedIdentifier oTarget = o.target;
-        checkElidablePrefix(oTarget.prefix);
-        checkElidablePrefix(oTarget.identifier);
-        compareConstAsts(r, o.propertyName, desc);
-      } else if (o is SuperExpression && r is SuperExpression) {
-        // Nothing to compare.
-      } else if (o is ThisExpression && r is ThisExpression) {
-        // Nothing to compare.
-      } else if (o is NullLiteral) {
-        expect(r, new TypeMatcher<NullLiteral>(), reason: desc);
-      } else if (o is BooleanLiteral && r is BooleanLiteral) {
-        expect(r.value, o.value, reason: desc);
-      } else if (o is IntegerLiteral && r is IntegerLiteral) {
-        expect(r.value ?? 0, o.value ?? 0, reason: desc);
-      } else if (o is IntegerLiteral && r is PrefixExpression) {
-        expect(r.operator.type, TokenType.MINUS);
-        IntegerLiteral ri = r.operand;
-        expect(-ri.value, o.value, reason: desc);
-      } else if (o is DoubleLiteral && r is DoubleLiteral) {
-        if (r.value != null &&
-            r.value.isNaN &&
-            o.value != null &&
-            o.value.isNaN) {
-          // NaN is not comparable.
-        } else {
-          expect(r.value, o.value, reason: desc);
-        }
-      } else if (o is StringInterpolation && r is StringInterpolation) {
-        compareConstAstLists(r.elements, o.elements, desc);
-      } else if (o is StringLiteral && r is StringLiteral) {
-        // We don't keep all the tokens of AdjacentStrings.
-        // So, we can compare only their values.
-        expect(r.stringValue, o.stringValue, reason: desc);
-      } else if (o is SymbolLiteral && r is SymbolLiteral) {
-        // We don't keep all the tokens of symbol literals.
-        // So, we can compare only their values.
-        expect(r.components.map((t) => t.lexeme).join('.'),
-            o.components.map((t) => t.lexeme).join('.'),
-            reason: desc);
-      } else if (o is NamedExpression && r is NamedExpression) {
-        expect(r.name.label.name, o.name.label.name, reason: desc);
-        compareConstAsts(r.expression, o.expression, desc);
-      } else if (o is BinaryExpression && r is BinaryExpression) {
-        expect(r.operator.lexeme, o.operator.lexeme, reason: desc);
-        compareConstAsts(r.leftOperand, o.leftOperand, desc);
-        compareConstAsts(r.rightOperand, o.rightOperand, desc);
-      } else if (o is PrefixExpression && r is PrefixExpression) {
-        expect(r.operator.lexeme, o.operator.lexeme, reason: desc);
-        compareConstAsts(r.operand, o.operand, desc);
-      } else if (o is ConditionalExpression && r is ConditionalExpression) {
-        compareConstAsts(r.condition, o.condition, desc);
-        compareConstAsts(r.thenExpression, o.thenExpression, desc);
-        compareConstAsts(r.elseExpression, o.elseExpression, desc);
-      } else if (o is ListLiteral && r is ListLiteral) {
-        compareConstAstLists(
-            r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
-        compareConstAstLists(r.elements, o.elements, desc);
-      } else if (o is MapLiteral && r is MapLiteral) {
-        compareConstAstLists(
-            r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
-        compareConstAstLists(r.entries, o.entries, desc);
-      } else if (o is MethodInvocation && r is MethodInvocation) {
-        compareConstAsts(r.target, o.target, desc);
-        compareConstAsts(r.methodName, o.methodName, desc);
-        compareConstAstLists(
-            r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
-        compareConstAstLists(
-            r.argumentList?.arguments, o.argumentList?.arguments, desc);
-      } else if (o is InstanceCreationExpression &&
-          r is InstanceCreationExpression) {
-        compareElements(r.staticElement, o.staticElement, desc);
-        ConstructorName oConstructor = o.constructorName;
-        ConstructorName rConstructor = r.constructorName;
-        expect(oConstructor, isNotNull, reason: desc);
-        expect(rConstructor, isNotNull, reason: desc);
-        // Note: just compare rConstructor.staticElement and
-        // oConstructor.staticElement as elements, because we just want to
-        // check that they're pointing to the correct elements; we don't want
-        // to check that their constructor initializers match, because that
-        // could lead to infinite regress.
-        compareElements(
-            rConstructor.staticElement, oConstructor.staticElement, desc);
-        TypeName oType = oConstructor.type;
-        TypeName rType = rConstructor.type;
-        expect(oType, isNotNull, reason: desc);
-        expect(rType, isNotNull, reason: desc);
-        compareConstAsts(rType.name, oType.name, desc);
-        compareConstAsts(rConstructor.name, oConstructor.name, desc);
-        // In strong mode type inference is performed, so that
-        // `C<int> v = new C();` is serialized as `C<int> v = new C<int>();`.
-        // So, if there are not type arguments originally, not need to check.
-        if (oType.typeArguments?.arguments?.isNotEmpty ?? false) {
-          compareConstAstLists(rType.typeArguments?.arguments,
-              oType.typeArguments?.arguments, desc);
-        }
-        compareConstAstLists(
-            r.argumentList.arguments, o.argumentList.arguments, desc);
-      } else if (o is AnnotationImpl && r is AnnotationImpl) {
-        expect(o.atSign.lexeme, r.atSign.lexeme, reason: desc);
-        Identifier rName = r.name;
-        Identifier oName = o.name;
-        if (oName is PrefixedIdentifier &&
-            rName is PrefixedIdentifier &&
-            o.constructorName != null &&
-            o.element != null &&
-            r.constructorName == null) {
-          // E.g. `@prefix.cls.ctor`.  This sometimes gets resynthesized as
-          // `@cls.ctor`, with `cls.ctor` represented as a PrefixedIdentifier.
-          compareConstAsts(rName.prefix, oName.identifier, desc);
-          expect(rName.period.lexeme, '.', reason: desc);
-          compareConstAsts(rName.identifier, o.constructorName, desc);
-          expect(r.period, isNull, reason: desc);
-          expect(r.constructorName, isNull, reason: desc);
-        } else {
-          compareConstAsts(r.name, o.name, desc);
-          expect(r.period?.lexeme, o.period?.lexeme, reason: desc);
-          compareConstAsts(r.constructorName, o.constructorName, desc);
-        }
-        compareConstAstLists(
-            r.arguments?.arguments, o.arguments?.arguments, desc);
-        compareElements(r.element, o.element, desc);
-        // elementAnnotation should be null; it is only used in the full AST.
-        expect(o.elementAnnotation, isNull);
-        expect(r.elementAnnotation, isNull);
-      } else {
-        fail('Not implemented for ${r.runtimeType} vs. ${o.runtimeType}');
-      }
-    }
-  }
-
-  void compareConstructorElements(ConstructorElement resynthesized,
-      ConstructorElement original, String desc) {
-    if (original == null && resynthesized == null) {
-      return;
-    }
-    compareExecutableElements(resynthesized, original, desc);
-    ConstructorElementImpl resynthesizedImpl =
-        getActualElement(resynthesized, desc);
-    ConstructorElementImpl originalImpl = getActualElement(original, desc);
-    if (original.isConst) {
-      compareConstAstLists(resynthesizedImpl.constantInitializers,
-          originalImpl.constantInitializers, desc);
-    }
-    if (original.redirectedConstructor == null) {
-      expect(resynthesized.redirectedConstructor, isNull, reason: desc);
-    } else {
-      compareConstructorElements(resynthesized.redirectedConstructor,
-          original.redirectedConstructor, '$desc redirectedConstructor');
-    }
-    checkPossibleMember(resynthesized, original, desc);
-    expect(resynthesized.nameEnd, original.nameEnd, reason: desc);
-    expect(resynthesized.periodOffset, original.periodOffset, reason: desc);
-    expect(resynthesizedImpl.isCycleFree, originalImpl.isCycleFree,
-        reason: desc);
-  }
-
-  void compareConstValues(
-      DartObject resynthesized, DartObject original, String desc) {
-    if (original == null) {
-      expect(resynthesized, isNull, reason: desc);
-    } else {
-      expect(resynthesized, isNotNull, reason: desc);
-      compareTypes(resynthesized.type, original.type, desc);
-      expect(resynthesized.hasKnownValue, original.hasKnownValue, reason: desc);
-      if (original.isNull) {
-        expect(resynthesized.isNull, isTrue, reason: desc);
-      } else if (original.toBoolValue() != null) {
-        expect(resynthesized.toBoolValue(), original.toBoolValue(),
-            reason: desc);
-      } else if (original.toIntValue() != null) {
-        expect(resynthesized.toIntValue(), original.toIntValue(), reason: desc);
-      } else if (original.toDoubleValue() != null) {
-        expect(resynthesized.toDoubleValue(), original.toDoubleValue(),
-            reason: desc);
-      } else if (original.toListValue() != null) {
-        List<DartObject> resynthesizedList = resynthesized.toListValue();
-        List<DartObject> originalList = original.toListValue();
-        expect(resynthesizedList, hasLength(originalList.length));
-        for (int i = 0; i < originalList.length; i++) {
-          compareConstValues(resynthesizedList[i], originalList[i], desc);
-        }
-      } else if (original.toMapValue() != null) {
-        Map<DartObject, DartObject> resynthesizedMap =
-            resynthesized.toMapValue();
-        Map<DartObject, DartObject> originalMap = original.toMapValue();
-        expect(resynthesizedMap, hasLength(originalMap.length));
-        List<DartObject> resynthesizedKeys = resynthesizedMap.keys.toList();
-        List<DartObject> originalKeys = originalMap.keys.toList();
-        for (int i = 0; i < originalKeys.length; i++) {
-          DartObject resynthesizedKey = resynthesizedKeys[i];
-          DartObject originalKey = originalKeys[i];
-          compareConstValues(resynthesizedKey, originalKey, desc);
-          DartObject resynthesizedValue = resynthesizedMap[resynthesizedKey];
-          DartObject originalValue = originalMap[originalKey];
-          compareConstValues(resynthesizedValue, originalValue, desc);
-        }
-      } else if (original.toStringValue() != null) {
-        expect(resynthesized.toStringValue(), original.toStringValue(),
-            reason: desc);
-      } else if (original.toSymbolValue() != null) {
-        expect(resynthesized.toSymbolValue(), original.toSymbolValue(),
-            reason: desc);
-      } else if (original.toTypeValue() != null) {
-        fail('Not implemented');
-      }
-    }
-  }
-
-  void compareElementAnnotations(ElementAnnotationImpl resynthesized,
-      ElementAnnotationImpl original, String desc) {
-    if (original.element == null) {
-      expect(resynthesized.element, isNull);
-    } else {
-      expect(resynthesized.element, isNotNull, reason: desc);
-      expect(resynthesized.element.kind, original.element.kind, reason: desc);
-      expect(resynthesized.element.location, original.element.location,
-          reason: desc);
-    }
-    expect(resynthesized.compilationUnit, isNotNull, reason: desc);
-    expect(resynthesized.compilationUnit.location,
-        original.compilationUnit.location,
-        reason: desc);
-    expect(resynthesized.annotationAst, isNotNull, reason: desc);
-    compareConstAsts(resynthesized.annotationAst, original.annotationAst, desc);
-  }
-
-  void compareElementLocations(
-      Element resynthesized, Element original, String desc) {
-    bool hasFunctionElementByValue(Element e) {
-      if (e == null) {
-        return false;
-      }
-      if (e is FunctionElementImpl_forLUB) {
-        return true;
-      }
-      return hasFunctionElementByValue(e.enclosingElement);
-    }
-
-    if (hasFunctionElementByValue(resynthesized)) {
-      // We resynthesize elements representing types of local functions
-      // without corresponding name offsets, so their locations don't have
-      // corresponding valid @offset components. Also, we don't put
-      // resynthesized local functions into initializers of variables.
-      return;
-    }
-    expect(resynthesized.location, original.location, reason: desc);
-  }
-
-  void compareElements(Element resynthesized, Element original, String desc) {
-    ElementImpl rImpl = getActualElement(resynthesized, desc);
-    ElementImpl oImpl = getActualElement(original, desc);
-    if (oImpl == null && rImpl == null) {
-      return;
-    }
-    if (oImpl is PrefixElement) {
-      // TODO(scheglov) prefixes cannot be resynthesized
-      return;
-    }
-    expect(original, isNotNull);
-    expect(resynthesized, isNotNull, reason: desc);
-    if (rImpl is DefaultParameterElementImpl && oImpl is ParameterElementImpl) {
-      // This is ok provided the resynthesized parameter element doesn't have
-      // any evaluation result.
-      expect(rImpl.evaluationResult, isNull);
-    } else {
-      Type rRuntimeType;
-      if (rImpl is ConstFieldElementImpl) {
-        rRuntimeType = ConstFieldElementImpl;
-      } else if (rImpl is FunctionElementImpl) {
-        rRuntimeType = FunctionElementImpl;
-      } else {
-        rRuntimeType = rImpl.runtimeType;
-      }
-      expect(rRuntimeType, oImpl.runtimeType);
-    }
-    expect(resynthesized.kind, original.kind);
-    compareElementLocations(resynthesized, original, desc);
-    expect(resynthesized.name, original.name);
-    expect(resynthesized.nameOffset, original.nameOffset,
-        reason: '$desc.nameOffset');
-    expect(rImpl.codeOffset, oImpl.codeOffset, reason: desc);
-    expect(rImpl.codeLength, oImpl.codeLength, reason: desc);
-    expect(resynthesized.documentationComment, original.documentationComment,
-        reason: desc);
-    compareMetadata(resynthesized.metadata, original.metadata, desc);
-
-    // Validate modifiers.
-    for (Modifier modifier in Modifier.values) {
-      bool got = _hasModifier(resynthesized, modifier);
-      bool want = _hasModifier(original, modifier);
-      expect(got, want,
-          reason: 'Mismatch in $desc.$modifier: got $got, want $want');
-    }
-
-    // Validate members.
-    if (oImpl is Member) {
-      expect(rImpl, new TypeMatcher<Member>(), reason: desc);
-    } else {
-      expect(rImpl, isNot(new TypeMatcher<Member>()), reason: desc);
-    }
-  }
-
-  void compareExecutableElements(
-      ExecutableElement resynthesized, ExecutableElement original, String desc,
-      {bool shallow: false}) {
-    compareElements(resynthesized, original, desc);
-    compareParameterElementLists(
-        resynthesized.parameters, original.parameters, desc);
-    if (!original.hasImplicitReturnType) {
-      compareTypes(
-          resynthesized.returnType, original.returnType, '$desc return type');
-    }
-    if (!shallow) {
-      compareTypes(resynthesized.type, original.type, desc);
-    }
-    expect(resynthesized.typeParameters.length, original.typeParameters.length);
-    for (int i = 0; i < resynthesized.typeParameters.length; i++) {
-      compareTypeParameterElements(
-          resynthesized.typeParameters[i],
-          original.typeParameters[i],
-          '$desc type parameter ${original.typeParameters[i].name}');
-    }
-  }
-
-  void compareExportElements(ExportElementImpl resynthesized,
-      ExportElementImpl original, String desc) {
-    expect(resynthesized.exportedLibrary.location,
-        original.exportedLibrary.location);
-    expect(resynthesized.combinators.length, original.combinators.length);
-    for (int i = 0; i < resynthesized.combinators.length; i++) {
-      compareNamespaceCombinators(
-          resynthesized.combinators[i], original.combinators[i]);
-    }
-  }
-
-  void compareFieldElements(
-      FieldElementImpl resynthesized, FieldElementImpl original, String desc) {
-    comparePropertyInducingElements(resynthesized, original, desc);
-  }
-
-  void compareFunctionElements(
-      FunctionElement resynthesized, FunctionElement original, String desc,
-      {bool shallow: false}) {
-    if (original == null && resynthesized == null) {
-      return;
-    }
-    expect(resynthesized, isNotNull, reason: desc);
-    compareExecutableElements(resynthesized, original, desc, shallow: shallow);
-    checkPossibleLocalElements(resynthesized, original);
-  }
-
-  void compareFunctionTypeAliasElements(FunctionTypeAliasElement resynthesized,
-      FunctionTypeAliasElement original, String desc) {
-    compareElements(resynthesized, original, desc);
-    ElementImpl rImpl = getActualElement(resynthesized, desc);
-    ElementImpl oImpl = getActualElement(original, desc);
-    if (rImpl is GenericTypeAliasElementImpl) {
-      if (oImpl is GenericTypeAliasElementImpl) {
-        compareGenericFunctionTypeElements(
-            rImpl.function, oImpl.function, '$desc.function');
-      } else {
-        fail(
-            'Resynthesized a GenericTypeAliasElementImpl, but expected a ${oImpl.runtimeType}');
-      }
-    } else {
-      fail('Resynthesized a ${rImpl.runtimeType}');
-    }
-    compareTypes(resynthesized.type, original.type, desc);
-    expect(resynthesized.typeParameters.length, original.typeParameters.length);
-    for (int i = 0; i < resynthesized.typeParameters.length; i++) {
-      compareTypeParameterElements(
-          resynthesized.typeParameters[i],
-          original.typeParameters[i],
-          '$desc.typeParameters[$i] /* ${original.typeParameters[i].name} */');
-    }
-  }
-
-  void compareGenericFunctionTypeElements(
-      GenericFunctionTypeElement resynthesized,
-      GenericFunctionTypeElement original,
-      String desc) {
-    if (resynthesized == null) {
-      if (original != null) {
-        fail('Failed to resynthesize generic function type');
-      }
-    } else if (original == null) {
-      fail('Resynthesizes a generic function type when none expected');
-    }
-    compareTypeParameterElementLists(resynthesized.typeParameters,
-        original.typeParameters, '$desc.typeParameters');
-    compareParameterElementLists(
-        resynthesized.parameters, original.parameters, '$desc.parameters');
-    compareTypes(
-        resynthesized.returnType, original.returnType, '$desc.returnType');
-  }
-
-  void compareImportElements(ImportElementImpl resynthesized,
-      ImportElementImpl original, String desc) {
-    expect(resynthesized.importedLibrary.location,
-        original.importedLibrary.location,
-        reason: '$desc importedLibrary location');
-    expect(resynthesized.prefixOffset, original.prefixOffset,
-        reason: '$desc prefixOffset');
-    if (original.prefix == null) {
-      expect(resynthesized.prefix, isNull, reason: '$desc prefix');
-    } else {
-      comparePrefixElements(
-          resynthesized.prefix, original.prefix, original.prefix.name);
-    }
-    expect(resynthesized.combinators.length, original.combinators.length,
-        reason: '$desc combinators');
-    for (int i = 0; i < resynthesized.combinators.length; i++) {
-      compareNamespaceCombinators(
-          resynthesized.combinators[i], original.combinators[i]);
-    }
-  }
-
-  void compareLabelElements(
-      LabelElementImpl resynthesized, LabelElementImpl original, String desc) {
-    expect(resynthesized.isOnSwitchMember, original.isOnSwitchMember,
-        reason: desc);
-    expect(resynthesized.isOnSwitchStatement, original.isOnSwitchStatement,
-        reason: desc);
-    compareElements(resynthesized, original, desc);
-  }
-
-  void compareLineInfo(LineInfo resynthesized, LineInfo original) {
-    expect(resynthesized.lineCount, original.lineCount);
-    expect(resynthesized.lineStarts, original.lineStarts);
-  }
-
-  void compareMetadata(List<ElementAnnotation> resynthesized,
-      List<ElementAnnotation> original, String desc) {
-    expect(resynthesized, hasLength(original.length), reason: desc);
-    for (int i = 0; i < original.length; i++) {
-      compareElementAnnotations(
-          resynthesized[i], original[i], '$desc annotation $i');
-    }
-  }
-
-  void compareMethodElements(MethodElementImpl resynthesized,
-      MethodElementImpl original, String desc) {
-    // TODO(paulberry): do we need to deal with
-    // MultiplyInheritedMethodElementImpl?
-    compareExecutableElements(resynthesized, original, desc);
-  }
-
-  void compareNamespaceCombinators(
-      NamespaceCombinator resynthesized, NamespaceCombinator original) {
-    if (original is ShowElementCombinatorImpl &&
-        resynthesized is ShowElementCombinatorImpl) {
-      expect(resynthesized.shownNames, original.shownNames,
-          reason: 'shownNames');
-      expect(resynthesized.offset, original.offset, reason: 'offset');
-      expect(resynthesized.end, original.end, reason: 'end');
-    } else if (original is HideElementCombinatorImpl &&
-        resynthesized is HideElementCombinatorImpl) {
-      expect(resynthesized.hiddenNames, original.hiddenNames,
-          reason: 'hiddenNames');
-    } else if (resynthesized.runtimeType != original.runtimeType) {
-      fail(
-          'Type mismatch: expected ${original.runtimeType}, got ${resynthesized.runtimeType}');
-    } else {
-      fail('Unimplemented comparison for ${original.runtimeType}');
-    }
-  }
-
-  void compareNamespaces(
-      Namespace resynthesized, Namespace original, String desc) {
-    Map<String, Element> resynthesizedMap = resynthesized.definedNames;
-    Map<String, Element> originalMap = original.definedNames;
-    expect(resynthesizedMap.keys.toSet(), originalMap.keys.toSet(),
-        reason: desc);
-    for (String key in originalMap.keys) {
-      Element resynthesizedElement = resynthesizedMap[key];
-      Element originalElement = originalMap[key];
-      compareElements(resynthesizedElement, originalElement, key);
-    }
-  }
-
-  void compareParameterElementLists(
-      List<ParameterElement> resynthesizedParameters,
-      List<ParameterElement> originalParameters,
-      String desc) {
-    expect(resynthesizedParameters.length, originalParameters.length);
-    for (int i = 0; i < resynthesizedParameters.length; i++) {
-      compareParameterElements(
-          resynthesizedParameters[i],
-          originalParameters[i],
-          '$desc.parameters[$i] /* ${originalParameters[i].name} */');
-    }
-  }
-
-  void compareParameterElements(
-      ParameterElement resynthesized, ParameterElement original, String desc) {
-    compareVariableElements(resynthesized, original, desc);
-    compareParameterElementLists(
-        resynthesized.parameters, original.parameters, desc);
-    // ignore: deprecated_member_use
-    expect(resynthesized.parameterKind, original.parameterKind, reason: desc);
-    expect(resynthesized.isInitializingFormal, original.isInitializingFormal,
-        reason: desc);
-    expect(resynthesized is FieldFormalParameterElementImpl,
-        original is FieldFormalParameterElementImpl);
-    if (resynthesized is FieldFormalParameterElementImpl &&
-        original is FieldFormalParameterElementImpl) {
-      if (original.field == null) {
-        expect(resynthesized.field, isNull, reason: '$desc field');
-      } else {
-        expect(resynthesized.field, isNotNull, reason: '$desc field');
-        compareFieldElements(
-            resynthesized.field, original.field, '$desc field');
-      }
-    }
-    expect(resynthesized.defaultValueCode, original.defaultValueCode,
-        reason: desc);
-    expect(resynthesized.isCovariant, original.isCovariant,
-        reason: '$desc isCovariant');
-    ParameterElementImpl resynthesizedActual =
-        getActualElement(resynthesized, desc);
-    ParameterElementImpl originalActual = getActualElement(original, desc);
-    expect(resynthesizedActual.isExplicitlyCovariant,
-        originalActual.isExplicitlyCovariant,
-        reason: desc);
-    compareFunctionElements(
-        resynthesizedActual.initializer, originalActual.initializer, desc);
-  }
-
-  void comparePrefixElements(PrefixElementImpl resynthesized,
-      PrefixElementImpl original, String desc) {
-    compareElements(resynthesized, original, desc);
-  }
-
-  void comparePropertyAccessorElements(
-      PropertyAccessorElementImpl resynthesized,
-      PropertyAccessorElementImpl original,
-      String desc) {
-    // TODO(paulberry): do I need to worry about
-    // MultiplyInheritedPropertyAccessorElementImpl?
-    compareExecutableElements(resynthesized, original, desc);
-    expect(resynthesized.variable, isNotNull);
-    expect(resynthesized.variable.location, original.variable.location);
-  }
-
-  void comparePropertyInducingElements(
-      PropertyInducingElementImpl resynthesized,
-      PropertyInducingElementImpl original,
-      String desc) {
-    compareVariableElements(resynthesized, original, desc);
-    if (original.getter == null) {
-      expect(resynthesized.getter, isNull);
-    } else {
-      expect(resynthesized.getter, isNotNull);
-      expect(resynthesized.getter.location, original.getter.location);
-    }
-    if (original.setter == null) {
-      expect(resynthesized.setter, isNull);
-    } else {
-      expect(resynthesized.setter, isNotNull);
-      expect(resynthesized.setter.location, original.setter.location);
-    }
-  }
-
-  void compareTopLevelVariableElements(
-      TopLevelVariableElementImpl resynthesized,
-      TopLevelVariableElementImpl original,
-      String desc) {
-    comparePropertyInducingElements(resynthesized, original, desc);
-  }
-
-  void compareTypeImpls(
-      TypeImpl resynthesized, TypeImpl original, String desc) {
-    compareElementLocations(
-        resynthesized.element, original.element, '$desc.element.location');
-    expect(resynthesized.name, original.name, reason: '$desc.name');
-  }
-
-  void compareTypeParameterElementLists(
-      List<TypeParameterElement> resynthesized,
-      List<TypeParameterElement> original,
-      String desc) {
-    int length = original.length;
-    expect(resynthesized.length, length, reason: '$desc.length');
-    for (int i = 0; i < length; i++) {
-      compareTypeParameterElements(resynthesized[i], original[i], '$desc[$i]');
-    }
-  }
-
-  void compareTypeParameterElements(TypeParameterElement resynthesized,
-      TypeParameterElement original, String desc) {
-    compareElements(resynthesized, original, desc);
-    compareTypes(resynthesized.type, original.type, '$desc.type');
-    compareTypes(resynthesized.bound, original.bound, '$desc.bound');
-  }
-
-  void compareTypes(DartType resynthesized, DartType original, String desc) {
-    if (original == null) {
-      expect(resynthesized, isNull, reason: desc);
-    } else if (resynthesized is InterfaceTypeImpl &&
-        original is InterfaceTypeImpl) {
-      compareTypeImpls(resynthesized, original, desc);
-      expect(resynthesized.typeArguments.length, original.typeArguments.length,
-          reason: '$desc.typeArguments.length');
-      for (int i = 0; i < resynthesized.typeArguments.length; i++) {
-        compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
-            '$desc.typeArguments[$i] /* ${original.typeArguments[i].name} */');
-      }
-    } else if (resynthesized is TypeParameterTypeImpl &&
-        original is TypeParameterTypeImpl) {
-      compareTypeImpls(resynthesized, original, desc);
-    } else if (resynthesized is DynamicTypeImpl &&
-        original is DynamicTypeImpl) {
-      expect(resynthesized, same(original));
-    } else if (resynthesized is UndefinedTypeImpl &&
-        original is UndefinedTypeImpl) {
-      expect(resynthesized, same(original));
-    } else if (resynthesized is FunctionTypeImpl &&
-        original is FunctionTypeImpl) {
-      compareTypeImpls(resynthesized, original, desc);
-      expect(resynthesized.isInstantiated, original.isInstantiated,
-          reason: desc);
-      if (original.element.enclosingElement == null &&
-          original.element is FunctionElement) {
-        expect(resynthesized.element, new TypeMatcher<FunctionElement>());
-        expect(resynthesized.element.enclosingElement, isNull, reason: desc);
-        compareFunctionElements(
-            resynthesized.element, original.element, '$desc.element',
-            shallow: true);
-        expect(resynthesized.element.type, same(resynthesized));
-      }
-      expect(resynthesized.typeArguments.length, original.typeArguments.length,
-          reason: '$desc.typeArguments.length');
-      for (int i = 0; i < resynthesized.typeArguments.length; i++) {
-        if (resynthesized.typeArguments[i].isDynamic &&
-            original.typeArguments[i] is TypeParameterType) {
-          // It's ok for type arguments to get converted to `dynamic` if they
-          // are not used.
-          expect(
-              isTypeParameterUsed(
-                  original.typeArguments[i], original.element.type),
-              isFalse);
-        } else {
-          compareTypes(
-              resynthesized.typeArguments[i],
-              original.typeArguments[i],
-              '$desc.typeArguments[$i] /* ${original.typeArguments[i].name} */');
-        }
-      }
-      if (original.typeParameters == null) {
-        expect(resynthesized.typeParameters, isNull, reason: desc);
-      } else {
-        expect(resynthesized.typeParameters, isNotNull, reason: desc);
-        expect(
-            resynthesized.typeParameters.length, original.typeParameters.length,
-            reason: desc);
-        for (int i = 0; i < resynthesized.typeParameters.length; i++) {
-          compareTypeParameterElements(resynthesized.typeParameters[i],
-              original.typeParameters[i], '$desc.typeParameters[$i]');
-        }
-      }
-      expect(resynthesized.typeFormals.length, original.typeFormals.length,
-          reason: desc);
-      for (int i = 0; i < resynthesized.typeFormals.length; i++) {
-        compareTypeParameterElements(resynthesized.typeFormals[i],
-            original.typeFormals[i], '$desc.typeFormals[$i]');
-      }
-    } else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
-      expect(resynthesized, same(original));
-    } else if (resynthesized is DynamicTypeImpl &&
-        original is UndefinedTypeImpl) {
-      // TODO(scheglov) In the strong mode constant variable like
-      //  `var V = new Unresolved()` gets `UndefinedTypeImpl`, and it gets
-      // `DynamicTypeImpl` in the spec mode.
-    } else if (resynthesized is BottomTypeImpl && original is BottomTypeImpl) {
-      expect(resynthesized, same(original));
-    } else if (resynthesized.runtimeType != original.runtimeType) {
-      fail('Type mismatch: expected $original,'
-          ' got $resynthesized ($desc)');
-    } else {
-      fail('Unimplemented comparison for ${original.runtimeType}');
-    }
-  }
-
-  void compareVariableElements(
-      VariableElement resynthesized, VariableElement original, String desc) {
-    compareElements(resynthesized, original, desc);
-    if ((resynthesized as VariableElementImpl).typeInferenceError == null) {
-      compareTypes(resynthesized.type, original.type, '$desc.type');
-    }
-    VariableElementImpl resynthesizedActual =
-        getActualElement(resynthesized, desc);
-    VariableElementImpl originalActual = getActualElement(original, desc);
-    compareFunctionElements(resynthesizedActual.initializer,
-        originalActual.initializer, '$desc.initializer');
-    if (originalActual is ConstVariableElement) {
-      Element oEnclosing = original.enclosingElement;
-      if (oEnclosing is ClassElement && oEnclosing.isEnum) {
-        compareConstValues(resynthesized.constantValue, original.constantValue,
-            '$desc.constantValue');
-      } else {
-        Expression initializer = resynthesizedActual.constantInitializer;
-        if (variablesWithNotConstInitializers.contains(resynthesized.name)) {
-          expect(initializer, isNull, reason: desc);
-        } else {
-          compareConstAsts(initializer, originalActual.constantInitializer,
-              '$desc.constantInitializer');
-        }
-      }
-    }
-    checkPossibleMember(resynthesized, original, desc);
-    checkPossibleLocalElements(resynthesized, original);
-  }
-
   DartSdk createDartSdk() => AbstractContextTest.SHARED_MOCK_SDK;
 
   /**
@@ -1188,161 +109,17 @@
    */
   AnalysisOptionsImpl createOptions() => new AnalysisOptionsImpl();
 
-  ElementImpl getActualElement(Element element, String desc) {
-    if (element == null) {
-      return null;
-    } else if (element is ElementImpl) {
-      return element;
-    } else if (element is ElementHandle) {
-      Element actualElement = element.actualElement;
-      // A handle should never point to a member, because if it did, then
-      // "is Member" checks on the handle would produce the wrong result.
-      expect(actualElement, isNot(new TypeMatcher<Member>()), reason: desc);
-      return getActualElement(actualElement, desc);
-    } else if (element is Member) {
-      return getActualElement(element.baseElement, desc);
-    } else {
-      fail('Unexpected type for resynthesized ($desc):'
-          ' ${element.runtimeType}');
-    }
-  }
-
-  /**
-   * Determine if [type] makes use of the given [typeParameter].
-   */
-  bool isTypeParameterUsed(TypeParameterType typeParameter, DartType type) {
-    if (type is FunctionType) {
-      return isTypeParameterUsed(typeParameter, type.returnType) ||
-          type.parameters.any((ParameterElement e) =>
-              isTypeParameterUsed(typeParameter, e.type));
-    } else if (type is InterfaceType) {
-      return type.typeArguments
-          .any((DartType t) => isTypeParameterUsed(typeParameter, t));
-    } else if (type is TypeParameterType) {
-      return type == typeParameter;
-    } else {
-      expect(type.isDynamic || type.isVoid, isTrue);
-      return false;
-    }
-  }
-
   @override
   void setUp() {
     super.setUp();
     prepareAnalysisContext(createOptions());
   }
-
-  List<PropertyAccessorElement> _getSortedPropertyAccessors(
-      ClassElement classElement) {
-    List<PropertyAccessorElement> accessors = classElement.accessors.toList();
-    accessors.sort((a, b) => a.displayName.compareTo(b.displayName));
-    return accessors;
-  }
-
-  bool _hasModifier(Element element, Modifier modifier) {
-    if (modifier == Modifier.ABSTRACT) {
-      if (element is ClassElement) {
-        return element.isAbstract;
-      }
-      if (element is ExecutableElement) {
-        return element.isAbstract;
-      }
-      return false;
-    } else if (modifier == Modifier.ASYNCHRONOUS) {
-      if (element is ExecutableElement) {
-        return element.isAsynchronous;
-      }
-      return false;
-    } else if (modifier == Modifier.CONST) {
-      if (element is VariableElement) {
-        return element.isConst;
-      }
-      return false;
-    } else if (modifier == Modifier.COVARIANT) {
-      if (element is ParameterElementImpl) {
-        return element.isExplicitlyCovariant;
-      }
-      return false;
-    } else if (modifier == Modifier.DEFERRED) {
-      if (element is ImportElement) {
-        return element.isDeferred;
-      }
-      return false;
-    } else if (modifier == Modifier.ENUM) {
-      if (element is ClassElement) {
-        return element.isEnum;
-      }
-      return false;
-    } else if (modifier == Modifier.EXTERNAL) {
-      if (element is ExecutableElement) {
-        return element.isExternal;
-      }
-      return false;
-    } else if (modifier == Modifier.FACTORY) {
-      if (element is ConstructorElement) {
-        return element.isFactory;
-      }
-      return false;
-    } else if (modifier == Modifier.FINAL) {
-      if (element is VariableElement) {
-        return element.isFinal;
-      }
-      return false;
-    } else if (modifier == Modifier.GENERATOR) {
-      if (element is ExecutableElement) {
-        return element.isGenerator;
-      }
-      return false;
-    } else if (modifier == Modifier.GETTER) {
-      if (element is PropertyAccessorElement) {
-        return element.isGetter;
-      }
-      return false;
-    } else if (modifier == Modifier.HAS_EXT_URI) {
-      if (element is LibraryElement) {
-        return element.hasExtUri;
-      }
-      return false;
-    } else if (modifier == Modifier.IMPLICIT_TYPE) {
-      if (element is ExecutableElement) {
-        return element.hasImplicitReturnType;
-      }
-      return false;
-    } else if (modifier == Modifier.MIXIN_APPLICATION) {
-      if (element is ClassElement) {
-        return element.isMixinApplication;
-      }
-      return false;
-    } else if (modifier == Modifier.REFERENCES_SUPER) {
-      if (element is ClassElement) {
-        return element.hasReferenceToSuper;
-      }
-      return false;
-    } else if (modifier == Modifier.SETTER) {
-      if (element is PropertyAccessorElement) {
-        return element.isSetter;
-      }
-      return false;
-    } else if (modifier == Modifier.STATIC) {
-      if (element is ExecutableElement) {
-        return element.isStatic;
-      } else if (element is FieldElement) {
-        return element.isStatic;
-      }
-      return false;
-    } else if (modifier == Modifier.SYNTHETIC) {
-      return element.isSynthetic;
-    }
-    throw new UnimplementedError(
-        'Modifier $modifier for ${element?.runtimeType}');
-  }
 }
 
-@reflectiveTest
-abstract class ResynthesizeTest extends AbstractResynthesizeTest {
-  Future<LibraryElementImpl> checkLibrary(String text,
-      {bool allowErrors: false, bool dumpSummaries: false});
-
+/// Mixin containing test cases exercising summary resynthesis.  Intended to be
+/// applied to a class implementing [ResynthesizeTestStrategy], along with the
+/// mixin [ResynthesizeTestHelpers].
+abstract class ResynthesizeTestCases implements ResynthesizeTestHelpers {
   test_class_abstract() async {
     var library = await checkLibrary('abstract class C {}');
     checkElementText(library, r'''
@@ -6106,6 +4883,88 @@
 ''');
   }
 
+  test_getElement_constructor_named() async {
+    String text = 'class C { C.named(); }';
+    Source source = addLibrarySource('/test.dart', text);
+    ConstructorElement original = context
+        .computeLibraryElement(source)
+        .getType('C')
+        .getNamedConstructor('named');
+    expect(original, isNotNull);
+    ConstructorElement resynthesized = _validateGetElement(text, original);
+    compareConstructorElements(resynthesized, original, 'C.constructor named');
+  }
+
+  test_getElement_constructor_unnamed() async {
+    String text = 'class C { C(); }';
+    Source source = addLibrarySource('/test.dart', text);
+    ConstructorElement original =
+        context.computeLibraryElement(source).getType('C').unnamedConstructor;
+    expect(original, isNotNull);
+    ConstructorElement resynthesized = _validateGetElement(text, original);
+    compareConstructorElements(resynthesized, original, 'C.constructor');
+  }
+
+  test_getElement_field() async {
+    String text = 'class C { var f; }';
+    Source source = addLibrarySource('/test.dart', text);
+    FieldElement original =
+        context.computeLibraryElement(source).getType('C').getField('f');
+    expect(original, isNotNull);
+    FieldElement resynthesized = _validateGetElement(text, original);
+    compareFieldElements(resynthesized, original, 'C.field f');
+  }
+
+  test_getElement_getter() async {
+    String text = 'class C { get f => null; }';
+    Source source = addLibrarySource('/test.dart', text);
+    PropertyAccessorElement original =
+        context.computeLibraryElement(source).getType('C').getGetter('f');
+    expect(original, isNotNull);
+    PropertyAccessorElement resynthesized = _validateGetElement(text, original);
+    comparePropertyAccessorElements(resynthesized, original, 'C.getter f');
+  }
+
+  test_getElement_method() async {
+    String text = 'class C { f() {} }';
+    Source source = addLibrarySource('/test.dart', text);
+    MethodElement original =
+        context.computeLibraryElement(source).getType('C').getMethod('f');
+    expect(original, isNotNull);
+    MethodElement resynthesized = _validateGetElement(text, original);
+    compareMethodElements(resynthesized, original, 'C.method f');
+  }
+
+  test_getElement_operator() async {
+    String text = 'class C { operator+(x) => null; }';
+    Source source = addLibrarySource('/test.dart', text);
+    MethodElement original =
+        context.computeLibraryElement(source).getType('C').getMethod('+');
+    expect(original, isNotNull);
+    MethodElement resynthesized = _validateGetElement(text, original);
+    compareMethodElements(resynthesized, original, 'C.operator+');
+  }
+
+  test_getElement_setter() async {
+    String text = 'class C { void set f(value) {} }';
+    Source source = addLibrarySource('/test.dart', text);
+    PropertyAccessorElement original =
+        context.computeLibraryElement(source).getType('C').getSetter('f');
+    expect(original, isNotNull);
+    PropertyAccessorElement resynthesized = _validateGetElement(text, original);
+    comparePropertyAccessorElements(resynthesized, original, 'C.setter f');
+  }
+
+  test_getElement_unit() async {
+    String text = 'class C { f() {} }';
+    Source source = addLibrarySource('/test.dart', text);
+    CompilationUnitElement original =
+        context.computeLibraryElement(source).definingCompilationUnit;
+    expect(original, isNotNull);
+    CompilationUnitElement resynthesized = _validateGetElement(text, original);
+    compareCompilationUnitElements(resynthesized, original);
+  }
+
   test_getter_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -9828,6 +8687,1272 @@
 int j;
 ''');
   }
+
+  /**
+   * Encode the library containing [original] into a summary and then use
+   * [TestSummaryResynthesizer.getElement] to retrieve just the original
+   * element from the resynthesized summary.
+   */
+  Element _validateGetElement(String text, Element original) {
+    SummaryResynthesizer resynthesizer = encodeLibrary(original.library.source);
+    ElementLocationImpl location = original.location;
+    Element result = resynthesizer.getElement(location);
+    checkMinimalResynthesisWork(resynthesizer, original.library);
+    // Check that no other summaries needed to be resynthesized to resynthesize
+    // the library element.
+    expect(resynthesizer.resynthesisCount, 3);
+    expect(result.location, location);
+    return result;
+  }
+}
+
+/// Mixin containing helper methods for testing summary resynthesis.  Intended
+/// to be applied to a class implementing [ResynthesizeTestStrategy].
+abstract class ResynthesizeTestHelpers implements ResynthesizeTestStrategy {
+  /**
+   * Names of variables which have initializers that are not valid constants,
+   * so they are not resynthesized.
+   */
+  final variablesWithNotConstInitializers = Set<String>();
+
+  /**
+   * Tests may set this to `false` to indicate that resynthesized elements
+   * should not be compare with elements created using AnalysisContext.
+   */
+  bool shouldCompareLibraryElements = true;
+
+  /**
+   * Names that cannot be resolved, e.g. because of duplicate declaration.
+   */
+  final namesThatCannotBeResolved = Set<String>();
+
+  /**
+   * Verify that the given prefix is safe to elide from a resynthesized AST.
+   */
+  void checkElidablePrefix(SimpleIdentifier prefix) {
+    if (prefix.staticElement is! PrefixElement &&
+        prefix.staticElement is! ClassElement) {
+      fail('Prefix of type ${prefix.staticElement.runtimeType}'
+          ' should not have been elided');
+    }
+  }
+
+  Future<LibraryElementImpl> checkLibrary(String text,
+      {bool allowErrors: false, bool dumpSummaries: false}) async {
+    Source source = addTestSource(text);
+    LibraryElementImpl resynthesized = _encodeDecodeLibraryElement(source);
+    LibraryElementImpl original = context.computeLibraryElement(source);
+    if (!allowErrors) {
+      List<AnalysisError> errors = context.computeErrors(source);
+      if (errors.where((e) => e.message.startsWith('unused')).isNotEmpty) {
+        fail('Analysis errors: $errors');
+      }
+    }
+    if (shouldCompareLibraryElements) {
+      checkLibraryElements(original, resynthesized);
+    }
+    return resynthesized;
+  }
+
+  void checkLibraryElements(
+      LibraryElementImpl original, LibraryElementImpl resynthesized) {
+    compareElements(resynthesized, original, '(library)');
+    expect(resynthesized.displayName, original.displayName);
+    expect(original.enclosingElement, isNull);
+    expect(resynthesized.enclosingElement, isNull);
+    expect(resynthesized.hasExtUri, original.hasExtUri);
+    compareCompilationUnitElements(resynthesized.definingCompilationUnit,
+        original.definingCompilationUnit);
+    expect(resynthesized.parts.length, original.parts.length, reason: 'parts');
+    for (int i = 0; i < resynthesized.parts.length; i++) {
+      compareCompilationUnitElements(resynthesized.parts[i], original.parts[i]);
+    }
+    expect(resynthesized.imports.length, original.imports.length,
+        reason: 'imports');
+    for (int i = 0; i < resynthesized.imports.length; i++) {
+      ImportElement originalImport = original.imports[i];
+      compareImportElements(
+          resynthesized.imports[i], originalImport, originalImport.toString());
+    }
+    expect(resynthesized.exports.length, original.exports.length,
+        reason: 'exports');
+    for (int i = 0; i < resynthesized.exports.length; i++) {
+      ExportElement originalExport = original.exports[i];
+      compareExportElements(
+          resynthesized.exports[i], originalExport, originalExport.toString());
+    }
+    expect(resynthesized.nameLength, original.nameLength);
+    compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
+        '(public namespace)');
+    compareNamespaces(resynthesized.exportNamespace, original.exportNamespace,
+        '(export namespace)');
+    if (original.entryPoint == null) {
+      expect(resynthesized.entryPoint, isNull);
+    } else {
+      expect(resynthesized.entryPoint, isNotNull);
+      compareFunctionElements(
+          resynthesized.entryPoint, original.entryPoint, '(entry point)');
+    }
+    // The libraries `dart:core` and `dart:async` cannot create their
+    // `loadLibrary` functions until after both are created.
+    if (original.name != 'dart.core' && original.name != 'dart.async') {
+      compareExecutableElements(
+          resynthesized.loadLibraryFunction as ExecutableElementImpl,
+          original.loadLibraryFunction as ExecutableElementImpl,
+          '(loadLibraryFunction)');
+    }
+    expect(resynthesized.libraryCycle.toSet(), original.libraryCycle.toSet());
+  }
+
+  void checkPossibleLocalElements(Element resynthesized, Element original) {
+    if (original is! LocalElement && resynthesized is! LocalElement) {
+      return;
+    }
+    if (original is LocalElement && resynthesized is LocalElement) {
+      expect(resynthesized.visibleRange, original.visibleRange);
+    } else {
+      fail('Incompatible local elements '
+          '${resynthesized.runtimeType} vs. ${original.runtimeType}');
+    }
+  }
+
+  void checkPossibleMember(
+      Element resynthesized, Element original, String desc) {
+    Element resynthesizedNonHandle = resynthesized is ElementHandle
+        ? resynthesized.actualElement
+        : resynthesized;
+    if (original is Member) {
+      expect(resynthesizedNonHandle, new TypeMatcher<Member>(), reason: desc);
+      if (resynthesizedNonHandle is Member) {
+        List<DartType> resynthesizedTypeArguments =
+            resynthesizedNonHandle.definingType.typeArguments;
+        List<DartType> originalTypeArguments =
+            original.definingType.typeArguments;
+        expect(
+            resynthesizedTypeArguments, hasLength(originalTypeArguments.length),
+            reason: desc);
+        for (int i = 0; i < originalTypeArguments.length; i++) {
+          compareTypeImpls(resynthesizedTypeArguments[i],
+              originalTypeArguments[i], '$desc type argument $i');
+        }
+      }
+    } else {
+      expect(
+          resynthesizedNonHandle, isNot(new TypeMatcher<ConstructorMember>()),
+          reason: desc);
+    }
+  }
+
+  void compareClassElements(ClassElement r, ClassElement o, String desc) {
+    compareElements(r, o, desc);
+    expect(r.fields.length, o.fields.length, reason: '$desc fields.length');
+    for (int i = 0; i < r.fields.length; i++) {
+      String name = o.fields[i].name;
+      compareFieldElements(r.fields[i], o.fields[i], '$desc.field $name');
+    }
+    compareTypes(r.supertype, o.supertype, '$desc supertype');
+    expect(r.interfaces.length, o.interfaces.length,
+        reason: '$desc interfaces.length');
+    for (int i = 0; i < r.interfaces.length; i++) {
+      compareTypes(r.interfaces[i], o.interfaces[i],
+          '$desc interface ${o.interfaces[i].name}');
+    }
+    expect(r.mixins.length, o.mixins.length, reason: '$desc mixins.length');
+    for (int i = 0; i < r.mixins.length; i++) {
+      compareTypes(r.mixins[i], o.mixins[i], '$desc mixin ${o.mixins[i].name}');
+    }
+    expect(r.typeParameters.length, o.typeParameters.length,
+        reason: '$desc typeParameters.length');
+    for (int i = 0; i < r.typeParameters.length; i++) {
+      compareTypeParameterElements(r.typeParameters[i], o.typeParameters[i],
+          '$desc type parameter ${o.typeParameters[i].name}');
+    }
+    expect(r.constructors.length, o.constructors.length,
+        reason: '$desc constructors.length');
+    for (int i = 0; i < r.constructors.length; i++) {
+      compareConstructorElements(r.constructors[i], o.constructors[i],
+          '$desc constructor ${o.constructors[i].name}');
+    }
+    expect(r.accessors.length, o.accessors.length,
+        reason: '$desc accessors.length');
+    List<PropertyAccessorElement> rAccessors = _getSortedPropertyAccessors(r);
+    List<PropertyAccessorElement> oAccessors = _getSortedPropertyAccessors(o);
+    for (int i = 0; i < r.accessors.length; i++) {
+      comparePropertyAccessorElements(
+          rAccessors[i], oAccessors[i], '$desc accessor ${oAccessors[i].name}');
+    }
+    expect(r.methods.length, o.methods.length, reason: '$desc methods.length');
+    for (int i = 0; i < r.methods.length; i++) {
+      compareMethodElements(
+          r.methods[i], o.methods[i], '$desc.${o.methods[i].name}');
+    }
+    compareTypes(r.type, o.type, desc);
+    if (r is ClassElementImpl && o is ClassElementImpl) {
+      expect(r.hasBeenInferred, o.hasBeenInferred, reason: desc);
+    }
+  }
+
+  void compareCompilationUnitElements(CompilationUnitElementImpl resynthesized,
+      CompilationUnitElementImpl original) {
+    String desc = 'Compilation unit ${original.source.uri}';
+    expect(resynthesized.source, original.source);
+    expect(resynthesized.librarySource, original.librarySource);
+    compareLineInfo(resynthesized.lineInfo, original.lineInfo);
+
+    expect(resynthesized.types.length, original.types.length,
+        reason: '$desc.types.length');
+    for (int i = 0; i < resynthesized.types.length; i++) {
+      compareClassElements(
+          resynthesized.types[i], original.types[i], original.types[i].name);
+    }
+
+    // TODO(scheglov) Uncomment once the tasks based implementation is ready.
+//    expect(resynthesized.mixins.length, original.mixins.length,
+//        reason: '$desc.mixins.length');
+//    for (int i = 0; i < resynthesized.mixins.length; i++) {
+//      compareClassElements(
+//          resynthesized.mixins[i], original.mixins[i], original.mixins[i].name);
+//    }
+
+    expect(resynthesized.topLevelVariables.length,
+        original.topLevelVariables.length,
+        reason: '$desc.topLevelVariables.length');
+    for (int i = 0; i < resynthesized.topLevelVariables.length; i++) {
+      String name = resynthesized.topLevelVariables[i].name;
+      compareTopLevelVariableElements(
+          resynthesized.topLevelVariables[i],
+          original.topLevelVariables
+              .singleWhere((TopLevelVariableElement e) => e.name == name),
+          '$desc.topLevelVariables[$name]');
+    }
+    expect(resynthesized.functions.length, original.functions.length,
+        reason: '$desc.functions.length');
+    for (int i = 0; i < resynthesized.functions.length; i++) {
+      compareFunctionElements(resynthesized.functions[i], original.functions[i],
+          '$desc.functions[$i] /* ${original.functions[i].name} */');
+    }
+    expect(resynthesized.functionTypeAliases.length,
+        original.functionTypeAliases.length,
+        reason: '$desc.functionTypeAliases.length');
+    for (int i = 0; i < resynthesized.functionTypeAliases.length; i++) {
+      compareFunctionTypeAliasElements(
+          resynthesized.functionTypeAliases[i],
+          original.functionTypeAliases[i],
+          original.functionTypeAliases[i].name);
+    }
+    expect(resynthesized.enums.length, original.enums.length,
+        reason: '$desc.enums.length');
+    for (int i = 0; i < resynthesized.enums.length; i++) {
+      compareClassElements(
+          resynthesized.enums[i], original.enums[i], original.enums[i].name);
+    }
+    expect(resynthesized.accessors.length, original.accessors.length,
+        reason: '$desc.accessors.length');
+    for (int i = 0; i < resynthesized.accessors.length; i++) {
+      String name = resynthesized.accessors[i].name;
+      if (original.accessors[i].isGetter) {
+        comparePropertyAccessorElements(
+            resynthesized.accessors[i],
+            original.accessors
+                .singleWhere((PropertyAccessorElement e) => e.name == name),
+            '$desc.accessors[$i] /* getter $name */');
+      } else {
+        comparePropertyAccessorElements(
+            resynthesized.accessors[i],
+            original.accessors
+                .singleWhere((PropertyAccessorElement e) => e.name == name),
+            '$desc.accessors[$i] /* setter $name */');
+      }
+    }
+    // Note: no need to test CompilationUnitElementImpl._offsetToElementMap
+    // since it is built on demand when needed (see
+    // CompilationUnitElementImpl.getElementAt])
+  }
+
+  void compareConstAstLists(
+      List<Object> rItems, List<Object> oItems, String desc) {
+    if (rItems == null && oItems == null) {
+      return;
+    }
+    expect(rItems != null && oItems != null, isTrue);
+    expect(rItems, hasLength(oItems.length));
+    for (int i = 0; i < oItems.length; i++) {
+      Object rItem = rItems[i];
+      Object oItem = oItems[i];
+      if (rItem is Expression && oItem is Expression) {
+        compareConstAsts(rItem, oItem, desc);
+      } else if (rItem is TypeName && oItem is TypeName) {
+        compareConstAsts(rItem.name, oItem.name, desc);
+      } else if (rItem is InterpolationString && oItem is InterpolationString) {
+        expect(rItem.value, oItem.value);
+      } else if (rItem is InterpolationExpression &&
+          oItem is InterpolationExpression) {
+        compareConstAsts(rItem.expression, oItem.expression, desc);
+      } else if (rItem is MapLiteralEntry && oItem is MapLiteralEntry) {
+        compareConstAsts(rItem.key, oItem.key, desc);
+        compareConstAsts(rItem.value, oItem.value, desc);
+      } else if (oItem is ConstructorFieldInitializer &&
+          rItem is ConstructorFieldInitializer) {
+        compareConstAsts(rItem.fieldName, oItem.fieldName, desc);
+        if (variablesWithNotConstInitializers.contains(rItem.fieldName.name)) {
+          expect(rItem.expression, isNull, reason: desc);
+        } else {
+          compareConstAsts(rItem.expression, oItem.expression, desc);
+        }
+      } else if (oItem is AssertInitializer && rItem is AssertInitializer) {
+        compareConstAsts(rItem.condition, oItem.condition, '$desc condition');
+        compareConstAsts(rItem.message, oItem.message, '$desc message');
+      } else if (oItem is SuperConstructorInvocation &&
+          rItem is SuperConstructorInvocation) {
+        compareElements(rItem.staticElement, oItem.staticElement, desc);
+        compareConstAsts(rItem.constructorName, oItem.constructorName, desc);
+        compareConstAstLists(
+            rItem.argumentList.arguments, oItem.argumentList.arguments, desc);
+      } else if (oItem is RedirectingConstructorInvocation &&
+          rItem is RedirectingConstructorInvocation) {
+        compareElements(rItem.staticElement, oItem.staticElement, desc);
+        compareConstAsts(rItem.constructorName, oItem.constructorName, desc);
+        compareConstAstLists(
+            rItem.argumentList.arguments, oItem.argumentList.arguments, desc);
+      } else {
+        fail('$desc Incompatible item types: '
+            '${rItem.runtimeType} vs. ${oItem.runtimeType}');
+      }
+    }
+  }
+
+  void compareConstAsts(AstNode r, AstNode o, String desc) {
+    if (o == null) {
+      expect(r, isNull, reason: desc);
+    } else {
+      expect(r, isNotNull, reason: desc);
+      // ConstantAstCloner does not copy static types, and constant values
+      // computer does not use static types. So, we don't set them during
+      // resynthesis and should not check them here.
+      if (o is ParenthesizedExpression) {
+        // We don't resynthesize parenthesis, so just ignore it.
+        compareConstAsts(r, o.expression, desc);
+      } else if (o is SimpleIdentifier && r is SimpleIdentifier) {
+        expect(r.name, o.name, reason: desc);
+        if (namesThatCannotBeResolved.contains(r.name)) {
+          expect(r.staticElement, isNull);
+        } else {
+          compareElements(r.staticElement, o.staticElement, desc);
+        }
+      } else if (o is PrefixedIdentifier && r is SimpleIdentifier) {
+        // We don't resynthesize prefixed identifiers when the prefix refers to
+        // a PrefixElement or a ClassElement.  We use simple identifiers with
+        // correct elements.
+        if (o.prefix.staticElement is PrefixElement ||
+            o.prefix.staticElement is ClassElement) {
+          compareConstAsts(r, o.identifier, desc);
+        } else {
+          fail('Prefix of type ${o.prefix.staticElement.runtimeType} should not'
+              ' have been elided');
+        }
+      } else if (o is SimpleIdentifier && r is PrefixedIdentifier) {
+        // In 'class C {static const a = 0; static const b = a;}' the reference
+        // to 'a' in 'b' is serialized as a fully qualified 'C.a' reference.
+        if (r.prefix.staticElement is ClassElement) {
+          Element oElement = resolutionMap.staticElementForIdentifier(o);
+          compareElements(
+              r.prefix.staticElement, oElement?.enclosingElement, desc);
+          compareConstAsts(r.identifier, o, desc);
+        } else {
+          fail('Prefix of type ${r.prefix.staticElement.runtimeType} should not'
+              ' have been elided');
+        }
+      } else if (o is PropertyAccess &&
+          o.target is PrefixedIdentifier &&
+          r is PrefixedIdentifier) {
+        // We don't resynthesize prefixed identifiers when the prefix refers to
+        // a PrefixElement or a ClassElement.  Which means that if the original
+        // expression was e.g. `prefix.topLevelVariableName.length`, it will get
+        // resynthesized as `topLevelVariableName.length`
+        PrefixedIdentifier oTarget = o.target;
+        checkElidablePrefix(oTarget.prefix);
+        compareConstAsts(
+            r,
+            AstTestFactory.identifier(oTarget.identifier, o.propertyName),
+            desc);
+      } else if (o is PrefixedIdentifier && r is PrefixedIdentifier) {
+        compareConstAsts(r.prefix, o.prefix, desc);
+        compareConstAsts(r.identifier, o.identifier, desc);
+      } else if (o is PropertyAccess && r is PropertyAccess) {
+        compareConstAsts(r.target, o.target, desc);
+        String oName = o.propertyName.name;
+        String rName = r.propertyName.name;
+        expect(rName, oName, reason: desc);
+        if (oName == 'length') {
+          compareElements(
+              r.propertyName.staticElement, o.propertyName.staticElement, desc);
+        }
+      } else if (o is PropertyAccess &&
+          o.target is PrefixedIdentifier &&
+          r is SimpleIdentifier) {
+        // We don't resynthesize property access when it takes the form
+        // `prefixName.className.staticMember`.  We just resynthesize a
+        // SimpleIdentifier correctly resolved to the static member.
+        PrefixedIdentifier oTarget = o.target;
+        checkElidablePrefix(oTarget.prefix);
+        checkElidablePrefix(oTarget.identifier);
+        compareConstAsts(r, o.propertyName, desc);
+      } else if (o is SuperExpression && r is SuperExpression) {
+        // Nothing to compare.
+      } else if (o is ThisExpression && r is ThisExpression) {
+        // Nothing to compare.
+      } else if (o is NullLiteral) {
+        expect(r, new TypeMatcher<NullLiteral>(), reason: desc);
+      } else if (o is BooleanLiteral && r is BooleanLiteral) {
+        expect(r.value, o.value, reason: desc);
+      } else if (o is IntegerLiteral && r is IntegerLiteral) {
+        expect(r.value ?? 0, o.value ?? 0, reason: desc);
+      } else if (o is IntegerLiteral && r is PrefixExpression) {
+        expect(r.operator.type, TokenType.MINUS);
+        IntegerLiteral ri = r.operand;
+        expect(-ri.value, o.value, reason: desc);
+      } else if (o is DoubleLiteral && r is DoubleLiteral) {
+        if (r.value != null &&
+            r.value.isNaN &&
+            o.value != null &&
+            o.value.isNaN) {
+          // NaN is not comparable.
+        } else {
+          expect(r.value, o.value, reason: desc);
+        }
+      } else if (o is StringInterpolation && r is StringInterpolation) {
+        compareConstAstLists(r.elements, o.elements, desc);
+      } else if (o is StringLiteral && r is StringLiteral) {
+        // We don't keep all the tokens of AdjacentStrings.
+        // So, we can compare only their values.
+        expect(r.stringValue, o.stringValue, reason: desc);
+      } else if (o is SymbolLiteral && r is SymbolLiteral) {
+        // We don't keep all the tokens of symbol literals.
+        // So, we can compare only their values.
+        expect(r.components.map((t) => t.lexeme).join('.'),
+            o.components.map((t) => t.lexeme).join('.'),
+            reason: desc);
+      } else if (o is NamedExpression && r is NamedExpression) {
+        expect(r.name.label.name, o.name.label.name, reason: desc);
+        compareConstAsts(r.expression, o.expression, desc);
+      } else if (o is BinaryExpression && r is BinaryExpression) {
+        expect(r.operator.lexeme, o.operator.lexeme, reason: desc);
+        compareConstAsts(r.leftOperand, o.leftOperand, desc);
+        compareConstAsts(r.rightOperand, o.rightOperand, desc);
+      } else if (o is PrefixExpression && r is PrefixExpression) {
+        expect(r.operator.lexeme, o.operator.lexeme, reason: desc);
+        compareConstAsts(r.operand, o.operand, desc);
+      } else if (o is ConditionalExpression && r is ConditionalExpression) {
+        compareConstAsts(r.condition, o.condition, desc);
+        compareConstAsts(r.thenExpression, o.thenExpression, desc);
+        compareConstAsts(r.elseExpression, o.elseExpression, desc);
+      } else if (o is ListLiteral && r is ListLiteral) {
+        compareConstAstLists(
+            r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
+        compareConstAstLists(r.elements, o.elements, desc);
+      } else if (o is MapLiteral && r is MapLiteral) {
+        compareConstAstLists(
+            r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
+        compareConstAstLists(r.entries, o.entries, desc);
+      } else if (o is MethodInvocation && r is MethodInvocation) {
+        compareConstAsts(r.target, o.target, desc);
+        compareConstAsts(r.methodName, o.methodName, desc);
+        compareConstAstLists(
+            r.typeArguments?.arguments, o.typeArguments?.arguments, desc);
+        compareConstAstLists(
+            r.argumentList?.arguments, o.argumentList?.arguments, desc);
+      } else if (o is InstanceCreationExpression &&
+          r is InstanceCreationExpression) {
+        compareElements(r.staticElement, o.staticElement, desc);
+        ConstructorName oConstructor = o.constructorName;
+        ConstructorName rConstructor = r.constructorName;
+        expect(oConstructor, isNotNull, reason: desc);
+        expect(rConstructor, isNotNull, reason: desc);
+        // Note: just compare rConstructor.staticElement and
+        // oConstructor.staticElement as elements, because we just want to
+        // check that they're pointing to the correct elements; we don't want
+        // to check that their constructor initializers match, because that
+        // could lead to infinite regress.
+        compareElements(
+            rConstructor.staticElement, oConstructor.staticElement, desc);
+        TypeName oType = oConstructor.type;
+        TypeName rType = rConstructor.type;
+        expect(oType, isNotNull, reason: desc);
+        expect(rType, isNotNull, reason: desc);
+        compareConstAsts(rType.name, oType.name, desc);
+        compareConstAsts(rConstructor.name, oConstructor.name, desc);
+        // In strong mode type inference is performed, so that
+        // `C<int> v = new C();` is serialized as `C<int> v = new C<int>();`.
+        // So, if there are not type arguments originally, not need to check.
+        if (oType.typeArguments?.arguments?.isNotEmpty ?? false) {
+          compareConstAstLists(rType.typeArguments?.arguments,
+              oType.typeArguments?.arguments, desc);
+        }
+        compareConstAstLists(
+            r.argumentList.arguments, o.argumentList.arguments, desc);
+      } else if (o is AnnotationImpl && r is AnnotationImpl) {
+        expect(o.atSign.lexeme, r.atSign.lexeme, reason: desc);
+        Identifier rName = r.name;
+        Identifier oName = o.name;
+        if (oName is PrefixedIdentifier &&
+            rName is PrefixedIdentifier &&
+            o.constructorName != null &&
+            o.element != null &&
+            r.constructorName == null) {
+          // E.g. `@prefix.cls.ctor`.  This sometimes gets resynthesized as
+          // `@cls.ctor`, with `cls.ctor` represented as a PrefixedIdentifier.
+          compareConstAsts(rName.prefix, oName.identifier, desc);
+          expect(rName.period.lexeme, '.', reason: desc);
+          compareConstAsts(rName.identifier, o.constructorName, desc);
+          expect(r.period, isNull, reason: desc);
+          expect(r.constructorName, isNull, reason: desc);
+        } else {
+          compareConstAsts(r.name, o.name, desc);
+          expect(r.period?.lexeme, o.period?.lexeme, reason: desc);
+          compareConstAsts(r.constructorName, o.constructorName, desc);
+        }
+        compareConstAstLists(
+            r.arguments?.arguments, o.arguments?.arguments, desc);
+        compareElements(r.element, o.element, desc);
+        // elementAnnotation should be null; it is only used in the full AST.
+        expect(o.elementAnnotation, isNull);
+        expect(r.elementAnnotation, isNull);
+      } else {
+        fail('Not implemented for ${r.runtimeType} vs. ${o.runtimeType}');
+      }
+    }
+  }
+
+  void compareConstructorElements(ConstructorElement resynthesized,
+      ConstructorElement original, String desc) {
+    if (original == null && resynthesized == null) {
+      return;
+    }
+    compareExecutableElements(resynthesized, original, desc);
+    ConstructorElementImpl resynthesizedImpl =
+        getActualElement(resynthesized, desc);
+    ConstructorElementImpl originalImpl = getActualElement(original, desc);
+    if (original.isConst) {
+      compareConstAstLists(resynthesizedImpl.constantInitializers,
+          originalImpl.constantInitializers, desc);
+    }
+    if (original.redirectedConstructor == null) {
+      expect(resynthesized.redirectedConstructor, isNull, reason: desc);
+    } else {
+      compareConstructorElements(resynthesized.redirectedConstructor,
+          original.redirectedConstructor, '$desc redirectedConstructor');
+    }
+    checkPossibleMember(resynthesized, original, desc);
+    expect(resynthesized.nameEnd, original.nameEnd, reason: desc);
+    expect(resynthesized.periodOffset, original.periodOffset, reason: desc);
+    expect(resynthesizedImpl.isCycleFree, originalImpl.isCycleFree,
+        reason: desc);
+  }
+
+  void compareConstValues(
+      DartObject resynthesized, DartObject original, String desc) {
+    if (original == null) {
+      expect(resynthesized, isNull, reason: desc);
+    } else {
+      expect(resynthesized, isNotNull, reason: desc);
+      compareTypes(resynthesized.type, original.type, desc);
+      expect(resynthesized.hasKnownValue, original.hasKnownValue, reason: desc);
+      if (original.isNull) {
+        expect(resynthesized.isNull, isTrue, reason: desc);
+      } else if (original.toBoolValue() != null) {
+        expect(resynthesized.toBoolValue(), original.toBoolValue(),
+            reason: desc);
+      } else if (original.toIntValue() != null) {
+        expect(resynthesized.toIntValue(), original.toIntValue(), reason: desc);
+      } else if (original.toDoubleValue() != null) {
+        expect(resynthesized.toDoubleValue(), original.toDoubleValue(),
+            reason: desc);
+      } else if (original.toListValue() != null) {
+        List<DartObject> resynthesizedList = resynthesized.toListValue();
+        List<DartObject> originalList = original.toListValue();
+        expect(resynthesizedList, hasLength(originalList.length));
+        for (int i = 0; i < originalList.length; i++) {
+          compareConstValues(resynthesizedList[i], originalList[i], desc);
+        }
+      } else if (original.toMapValue() != null) {
+        Map<DartObject, DartObject> resynthesizedMap =
+            resynthesized.toMapValue();
+        Map<DartObject, DartObject> originalMap = original.toMapValue();
+        expect(resynthesizedMap, hasLength(originalMap.length));
+        List<DartObject> resynthesizedKeys = resynthesizedMap.keys.toList();
+        List<DartObject> originalKeys = originalMap.keys.toList();
+        for (int i = 0; i < originalKeys.length; i++) {
+          DartObject resynthesizedKey = resynthesizedKeys[i];
+          DartObject originalKey = originalKeys[i];
+          compareConstValues(resynthesizedKey, originalKey, desc);
+          DartObject resynthesizedValue = resynthesizedMap[resynthesizedKey];
+          DartObject originalValue = originalMap[originalKey];
+          compareConstValues(resynthesizedValue, originalValue, desc);
+        }
+      } else if (original.toStringValue() != null) {
+        expect(resynthesized.toStringValue(), original.toStringValue(),
+            reason: desc);
+      } else if (original.toSymbolValue() != null) {
+        expect(resynthesized.toSymbolValue(), original.toSymbolValue(),
+            reason: desc);
+      } else if (original.toTypeValue() != null) {
+        fail('Not implemented');
+      }
+    }
+  }
+
+  void compareElementAnnotations(ElementAnnotationImpl resynthesized,
+      ElementAnnotationImpl original, String desc) {
+    if (original.element == null) {
+      expect(resynthesized.element, isNull);
+    } else {
+      expect(resynthesized.element, isNotNull, reason: desc);
+      expect(resynthesized.element.kind, original.element.kind, reason: desc);
+      expect(resynthesized.element.location, original.element.location,
+          reason: desc);
+    }
+    expect(resynthesized.compilationUnit, isNotNull, reason: desc);
+    expect(resynthesized.compilationUnit.location,
+        original.compilationUnit.location,
+        reason: desc);
+    expect(resynthesized.annotationAst, isNotNull, reason: desc);
+    compareConstAsts(resynthesized.annotationAst, original.annotationAst, desc);
+  }
+
+  void compareElementLocations(
+      Element resynthesized, Element original, String desc) {
+    bool hasFunctionElementByValue(Element e) {
+      if (e == null) {
+        return false;
+      }
+      if (e is FunctionElementImpl_forLUB) {
+        return true;
+      }
+      return hasFunctionElementByValue(e.enclosingElement);
+    }
+
+    if (hasFunctionElementByValue(resynthesized)) {
+      // We resynthesize elements representing types of local functions
+      // without corresponding name offsets, so their locations don't have
+      // corresponding valid @offset components. Also, we don't put
+      // resynthesized local functions into initializers of variables.
+      return;
+    }
+    expect(resynthesized.location, original.location, reason: desc);
+  }
+
+  void compareElements(Element resynthesized, Element original, String desc) {
+    ElementImpl rImpl = getActualElement(resynthesized, desc);
+    ElementImpl oImpl = getActualElement(original, desc);
+    if (oImpl == null && rImpl == null) {
+      return;
+    }
+    if (oImpl is PrefixElement) {
+      // TODO(scheglov) prefixes cannot be resynthesized
+      return;
+    }
+    expect(original, isNotNull);
+    expect(resynthesized, isNotNull, reason: desc);
+    if (rImpl is DefaultParameterElementImpl && oImpl is ParameterElementImpl) {
+      // This is ok provided the resynthesized parameter element doesn't have
+      // any evaluation result.
+      expect(rImpl.evaluationResult, isNull);
+    } else {
+      Type rRuntimeType;
+      if (rImpl is ConstFieldElementImpl) {
+        rRuntimeType = ConstFieldElementImpl;
+      } else if (rImpl is FunctionElementImpl) {
+        rRuntimeType = FunctionElementImpl;
+      } else {
+        rRuntimeType = rImpl.runtimeType;
+      }
+      expect(rRuntimeType, oImpl.runtimeType);
+    }
+    expect(resynthesized.kind, original.kind);
+    compareElementLocations(resynthesized, original, desc);
+    expect(resynthesized.name, original.name);
+    expect(resynthesized.nameOffset, original.nameOffset,
+        reason: '$desc.nameOffset');
+    expect(rImpl.codeOffset, oImpl.codeOffset, reason: desc);
+    expect(rImpl.codeLength, oImpl.codeLength, reason: desc);
+    expect(resynthesized.documentationComment, original.documentationComment,
+        reason: desc);
+    compareMetadata(resynthesized.metadata, original.metadata, desc);
+
+    // Validate modifiers.
+    for (Modifier modifier in Modifier.values) {
+      bool got = _hasModifier(resynthesized, modifier);
+      bool want = _hasModifier(original, modifier);
+      expect(got, want,
+          reason: 'Mismatch in $desc.$modifier: got $got, want $want');
+    }
+
+    // Validate members.
+    if (oImpl is Member) {
+      expect(rImpl, new TypeMatcher<Member>(), reason: desc);
+    } else {
+      expect(rImpl, isNot(new TypeMatcher<Member>()), reason: desc);
+    }
+  }
+
+  void compareExecutableElements(
+      ExecutableElement resynthesized, ExecutableElement original, String desc,
+      {bool shallow: false}) {
+    compareElements(resynthesized, original, desc);
+    compareParameterElementLists(
+        resynthesized.parameters, original.parameters, desc);
+    if (!original.hasImplicitReturnType) {
+      compareTypes(
+          resynthesized.returnType, original.returnType, '$desc return type');
+    }
+    if (!shallow) {
+      compareTypes(resynthesized.type, original.type, desc);
+    }
+    expect(resynthesized.typeParameters.length, original.typeParameters.length);
+    for (int i = 0; i < resynthesized.typeParameters.length; i++) {
+      compareTypeParameterElements(
+          resynthesized.typeParameters[i],
+          original.typeParameters[i],
+          '$desc type parameter ${original.typeParameters[i].name}');
+    }
+  }
+
+  void compareExportElements(ExportElementImpl resynthesized,
+      ExportElementImpl original, String desc) {
+    expect(resynthesized.exportedLibrary.location,
+        original.exportedLibrary.location);
+    expect(resynthesized.combinators.length, original.combinators.length);
+    for (int i = 0; i < resynthesized.combinators.length; i++) {
+      compareNamespaceCombinators(
+          resynthesized.combinators[i], original.combinators[i]);
+    }
+  }
+
+  void compareFieldElements(
+      FieldElementImpl resynthesized, FieldElementImpl original, String desc) {
+    comparePropertyInducingElements(resynthesized, original, desc);
+  }
+
+  void compareFunctionElements(
+      FunctionElement resynthesized, FunctionElement original, String desc,
+      {bool shallow: false}) {
+    if (original == null && resynthesized == null) {
+      return;
+    }
+    expect(resynthesized, isNotNull, reason: desc);
+    compareExecutableElements(resynthesized, original, desc, shallow: shallow);
+    checkPossibleLocalElements(resynthesized, original);
+  }
+
+  void compareFunctionTypeAliasElements(FunctionTypeAliasElement resynthesized,
+      FunctionTypeAliasElement original, String desc) {
+    compareElements(resynthesized, original, desc);
+    ElementImpl rImpl = getActualElement(resynthesized, desc);
+    ElementImpl oImpl = getActualElement(original, desc);
+    if (rImpl is GenericTypeAliasElementImpl) {
+      if (oImpl is GenericTypeAliasElementImpl) {
+        compareGenericFunctionTypeElements(
+            rImpl.function, oImpl.function, '$desc.function');
+      } else {
+        fail(
+            'Resynthesized a GenericTypeAliasElementImpl, but expected a ${oImpl.runtimeType}');
+      }
+    } else {
+      fail('Resynthesized a ${rImpl.runtimeType}');
+    }
+    compareTypes(resynthesized.type, original.type, desc);
+    expect(resynthesized.typeParameters.length, original.typeParameters.length);
+    for (int i = 0; i < resynthesized.typeParameters.length; i++) {
+      compareTypeParameterElements(
+          resynthesized.typeParameters[i],
+          original.typeParameters[i],
+          '$desc.typeParameters[$i] /* ${original.typeParameters[i].name} */');
+    }
+  }
+
+  void compareGenericFunctionTypeElements(
+      GenericFunctionTypeElement resynthesized,
+      GenericFunctionTypeElement original,
+      String desc) {
+    if (resynthesized == null) {
+      if (original != null) {
+        fail('Failed to resynthesize generic function type');
+      }
+    } else if (original == null) {
+      fail('Resynthesizes a generic function type when none expected');
+    }
+    compareTypeParameterElementLists(resynthesized.typeParameters,
+        original.typeParameters, '$desc.typeParameters');
+    compareParameterElementLists(
+        resynthesized.parameters, original.parameters, '$desc.parameters');
+    compareTypes(
+        resynthesized.returnType, original.returnType, '$desc.returnType');
+  }
+
+  void compareImportElements(ImportElementImpl resynthesized,
+      ImportElementImpl original, String desc) {
+    expect(resynthesized.importedLibrary.location,
+        original.importedLibrary.location,
+        reason: '$desc importedLibrary location');
+    expect(resynthesized.prefixOffset, original.prefixOffset,
+        reason: '$desc prefixOffset');
+    if (original.prefix == null) {
+      expect(resynthesized.prefix, isNull, reason: '$desc prefix');
+    } else {
+      comparePrefixElements(
+          resynthesized.prefix, original.prefix, original.prefix.name);
+    }
+    expect(resynthesized.combinators.length, original.combinators.length,
+        reason: '$desc combinators');
+    for (int i = 0; i < resynthesized.combinators.length; i++) {
+      compareNamespaceCombinators(
+          resynthesized.combinators[i], original.combinators[i]);
+    }
+  }
+
+  void compareLabelElements(
+      LabelElementImpl resynthesized, LabelElementImpl original, String desc) {
+    expect(resynthesized.isOnSwitchMember, original.isOnSwitchMember,
+        reason: desc);
+    expect(resynthesized.isOnSwitchStatement, original.isOnSwitchStatement,
+        reason: desc);
+    compareElements(resynthesized, original, desc);
+  }
+
+  void compareLineInfo(LineInfo resynthesized, LineInfo original) {
+    expect(resynthesized.lineCount, original.lineCount);
+    expect(resynthesized.lineStarts, original.lineStarts);
+  }
+
+  void compareMetadata(List<ElementAnnotation> resynthesized,
+      List<ElementAnnotation> original, String desc) {
+    expect(resynthesized, hasLength(original.length), reason: desc);
+    for (int i = 0; i < original.length; i++) {
+      compareElementAnnotations(
+          resynthesized[i], original[i], '$desc annotation $i');
+    }
+  }
+
+  void compareMethodElements(MethodElementImpl resynthesized,
+      MethodElementImpl original, String desc) {
+    // TODO(paulberry): do we need to deal with
+    // MultiplyInheritedMethodElementImpl?
+    compareExecutableElements(resynthesized, original, desc);
+  }
+
+  void compareNamespaceCombinators(
+      NamespaceCombinator resynthesized, NamespaceCombinator original) {
+    if (original is ShowElementCombinatorImpl &&
+        resynthesized is ShowElementCombinatorImpl) {
+      expect(resynthesized.shownNames, original.shownNames,
+          reason: 'shownNames');
+      expect(resynthesized.offset, original.offset, reason: 'offset');
+      expect(resynthesized.end, original.end, reason: 'end');
+    } else if (original is HideElementCombinatorImpl &&
+        resynthesized is HideElementCombinatorImpl) {
+      expect(resynthesized.hiddenNames, original.hiddenNames,
+          reason: 'hiddenNames');
+    } else if (resynthesized.runtimeType != original.runtimeType) {
+      fail(
+          'Type mismatch: expected ${original.runtimeType}, got ${resynthesized.runtimeType}');
+    } else {
+      fail('Unimplemented comparison for ${original.runtimeType}');
+    }
+  }
+
+  void compareNamespaces(
+      Namespace resynthesized, Namespace original, String desc) {
+    Map<String, Element> resynthesizedMap = resynthesized.definedNames;
+    Map<String, Element> originalMap = original.definedNames;
+    expect(resynthesizedMap.keys.toSet(), originalMap.keys.toSet(),
+        reason: desc);
+    for (String key in originalMap.keys) {
+      Element resynthesizedElement = resynthesizedMap[key];
+      Element originalElement = originalMap[key];
+      compareElements(resynthesizedElement, originalElement, key);
+    }
+  }
+
+  void compareParameterElementLists(
+      List<ParameterElement> resynthesizedParameters,
+      List<ParameterElement> originalParameters,
+      String desc) {
+    expect(resynthesizedParameters.length, originalParameters.length);
+    for (int i = 0; i < resynthesizedParameters.length; i++) {
+      compareParameterElements(
+          resynthesizedParameters[i],
+          originalParameters[i],
+          '$desc.parameters[$i] /* ${originalParameters[i].name} */');
+    }
+  }
+
+  void compareParameterElements(
+      ParameterElement resynthesized, ParameterElement original, String desc) {
+    compareVariableElements(resynthesized, original, desc);
+    compareParameterElementLists(
+        resynthesized.parameters, original.parameters, desc);
+    // ignore: deprecated_member_use
+    expect(resynthesized.parameterKind, original.parameterKind, reason: desc);
+    expect(resynthesized.isInitializingFormal, original.isInitializingFormal,
+        reason: desc);
+    expect(resynthesized is FieldFormalParameterElementImpl,
+        original is FieldFormalParameterElementImpl);
+    if (resynthesized is FieldFormalParameterElementImpl &&
+        original is FieldFormalParameterElementImpl) {
+      if (original.field == null) {
+        expect(resynthesized.field, isNull, reason: '$desc field');
+      } else {
+        expect(resynthesized.field, isNotNull, reason: '$desc field');
+        compareFieldElements(
+            resynthesized.field, original.field, '$desc field');
+      }
+    }
+    expect(resynthesized.defaultValueCode, original.defaultValueCode,
+        reason: desc);
+    expect(resynthesized.isCovariant, original.isCovariant,
+        reason: '$desc isCovariant');
+    ParameterElementImpl resynthesizedActual =
+        getActualElement(resynthesized, desc);
+    ParameterElementImpl originalActual = getActualElement(original, desc);
+    expect(resynthesizedActual.isExplicitlyCovariant,
+        originalActual.isExplicitlyCovariant,
+        reason: desc);
+    compareFunctionElements(
+        resynthesizedActual.initializer, originalActual.initializer, desc);
+  }
+
+  void comparePrefixElements(PrefixElementImpl resynthesized,
+      PrefixElementImpl original, String desc) {
+    compareElements(resynthesized, original, desc);
+  }
+
+  void comparePropertyAccessorElements(
+      PropertyAccessorElementImpl resynthesized,
+      PropertyAccessorElementImpl original,
+      String desc) {
+    // TODO(paulberry): do I need to worry about
+    // MultiplyInheritedPropertyAccessorElementImpl?
+    compareExecutableElements(resynthesized, original, desc);
+    expect(resynthesized.variable, isNotNull);
+    expect(resynthesized.variable.location, original.variable.location);
+  }
+
+  void comparePropertyInducingElements(
+      PropertyInducingElementImpl resynthesized,
+      PropertyInducingElementImpl original,
+      String desc) {
+    compareVariableElements(resynthesized, original, desc);
+    if (original.getter == null) {
+      expect(resynthesized.getter, isNull);
+    } else {
+      expect(resynthesized.getter, isNotNull);
+      expect(resynthesized.getter.location, original.getter.location);
+    }
+    if (original.setter == null) {
+      expect(resynthesized.setter, isNull);
+    } else {
+      expect(resynthesized.setter, isNotNull);
+      expect(resynthesized.setter.location, original.setter.location);
+    }
+  }
+
+  void compareTopLevelVariableElements(
+      TopLevelVariableElementImpl resynthesized,
+      TopLevelVariableElementImpl original,
+      String desc) {
+    comparePropertyInducingElements(resynthesized, original, desc);
+  }
+
+  void compareTypeImpls(
+      TypeImpl resynthesized, TypeImpl original, String desc) {
+    compareElementLocations(
+        resynthesized.element, original.element, '$desc.element.location');
+    expect(resynthesized.name, original.name, reason: '$desc.name');
+  }
+
+  void compareTypeParameterElementLists(
+      List<TypeParameterElement> resynthesized,
+      List<TypeParameterElement> original,
+      String desc) {
+    int length = original.length;
+    expect(resynthesized.length, length, reason: '$desc.length');
+    for (int i = 0; i < length; i++) {
+      compareTypeParameterElements(resynthesized[i], original[i], '$desc[$i]');
+    }
+  }
+
+  void compareTypeParameterElements(TypeParameterElement resynthesized,
+      TypeParameterElement original, String desc) {
+    compareElements(resynthesized, original, desc);
+    compareTypes(resynthesized.type, original.type, '$desc.type');
+    compareTypes(resynthesized.bound, original.bound, '$desc.bound');
+  }
+
+  void compareTypes(DartType resynthesized, DartType original, String desc) {
+    if (original == null) {
+      expect(resynthesized, isNull, reason: desc);
+    } else if (resynthesized is InterfaceTypeImpl &&
+        original is InterfaceTypeImpl) {
+      compareTypeImpls(resynthesized, original, desc);
+      expect(resynthesized.typeArguments.length, original.typeArguments.length,
+          reason: '$desc.typeArguments.length');
+      for (int i = 0; i < resynthesized.typeArguments.length; i++) {
+        compareTypes(resynthesized.typeArguments[i], original.typeArguments[i],
+            '$desc.typeArguments[$i] /* ${original.typeArguments[i].name} */');
+      }
+    } else if (resynthesized is TypeParameterTypeImpl &&
+        original is TypeParameterTypeImpl) {
+      compareTypeImpls(resynthesized, original, desc);
+    } else if (resynthesized is DynamicTypeImpl &&
+        original is DynamicTypeImpl) {
+      expect(resynthesized, same(original));
+    } else if (resynthesized is UndefinedTypeImpl &&
+        original is UndefinedTypeImpl) {
+      expect(resynthesized, same(original));
+    } else if (resynthesized is FunctionTypeImpl &&
+        original is FunctionTypeImpl) {
+      compareTypeImpls(resynthesized, original, desc);
+      expect(resynthesized.isInstantiated, original.isInstantiated,
+          reason: desc);
+      if (original.element.enclosingElement == null &&
+          original.element is FunctionElement) {
+        expect(resynthesized.element, new TypeMatcher<FunctionElement>());
+        expect(resynthesized.element.enclosingElement, isNull, reason: desc);
+        compareFunctionElements(
+            resynthesized.element, original.element, '$desc.element',
+            shallow: true);
+        expect(resynthesized.element.type, same(resynthesized));
+      }
+      expect(resynthesized.typeArguments.length, original.typeArguments.length,
+          reason: '$desc.typeArguments.length');
+      for (int i = 0; i < resynthesized.typeArguments.length; i++) {
+        if (resynthesized.typeArguments[i].isDynamic &&
+            original.typeArguments[i] is TypeParameterType) {
+          // It's ok for type arguments to get converted to `dynamic` if they
+          // are not used.
+          expect(
+              isTypeParameterUsed(
+                  original.typeArguments[i], original.element.type),
+              isFalse);
+        } else {
+          compareTypes(
+              resynthesized.typeArguments[i],
+              original.typeArguments[i],
+              '$desc.typeArguments[$i] /* ${original.typeArguments[i].name} */');
+        }
+      }
+      if (original.typeParameters == null) {
+        expect(resynthesized.typeParameters, isNull, reason: desc);
+      } else {
+        expect(resynthesized.typeParameters, isNotNull, reason: desc);
+        expect(
+            resynthesized.typeParameters.length, original.typeParameters.length,
+            reason: desc);
+        for (int i = 0; i < resynthesized.typeParameters.length; i++) {
+          compareTypeParameterElements(resynthesized.typeParameters[i],
+              original.typeParameters[i], '$desc.typeParameters[$i]');
+        }
+      }
+      expect(resynthesized.typeFormals.length, original.typeFormals.length,
+          reason: desc);
+      for (int i = 0; i < resynthesized.typeFormals.length; i++) {
+        compareTypeParameterElements(resynthesized.typeFormals[i],
+            original.typeFormals[i], '$desc.typeFormals[$i]');
+      }
+    } else if (resynthesized is VoidTypeImpl && original is VoidTypeImpl) {
+      expect(resynthesized, same(original));
+    } else if (resynthesized is DynamicTypeImpl &&
+        original is UndefinedTypeImpl) {
+      // TODO(scheglov) In the strong mode constant variable like
+      //  `var V = new Unresolved()` gets `UndefinedTypeImpl`, and it gets
+      // `DynamicTypeImpl` in the spec mode.
+    } else if (resynthesized is BottomTypeImpl && original is BottomTypeImpl) {
+      expect(resynthesized, same(original));
+    } else if (resynthesized.runtimeType != original.runtimeType) {
+      fail('Type mismatch: expected $original,'
+          ' got $resynthesized ($desc)');
+    } else {
+      fail('Unimplemented comparison for ${original.runtimeType}');
+    }
+  }
+
+  void compareVariableElements(
+      VariableElement resynthesized, VariableElement original, String desc) {
+    compareElements(resynthesized, original, desc);
+    if ((resynthesized as VariableElementImpl).typeInferenceError == null) {
+      compareTypes(resynthesized.type, original.type, '$desc.type');
+    }
+    VariableElementImpl resynthesizedActual =
+        getActualElement(resynthesized, desc);
+    VariableElementImpl originalActual = getActualElement(original, desc);
+    compareFunctionElements(resynthesizedActual.initializer,
+        originalActual.initializer, '$desc.initializer');
+    if (originalActual is ConstVariableElement) {
+      Element oEnclosing = original.enclosingElement;
+      if (oEnclosing is ClassElement && oEnclosing.isEnum) {
+        compareConstValues(resynthesized.constantValue, original.constantValue,
+            '$desc.constantValue');
+      } else {
+        Expression initializer = resynthesizedActual.constantInitializer;
+        if (variablesWithNotConstInitializers.contains(resynthesized.name)) {
+          expect(initializer, isNull, reason: desc);
+        } else {
+          compareConstAsts(initializer, originalActual.constantInitializer,
+              '$desc.constantInitializer');
+        }
+      }
+    }
+    checkPossibleMember(resynthesized, original, desc);
+    checkPossibleLocalElements(resynthesized, original);
+  }
+
+  ElementImpl getActualElement(Element element, String desc) {
+    if (element == null) {
+      return null;
+    } else if (element is ElementImpl) {
+      return element;
+    } else if (element is ElementHandle) {
+      Element actualElement = element.actualElement;
+      // A handle should never point to a member, because if it did, then
+      // "is Member" checks on the handle would produce the wrong result.
+      expect(actualElement, isNot(new TypeMatcher<Member>()), reason: desc);
+      return getActualElement(actualElement, desc);
+    } else if (element is Member) {
+      return getActualElement(element.baseElement, desc);
+    } else {
+      fail('Unexpected type for resynthesized ($desc):'
+          ' ${element.runtimeType}');
+    }
+  }
+
+  /**
+   * Determine if [type] makes use of the given [typeParameter].
+   */
+  bool isTypeParameterUsed(TypeParameterType typeParameter, DartType type) {
+    if (type is FunctionType) {
+      return isTypeParameterUsed(typeParameter, type.returnType) ||
+          type.parameters.any((ParameterElement e) =>
+              isTypeParameterUsed(typeParameter, e.type));
+    } else if (type is InterfaceType) {
+      return type.typeArguments
+          .any((DartType t) => isTypeParameterUsed(typeParameter, t));
+    } else if (type is TypeParameterType) {
+      return type == typeParameter;
+    } else {
+      expect(type.isDynamic || type.isVoid, isTrue);
+      return false;
+    }
+  }
+
+  LibraryElementImpl _encodeDecodeLibraryElement(Source source) {
+    SummaryResynthesizer resynthesizer = encodeLibrary(source);
+    return resynthesizer.getLibraryElement(source.uri.toString());
+  }
+
+  List<PropertyAccessorElement> _getSortedPropertyAccessors(
+      ClassElement classElement) {
+    List<PropertyAccessorElement> accessors = classElement.accessors.toList();
+    accessors.sort((a, b) => a.displayName.compareTo(b.displayName));
+    return accessors;
+  }
+
+  bool _hasModifier(Element element, Modifier modifier) {
+    if (modifier == Modifier.ABSTRACT) {
+      if (element is ClassElement) {
+        return element.isAbstract;
+      }
+      if (element is ExecutableElement) {
+        return element.isAbstract;
+      }
+      return false;
+    } else if (modifier == Modifier.ASYNCHRONOUS) {
+      if (element is ExecutableElement) {
+        return element.isAsynchronous;
+      }
+      return false;
+    } else if (modifier == Modifier.CONST) {
+      if (element is VariableElement) {
+        return element.isConst;
+      }
+      return false;
+    } else if (modifier == Modifier.COVARIANT) {
+      if (element is ParameterElementImpl) {
+        return element.isExplicitlyCovariant;
+      }
+      return false;
+    } else if (modifier == Modifier.DEFERRED) {
+      if (element is ImportElement) {
+        return element.isDeferred;
+      }
+      return false;
+    } else if (modifier == Modifier.ENUM) {
+      if (element is ClassElement) {
+        return element.isEnum;
+      }
+      return false;
+    } else if (modifier == Modifier.EXTERNAL) {
+      if (element is ExecutableElement) {
+        return element.isExternal;
+      }
+      return false;
+    } else if (modifier == Modifier.FACTORY) {
+      if (element is ConstructorElement) {
+        return element.isFactory;
+      }
+      return false;
+    } else if (modifier == Modifier.FINAL) {
+      if (element is VariableElement) {
+        return element.isFinal;
+      }
+      return false;
+    } else if (modifier == Modifier.GENERATOR) {
+      if (element is ExecutableElement) {
+        return element.isGenerator;
+      }
+      return false;
+    } else if (modifier == Modifier.GETTER) {
+      if (element is PropertyAccessorElement) {
+        return element.isGetter;
+      }
+      return false;
+    } else if (modifier == Modifier.HAS_EXT_URI) {
+      if (element is LibraryElement) {
+        return element.hasExtUri;
+      }
+      return false;
+    } else if (modifier == Modifier.IMPLICIT_TYPE) {
+      if (element is ExecutableElement) {
+        return element.hasImplicitReturnType;
+      }
+      return false;
+    } else if (modifier == Modifier.MIXIN_APPLICATION) {
+      if (element is ClassElement) {
+        return element.isMixinApplication;
+      }
+      return false;
+    } else if (modifier == Modifier.REFERENCES_SUPER) {
+      if (element is ClassElement) {
+        return element.hasReferenceToSuper;
+      }
+      return false;
+    } else if (modifier == Modifier.SETTER) {
+      if (element is PropertyAccessorElement) {
+        return element.isSetter;
+      }
+      return false;
+    } else if (modifier == Modifier.STATIC) {
+      if (element is ExecutableElement) {
+        return element.isStatic;
+      } else if (element is FieldElement) {
+        return element.isStatic;
+      }
+      return false;
+    } else if (modifier == Modifier.SYNTHETIC) {
+      return element.isSynthetic;
+    }
+    throw new UnimplementedError(
+        'Modifier $modifier for ${element?.runtimeType}');
+  }
 }
 
 class TestSummaryResynthesizer extends SummaryResynthesizer {
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index 817e326..8a5da25 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -4,9 +4,13 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -18,10 +22,13 @@
 import 'package:analyzer/src/summary/prelink.dart';
 import 'package:analyzer/src/summary/summarize_ast.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:analyzer/src/task/api/dart.dart';
+import 'package:analyzer/src/task/api/general.dart';
 import 'package:path/path.dart' show posix;
 import 'package:test/test.dart';
 
 import '../context/mock_sdk.dart';
+import 'resynthesize_common.dart';
 
 /// Convert the given Posix style file [path] to the corresponding absolute URI.
 String absUri(String path) {
@@ -75,6 +82,164 @@
   }
 }
 
+/// Abstract base class for tests of summary resynthesis.
+///
+/// Test classes should not extend this class directly; they should extend a
+/// class that implements this class with methods that drive summary generation.
+/// The tests themselves can then be provided via mixin, allowing summaries to
+/// be tested in a variety of ways.
+abstract class ResynthesizeTestStrategy {
+  //Future<LibraryElementImpl> checkLibrary(String text,
+  //    {bool allowErrors: false, bool dumpSummaries: false});
+
+  void set allowMissingFiles(bool value);
+
+  AnalysisContextImpl get context;
+
+  MemoryResourceProvider get resourceProvider;
+
+  void set testFile(String value);
+
+  Source get testSource;
+
+  void addLibrary(String uri);
+
+  Source addLibrarySource(String filePath, String contents);
+
+  Source addSource(String path, String contents);
+
+  Source addTestSource(String code, [Uri uri]);
+
+  void checkMinimalResynthesisWork(
+      TestSummaryResynthesizer resynthesizer, LibraryElement library);
+
+  TestSummaryResynthesizer encodeLibrary(Source source);
+
+  void prepareAnalysisContext([AnalysisOptions options]);
+}
+
+/// Implementation of [SummaryBlackBoxTestStrategy] that drives summary
+/// generation using the old two-phase API.
+class ResynthesizeTestStrategyTwoPhase extends AbstractResynthesizeTest
+    implements ResynthesizeTestStrategy {
+  final Set<Source> serializedSources = new Set<Source>();
+
+  final Map<String, UnlinkedUnitBuilder> uriToUnit =
+      <String, UnlinkedUnitBuilder>{};
+
+  PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
+
+  TestSummaryResynthesizer encodeLibrary(Source source) {
+    _serializeLibrary(source);
+
+    PackageBundle bundle =
+        new PackageBundle.fromBuffer(bundleAssembler.assemble().toBuffer());
+
+    Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
+    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
+      String uri = bundle.unlinkedUnitUris[i];
+      unlinkedSummaries[uri] = bundle.unlinkedUnits[i];
+    }
+
+    LinkedLibrary getDependency(String absoluteUri) {
+      Map<String, LinkedLibrary> sdkLibraries =
+          SerializedMockSdk.instance.uriToLinkedLibrary;
+      LinkedLibrary linkedLibrary = sdkLibraries[absoluteUri];
+      if (linkedLibrary == null && !allowMissingFiles) {
+        fail('Linker unexpectedly requested LinkedLibrary for "$absoluteUri".'
+            '  Libraries available: ${sdkLibraries.keys}');
+      }
+      return linkedLibrary;
+    }
+
+    UnlinkedUnit getUnit(String absoluteUri) {
+      UnlinkedUnit unit = uriToUnit[absoluteUri] ??
+          SerializedMockSdk.instance.uriToUnlinkedUnit[absoluteUri];
+      if (unit == null && !allowMissingFiles) {
+        fail('Linker unexpectedly requested unit for "$absoluteUri".');
+      }
+      return unit;
+    }
+
+    Set<String> nonSdkLibraryUris = serializedSources
+        .where((Source source) =>
+            !source.isInSystemLibrary &&
+            context.computeKindOf(source) == SourceKind.LIBRARY)
+        .map((Source source) => source.uri.toString())
+        .toSet();
+
+    Map<String, LinkedLibrary> linkedSummaries = link(nonSdkLibraryUris,
+        getDependency, getUnit, context.declaredVariables.get);
+
+    return new TestSummaryResynthesizer(
+        context,
+        new Map<String, UnlinkedUnit>()
+          ..addAll(SerializedMockSdk.instance.uriToUnlinkedUnit)
+          ..addAll(unlinkedSummaries),
+        new Map<String, LinkedLibrary>()
+          ..addAll(SerializedMockSdk.instance.uriToLinkedLibrary)
+          ..addAll(linkedSummaries),
+        allowMissingFiles);
+  }
+
+  UnlinkedUnit _getUnlinkedUnit(Source source) {
+    if (source == null) {
+      return new UnlinkedUnitBuilder();
+    }
+
+    String uriStr = source.uri.toString();
+    {
+      UnlinkedUnit unlinkedUnitInSdk =
+          SerializedMockSdk.instance.uriToUnlinkedUnit[uriStr];
+      if (unlinkedUnitInSdk != null) {
+        return unlinkedUnitInSdk;
+      }
+    }
+    return uriToUnit.putIfAbsent(uriStr, () {
+      int modificationTime = context.computeResult(source, MODIFICATION_TIME);
+      if (modificationTime < 0) {
+        // Source does not exist.
+        if (!allowMissingFiles) {
+          fail('Unexpectedly tried to get unlinked summary for $source');
+        }
+        return null;
+      }
+      CompilationUnit unit = context.computeResult(source, PARSED_UNIT);
+      UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
+      bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
+      return unlinkedUnit;
+    });
+  }
+
+  void _serializeLibrary(Source librarySource) {
+    if (librarySource == null || librarySource.isInSystemLibrary) {
+      return;
+    }
+    if (!serializedSources.add(librarySource)) {
+      return;
+    }
+
+    UnlinkedUnit getPart(String absoluteUri) {
+      Source source = context.sourceFactory.forUri(absoluteUri);
+      return _getUnlinkedUnit(source);
+    }
+
+    UnlinkedPublicNamespace getImport(String relativeUri) {
+      return getPart(relativeUri)?.publicNamespace;
+    }
+
+    UnlinkedUnit definingUnit = _getUnlinkedUnit(librarySource);
+    if (definingUnit != null) {
+      LinkedLibraryBuilder linkedLibrary = prelink(librarySource.uri.toString(),
+          definingUnit, getPart, getImport, context.declaredVariables.get);
+      linkedLibrary.dependencies.skip(1).forEach((LinkedDependency d) {
+        Source source = context.sourceFactory.forUri(d.uri);
+        _serializeLibrary(source);
+      });
+    }
+  }
+}
+
 /// [SerializedMockSdk] is a singleton class representing the result of
 /// serializing the mock SDK to summaries.  It is computed once and then shared
 /// among test invocations so that we don't bog down the tests.
