New summaries work snapshot.

1. Extract LinkingBundleContext to store references and types.

2. Resolve and resynthesize metadata for many nodes.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I88334bd4509efe0182a4bba6a67edac99ed51886
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96262
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 35fe269..639bd5d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3096,10 +3096,10 @@
 
   /// Initialize a newly created element to have the given [name] at the given
   /// [_nameOffset].
-  ElementImpl(String name, this._nameOffset)
-      : reference = null,
-        linkedNode = null {
+  ElementImpl(String name, this._nameOffset, {this.reference})
+      : linkedNode = null {
     this._name = StringUtilities.intern(name);
+    this.reference?.element = this;
   }
 
   /// Initialize from linked node.
@@ -3399,6 +3399,11 @@
   }
 
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     return _metadata ?? const <ElementAnnotation>[];
   }
 
@@ -3608,6 +3613,23 @@
     }
   }
 
+  /// Return annotations for the given [nodeList] in the [unit].
+  List<ElementAnnotation> _buildAnnotations2(
+      CompilationUnitElementImpl unit, List<LinkedNode> nodeList) {
+    var length = nodeList.length;
+    if (length == 0) {
+      return const <ElementAnnotation>[];
+    }
+
+    var annotations = new List<ElementAnnotation>(length);
+    for (int i = 0; i < length; i++) {
+      var ast = unit.linkedContext.readNode(nodeList[i]);
+      annotations[i] = ElementAnnotationImpl(enclosingUnit)
+        ..annotationAst = ast;
+    }
+    return annotations;
+  }
+
   /// If the element associated with the given [type] is a generic function type
   /// element, then make it a child of this element. Return the [type] as a
   /// convenience.
@@ -4047,9 +4069,9 @@
 
   /// Initialize a newly created executable element to have the given [name] and
   /// [offset].
-  ExecutableElementImpl(String name, int offset)
+  ExecutableElementImpl(String name, int offset, {Reference reference})
       : serializedExecutable = null,
-        super(name, offset);
+        super(name, offset, reference: reference);
 
   /// Initialize using the given linked node.
   ExecutableElementImpl.forLinkedNode(
@@ -4296,8 +4318,11 @@
 
   @override
   FunctionType get type {
+    if (linkedNode != null) {
+      return _type ??= new FunctionTypeImpl(this);
+    }
     if (serializedExecutable != null) {
-      _type ??= new FunctionTypeImpl(this);
+      return _type ??= new FunctionTypeImpl(this);
     }
     return _type;
   }
@@ -4552,14 +4577,18 @@
       ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
       : super.forLinkedNode(enclosing, reference, linkedNode) {
     if (!linkedNode.isSynthetic) {
-      var getter = PropertyAccessorElementImpl_ImplicitGetter(this);
-      enclosing.reference.getChild('@getter').getChild(name).element = getter;
-      this.getter = getter;
+      var enclosingRef = enclosing.reference;
+
+      this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+        this,
+        reference: enclosingRef.getChild('@getter').getChild(name),
+      );
 
       if (!isConst && !isFinal) {
-        var setter = PropertyAccessorElementImpl_ImplicitSetter(this);
-        enclosing.reference.getChild('@setter').getChild(name).element = setter;
-        this.setter = setter;
+        this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+          this,
+          reference: enclosingRef.getChild('@setter').getChild(name),
+        );
       }
     }
   }
@@ -8044,8 +8073,9 @@
 
   /// Initialize a newly created synthetic property accessor element to be
   /// associated with the given [variable].
-  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable)
-      : super(variable.name, variable.nameOffset) {
+  PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable,
+      {Reference reference})
+      : super(variable.name, variable.nameOffset, reference: reference) {
     this.variable = variable;
     isStatic = variable.isStatic;
     isSynthetic = true;
@@ -8208,8 +8238,9 @@
     extends PropertyAccessorElementImpl {
   /// Create the implicit getter and bind it to the [property].
   PropertyAccessorElementImpl_ImplicitGetter(
-      PropertyInducingElementImpl property)
-      : super.forVariable(property) {
+      PropertyInducingElementImpl property,
+      {Reference reference})
+      : super.forVariable(property, reference: reference) {
     property.getter = this;
     enclosingElement = property.enclosingElement;
   }
@@ -8244,8 +8275,9 @@
     extends PropertyAccessorElementImpl {
   /// Create the implicit setter and bind it to the [property].
   PropertyAccessorElementImpl_ImplicitSetter(
-      PropertyInducingElementImpl property)
-      : super.forVariable(property) {
+      PropertyInducingElementImpl property,
+      {Reference reference})
+      : super.forVariable(property, reference: reference) {
     property.setter = this;
     enclosingElement = property.enclosingElement;
   }
@@ -8499,14 +8531,18 @@
       ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
       : super.forLinkedNode(enclosing, reference, linkedNode) {
     if (!linkedNode.isSynthetic) {
-      var getter = PropertyAccessorElementImpl_ImplicitGetter(this);
-      enclosing.reference.getChild('@getter').getChild(name).element = getter;
-      this.getter = getter;
+      var enclosingRef = enclosing.reference;
+
+      this.getter = PropertyAccessorElementImpl_ImplicitGetter(
+        this,
+        reference: enclosingRef.getChild('@getter').getChild(name),
+      );
 
       if (!isConst && !isFinal) {
-        var setter = PropertyAccessorElementImpl_ImplicitSetter(this);
-        enclosing.reference.getChild('@setter').getChild(name).element = setter;
-        this.setter = setter;
+        this.setter = PropertyAccessorElementImpl_ImplicitSetter(
+          this,
+          reference: enclosingRef.getChild('@setter').getChild(name),
+        );
       }
     }
   }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 019c4ad..5feed77 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -12,19 +12,13 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/tokens_context.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
 
 /// Deserializer of fully resolved ASTs from flat buffers.
 class AstBinaryReader {
-  final Reference _nameRoot;
-  final LinkedNodeReferences _linkedReferences;
-  final List<Reference> _references;
+  final LinkedUnitContext _unitContext;
 
-  final TokensContext _tokensContext;
-
-  AstBinaryReader(this._nameRoot, this._linkedReferences, this._tokensContext)
-      : _references = List<Reference>(_linkedReferences.name.length);
+  AstBinaryReader(this._unitContext);
 
   AstNode readNode(LinkedNode data) {
     if (data == null) return null;
@@ -268,7 +262,9 @@
   }
 
   T _getElement<T extends Element>(int index) {
-    return _getReferenceByIndex(index)?.element;
+    var bundleContext = _unitContext.bundleContext;
+    var reference = bundleContext.referenceOfIndex(index);
+    return bundleContext.elementFactory.elementOfReference(reference);
   }
 
   List<T> _getElements<T extends Element>(List<int> indexList) {
@@ -280,28 +276,8 @@
     return result;
   }
 
-  Reference _getReferenceByIndex(int index) {
-    var reference = _references[index];
-    if (reference != null) return reference;
-
-    if (index == 0) {
-      _references[index] = _nameRoot;
-      return _nameRoot;
-    }
-
-    var parentIndex = _linkedReferences.parent[index];
-    var parent = _getReferenceByIndex(parentIndex);
-    if (parent == null) return null;
-
-    var name = _linkedReferences.name[index];
-    reference = parent[name];
-    _references[index] = reference;
-
-    return reference;
-  }
-
   Token _getToken(int index) {
-    return _tokensContext.tokenOfIndex(index);
+    return _unitContext.tokensContext.tokenOfIndex(index);
   }
 
   List<Token> _getTokens(List<int> indexList) {
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index cf692e9..b437a4e 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -9,28 +9,22 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/tokens_context.dart';
 
 /// Serializer of fully resolved ASTs into flat buffers.
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
-  final TokensContext tokens;
-
-  final referenceRoot = Reference.root();
-  final referencesBuilder = LinkedNodeReferencesBuilder();
-  final _references = <Reference>[];
+  final LinkingBundleContext _linkingBundleContext;
+  final TokensContext _tokensContext;
 
   /// This field is set temporary while visiting [FieldDeclaration] or
   /// [TopLevelVariableDeclaration] to store data shared among all variables
   /// in these declarations.
   LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
 
-  AstBinaryWriter(this.tokens) {
-    _references.add(referenceRoot);
-  }
+  AstBinaryWriter(this._linkingBundleContext, this._tokensContext);
 
   @override
   LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) {
@@ -98,7 +92,7 @@
   @override
   LinkedNodeBuilder visitAssignmentExpression(AssignmentExpression node) {
     return LinkedNodeBuilder.assignmentExpression(
-      assignmentExpression_element: _getReference(node.staticElement).index,
+      assignmentExpression_element: _getReferenceIndex(node.staticElement),
       assignmentExpression_leftHandSide: node.leftHandSide.accept(this),
       assignmentExpression_operator: _getToken(node.operator),
       assignmentExpression_rightHandSide: node.rightHandSide.accept(this),
@@ -118,7 +112,7 @@
   @override
   LinkedNodeBuilder visitBinaryExpression(BinaryExpression node) {
     return LinkedNodeBuilder.binaryExpression(
-      binaryExpression_element: _getReference(node.staticElement).index,
+      binaryExpression_element: _getReferenceIndex(node.staticElement),
       binaryExpression_leftOperand: node.leftOperand.accept(this),
       binaryExpression_operator: _getToken(node.operator),
       binaryExpression_rightOperand: node.rightOperand.accept(this),
@@ -305,7 +299,7 @@
   @override
   LinkedNodeBuilder visitConstructorName(ConstructorName node) {
     return LinkedNodeBuilder.constructorName(
-      constructorName_element: _getReference(node.staticElement).index,
+      constructorName_element: _getReferenceIndex(node.staticElement),
       constructorName_name: node.name?.accept(this),
       constructorName_period: _getToken(node.period),
       constructorName_type: node.type.accept(this),
@@ -689,7 +683,7 @@
   @override
   LinkedNodeBuilder visitIndexExpression(IndexExpression node) {
     return LinkedNodeBuilder.indexExpression(
-      indexExpression_element: _getReference(node.staticElement).index,
+      indexExpression_element: _getReferenceIndex(node.staticElement),
       indexExpression_index: node.index.accept(this),
       indexExpression_leftBracket: _getToken(node.leftBracket),
       indexExpression_rightBracket: _getToken(node.rightBracket),
@@ -901,7 +895,7 @@
   LinkedNodeBuilder visitPostfixExpression(PostfixExpression node) {
     return LinkedNodeBuilder.postfixExpression(
       expression_type: _writeType(node.staticType),
-      postfixExpression_element: _getReference(node.staticElement).index,
+      postfixExpression_element: _getReferenceIndex(node.staticElement),
       postfixExpression_operand: node.operand.accept(this),
       postfixExpression_operator: _getToken(node.operator),
     );
@@ -921,7 +915,7 @@
   LinkedNodeBuilder visitPrefixExpression(PrefixExpression node) {
     return LinkedNodeBuilder.prefixExpression(
       expression_type: _writeType(node.staticType),
-      prefixExpression_element: _getReference(node.staticElement).index,
+      prefixExpression_element: _getReferenceIndex(node.staticElement),
       prefixExpression_operand: node.operand.accept(this),
       prefixExpression_operator: _getToken(node.operator),
     );
@@ -947,7 +941,7 @@
       redirectingConstructorInvocation_constructorName:
           node.constructorName?.accept(this),
       redirectingConstructorInvocation_element:
-          _getReference(node.staticElement).index,
+          _getReferenceIndex(node.staticElement),
       redirectingConstructorInvocation_period: _getToken(node.period),
       redirectingConstructorInvocation_thisKeyword: _getToken(node.thisKeyword),
     );
@@ -1018,7 +1012,7 @@
 
     return LinkedNodeBuilder.simpleIdentifier(
       simpleIdentifier_element:
-          isDeclared ? null : _getReference(node.staticElement).index,
+          isDeclared ? null : _getReferenceIndex(node.staticElement),
       simpleIdentifier_token: _getToken(node.token),
       expression_type: _writeType(node.staticType),
     );
@@ -1058,7 +1052,7 @@
       superConstructorInvocation_constructorName:
           node.constructorName?.accept(this),
       superConstructorInvocation_element:
-          _getReference(node.staticElement).index,
+          _getReferenceIndex(node.staticElement),
       superConstructorInvocation_period: _getToken(node.period),
       superConstructorInvocation_superKeyword: _getToken(node.superKeyword),
     );
@@ -1268,159 +1262,19 @@
     return node.accept(this);
   }
 
-  /// Write [referenceRoot] and all its children into [referencesBuilder].
-  void writeReferences() {
-    for (var reference in _references) {
-      referencesBuilder.parent.add(reference.parent?.index ?? 0);
-      referencesBuilder.name.add(reference.name);
+  int _getReferenceIndex(Element element) {
+    if (element == null) return 0;
+
+    var reference = (element as ElementImpl).reference;
+    if (identical(element, DynamicElementImpl.instance)) {
+      reference = _linkingBundleContext.dynamicReference;
     }
-  }
 
-  void _ensureReferenceIndex(Reference reference) {
-    if (reference.index == null) {
-      reference.index = _references.length;
-      _references.add(reference);
-    }
-  }
-
-  Reference _getReference(Element element) {
-    if (element == null) return referenceRoot;
-
-    // TODO(scheglov) handle Member elements
-
-    Reference result;
-    if (element is ClassElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@class');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is CompilationUnitElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@unit');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild('${element.source.uri}');
-    } else if (element is ConstructorElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@constructor');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is DynamicElementImpl) {
-      result = _getReference(element.library).getChild('@dynamic');
-    } else if (element is FieldElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@field');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is FunctionElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@function');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name ?? '');
-    } else if (element is FunctionTypeAliasElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@typeAlias');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is GenericFunctionTypeElement) {
-      if (element.enclosingElement is GenericTypeAliasElement) {
-        return _getReference(element.enclosingElement);
-      } else {
-        var enclosingRef = _getReference(element.enclosingElement);
-        var containerRef = enclosingRef.getChild('@functionType');
-        _ensureReferenceIndex(containerRef);
-
-        // TODO(scheglov) do we need to store these elements at all?
-        result = containerRef.getChild('<unnamed>');
-      }
-    } else if (element is GenericTypeAliasElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@typeAlias');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is GenericFunctionTypeElement &&
-        element.enclosingElement is ParameterElement) {
-      return _getReference(element.enclosingElement);
-    } else if (element is LibraryElement) {
-      var uriStr = element.source.uri.toString();
-      result = referenceRoot.getChild(uriStr);
-    } else if (element is LabelElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@label');
-      _ensureReferenceIndex(containerRef);
-
-      // TODO(scheglov) use index instead of offset
-      result = containerRef.getChild('${element.nameOffset}');
-    } else if (element is LocalVariableElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@localVariable');
-      _ensureReferenceIndex(containerRef);
-
-      // TODO(scheglov) use index instead of offset
-      result = containerRef.getChild('${element.nameOffset}');
-    } else if (element is MethodElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@method');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is MultiplyDefinedElement) {
-      return referenceRoot;
-    } else if (element is ParameterElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@parameter');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is PrefixElement) {
-      var containerRef = _getReference(element.library).getChild('@prefix');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is PropertyAccessorElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild(
-        element.isGetter ? '@getter' : '@setter',
-      );
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.displayName);
-    } else if (element is TopLevelVariableElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@variable');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else if (element is TypeParameterElement) {
-      var enclosingRef = _getReference(element.enclosingElement);
-      var containerRef = enclosingRef.getChild('@typeParameter');
-      _ensureReferenceIndex(containerRef);
-
-      result = containerRef.getChild(element.name);
-    } else {
-      throw UnimplementedError('(${element.runtimeType}) $element');
-    }
-    _ensureReferenceIndex(result);
-    return result;
-  }
-
-  List<int> _getReferences(List<Element> elements) {
-    var result = List<int>(elements.length);
-    for (var i = 0; i < elements.length; ++i) {
-      var element = elements[i];
-      result[i] = _getReference(element).index;
-    }
-    return result;
+    return _linkingBundleContext.indexOfReference(reference);
   }
 
   int _getToken(Token token) {
-    return tokens.indexOfToken(token);
+    return _tokensContext.indexOfToken(token);
   }
 
   List<int> _getTokens(List<Token> tokenList) {
@@ -1594,7 +1448,7 @@
     builder
       ..uriBasedDirective_uri = node.uri.accept(this)
       ..uriBasedDirective_uriContent = node.uriContent
-      ..uriBasedDirective_uriElement = _getReference(node.uriElement).index;
+      ..uriBasedDirective_uriElement = _getReferenceIndex(node.uriElement);
   }
 
   List<LinkedNodeBuilder> _writeNodeList(List<AstNode> nodeList) {
@@ -1610,40 +1464,6 @@
   }
 
   LinkedNodeTypeBuilder _writeType(DartType type) {
-    if (type == null) return null;
-
-    if (type.isBottom) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.bottom,
-      );
-    } else if (type.isDynamic) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.dynamic_,
-      );
-    } else if (type is FunctionType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.function,
-        functionFormalParameters: _getReferences(type.parameters),
-        functionReturnType: _writeType(type.returnType),
-        functionTypeParameters: _getReferences(type.parameters),
-      );
-    } else if (type is InterfaceType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.interface,
-        interfaceClass: _getReference(type.element).index,
-        interfaceTypeArguments: type.typeArguments.map(_writeType).toList(),
-      );
-    } else if (type is TypeParameterType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.typeParameter,
-        typeParameterParameter: _getReference(type.element).index,
-      );
-    } else if (type is VoidType) {
-      return LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.void_,
-      );
-    } else {
-      throw UnimplementedError('(${type.runtimeType}) $type');
-    }
+    return _linkingBundleContext.writeType(type);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
new file mode 100644
index 0000000..c3dcf81
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+/// Used to resolve some AST nodes - variable initializers, and annotations.
+class AstResolver {
+  final Linker _linker;
+
+  LibraryElement _library;
+  Scope _nameScope;
+
+  AstResolver(this._linker, Reference libraryRef) {
+    _library = _linker.elementFactory.elementOfReference(libraryRef);
+    _nameScope = LibraryScope(_library);
+  }
+
+  LinkedNode resolve(UnitBuilder unit, AstNode node) {
+    var source = _FakeSource();
+    var errorListener = AnalysisErrorListener.NULL_LISTENER;
+
+    var typeResolverVisitor = new TypeResolverVisitor(
+        _library, source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope);
+    node.accept(typeResolverVisitor);
+
+//    expression.accept(_astRewriteVisitor);
+//    expression.accept(_variableResolverVisitor);
+//    if (_linker.getAst != null) {
+//      expression.accept(_partialResolverVisitor);
+//    }
+
+    var resolverVisitor = new ResolverVisitor(_linker.inheritance, _library,
+        source, _linker.typeProvider, errorListener,
+        nameScope: _nameScope,
+        propagateTypes: false,
+        reportConstEvaluationErrors: false);
+    node.accept(resolverVisitor);
+
+    var writer = AstBinaryWriter(
+      _linker.linkingBundleContext,
+      unit.context.tokensContext,
+    );
+    return writer.writeNode(node);
+  }
+}
+
+class _FakeSource implements Source {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index 671e14e..ff64ff6 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/summary2/declaration.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/metadata_resolver.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/reference_resolver.dart';
 import 'package:analyzer/src/summary2/scope.dart';
@@ -185,16 +186,30 @@
     }
   }
 
+  void resolveMetadata() {
+    var metadataResolver = MetadataResolver(linker, reference);
+    for (var unit in units) {
+      metadataResolver.resolve(unit);
+    }
+  }
+
   void resolveTypes() {
     for (var unit in units) {
       var unitReference = reference.getChild('@unit').getChild('${unit.uri}');
-      ReferenceResolver(linker, unit, scope, unitReference).resolve();
+      ReferenceResolver(
+        linker.linkingBundleContext,
+        unit,
+        scope,
+        unitReference,
+      ).resolve();
     }
   }
 
   void storeExportScope() {
+    var linkingBundleContext = linker.linkingBundleContext;
     for (var declaration in exportScope.map.values) {
-      var index = linker.indexOfReference(declaration.reference);
+      var reference = declaration.reference;
+      var index = linkingBundleContext.indexOfReference(reference);
       node.exports.add(index);
     }
   }
@@ -228,13 +243,14 @@
       );
       var tokensContext = tokensResult.toContext();
 
-      var writer = AstBinaryWriter(tokensContext);
-      var unitNode = writer.writeNode(unit);
-
       var unitContext = LinkedUnitContext(
         linker.bundleContext,
         tokensContext,
       );
+
+      var writer = AstBinaryWriter(linker.linkingBundleContext, tokensContext);
+      var unitNode = writer.writeNode(unit);
+
       builder.units.add(
         UnitBuilder(unitSource.uri, unitContext, unitNode),
       );
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index d7b9425..2819b16 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -4,6 +4,8 @@
 
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -14,35 +16,25 @@
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 LinkResult link(
   AnalysisOptions analysisOptions,
   SourceFactory sourceFactory,
-  Reference rootReference,
   List<LinkedNodeBundle> inputs,
   Map<Source, Map<Source, CompilationUnit>> unitMap,
 ) {
-  var linker = Linker(analysisOptions, sourceFactory, rootReference);
+  var linker = Linker(analysisOptions, sourceFactory);
   linker.link(inputs, unitMap);
   return LinkResult(linker.linkingBundle);
 }
 
 class Linker {
-  final Reference rootReference;
+  final Reference rootReference = Reference.root();
   LinkedElementFactory elementFactory;
 
-  /// References used in all libraries being linked.
-  /// Element references in [LinkedNode]s are indexes in this list.
-  final List<Reference> references = [null];
-
-  /// The references of the [linkingBundle].
-  final LinkedNodeReferencesBuilder referencesBuilder =
-      LinkedNodeReferencesBuilder(
-    parent: [0],
-    name: [''],
-  );
-
+  LinkingBundleContext linkingBundleContext;
   List<LinkedNodeLibraryBuilder> linkingLibraries = [];
   LinkedNodeBundleBuilder linkingBundle;
   LinkedBundleContext bundleContext;
@@ -53,9 +45,14 @@
   _AnalysisContextForLinking analysisContext;
   TypeProvider typeProvider;
   Dart2TypeSystem typeSystem;
+  InheritanceManager2 inheritance;
 
-  Linker(AnalysisOptions analysisOptions, SourceFactory sourceFactory,
-      this.rootReference) {
+  Linker(AnalysisOptions analysisOptions, SourceFactory sourceFactory) {
+    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
+    dynamicRef.element = DynamicElementImpl.instance;
+
+    linkingBundleContext = LinkingBundleContext(dynamicRef);
+
     analysisContext = _AnalysisContextForLinking(
       analysisOptions,
       sourceFactory,
@@ -68,7 +65,7 @@
     );
 
     linkingBundle = LinkedNodeBundleBuilder(
-      references: referencesBuilder,
+      references: linkingBundleContext.referencesBuilder,
       libraries: linkingLibraries,
     );
 
@@ -78,19 +75,6 @@
     );
   }
 
-  int indexOfReference(Reference reference) {
-    if (reference.parent == null) return 0;
-    if (reference.index != null) return reference.index;
-
-    var parentIndex = indexOfReference(reference.parent);
-    referencesBuilder.parent.add(parentIndex);
-    referencesBuilder.name.add(reference.name);
-
-    reference.index = references.length;
-    references.add(reference);
-    return reference.index;
-  }
-
   void link(List<LinkedNodeBundle> inputs,
       Map<Source, Map<Source, CompilationUnit>> unitMap) {
     for (var input in inputs) {
@@ -119,6 +103,7 @@
     _createTypeSystem();
     _resolveTypes();
     _performTopLevelInference();
+    _resolveMetadata();
   }
 
   void _computeLibraryScopes() {
@@ -149,6 +134,8 @@
 
     typeSystem = Dart2TypeSystem(typeProvider);
     analysisContext.typeSystem = typeSystem;
+
+    inheritance = InheritanceManager2(typeSystem);
   }
 
   void _performTopLevelInference() {
@@ -157,6 +144,12 @@
     }
   }
 
+  void _resolveMetadata() {
+    for (var library in builders) {
+      library.resolveMetadata();
+    }
+  }
+
   void _resolveTypes() {
     for (var library in builders) {
       library.resolveTypes();
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index c7661d2..6eb53de 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -16,7 +16,8 @@
   final List<Reference> _references;
 
   LinkedBundleContext(this.elementFactory, this.referencesData)
-      : _references = List<Reference>(referencesData.name.length);
+      : _references = List<Reference>.filled(referencesData.name.length, null,
+            growable: true);
 
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
     var type = getType(linkedType);
@@ -47,17 +48,25 @@
   }
 
   Reference referenceOfIndex(int index) {
+    // When we are linking a bundle, we add new references.
+    // So, grow the list of references when we have data for them.
+    if (index >= _references.length) {
+      if (referencesData.name.length > _references.length) {
+        _references.length = referencesData.name.length;
+      }
+    }
+
     var reference = _references[index];
     if (reference != null) return reference;
 
     if (index == 0) {
-      _references[index] = elementFactory.rootReference;
-      return elementFactory.rootReference;
+      reference = elementFactory.rootReference;
+      _references[index] = reference;
+      return reference;
     }
 
     var parentIndex = referencesData.parent[index];
     var parent = referenceOfIndex(parentIndex);
-    if (parent == null) return null;
 
     var name = referencesData.name[index];
     reference = parent.getChild(name);
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 19be9f6..6ec9523 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -32,6 +32,9 @@
     if (reference.element != null) {
       return reference.element;
     }
+    if (reference.parent == null) {
+      return null;
+    }
 
     return _ElementRequest(this, reference).elementOfReference(reference);
   }
@@ -60,10 +63,56 @@
 
   _ElementRequest(this.elementFactory, this.input);
 
-  ClassElementImpl createClassElement(
+  ElementImpl elementOfReference(Reference reference) {
+    if (reference.element != null) {
+      return reference.element;
+    }
+
+    var parent2 = reference.parent.parent;
+    if (parent2 == null) {
+      return _createLibraryElement(reference);
+    }
+
+    var parentName = reference.parent.name;
+
+    if (parentName == '@class') {
+      var unit = elementOfReference(parent2);
+      return _class(unit, reference);
+    }
+
+    if (parentName == '@getter') {
+      var enclosing = elementOfReference(parent2);
+      return _getter(enclosing, reference);
+    }
+
+    if (parentName == '@typeAlias') {
+      var unit = elementOfReference(parent2);
+      return _typeAlias(unit, reference);
+    }
+
+    if (parentName == '@typeParameter') {
+      var enclosing = elementOfReference(parent2) as TypeParameterizedElement;
+      enclosing.typeParameters;
+      // Requesting type parameters sets elements for all their references.
+      assert(reference.element != null);
+      return reference.element;
+    }
+
+    if (parentName == '@unit') {
+      elementOfReference(parent2);
+      // Creating a library fills all its units.
+      assert(reference.element != null);
+      return reference.element;
+    }
+
+    // TODO(scheglov) support other elements
+    throw StateError('Not found: $input');
+  }
+
+  ClassElementImpl _class(
       CompilationUnitElementImpl unit, Reference reference) {
     if (reference.node == null) {
-      indexUnitDeclarations(unit);
+      _indexUnitDeclarations(unit);
       assert(reference.node != 0, '$reference');
     }
     return reference.element = ClassElementImpl.forLinkedNode(
@@ -73,20 +122,7 @@
     );
   }
 
-  GenericTypeAliasElementImpl createFunctionTypeAliasElement(
-      CompilationUnitElementImpl unit, Reference reference) {
-    if (reference.node == null) {
-      indexUnitDeclarations(unit);
-      assert(reference.node != 0, '$reference');
-    }
-    return reference.element = GenericTypeAliasElementImpl.forLinkedNode(
-      unit,
-      reference,
-      reference.node,
-    );
-  }
-
-  LibraryElementImpl createLibraryElement(Reference reference) {
+  LibraryElementImpl _createLibraryElement(Reference reference) {
     var uriStr = reference.name;
 
     var sourceFactory = elementFactory.analysisContext.sourceFactory;
@@ -125,48 +161,25 @@
     return reference.element = libraryElement;
   }
 
-  ElementImpl elementOfReference(Reference reference) {
-    if (reference.element != null) {
-      return reference.element;
-    }
-
-    var parent2 = reference.parent.parent;
-    if (parent2 == null) {
-      return createLibraryElement(reference);
-    }
-
-    var parentName = reference.parent.name;
-
-    if (parentName == '@class') {
-      var unit = elementOfReference(parent2);
-      return createClassElement(unit, reference);
-    }
-
-    if (parentName == '@typeAlias') {
-      var unit = elementOfReference(parent2);
-      return createFunctionTypeAliasElement(unit, reference);
-    }
-
-    if (parentName == '@typeParameter') {
-      var enclosing = elementOfReference(parent2) as TypeParameterizedElement;
-      enclosing.typeParameters;
-      // Requesting type parameters sets elements for all their references.
+  PropertyAccessorElementImpl _getter(
+      ElementImpl enclosing, Reference reference) {
+    if (enclosing is ClassElementImpl) {
+      enclosing.accessors;
+      // Requesting accessors sets elements for accessors and fields.
       assert(reference.element != null);
       return reference.element;
     }
-
-    if (parentName == '@unit') {
-      elementOfReference(parent2);
-      // Creating a library fills all its units.
+    if (enclosing is CompilationUnitElementImpl) {
+      enclosing.accessors;
+      // Requesting accessors sets elements for accessors and variables.
       assert(reference.element != null);
       return reference.element;
     }
-
-    // TODO(scheglov) support other elements
-    throw StateError('Not found: $input');
+    // Only classes and units have accessors.
+    throw StateError('${enclosing.runtimeType}');
   }
 
-  void indexUnitDeclarations(CompilationUnitElementImpl unit) {
+  void _indexUnitDeclarations(CompilationUnitElementImpl unit) {
     var context = unit.linkedContext;
     var unitRef = unit.reference;
     var classRef = unitRef.getChild('@class');
@@ -186,6 +199,19 @@
       }
     }
   }
+
+  GenericTypeAliasElementImpl _typeAlias(
+      CompilationUnitElementImpl unit, Reference reference) {
+    if (reference.node == null) {
+      _indexUnitDeclarations(unit);
+      assert(reference.node != 0, '$reference');
+    }
+    return reference.element = GenericTypeAliasElementImpl.forLinkedNode(
+      unit,
+      reference,
+      reference.node,
+    );
+  }
 }
 
 class _Library {
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 10a52bb..13d7e09 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -79,6 +79,21 @@
     return bundleContext.getInterfaceType(linkedType);
   }
 
+  List<LinkedNode> getMetadataOrEmpty(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.classDeclaration ||
+        kind == LinkedNodeKind.classTypeAlias ||
+        kind == LinkedNodeKind.constructorDeclaration ||
+        kind == LinkedNodeKind.functionDeclaration ||
+        kind == LinkedNodeKind.functionTypeAlias ||
+        kind == LinkedNodeKind.methodDeclaration ||
+        kind == LinkedNodeKind.mixinDeclaration ||
+        kind == LinkedNodeKind.variableDeclaration) {
+      return node.annotatedNode_metadata;
+    }
+    return const <LinkedNode>[];
+  }
+
   String getMethodName(LinkedNode node) {
     return getSimpleName(node.methodDeclaration_name);
   }
@@ -303,12 +318,12 @@
   }
 
   Expression readInitializer(LinkedNode linkedNode) {
-    var reader = AstBinaryReader(
-      bundleContext.elementFactory.rootReference,
-      bundleContext.referencesData,
-      tokensContext,
-    );
-    return reader.readNode(linkedNode.variableDeclaration_initializer);
+    return readNode(linkedNode.variableDeclaration_initializer);
+  }
+
+  AstNode readNode(LinkedNode linkedNode) {
+    var reader = AstBinaryReader(this);
+    return reader.readNode(linkedNode);
   }
 
   Iterable<LinkedNode> topLevelVariables(LinkedNode unit) sync* {
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
new file mode 100644
index 0000000..4c400d6
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class LinkingBundleContext {
+  /// The `dynamic` class is declared in `dart:core`, but is not a class.
+  /// Also, it is static, so we cannot set `reference` for it.
+  /// So, we have to push it in a separate way.
+  final Reference dynamicReference;
+
+  /// References used in all libraries being linked.
+  /// Element references in nodes are indexes in this list.
+  final List<Reference> references = [null];
+
+  /// Data about [references].
+  final LinkedNodeReferencesBuilder referencesBuilder =
+      LinkedNodeReferencesBuilder(
+    parent: [0],
+    name: [''],
+  );
+
+  LinkingBundleContext(this.dynamicReference);
+
+  int indexOfReference(Reference reference) {
+    if (reference.parent == null) return 0;
+    if (reference.index != null) return reference.index;
+
+    var parentIndex = indexOfReference(reference.parent);
+    referencesBuilder.parent.add(parentIndex);
+    referencesBuilder.name.add(reference.name);
+
+    reference.index = references.length;
+    references.add(reference);
+    return reference.index;
+  }
+
+  LinkedNodeTypeBuilder writeType(DartType type) {
+    if (type == null) return null;
+
+    if (type.isBottom) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.bottom,
+      );
+    } else if (type.isDynamic) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.dynamic_,
+      );
+    } else if (type is FunctionType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.function,
+        functionFormalParameters: _getReferences(type.parameters),
+        functionReturnType: writeType(type.returnType),
+        functionTypeParameters: _getReferences(type.parameters),
+      );
+    } else if (type is InterfaceType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.interface,
+        interfaceClass: _getReferenceIndex(type.element),
+        interfaceTypeArguments: type.typeArguments.map(writeType).toList(),
+      );
+    } else if (type is TypeParameterType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.typeParameter,
+        typeParameterParameter: _getReferenceIndex(type.element),
+      );
+    } else if (type is VoidType) {
+      return LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.void_,
+      );
+    } else {
+      throw UnimplementedError('(${type.runtimeType}) $type');
+    }
+  }
+
+  int _getReferenceIndex(Element element) {
+    if (element == null) return 0;
+
+    var reference = (element as ElementImpl).reference;
+    return indexOfReference(reference);
+  }
+
+  List<int> _getReferences(List<Element> elements) {
+    var result = List<int>(elements.length);
+    for (var i = 0; i < elements.length; ++i) {
+      var element = elements[i];
+      result[i] = _getReferenceIndex(element);
+    }
+    return result;
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
new file mode 100644
index 0000000..e73ceeb1
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_reader.dart';
+import 'package:analyzer/src/summary2/ast_resolver.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class MetadataResolver {
+  AstResolver _astResolver;
+
+  MetadataResolver(Linker linker, Reference libraryRef) {
+    _astResolver = AstResolver(linker, libraryRef);
+  }
+
+  void resolve(UnitBuilder unit) {
+    var unitDeclarations = unit.node.compilationUnit_declarations;
+    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+      var kind = unitDeclaration.kind;
+      if (_isAnnotatedNode(kind)) {
+        _annotatedNode(
+          unit,
+          unitDeclaration,
+        );
+      }
+      if (kind == LinkedNodeKind.classDeclaration) {
+        _class(unit, unitDeclaration);
+      } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
+        _variables(
+          unit,
+          unitDeclaration,
+          unitDeclaration.topLevelVariableDeclaration_variableList,
+        );
+      }
+    }
+  }
+
+  void _annotatedNode(UnitBuilder unit, LinkedNodeBuilder node) {
+    var unresolved = node.annotatedNode_metadata;
+    var resolved = _list(unit, unresolved);
+    node.annotatedNode_metadata = resolved;
+  }
+
+  void _class(UnitBuilder unit, LinkedNodeBuilder unitDeclaration) {
+    var members = unitDeclaration.classOrMixinDeclaration_members;
+    for (var classMember in members) {
+      var kind = classMember.kind;
+      if (_isAnnotatedNode(kind)) {
+        _annotatedNode(unit, classMember);
+      }
+      if (kind == LinkedNodeKind.fieldDeclaration) {
+        _variables(
+          unit,
+          classMember,
+          classMember.fieldDeclaration_fields,
+        );
+      }
+    }
+  }
+
+  List<LinkedNodeBuilder> _list(UnitBuilder unit, List<LinkedNode> unresolved) {
+    var resolved = List<LinkedNodeBuilder>(unresolved.length);
+    for (var i = 0; i < unresolved.length; ++i) {
+      var unresolvedNode = unresolved[i];
+
+      var reader = AstBinaryReader(unit.context);
+      var ast = reader.readNode(unresolvedNode) as Annotation;
+      ast.elementAnnotation = ElementAnnotationImpl(null);
+
+      // Set some parent, so that resolver does not bail out.
+      astFactory.libraryDirective(null, [ast], null, null, null);
+
+      var resolvedNode = _astResolver.resolve(unit, ast);
+      resolved[i] = resolvedNode;
+    }
+    return resolved;
+  }
+
+  /// Resolve annotations of the [declaration] (field or top-level variable),
+  /// and set them as metadata for each variable in the [variableList].
+  void _variables(UnitBuilder unit, LinkedNodeBuilder declaration,
+      LinkedNodeBuilder variableList) {
+    for (var variable in variableList.variableDeclarationList_variables) {
+      var unresolved = declaration.annotatedNode_metadata;
+      var resolved = _list(unit, unresolved);
+      variable.annotatedNode_metadata = resolved;
+    }
+  }
+
+  static bool _isAnnotatedNode(LinkedNodeKind kind) {
+    return kind == LinkedNodeKind.classDeclaration ||
+        kind == LinkedNodeKind.classTypeAlias ||
+        kind == LinkedNodeKind.constructorDeclaration ||
+        kind == LinkedNodeKind.functionDeclaration ||
+        kind == LinkedNodeKind.functionTypeAlias ||
+        kind == LinkedNodeKind.methodDeclaration;
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 016c987..43f1011 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -6,7 +6,7 @@
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
 import 'package:analyzer/src/summary2/declaration.dart';
-import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/scope.dart';
 
@@ -20,7 +20,7 @@
 /// the type is set, otherwise we keep it empty, so we will attempt to infer
 /// it later).
 class ReferenceResolver {
-  final Linker linker;
+  final LinkingBundleContext linkingBundleContext;
   final UnitBuilder unit;
 
   /// TODO(scheglov) Update scope with local scopes (formal / type parameters).
@@ -28,7 +28,12 @@
 
   Reference reference;
 
-  ReferenceResolver(this.linker, this.unit, this.scope, this.reference);
+  ReferenceResolver(
+    this.linkingBundleContext,
+    this.unit,
+    this.scope,
+    this.reference,
+  );
 
   LinkedNodeTypeBuilder get _dynamicType {
     return LinkedNodeTypeBuilder(
@@ -350,7 +355,7 @@
       }
 
       var reference = declaration.reference;
-      var referenceIndex = linker.indexOfReference(reference);
+      var referenceIndex = linkingBundleContext.indexOfReference(reference);
       identifier.simpleIdentifier_element = referenceIndex;
 
       var typeArguments = const <LinkedNodeTypeBuilder>[];
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index bb1c32d..def0f8d 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -2,18 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/resolver.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/summary2/ast_binary_reader.dart';
+import 'package:analyzer/src/summary2/ast_resolver.dart';
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/reference.dart';
@@ -118,7 +112,8 @@
             unitDeclaration.topLevelVariableDeclaration_variableList;
         for (var variable in variableList.variableDeclarationList_variables) {
           // TODO(scheglov) infer in the correct order
-          if (variable.variableDeclaration_type2 == null) {
+          if (variable.variableDeclaration_type2 == null ||
+              unit.context.isConst(variable)) {
             _inferVariableTypeFromInitializerTemporary(variable);
           }
         }
@@ -127,67 +122,32 @@
   }
 
   void _inferVariableTypeFromInitializerTemporary(LinkedNodeBuilder node) {
-    var storedInitializer = node.variableDeclaration_initializer;
+    var unresolvedNode = node.variableDeclaration_initializer;
 
-    if (storedInitializer == null) {
+    if (unresolvedNode == null) {
       node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
         kind: LinkedNodeTypeKind.dynamic_,
       );
       return;
     }
 
-    var reader = AstBinaryReader(
-      unit.context.bundleContext.elementFactory.rootReference,
-      unit.context.bundleContext.referencesData,
-      unit.context.tokensContext,
-    );
+    var expression = unit.context.readInitializer(node);
+    astFactory.expressionFunctionBody(null, null, expression, null);
 
-    // TODO(scheglov) This duplicates `readInitializer` in LinkedUnitContext
-    Expression initializer = reader.readNode(storedInitializer);
+    // TODO(scheglov) can be shared for the whole library
+    var astResolver = AstResolver(linker, libraryRef);
 
-    var container =
-        astFactory.expressionFunctionBody(null, null, initializer, null);
-//    expression.accept(_astRewriteVisitor);
-    initializer = container.expression;
-//    if (_linker.getAst != null) {
-//      expression.accept(_typeResolverVisitor);
-//    }
-//    expression.accept(_variableResolverVisitor);
-//    if (_linker.getAst != null) {
-//      expression.accept(_partialResolverVisitor);
-//    }
+    var resolvedNode = astResolver.resolve(unit, expression);
+    node.variableDeclaration_initializer = resolvedNode;
 
-    var bundleContext = unit.context.bundleContext;
-    var library = bundleContext.elementFactory.elementOfReference(libraryRef);
-    var inheritance = InheritanceManager2(linker.typeSystem);
+    if (node.variableDeclaration_type2 == null) {
+      var initializerType = expression.staticType;
+      initializerType = _dynamicIfNull(initializerType);
 
-    var errorListener = RecordingErrorListener();
-    var source = _FakeSource();
-    var resolverVisitor = new ResolverVisitor(
-        inheritance, library, source, linker.typeProvider, errorListener,
-        nameScope: LibraryScope(library),
-        propagateTypes: false,
-        reportConstEvaluationErrors: false);
-    initializer.accept(resolverVisitor);
-
-    // TODO(scheglov) use AstBinaryWriter to put resolved initializer
-
-    var initializerType = initializer.staticType;
-    initializerType = _dynamicIfNull(initializerType);
-
-    if (initializerType is DynamicTypeImpl) {
-      node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.dynamic_,
+      var linkingBundleContext = linker.linkingBundleContext;
+      node.variableDeclaration_type2 = linkingBundleContext.writeType(
+        initializerType,
       );
-    } else if (initializerType is InterfaceTypeImpl) {
-      var element = initializerType.element as ClassElementImpl;
-      node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
-        kind: LinkedNodeTypeKind.interface,
-        interfaceClass: linker.indexOfReference(element.reference),
-      );
-    } else {
-      // TODO(scheglov) support other types
-      throw UnimplementedError('${initializerType.runtimeType}');
     }
   }
 
@@ -213,18 +173,4 @@
       }
     }
   }
-
-  void _visitClassMethods(
-      LinkedNode class_, void Function(LinkedNodeBuilder) f) {
-    var members = class_.classOrMixinDeclaration_members;
-    for (var member in members) {
-      if (member.kind == LinkedNodeKind.methodDeclaration) {
-        f(member);
-      }
-    }
-  }
-}
-
-class _FakeSource implements Source {
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 38fa6ff..d714997 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -422,6 +422,8 @@
       buffer.write(e.expression);
     } else if (e is NullLiteral) {
       buffer.write('null');
+    } else if (e is ParenthesizedExpression) {
+      writeExpression(e.expression, e);
     } else if (e is PrefixExpression) {
       buffer.write(e.operator.lexeme);
       writeExpression(e.operand, e);
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 945a2b3..9dd8833 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -52,7 +52,11 @@
   const Object();
 }
 
-abstract class String {}
+abstract class String {
+  int get length;
+}
+
+abstract class Symbol {}
 
 abstract class Type {}
 
@@ -65,8 +69,7 @@
 abstract class num implements Comparable<num> {}
 ''';
 
-    var rootReference = Reference.root();
-    var dartCoreResult = _link(rootReference, dartCoreSource, dartCoreCode);
+    var dartCoreResult = _link(dartCoreSource, dartCoreCode);
 
     var source = addTestSource(text);
 
@@ -80,17 +83,20 @@
     var linkResult = link(
       AnalysisOptionsImpl(),
       sourceFactory,
-      rootReference,
       [dartCoreResult.bundle],
       libraryUnitMap,
     );
 
     var analysisContext = _FakeAnalysisContext(sourceFactory);
 
+    var rootReference = Reference.root();
+    rootReference.getChild('dart:core').getChild('dynamic').element =
+        DynamicElementImpl.instance;
+
     var elementFactory = LinkedElementFactory(
       analysisContext,
       null,
-      Reference.root(),
+      rootReference,
     );
     elementFactory.addBundle(dartCoreResult.bundle);
     elementFactory.addBundle(linkResult.bundle);
@@ -313,12 +319,6 @@
 
   @override
   @failingTest
-  test_const_invalid_typeMismatch() async {
-    await super.test_const_invalid_typeMismatch();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_generic_named() async {
     await super.test_const_invokeConstructor_generic_named();
   }
@@ -405,12 +405,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed() async {
-    await super.test_const_invokeConstructor_unnamed();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_unnamed_imported() async {
     await super.test_const_invokeConstructor_unnamed_imported();
   }
@@ -429,12 +423,6 @@
 
   @override
   @failingTest
-  test_const_length_ofClassConstField() async {
-    await super.test_const_length_ofClassConstField();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofClassConstField_imported() async {
     await super.test_const_length_ofClassConstField_imported();
   }
@@ -447,18 +435,6 @@
 
   @override
   @failingTest
-  test_const_length_ofStringLiteral() async {
-    await super.test_const_length_ofStringLiteral();
-  }
-
-  @override
-  @failingTest
-  test_const_length_ofTopLevelVariable() async {
-    await super.test_const_length_ofTopLevelVariable();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofTopLevelVariable_imported() async {
     await super.test_const_length_ofTopLevelVariable_imported();
   }
@@ -515,12 +491,6 @@
 
   @override
   @failingTest
-  test_const_reference_staticField() async {
-    await super.test_const_reference_staticField();
-  }
-
-  @override
-  @failingTest
   test_const_reference_staticField_imported() async {
     await super.test_const_reference_staticField_imported();
   }
@@ -575,12 +545,6 @@
 
   @override
   @failingTest
-  test_const_reference_topLevelVariable() async {
-    await super.test_const_reference_topLevelVariable();
-  }
-
-  @override
-  @failingTest
   test_const_reference_topLevelVariable_imported() async {
     await super.test_const_reference_topLevelVariable_imported();
   }
@@ -623,12 +587,6 @@
 
   @override
   @failingTest
-  test_const_reference_unresolved_prefix1() async {
-    await super.test_const_reference_unresolved_prefix1();
-  }
-
-  @override
-  @failingTest
   test_const_reference_unresolved_prefix2() async {
     await super.test_const_reference_unresolved_prefix2();
   }
@@ -653,12 +611,6 @@
 
   @override
   @failingTest
-  test_const_topLevel_literal() async {
-    await super.test_const_topLevel_literal();
-  }
-
-  @override
-  @failingTest
   test_const_topLevel_parenthesis() async {
     await super.test_const_topLevel_parenthesis();
   }
@@ -707,18 +659,6 @@
 
   @override
   @failingTest
-  test_const_topLevel_untypedList() async {
-    await super.test_const_topLevel_untypedList();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_untypedMap() async {
-    await super.test_const_topLevel_untypedMap();
-  }
-
-  @override
-  @failingTest
   test_constExpr_pushReference_enum_field() async {
     await super.test_constExpr_pushReference_enum_field();
   }
@@ -1398,12 +1338,6 @@
 
   @override
   @failingTest
-  test_infer_property_set() async {
-    await super.test_infer_property_set();
-  }
-
-  @override
-  @failingTest
   test_inference_issue_32394() async {
     await super.test_inference_issue_32394();
   }
@@ -1697,60 +1631,18 @@
 
   @override
   @failingTest
-  test_metadata_classDeclaration() async {
-    await super.test_metadata_classDeclaration();
-  }
-
-  @override
-  @failingTest
-  test_metadata_classTypeAlias() async {
-    await super.test_metadata_classTypeAlias();
-  }
-
-  @override
-  @failingTest
-  test_metadata_constructor_call_named() async {
-    await super.test_metadata_constructor_call_named();
-  }
-
-  @override
-  @failingTest
   test_metadata_constructor_call_named_prefixed() async {
     await super.test_metadata_constructor_call_named_prefixed();
   }
 
   @override
   @failingTest
-  test_metadata_constructor_call_unnamed() async {
-    await super.test_metadata_constructor_call_unnamed();
-  }
-
-  @override
-  @failingTest
   test_metadata_constructor_call_unnamed_prefixed() async {
     await super.test_metadata_constructor_call_unnamed_prefixed();
   }
 
   @override
   @failingTest
-  test_metadata_constructor_call_with_args() async {
-    await super.test_metadata_constructor_call_with_args();
-  }
-
-  @override
-  @failingTest
-  test_metadata_constructorDeclaration_named() async {
-    await super.test_metadata_constructorDeclaration_named();
-  }
-
-  @override
-  @failingTest
-  test_metadata_constructorDeclaration_unnamed() async {
-    await super.test_metadata_constructorDeclaration_unnamed();
-  }
-
-  @override
-  @failingTest
   test_metadata_enumConstantDeclaration() async {
     await super.test_metadata_enumConstantDeclaration();
   }
@@ -1769,12 +1661,6 @@
 
   @override
   @failingTest
-  test_metadata_fieldDeclaration() async {
-    await super.test_metadata_fieldDeclaration();
-  }
-
-  @override
-  @failingTest
   test_metadata_fieldFormalParameter() async {
     await super.test_metadata_fieldFormalParameter();
   }
@@ -1787,30 +1673,6 @@
 
   @override
   @failingTest
-  test_metadata_functionDeclaration_function() async {
-    await super.test_metadata_functionDeclaration_function();
-  }
-
-  @override
-  @failingTest
-  test_metadata_functionDeclaration_getter() async {
-    await super.test_metadata_functionDeclaration_getter();
-  }
-
-  @override
-  @failingTest
-  test_metadata_functionDeclaration_setter() async {
-    await super.test_metadata_functionDeclaration_setter();
-  }
-
-  @override
-  @failingTest
-  test_metadata_functionTypeAlias() async {
-    await super.test_metadata_functionTypeAlias();
-  }
-
-  @override
-  @failingTest
   test_metadata_functionTypedFormalParameter() async {
     await super.test_metadata_functionTypedFormalParameter();
   }
@@ -1841,24 +1703,6 @@
 
   @override
   @failingTest
-  test_metadata_methodDeclaration_getter() async {
-    await super.test_metadata_methodDeclaration_getter();
-  }
-
-  @override
-  @failingTest
-  test_metadata_methodDeclaration_method() async {
-    await super.test_metadata_methodDeclaration_method();
-  }
-
-  @override
-  @failingTest
-  test_metadata_methodDeclaration_setter() async {
-    await super.test_metadata_methodDeclaration_setter();
-  }
-
-  @override
-  @failingTest
   test_metadata_partDirective() async {
     await super.test_metadata_partDirective();
   }
@@ -1883,12 +1727,6 @@
 
   @override
   @failingTest
-  test_metadata_topLevelVariableDeclaration() async {
-    await super.test_metadata_topLevelVariableDeclaration();
-  }
-
-  @override
-  @failingTest
   test_method_inferred_type_nonStatic_implicit_param() async {
     await super.test_method_inferred_type_nonStatic_implicit_param();
   }
@@ -1907,12 +1745,6 @@
 
   @override
   @failingTest
-  test_methodInvocation_implicitCall() async {
-    await super.test_methodInvocation_implicitCall();
-  }
-
-  @override
-  @failingTest
   test_mixin() async {
     await super.test_mixin();
   }
@@ -2305,43 +2137,18 @@
 
   @override
   @failingTest
-  test_unresolved_annotation_instanceCreation_argument_this() async {
-    await super.test_unresolved_annotation_instanceCreation_argument_this();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_namedConstructorCall_noClass() async {
-    await super.test_unresolved_annotation_namedConstructorCall_noClass();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_namedConstructorCall_noConstructor() async {
     await super.test_unresolved_annotation_namedConstructorCall_noConstructor();
   }
 
   @override
   @failingTest
-  test_unresolved_annotation_prefixedIdentifier_badPrefix() async {
-    await super.test_unresolved_annotation_prefixedIdentifier_badPrefix();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_prefixedIdentifier_noDeclaration() async {
     await super.test_unresolved_annotation_prefixedIdentifier_noDeclaration();
   }
 
   @override
   @failingTest
-  test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix() async {
-    await super
-        .test_unresolved_annotation_prefixedNamedConstructorCall_badPrefix();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_prefixedNamedConstructorCall_noClass() async {
     await super
         .test_unresolved_annotation_prefixedNamedConstructorCall_noClass();
@@ -2356,13 +2163,6 @@
 
   @override
   @failingTest
-  test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix() async {
-    await super
-        .test_unresolved_annotation_prefixedUnnamedConstructorCall_badPrefix();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass() async {
     await super
         .test_unresolved_annotation_prefixedUnnamedConstructorCall_noClass();
@@ -2370,18 +2170,6 @@
 
   @override
   @failingTest
-  test_unresolved_annotation_simpleIdentifier() async {
-    await super.test_unresolved_annotation_simpleIdentifier();
-  }
-
-  @override
-  @failingTest
-  test_unresolved_annotation_unnamedConstructorCall_noClass() async {
-    await super.test_unresolved_annotation_unnamedConstructorCall_noClass();
-  }
-
-  @override
-  @failingTest
   test_unresolved_export() async {
     await super.test_unresolved_export();
   }
@@ -2446,7 +2234,7 @@
     await super.test_variable_setterInPart_getterInPart();
   }
 
-  LinkResult _link(Reference root, Source source, String code) {
+  LinkResult _link(Source source, String code) {
     var unit = parseText(code, experimentStatus: experimentStatus);
 
     // TODO(scheglov) add other libraries
@@ -2454,11 +2242,9 @@
       source: {source: unit},
     };
 
-    var rootReference = Reference.root();
     return link(
       AnalysisOptionsImpl(),
       sourceFactory,
-      rootReference,
       [],
       libraryUnitMap,
     );
diff --git a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
index 3bcd3ea..53f650d 100644
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
@@ -6,6 +6,10 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/summary2/ast_binary_reader.dart';
 import 'package:analyzer/src/summary2/ast_binary_writer.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linking_bundle_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/tokens_writer.dart';
 import 'package:test/test.dart';
@@ -129,15 +133,20 @@
     );
     var tokensContext = tokensResult.toContext();
 
-    var writer = new AstBinaryWriter(tokensContext);
-    var builder = writer.writeNode(originalUnit);
-    writer.writeReferences();
+    var rootReference = Reference.root();
+    var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
 
-    var reader = AstBinaryReader(
-      Reference.root(),
-      writer.referencesBuilder,
-      writer.tokens,
+    var linkingBundleContext = LinkingBundleContext(dynamicRef);
+    var writer = new AstBinaryWriter(linkingBundleContext, tokensContext);
+    var builder = writer.writeNode(originalUnit);
+
+    var bundleContext = LinkedBundleContext(
+      LinkedElementFactory(null, null, rootReference),
+      linkingBundleContext.referencesBuilder,
     );
+    var unitContext = LinkedUnitContext(bundleContext, tokensContext);
+
+    var reader = AstBinaryReader(unitContext);
     var deserializedUnit = reader.readNode(builder);
     var deserializedCode = deserializedUnit.toSource();