Resolve types in scopes, resynthesize some elements.

Also some very basic top-level inference: field formal initializers in
constructors, initializers of top-level variables (for now ignoring
dependencies), setter return type to `void`.

We pass 172 or 590 resynthesis tests, about 29%.

Change-Id: Id70b80ceb7c794627626a1fe94172b0e9ccdda8b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/95672
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 8239a74..2ff8321 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -60,6 +60,10 @@
   /// given [offset] in the file that contains the declaration of this element.
   AbstractClassElementImpl(String name, int offset) : super(name, offset);
 
+  AbstractClassElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created class element to have the given [name].
   AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -414,9 +418,6 @@
   /// The unlinked representation of the class in the summary.
   final UnlinkedClass _unlinkedClass;
 
-  final Reference reference;
-  final LinkedNode _linkedNode;
-
   /// If this class is resynthesized, whether it has a constant constructor.
   bool _hasConstConstructorCached;
 
@@ -455,31 +456,25 @@
   /// Initialize a newly created class element to have the given [name] at the
   /// given [offset] in the file that contains the declaration of this element.
   ClassElementImpl(String name, int offset)
-      : reference = null,
-        _linkedNode = null,
-        _unlinkedClass = null,
+      : _unlinkedClass = null,
         super(name, offset);
 
-  ClassElementImpl.forLinkedNode(this.reference, this._linkedNode,
-      CompilationUnitElementImpl enclosingUnit)
+  ClassElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+      Reference reference, LinkedNode linkedNode)
       : _unlinkedClass = null,
-        super.forSerialized(enclosingUnit) {
-    reference.element = this;
+        super.forLinkedNode(enclosing, reference, linkedNode) {
+    enclosing.linkedContext.loadClassMemberReferences(reference);
   }
 
   /// Initialize a newly created class element to have the given [name].
   ClassElementImpl.forNode(Identifier name)
-      : reference = null,
-        _linkedNode = null,
-        _unlinkedClass = null,
+      : _unlinkedClass = null,
         super.forNode(name);
 
   /// Initialize using the given serialized information.
   ClassElementImpl.forSerialized(
       this._unlinkedClass, CompilationUnitElementImpl enclosingUnit)
-      : reference = null,
-        _linkedNode = null,
-        super.forSerialized(enclosingUnit);
+      : super.forSerialized(enclosingUnit);
 
   /// Set whether this class is abstract.
   void set abstract(bool isAbstract) {
@@ -489,6 +484,18 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    if (linkedNode != null) {
+      if (_accessors != null) return _accessors;
+
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        _createPropertiesAndAccessors();
+        assert(_accessors != null);
+        return _accessors;
+      } else {
+        return _accessors = const [];
+      }
+    }
     if (_accessors == null) {
       if (_unlinkedClass != null) {
         _resynthesizeFieldsAndPropertyAccessors();
@@ -536,16 +543,18 @@
       return _constructors = _computeMixinAppConstructors();
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@constructor');
-      _constructors = _linkedNode.classOrMixinDeclaration_members
-          .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
-          .map((node) {
-        var name = context.getConstructorDeclarationName(node);
-        var reference = containerRef.getChild(name);
-        return ConstructorElementImpl.forLinkedNode(reference, node, this);
-      }).toList();
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        _constructors = linkedNode.classOrMixinDeclaration_members
+            .where((node) => node.kind == LinkedNodeKind.constructorDeclaration)
+            .map((node) {
+          var name = context.getConstructorDeclarationName(node);
+          var reference = containerRef.getChild(name);
+          return ConstructorElementImpl.forLinkedNode(reference, node, this);
+        }).toList();
+      }
     }
 
     if (_unlinkedClass != null) {
@@ -601,6 +610,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedClass != null) {
       return _unlinkedClass.documentationComment?.text;
     }
@@ -612,6 +626,18 @@
 
   @override
   List<FieldElement> get fields {
+    if (linkedNode != null) {
+      if (_fields != null) return _fields;
+
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        _createPropertiesAndAccessors();
+        assert(_fields != null);
+        return _fields;
+      } else {
+        _fields = const [];
+      }
+    }
     if (_fields == null) {
       if (_unlinkedClass != null) {
         _resynthesizeFieldsAndPropertyAccessors();
@@ -710,13 +736,13 @@
       return _interfaces;
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
-      var implementsClause =
-          _linkedNode.classOrMixinDeclaration_implementsClause;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var implementsClause = context.getImplementsClause(linkedNode);
       if (implementsClause != null) {
         return _interfaces = implementsClause.implementsClause_interfaces
             .map((node) => context.getInterfaceType(node.typeName_type))
+            .where((type) => type != null)
             .toList();
       }
     } else if (_unlinkedClass != null) {
@@ -757,8 +783,12 @@
 
   @override
   bool get isAbstract {
-    if (_linkedNode != null) {
-      return _linkedNode.classDeclaration_abstractKeyword != 0;
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        return linkedNode.classDeclaration_abstractKeyword != 0;
+      } else {
+        return linkedNode.classTypeAlias_abstractKeyword != 0;
+      }
     }
     if (_unlinkedClass != null) {
       return _unlinkedClass.isAbstract;
@@ -768,6 +798,9 @@
 
   @override
   bool get isMixinApplication {
+    if (linkedNode != null) {
+      return linkedNode.kind == LinkedNodeKind.classTypeAlias;
+    }
     if (_unlinkedClass != null) {
       return _unlinkedClass.isMixinApplication;
     }
@@ -819,6 +852,24 @@
       return _methods;
     }
 
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@method');
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration ||
+          linkedNode.kind == LinkedNodeKind.mixinDeclaration) {
+        return _methods = linkedNode.classOrMixinDeclaration_members
+            .where((node) => node.kind == LinkedNodeKind.methodDeclaration)
+            .where((node) => node.methodDeclaration_propertyKeyword == 0)
+            .map((node) {
+          var name = context.getSimpleName(node.methodDeclaration_name);
+          var reference = containerRef.getChild(name);
+          return MethodElementImpl.forLinkedNode(reference, node, this);
+        }).toList();
+      } else {
+        return _methods = const <MethodElement>[];
+      }
+    }
+
     if (_unlinkedClass != null) {
       var unlinkedExecutables = _unlinkedClass.executables;
 
@@ -872,12 +923,18 @@
       return _mixins;
     }
 
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
-      var withClause = _linkedNode.classDeclaration_withClause;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      LinkedNode withClause;
+      if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+        withClause = linkedNode.classDeclaration_withClause;
+      } else {
+        withClause = linkedNode.classTypeAlias_withClause;
+      }
       if (withClause != null) {
         return _mixins = withClause.withClause_mixinTypes
             .map((node) => context.getInterfaceType(node.typeName_type))
+            .where((type) => type != null)
             .toList();
       }
     } else if (_unlinkedClass != null) {
@@ -923,7 +980,7 @@
 
   @override
   String get name {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     if (_unlinkedClass != null) {
@@ -949,13 +1006,17 @@
   @override
   InterfaceType get supertype {
     if (_supertype == null) {
-      if (_linkedNode != null) {
-        var context = enclosingUnit._linkedContext;
-        var extendsClause = _linkedNode.classDeclaration_extendsClause;
-        if (extendsClause != null) {
-          _supertype = context.getInterfaceType(
-            extendsClause.extendsClause_superclass.typeName_type,
-          );
+      if (linkedNode != null) {
+        var context = enclosingUnit.linkedContext;
+        LinkedNode superclass;
+        if (linkedNode.kind == LinkedNodeKind.classDeclaration) {
+          superclass = linkedNode
+              .classDeclaration_extendsClause?.extendsClause_superclass;
+        } else {
+          superclass = linkedNode.classTypeAlias_superclass;
+        }
+        if (superclass != null) {
+          _supertype = context.getInterfaceType(superclass.typeName_type);
         }
       } else if (_unlinkedClass != null) {
         if (_unlinkedClass.supertype != null) {
@@ -991,6 +1052,27 @@
     return _type;
   }
 
+  @override
+  List<TypeParameterElement> get typeParameters {
+    if (_typeParameterElements != null) return _typeParameterElements;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@typeParameter');
+      var typeParameters = context.getTypeParameters(linkedNode);
+      if (typeParameters == null) {
+        return _typeParameterElements = const [];
+      }
+      return _typeParameterElements = typeParameters.map((node) {
+        var name = context.getSimpleName(node.typeParameter_name);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
+    return super.typeParameters;
+  }
+
   /// Set the type parameters defined for this class to the given
   /// [typeParameters].
   void set typeParameters(List<TypeParameterElement> typeParameters) {
@@ -1208,6 +1290,75 @@
     }).toList(growable: false);
   }
 
+  void _createPropertiesAndAccessors() {
+    assert(_accessors == null);
+    assert(_fields == null);
+
+    var context = enclosingUnit.linkedContext;
+    var accessorList = <PropertyAccessorElementImpl>[];
+    var fieldList = <FieldElementImpl>[];
+
+    var fields = context.classFields(linkedNode);
+    for (var field in fields) {
+      var name = context.getVariableName(field);
+      var fieldElement = FieldElementImpl.forLinkedNodeFactory(
+        this,
+        reference.getChild('@field').getChild(name),
+        field,
+      );
+      fieldList.add(fieldElement);
+
+      accessorList.add(fieldElement.getter);
+      if (fieldElement.setter != null) {
+        accessorList.add(fieldElement.setter);
+      }
+    }
+
+    for (var node in linkedNode.classOrMixinDeclaration_members) {
+      if (node.kind == LinkedNodeKind.methodDeclaration) {
+        var isGetter = context.isGetterMethod(node);
+        var isSetter = context.isSetterMethod(node);
+        if (!isGetter && !isSetter) continue;
+
+        var name = context.getMethodName(node);
+        var containerRef = isGetter
+            ? reference.getChild('@getter')
+            : reference.getChild('@setter');
+
+        var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+          this,
+          containerRef.getChild(name),
+          node,
+        );
+        accessorList.add(accessorElement);
+
+        var fieldRef = reference.getChild('@field').getChild(name);
+        FieldElementImpl field = fieldRef.element;
+        if (field == null) {
+          field = new FieldElementImpl(name, -1);
+          fieldRef.element = field;
+          field.enclosingElement = this;
+          field.isSynthetic = true;
+          field.isFinal = isGetter;
+          field.isStatic = accessorElement.isStatic;
+          fieldList.add(field);
+        } else {
+          field.isFinal = false;
+        }
+
+        accessorElement.variable = field;
+        if (isGetter) {
+          field.getter = accessorElement;
+        } else {
+          field.setter = accessorElement;
+        }
+      }
+    }
+
+    _accessors = accessorList;
+    _fields = fieldList;
+  }
+
   /// Return `true` if the given [type] is an [InterfaceType] that can be used
   /// as a class.
   bool _isInterfaceTypeClass(DartType type) {
@@ -1412,9 +1563,7 @@
   /// The unlinked representation of the part in the summary.
   final UnlinkedPart _unlinkedPart;
 
-  final LinkedUnitContext _linkedContext;
-  final Reference reference;
-  final LinkedNode _linkedNode;
+  final LinkedUnitContext linkedContext;
 
   /// The source that corresponds to this compilation unit.
   @override
@@ -1477,27 +1626,20 @@
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        _linkedContext = null,
-        reference = null,
-        _linkedNode = null,
+        linkedContext = null,
         super(null, -1);
 
   CompilationUnitElementImpl.forLinkedNode(LibraryElementImpl enclosingLibrary,
-      this._linkedContext, this.reference, this._linkedNode)
+      this.linkedContext, Reference reference, LinkedNode linkedNode)
       : resynthesizerContext = null,
         _unlinkedUnit = null,
         _unlinkedPart = null,
-        super.forSerialized(null) {
-    _enclosingElement = enclosingLibrary;
-    _nameOffset = -1;
-  }
+        super.forLinkedNode(enclosingLibrary, reference, linkedNode);
 
   /// Initialize using the given serialized information.
   CompilationUnitElementImpl.forSerialized(LibraryElementImpl enclosingLibrary,
       this.resynthesizerContext, this._unlinkedUnit, this._unlinkedPart)
-      : _linkedContext = null,
-        reference = null,
-        _linkedNode = null,
+      : linkedContext = null,
         super.forSerialized(null) {
     _enclosingElement = enclosingLibrary;
     _nameOffset = -1;
@@ -1505,6 +1647,12 @@
 
   @override
   List<PropertyAccessorElement> get accessors {
+    if (linkedNode != null) {
+      if (_accessors != null) return _accessors;
+      _createPropertiesAndAccessors(this);
+      assert(_accessors != null);
+      return _accessors;
+    }
     if (_accessors == null) {
       if (_unlinkedUnit != null) {
         _explicitTopLevelAccessors ??=
@@ -1576,8 +1724,23 @@
 
   @override
   List<FunctionElement> get functions {
-    if (_unlinkedUnit != null) {
-      _functions ??= _unlinkedUnit.executables
+    if (_functions != null) return _functions;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@function');
+      _functions = linkedNode.compilationUnit_declarations
+          .where((node) =>
+              node.kind == LinkedNodeKind.functionDeclaration &&
+              !context.isGetterFunction(node) &&
+              !context.isSetterFunction(node))
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        return FunctionElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    } else if (_unlinkedUnit != null) {
+      _functions = _unlinkedUnit.executables
           .where((e) => e.kind == UnlinkedExecutableKind.functionOrMethod)
           .map((e) => new FunctionElementImpl.forSerialized(e, this))
           .toList(growable: false);
@@ -1657,6 +1820,12 @@
 
   @override
   List<TopLevelVariableElement> get topLevelVariables {
+    if (linkedNode != null) {
+      if (_variables != null) return _variables;
+      _createPropertiesAndAccessors(this);
+      assert(_variables != null);
+      return _variables;
+    }
     if (_variables == null) {
       if (_unlinkedUnit != null) {
         _explicitTopLevelAccessors ??=
@@ -1711,15 +1880,18 @@
 
   @override
   List<ClassElement> get types {
-    if (_linkedNode != null) {
-      var context = enclosingUnit._linkedContext;
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@class');
-      _types = _linkedNode.compilationUnit_declarations
-          .where((node) => node.kind == LinkedNodeKind.classDeclaration)
+      _types = linkedNode.compilationUnit_declarations
+          .where((node) =>
+              node.kind == LinkedNodeKind.classDeclaration ||
+              node.kind == LinkedNodeKind.classTypeAlias)
           .map((node) {
         var name = context.getUnitMemberName(node);
         var reference = containerRef.getChild(name);
-        return ClassElementImpl.forLinkedNode(reference, node, this);
+        reference.node = node;
+        return ClassElementImpl.forLinkedNode(this, reference, node);
       }).toList();
     } else if (_unlinkedUnit != null) {
       _types ??= _unlinkedUnit.classes
@@ -1880,6 +2052,89 @@
     }
     return null;
   }
+
+  static void _createPropertiesAndAccessors(CompilationUnitElementImpl unit) {
+    if (unit._variables != null) return;
+    assert(unit._accessors == null);
+
+    var accessorMap =
+        <CompilationUnitElementImpl, List<PropertyAccessorElementImpl>>{};
+    var variableMap =
+        <CompilationUnitElementImpl, List<TopLevelVariableElementImpl>>{};
+
+    var units = unit.library.units;
+    for (CompilationUnitElementImpl unit in units) {
+      var context = unit.linkedContext;
+
+      var accessorList = <PropertyAccessorElementImpl>[];
+      accessorMap[unit] = accessorList;
+
+      var variableList = <TopLevelVariableElementImpl>[];
+      variableMap[unit] = variableList;
+
+      var variables = context.topLevelVariables(unit.linkedNode);
+      for (var variable in variables) {
+        var name = context.getVariableName(variable);
+        var reference = unit.reference.getChild('@variable').getChild(name);
+        var variableElement = TopLevelVariableElementImpl.forLinkedNodeFactory(
+          unit,
+          reference,
+          variable,
+        );
+        variableList.add(variableElement);
+
+        accessorList.add(variableElement.getter);
+        if (variableElement.setter != null) {
+          accessorList.add(variableElement.setter);
+        }
+      }
+
+      for (var node in unit.linkedNode.compilationUnit_declarations) {
+        if (node.kind == LinkedNodeKind.functionDeclaration) {
+          var isGetter = context.isGetterFunction(node);
+          var isSetter = context.isSetterFunction(node);
+          if (!isGetter && !isSetter) continue;
+
+          var name = context.getUnitMemberName(node);
+          var containerRef = isGetter
+              ? unit.reference.getChild('@getter')
+              : unit.reference.getChild('@setter');
+
+          var accessorElement = PropertyAccessorElementImpl.forLinkedNode(
+            unit,
+            containerRef.getChild(name),
+            node,
+          );
+          accessorList.add(accessorElement);
+
+          var fieldRef = unit.reference.getChild('@field').getChild(name);
+          TopLevelVariableElementImpl field = fieldRef.element;
+          if (field == null) {
+            field = new TopLevelVariableElementImpl(name, -1);
+            fieldRef.element = field;
+            field.enclosingElement = unit;
+            field.isSynthetic = true;
+            field.isFinal = isGetter;
+            variableList.add(field);
+          } else {
+            field.isFinal = false;
+          }
+
+          accessorElement.variable = field;
+          if (isGetter) {
+            field.getter = accessorElement;
+          } else {
+            field.setter = accessorElement;
+          }
+        }
+      }
+    }
+
+    for (CompilationUnitElementImpl unit in units) {
+      unit._accessors = accessorMap[unit];
+      unit._variables = variableMap[unit];
+    }
+  }
 }
 
 /// A [FieldElement] for a 'const' or 'final' field that has an initializer.
@@ -1895,6 +2150,10 @@
   /// [name] and [offset].
   ConstFieldElementImpl(String name, int offset) : super(name, offset);
 
+  ConstFieldElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created field element to have the given [name].
   ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -2080,34 +2339,21 @@
   @override
   bool isConstantEvaluated = false;
 
-  final Reference reference;
-  final LinkedNode _linkedNode;
+  /// Initialize a newly created constructor element to have the given [name]
+  /// and [offset].
+  ConstructorElementImpl(String name, int offset) : super(name, offset);
 
-  /// Initialize a newly created constructor element to have the given [name
-  /// ] and[offset].
-  ConstructorElementImpl(String name, int offset)
-      : reference = null,
-        _linkedNode = null,
-        super(name, offset);
-
-  ConstructorElementImpl.forLinkedNode(
-      this.reference, this._linkedNode, ClassElementImpl enclosingClass)
-      : super.forLinkedNode(enclosingClass) {
-    reference.element = this;
-  }
+  ConstructorElementImpl.forLinkedNode(Reference reference,
+      LinkedNode linkedNode, ClassElementImpl enclosingClass)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode);
 
   /// Initialize a newly created constructor element to have the given [name].
-  ConstructorElementImpl.forNode(Identifier name)
-      : reference = null,
-        _linkedNode = null,
-        super.forNode(name);
+  ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
 
   /// Initialize using the given serialized information.
   ConstructorElementImpl.forSerialized(
       UnlinkedExecutable serializedExecutable, ClassElementImpl enclosingClass)
-      : reference = null,
-        _linkedNode = null,
-        super.forSerialized(serializedExecutable, enclosingClass);
+      : super.forSerialized(serializedExecutable, enclosingClass);
 
   /// Return the constant initializers for this element, which will be empty if
   /// there are no initializers, or `null` if there was an error in the source.
@@ -2130,7 +2376,7 @@
 
   @override
   String get displayName {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     return super.displayName;
@@ -2152,8 +2398,8 @@
 
   @override
   bool get isConst {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_constKeyword != 0;
+    if (linkedNode != null) {
+      return linkedNode.constructorDeclaration_constKeyword != 0;
     }
     if (serializedExecutable != null) {
       return serializedExecutable.isConst;
@@ -2200,17 +2446,9 @@
   }
 
   @override
-  bool get isExternal {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_externalKeyword != 0;
-    }
-    return super.isExternal;
-  }
-
-  @override
   bool get isFactory {
-    if (_linkedNode != null) {
-      return _linkedNode.constructorDeclaration_factoryKeyword != 0;
+    if (linkedNode != null) {
+      return linkedNode.constructorDeclaration_factoryKeyword != 0;
     }
     if (serializedExecutable != null) {
       return serializedExecutable.isFactory;
@@ -2222,19 +2460,11 @@
   bool get isStatic => false;
 
   @override
-  bool get isSynthetic {
-    if (_linkedNode != null) {
-      return _linkedNode.isSynthetic;
-    }
-    return super.isSynthetic;
-  }
-
-  @override
   ElementKind get kind => ElementKind.CONSTRUCTOR;
 
   @override
   String get name {
-    if (_linkedNode != null) {
+    if (linkedNode != null) {
       return reference.name;
     }
     return super.name;
@@ -2415,6 +2645,10 @@
   ConstTopLevelVariableElementImpl(String name, int offset)
       : super(name, offset);
 
+  ConstTopLevelVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created top-level variable element to have the given
   /// [name].
   ConstTopLevelVariableElementImpl.forNode(Identifier name)
@@ -2448,11 +2682,16 @@
   EvaluationResultImpl _evaluationResult;
 
   Expression get constantInitializer {
-    if (_constantInitializer == null) {
-      if (_unlinkedConst != null) {
-        _constantInitializer = enclosingUnit.resynthesizerContext
-            .buildExpression(this, _unlinkedConst);
-      }
+    if (_constantInitializer != null) return _constantInitializer;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      return _constantInitializer = context.readInitializer(linkedNode);
+    }
+
+    if (_unlinkedConst != null) {
+      _constantInitializer = enclosingUnit.resynthesizerContext
+          .buildExpression(this, _unlinkedConst);
     }
     return _constantInitializer;
   }
@@ -2807,6 +3046,9 @@
   /// root of the element structure.
   ElementImpl _enclosingElement;
 
+  final Reference reference;
+  final LinkedNode linkedNode;
+
   /// The name of this element.
   String _name;
 
@@ -2838,19 +3080,26 @@
 
   /// Initialize a newly created element to have the given [name] at the given
   /// [_nameOffset].
-  ElementImpl(String name, this._nameOffset) {
+  ElementImpl(String name, this._nameOffset)
+      : reference = null,
+        linkedNode = null {
     this._name = StringUtilities.intern(name);
   }
 
   /// Initialize from linked node.
-  ElementImpl.forLinkedNode(this._enclosingElement);
+  ElementImpl.forLinkedNode(
+      this._enclosingElement, this.reference, this.linkedNode) {
+    reference.element = this;
+  }
 
   /// Initialize a newly created element to have the given [name].
   ElementImpl.forNode(Identifier name)
       : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
 
   /// Initialize from serialized information.
-  ElementImpl.forSerialized(this._enclosingElement);
+  ElementImpl.forSerialized(this._enclosingElement)
+      : reference = null,
+        linkedNode = null;
 
   /// The length of the element's code, or `null` if the element is synthetic.
   int get codeLength => _codeLength;
@@ -3100,7 +3349,12 @@
   bool get isResynthesized => enclosingUnit?.resynthesizerContext != null;
 
   @override
-  bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
+  bool get isSynthetic {
+    if (linkedNode != null) {
+      return linkedNode.isSynthetic;
+    }
+    return hasModifier(Modifier.SYNTHETIC);
+  }
 
   /// Set whether this element is synthetic.
   void set isSynthetic(bool isSynthetic) {
@@ -3157,8 +3411,6 @@
     _nameOffset = offset;
   }
 
-  Reference get reference => null;
-
   @override
   AnalysisSession get session {
     return _enclosingElement?.session;
@@ -3784,9 +4036,12 @@
         super(name, offset);
 
   /// Initialize using the given linked node.
-  ExecutableElementImpl.forLinkedNode(ElementImpl enclosingElement)
+  ExecutableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
       : serializedExecutable = null,
-        super.forLinkedNode(enclosingElement);
+        super.forLinkedNode(enclosing, reference, linkedNode) {
+    reference.element = this;
+  }
 
   /// Initialize a newly created executable element to have the given [name].
   ExecutableElementImpl.forNode(Identifier name)
@@ -3827,6 +4082,9 @@
 
   @override
   String get displayName {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -3835,6 +4093,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.documentationComment?.text;
     }
@@ -3878,6 +4141,9 @@
 
   @override
   bool get isAsynchronous {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isAsynchronous(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isAsynchronous;
     }
@@ -3886,6 +4152,9 @@
 
   @override
   bool get isExternal {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isExternal(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isExternal;
     }
@@ -3894,6 +4163,9 @@
 
   @override
   bool get isGenerator {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isGenerator(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isGenerator;
     }
@@ -3917,6 +4189,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -3925,6 +4200,12 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.namedCompilationUnitMember_name,
+      );
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && serializedExecutable != null) {
       return serializedExecutable.nameOffset;
@@ -3935,6 +4216,25 @@
   @override
   List<ParameterElement> get parameters {
     if (_parameters == null) {
+      if (linkedNode != null) {
+        var context = enclosingUnit.linkedContext;
+        var containerRef = reference.getChild('@parameter');
+        var formalParameters = context.getFormalParameters(linkedNode);
+        if (formalParameters != null) {
+          _parameters = formalParameters.map((node) {
+            var name = context.getFormalParameterName(node);
+            var reference = containerRef.getChild(name);
+            reference.node = node;
+            return ParameterElementImpl.forLinkedNodeFactory(
+              this,
+              reference,
+              node,
+            );
+          }).toList();
+        } else {
+          _parameters = const [];
+        }
+      }
       if (serializedExecutable != null) {
         _parameters = ParameterElementImpl.resynthesizeList(
             serializedExecutable.parameters, this);
@@ -3955,6 +4255,10 @@
 
   @override
   DartType get returnType {
+    if (linkedNode != null) {
+      return _returnType ??=
+          enclosingUnit.linkedContext.getReturnType(linkedNode);
+    }
     if (serializedExecutable != null &&
         _declaredReturnType == null &&
         _returnType == null) {
@@ -4228,6 +4532,34 @@
   /// [name] at the given [offset].
   FieldElementImpl(String name, int offset) : super(name, offset);
 
+  FieldElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (!linkedNode.isSynthetic) {
+      var getter = PropertyAccessorElementImpl_ImplicitGetter(this);
+      enclosing.reference.getChild('@getter').getChild(name).element = getter;
+      this.getter = getter;
+
+      if (!isConst && !isFinal) {
+        var setter = PropertyAccessorElementImpl_ImplicitSetter(this);
+        enclosing.reference.getChild('@setter').getChild(name).element = setter;
+        this.setter = setter;
+      }
+    }
+  }
+
+  factory FieldElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+      return ConstFieldElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    }
+    return FieldElementImpl.forLinkedNode(enclosing, reference, linkedNode);
+  }
+
   /// Initialize a newly created field element to have the given [name].
   FieldElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -4275,6 +4607,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isStatic(linkedNode);
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.isStatic;
     }
@@ -4320,6 +4655,10 @@
   FieldFormalParameterElementImpl(String name, int nameOffset)
       : super(name, nameOffset);
 
+  FieldFormalParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created parameter element to have the given [name].
   FieldFormalParameterElementImpl.forNode(Identifier name)
       : super.forNode(name);
@@ -4362,6 +4701,11 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      return _type ??= enclosingUnit.linkedContext.getType(
+        linkedNode.fieldFormalParameter_type2,
+      );
+    }
     if (unlinkedParam != null &&
         unlinkedParam.type == null &&
         !unlinkedParam.isFunctionTyped &&
@@ -4396,6 +4740,10 @@
   /// [offset].
   FunctionElementImpl(String name, int offset) : super(name, offset);
 
+  FunctionElementImpl.forLinkedNode(CompilationUnitElementImpl enclosingUnit,
+      Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosingUnit, reference, linkedNode);
+
   /// Initialize a newly created function element to have the given [name].
   FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -4447,6 +4795,16 @@
   ElementKind get kind => ElementKind.FUNCTION;
 
   @override
+  DartType get returnType {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getType(
+        linkedNode.functionDeclaration_returnType2,
+      );
+    }
+    return super.returnType;
+  }
+
+  @override
   SourceRange get visibleRange {
     if (serializedExecutable != null) {
       if (serializedExecutable.visibleLength == 0) {
@@ -6163,6 +6521,10 @@
   /// given [offset].
   MethodElementImpl(String name, int offset) : super(name, offset);
 
+  MethodElementImpl.forLinkedNode(Reference reference, LinkedNode linkedNode,
+      ClassElementImpl enclosingClass)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode);
+
   /// Initialize a newly created method element to have the given [name].
   MethodElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -6194,6 +6556,14 @@
       super.enclosingElement as ClassElementImpl;
 
   @override
+  bool get isAbstract {
+    if (linkedNode != null) {
+      return !isExternal && enclosingUnit.linkedContext.isAbstract(linkedNode);
+    }
+    return super.isAbstract;
+  }
+
+  @override
   bool get isOperator {
     String name = displayName;
     if (name.isEmpty) {
@@ -6208,6 +6578,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return linkedNode.methodDeclaration_modifierKeyword != 0;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isStatic;
     }
@@ -6233,6 +6606,16 @@
   }
 
   @override
+  DartType get returnType {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getType(
+        linkedNode.methodDeclaration_returnType2,
+      );
+    }
+    return super.returnType;
+  }
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
   @override
@@ -6772,6 +7155,11 @@
       : _unlinkedVariable = null,
         super(name, offset);
 
+  NonParameterVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : _unlinkedVariable = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created variable element to have the given [name].
   NonParameterVariableElementImpl.forNode(Identifier name)
       : _unlinkedVariable = null,
@@ -6800,6 +7188,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.variableDeclaration_declaration.comment,
+      );
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.documentationComment?.text;
     }
@@ -6883,6 +7276,11 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleName(
+        linkedNode.variableDeclaration_name,
+      );
+    }
     if (_unlinkedVariable != null) {
       return _unlinkedVariable.name;
     }
@@ -6891,6 +7289,11 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.variableDeclaration_name,
+      );
+    }
     int offset = super.nameOffset;
     if (offset == 0) {
       if (_unlinkedVariable != null) {
@@ -6959,6 +7362,31 @@
       : unlinkedParam = null,
         super(name, nameOffset);
 
+  ParameterElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : unlinkedParam = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
+  factory ParameterElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    var kind = linkedNode.kind;
+    if (kind == LinkedNodeKind.fieldFormalParameter) {
+      return FieldFormalParameterElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    } else if (kind == LinkedNodeKind.simpleFormalParameter) {
+      return ParameterElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   /// Initialize a newly created parameter element to have the given [name].
   ParameterElementImpl.forNode(Identifier name)
       : unlinkedParam = null,
@@ -7110,6 +7538,9 @@
 
   @override
   bool get isCovariant {
+    if (linkedNode != null) {
+      return linkedNode.normalFormalParameter_isCovariant;
+    }
     if (isExplicitlyCovariant || inheritsCovariant) {
       return true;
     }
@@ -7133,6 +7564,12 @@
 
   @override
   bool get isFinal {
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.fieldFormalParameter) {
+        return false;
+      }
+      return linkedNode.simpleFormalParameter_keyword != 0;
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.isFinal;
     }
@@ -7168,6 +7605,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (unlinkedParam != null) {
       return unlinkedParam.name;
     }
@@ -7176,6 +7616,12 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.normalFormalParameter_identifier,
+      );
+    }
+
     int offset = super.nameOffset;
     if (offset == 0) {
       if (unlinkedParam != null) {
@@ -7193,7 +7639,13 @@
 
   @override
   ParameterKind get parameterKind {
-    if (unlinkedParam != null && _parameterKind == null) {
+    if (_parameterKind != null) return _parameterKind;
+
+    if (linkedNode != null) {
+      // TODO(scheglov) implement
+      _parameterKind = ParameterKind.REQUIRED;
+    }
+    if (unlinkedParam != null) {
       switch (unlinkedParam.kind) {
         case UnlinkedParamKind.named:
           _parameterKind = ParameterKind.NAMED;
@@ -7221,6 +7673,12 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      if (_type != null) return _type;
+      return _type ??= enclosingUnit.linkedContext.getType(
+        linkedNode.simpleFormalParameter_type2,
+      );
+    }
     _resynthesizeTypeAndParameters();
     return super.type;
   }
@@ -7518,6 +7976,10 @@
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
 
+  PropertyAccessorElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created property accessor element to have the given
   /// [name].
   PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7587,7 +8049,18 @@
   }
 
   @override
+  bool get isAbstract {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isAbstract(linkedNode);
+    }
+    return super.isAbstract;
+  }
+
+  @override
   bool get isGetter {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isGetter(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.kind == UnlinkedExecutableKind.getter;
     }
@@ -7596,6 +8069,9 @@
 
   @override
   bool get isSetter {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isSetter(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.kind == UnlinkedExecutableKind.setter;
     }
@@ -7604,6 +8080,9 @@
 
   @override
   bool get isStatic {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isStatic(linkedNode);
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.isStatic ||
           variable is TopLevelVariableElement;
@@ -7627,6 +8106,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (serializedExecutable != null) {
       return serializedExecutable.name;
     }
@@ -7759,6 +8241,10 @@
   /// [offset].
   PropertyInducingElementImpl(String name, int offset) : super(name, offset);
 
+  PropertyInducingElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created element to have the given [name].
   PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -7779,6 +8265,12 @@
 
   @override
   DartType get type {
+    if (linkedNode != null) {
+      if (_type != null) return _type;
+      return _type = enclosingUnit.linkedContext.getType(
+        linkedNode.variableDeclaration_type2,
+      );
+    }
     if (isSynthetic && _type == null) {
       if (getter != null) {
         _type = getter.returnType;
@@ -7950,6 +8442,38 @@
   /// the given [name] and [offset].
   TopLevelVariableElementImpl(String name, int offset) : super(name, offset);
 
+  TopLevelVariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (!linkedNode.isSynthetic) {
+      var getter = PropertyAccessorElementImpl_ImplicitGetter(this);
+      enclosing.reference.getChild('@getter').getChild(name).element = getter;
+      this.getter = getter;
+
+      if (!isConst && !isFinal) {
+        var setter = PropertyAccessorElementImpl_ImplicitSetter(this);
+        enclosing.reference.getChild('@setter').getChild(name).element = setter;
+        this.setter = setter;
+      }
+    }
+  }
+
+  factory TopLevelVariableElementImpl.forLinkedNodeFactory(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode) {
+    if (enclosing.enclosingUnit.linkedContext.isConst(linkedNode)) {
+      return ConstTopLevelVariableElementImpl.forLinkedNode(
+        enclosing,
+        reference,
+        linkedNode,
+      );
+    }
+    return TopLevelVariableElementImpl.forLinkedNode(
+      enclosing,
+      reference,
+      linkedNode,
+    );
+  }
+
   /// Initialize a newly created top-level variable element to have the given
   /// [name].
   TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);
@@ -7996,6 +8520,13 @@
       : _unlinkedTypeParam = null,
         super(name, offset);
 
+  TypeParameterElementImpl.forLinkedNode(
+      TypeParameterizedElementMixin enclosing,
+      Reference reference,
+      LinkedNode linkedNode)
+      : _unlinkedTypeParam = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created type parameter element to have the given
   /// [name].
   TypeParameterElementImpl.forNode(Identifier name)
@@ -8067,6 +8598,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedTypeParam != null) {
       return _unlinkedTypeParam.name;
     }
@@ -8243,6 +8777,10 @@
   /// [offset]. The offset may be `-1` if the element is synthetic.
   UriReferencedElementImpl(String name, int offset) : super(name, offset);
 
+  UriReferencedElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize using the given serialized information.
   UriReferencedElementImpl.forSerialized(ElementImpl enclosingElement)
       : super.forSerialized(enclosingElement);
@@ -8303,6 +8841,10 @@
   /// [offset].
   VariableElementImpl(String name, int offset) : super(name, offset);
 
+  VariableElementImpl.forLinkedNode(
+      ElementImpl enclosing, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created variable element to have the given [name].
   VariableElementImpl.forNode(Identifier name) : super.forNode(name);
 
@@ -8366,6 +8908,9 @@
 
   @override
   bool get isConst {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isConst(linkedNode);
+    }
     return hasModifier(Modifier.CONST);
   }
 
@@ -8379,6 +8924,9 @@
 
   @override
   bool get isFinal {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.isFinal(linkedNode);
+    }
     return hasModifier(Modifier.FINAL);
   }
 
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index f77a8b6..2143074 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4571,6 +4571,7 @@
   bool _variantField_31;
   String _variantField_20;
   String _variantField_22;
+  LinkedNodeVariablesDeclarationBuilder _variantField_32;
 
   @override
   List<LinkedNodeBuilder> get adjacentStrings_strings {
@@ -8781,6 +8782,12 @@
   }
 
   @override
+  int get methodDeclaration_actualProperty {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_19 ??= 0;
+  }
+
+  @override
   int get normalFormalParameter_covariantKeyword {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8862,6 +8869,12 @@
     _variantField_19 = value;
   }
 
+  void set methodDeclaration_actualProperty(int value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    assert(value == null || value >= 0);
+    _variantField_19 = value;
+  }
+
   void set normalFormalParameter_covariantKeyword(int value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -8906,6 +8919,18 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get fieldFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get functionDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -8913,27 +8938,70 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get methodDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    return _variantField_24;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get simpleFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get typeName_type {
     assert(kind == idl.LinkedNodeKind.typeName);
     return _variantField_24;
   }
 
+  @override
+  LinkedNodeTypeBuilder get variableDeclaration_type2 {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_24;
+  }
+
   void set binaryExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.binaryExpression);
     _variantField_24 = value;
   }
 
+  void set fieldFormalParameter_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    _variantField_24 = value;
+  }
+
+  void set functionDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    _variantField_24 = value;
+  }
+
   void set invocationExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
     _variantField_24 = value;
   }
 
+  void set methodDeclaration_returnType2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_24 = value;
+  }
+
+  void set simpleFormalParameter_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_24 = value;
+  }
+
   void set typeName_type(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.typeName);
     _variantField_24 = value;
   }
 
+  void set variableDeclaration_type2(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_24 = value;
+  }
+
   @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
@@ -8947,6 +9015,14 @@
   }
 
   @override
+  bool get normalFormalParameter_isCovariant {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_27 ??= false;
+  }
+
+  @override
   bool get setOrMapLiteral_isMap {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     return _variantField_27 ??= false;
@@ -8962,6 +9038,13 @@
     _variantField_27 = value;
   }
 
+  void set normalFormalParameter_isCovariant(bool value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_27 = value;
+  }
+
   void set setOrMapLiteral_isMap(bool value) {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     _variantField_27 = value;
@@ -9454,6 +9537,18 @@
     _variantField_22 = value;
   }
 
+  @override
+  LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_32;
+  }
+
+  void set variableDeclaration_declaration(
+      LinkedNodeVariablesDeclarationBuilder value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 = value;
+  }
+
   LinkedNodeBuilder.adjacentStrings({
     List<LinkedNodeBuilder> adjacentStrings_strings,
     LinkedNodeTypeBuilder expression_type,
@@ -9862,6 +9957,7 @@
     int functionDeclaration_externalKeyword,
     LinkedNodeBuilder functionDeclaration_returnType,
     int functionDeclaration_propertyKeyword,
+    LinkedNodeTypeBuilder functionDeclaration_returnType2,
     LinkedNodeBuilder namedCompilationUnitMember_name,
   })  : _kind = idl.LinkedNodeKind.functionDeclaration,
         _variantField_11 = annotatedNode_comment,
@@ -9870,6 +9966,7 @@
         _variantField_15 = functionDeclaration_externalKeyword,
         _variantField_7 = functionDeclaration_returnType,
         _variantField_16 = functionDeclaration_propertyKeyword,
+        _variantField_24 = functionDeclaration_returnType2,
         _variantField_14 = namedCompilationUnitMember_name;
 
   LinkedNodeBuilder.functionTypeAlias({
@@ -9933,6 +10030,8 @@
     int methodDeclaration_modifierKeyword,
     int methodDeclaration_operatorKeyword,
     int methodDeclaration_propertyKeyword,
+    int methodDeclaration_actualProperty,
+    LinkedNodeTypeBuilder methodDeclaration_returnType2,
     LinkedNodeBuilder methodDeclaration_typeParameters,
     LinkedNodeBuilder methodDeclaration_name,
   })  : _kind = idl.LinkedNodeKind.methodDeclaration,
@@ -9945,6 +10044,8 @@
         _variantField_16 = methodDeclaration_modifierKeyword,
         _variantField_17 = methodDeclaration_operatorKeyword,
         _variantField_18 = methodDeclaration_propertyKeyword,
+        _variantField_19 = methodDeclaration_actualProperty,
+        _variantField_24 = methodDeclaration_returnType2,
         _variantField_9 = methodDeclaration_typeParameters,
         _variantField_10 = methodDeclaration_name;
 
@@ -10039,12 +10140,16 @@
     LinkedNodeBuilder variableDeclaration_initializer,
     int variableDeclaration_equals,
     LinkedNodeBuilder variableDeclaration_name,
+    LinkedNodeTypeBuilder variableDeclaration_type2,
+    LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
   })  : _kind = idl.LinkedNodeKind.variableDeclaration,
         _variantField_11 = annotatedNode_comment,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = variableDeclaration_initializer,
         _variantField_15 = variableDeclaration_equals,
-        _variantField_7 = variableDeclaration_name;
+        _variantField_7 = variableDeclaration_name,
+        _variantField_24 = variableDeclaration_type2,
+        _variantField_32 = variableDeclaration_declaration;
 
   LinkedNodeBuilder.fieldFormalParameter({
     List<LinkedNodeBuilder> normalFormalParameter_metadata,
@@ -10055,6 +10160,8 @@
     int fieldFormalParameter_period,
     int fieldFormalParameter_thisKeyword,
     int normalFormalParameter_covariantKeyword,
+    LinkedNodeTypeBuilder fieldFormalParameter_type2,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10067,6 +10174,8 @@
         _variantField_16 = fieldFormalParameter_period,
         _variantField_17 = fieldFormalParameter_thisKeyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_24 = fieldFormalParameter_type2,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10077,6 +10186,7 @@
     LinkedNodeBuilder functionTypedFormalParameter_returnType,
     LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
     int normalFormalParameter_covariantKeyword,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10086,6 +10196,7 @@
         _variantField_7 = functionTypedFormalParameter_returnType,
         _variantField_8 = functionTypedFormalParameter_typeParameters,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10095,6 +10206,8 @@
     LinkedNodeBuilder simpleFormalParameter_type,
     int simpleFormalParameter_keyword,
     int normalFormalParameter_covariantKeyword,
+    LinkedNodeTypeBuilder simpleFormalParameter_type2,
+    bool normalFormalParameter_isCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
@@ -10103,6 +10216,8 @@
         _variantField_6 = simpleFormalParameter_type,
         _variantField_15 = simpleFormalParameter_keyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
+        _variantField_24 = simpleFormalParameter_type2,
+        _variantField_27 = normalFormalParameter_isCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
@@ -10899,6 +11014,7 @@
     _variantField_10?.flushInformative();
     _variantField_25?.flushInformative();
     _variantField_14?.flushInformative();
+    _variantField_32?.flushInformative();
   }
 
   /**
@@ -10985,6 +11101,8 @@
         this._variantField_29 == null ? 0 : this._variantField_29.index);
     signature.addString(this._variantField_30 ?? '');
     signature.addBool(this._variantField_31 == true);
+    signature.addBool(this._variantField_32 != null);
+    this._variantField_32?.collectApiSignature(signature);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -11008,6 +11126,7 @@
     fb.Offset offset_variantField_23;
     fb.Offset offset_variantField_20;
     fb.Offset offset_variantField_22;
+    fb.Offset offset_variantField_32;
     if (!(_variantField_2 == null || _variantField_2.isEmpty)) {
       offset_variantField_2 = fbBuilder
           .writeList(_variantField_2.map((b) => b.finish(fbBuilder)).toList());
@@ -11072,6 +11191,9 @@
     if (_variantField_22 != null) {
       offset_variantField_22 = fbBuilder.writeString(_variantField_22);
     }
+    if (_variantField_32 != null) {
+      offset_variantField_32 = _variantField_32.finish(fbBuilder);
+    }
     fbBuilder.startTable();
     if (offset_variantField_2 != null) {
       fbBuilder.addOffset(2, offset_variantField_2);
@@ -11171,6 +11293,9 @@
     if (offset_variantField_22 != null) {
       fbBuilder.addOffset(22, offset_variantField_22);
     }
+    if (offset_variantField_32 != null) {
+      fbBuilder.addOffset(32, offset_variantField_32);
+    }
     return fbBuilder.endTable();
   }
 }
@@ -11223,6 +11348,7 @@
   bool _variantField_31;
   String _variantField_20;
   String _variantField_22;
+  idl.LinkedNodeVariablesDeclaration _variantField_32;
 
   @override
   List<idl.LinkedNode> get adjacentStrings_strings {
@@ -14174,6 +14300,14 @@
   }
 
   @override
+  int get methodDeclaration_actualProperty {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_19 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+    return _variantField_19;
+  }
+
+  @override
   int get normalFormalParameter_covariantKeyword {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -14229,6 +14363,22 @@
   }
 
   @override
+  idl.LinkedNodeType get fieldFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get functionDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.functionDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -14238,6 +14388,22 @@
   }
 
   @override
+  idl.LinkedNodeType get methodDeclaration_returnType2 {
+    assert(kind == idl.LinkedNodeKind.methodDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
+  idl.LinkedNodeType get simpleFormalParameter_type2 {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get typeName_type {
     assert(kind == idl.LinkedNodeKind.typeName);
     _variantField_24 ??=
@@ -14246,6 +14412,14 @@
   }
 
   @override
+  idl.LinkedNodeType get variableDeclaration_type2 {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     _variantField_27 ??=
@@ -14262,6 +14436,16 @@
   }
 
   @override
+  bool get normalFormalParameter_isCovariant {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
   bool get setOrMapLiteral_isMap {
     assert(kind == idl.LinkedNodeKind.setOrMapLiteral);
     _variantField_27 ??=
@@ -14601,6 +14785,14 @@
         const fb.StringReader().vTableGet(_bc, _bcOffset, 22, '');
     return _variantField_22;
   }
+
+  @override
+  idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
+    assert(kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
+        .vTableGet(_bc, _bcOffset, 32, null);
+    return _variantField_32;
+  }
 }
 
 abstract class _LinkedNodeMixin implements idl.LinkedNode {
@@ -15119,6 +15311,9 @@
       if (functionDeclaration_propertyKeyword != 0)
         _result["functionDeclaration_propertyKeyword"] =
             functionDeclaration_propertyKeyword;
+      if (functionDeclaration_returnType2 != null)
+        _result["functionDeclaration_returnType2"] =
+            functionDeclaration_returnType2.toJson();
       if (namedCompilationUnitMember_name != null)
         _result["namedCompilationUnitMember_name"] =
             namedCompilationUnitMember_name.toJson();
@@ -15207,6 +15402,12 @@
       if (methodDeclaration_propertyKeyword != 0)
         _result["methodDeclaration_propertyKeyword"] =
             methodDeclaration_propertyKeyword;
+      if (methodDeclaration_actualProperty != 0)
+        _result["methodDeclaration_actualProperty"] =
+            methodDeclaration_actualProperty;
+      if (methodDeclaration_returnType2 != null)
+        _result["methodDeclaration_returnType2"] =
+            methodDeclaration_returnType2.toJson();
       if (methodDeclaration_typeParameters != null)
         _result["methodDeclaration_typeParameters"] =
             methodDeclaration_typeParameters.toJson();
@@ -15326,6 +15527,12 @@
         _result["variableDeclaration_equals"] = variableDeclaration_equals;
       if (variableDeclaration_name != null)
         _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+      if (variableDeclaration_type2 != null)
+        _result["variableDeclaration_type2"] =
+            variableDeclaration_type2.toJson();
+      if (variableDeclaration_declaration != null)
+        _result["variableDeclaration_declaration"] =
+            variableDeclaration_declaration.toJson();
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
       if (normalFormalParameter_metadata.isNotEmpty)
@@ -15352,6 +15559,12 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (fieldFormalParameter_type2 != null)
+        _result["fieldFormalParameter_type2"] =
+            fieldFormalParameter_type2.toJson();
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15380,6 +15593,9 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -15405,6 +15621,12 @@
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
+      if (simpleFormalParameter_type2 != null)
+        _result["simpleFormalParameter_type2"] =
+            simpleFormalParameter_type2.toJson();
+      if (normalFormalParameter_isCovariant != false)
+        _result["normalFormalParameter_isCovariant"] =
+            normalFormalParameter_isCovariant;
       if (normalFormalParameter_identifier != null)
         _result["normalFormalParameter_identifier"] =
             normalFormalParameter_identifier.toJson();
@@ -16589,6 +16811,7 @@
         "functionDeclaration_returnType": functionDeclaration_returnType,
         "functionDeclaration_propertyKeyword":
             functionDeclaration_propertyKeyword,
+        "functionDeclaration_returnType2": functionDeclaration_returnType2,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -16646,6 +16869,8 @@
         "methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
         "methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
         "methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
+        "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
+        "methodDeclaration_returnType2": methodDeclaration_returnType2,
         "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
         "methodDeclaration_name": methodDeclaration_name,
         "isSynthetic": isSynthetic,
@@ -16732,8 +16957,10 @@
         "variableDeclaration_initializer": variableDeclaration_initializer,
         "variableDeclaration_equals": variableDeclaration_equals,
         "variableDeclaration_name": variableDeclaration_name,
+        "variableDeclaration_type2": variableDeclaration_type2,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "variableDeclaration_declaration": variableDeclaration_declaration,
       };
     }
     if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
@@ -16749,6 +16976,8 @@
         "fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "fieldFormalParameter_type2": fieldFormalParameter_type2,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16767,6 +16996,7 @@
             functionTypedFormalParameter_typeParameters,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -16781,6 +17011,8 @@
         "simpleFormalParameter_keyword": simpleFormalParameter_keyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
+        "simpleFormalParameter_type2": simpleFormalParameter_type2,
+        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
@@ -17547,58 +17779,53 @@
 class LinkedNodeBundleBuilder extends Object
     with _LinkedNodeBundleMixin
     implements idl.LinkedNodeBundle {
-  LinkedNodeBuilder _node;
-  LinkedNodeReferenceBuilder _references;
-  UnlinkedTokensBuilder _tokens;
+  List<LinkedNodeLibraryBuilder> _libraries;
+  LinkedNodeReferencesBuilder _references;
 
   @override
-  LinkedNodeBuilder get node => _node;
+  List<LinkedNodeLibraryBuilder> get libraries =>
+      _libraries ??= <LinkedNodeLibraryBuilder>[];
 
-  void set node(LinkedNodeBuilder value) {
-    this._node = value;
+  void set libraries(List<LinkedNodeLibraryBuilder> value) {
+    this._libraries = value;
   }
 
   @override
-  LinkedNodeReferenceBuilder get references => _references;
+  LinkedNodeReferencesBuilder get references => _references;
 
-  void set references(LinkedNodeReferenceBuilder value) {
+  /// The shared list of references used in the [libraries].
+  void set references(LinkedNodeReferencesBuilder value) {
     this._references = value;
   }
 
-  @override
-  UnlinkedTokensBuilder get tokens => _tokens;
-
-  void set tokens(UnlinkedTokensBuilder value) {
-    this._tokens = value;
-  }
-
   LinkedNodeBundleBuilder(
-      {LinkedNodeBuilder node,
-      LinkedNodeReferenceBuilder references,
-      UnlinkedTokensBuilder tokens})
-      : _node = node,
-        _references = references,
-        _tokens = tokens;
+      {List<LinkedNodeLibraryBuilder> libraries,
+      LinkedNodeReferencesBuilder references})
+      : _libraries = libraries,
+        _references = references;
 
   /**
    * Flush [informative] data recursively.
    */
   void flushInformative() {
-    _node?.flushInformative();
+    _libraries?.forEach((b) => b.flushInformative());
     _references?.flushInformative();
-    _tokens?.flushInformative();
   }
 
   /**
    * Accumulate non-[informative] data into [signature].
    */
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addBool(this._tokens != null);
-    this._tokens?.collectApiSignature(signature);
     signature.addBool(this._references != null);
     this._references?.collectApiSignature(signature);
-    signature.addBool(this._node != null);
-    this._node?.collectApiSignature(signature);
+    if (this._libraries == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._libraries.length);
+      for (var x in this._libraries) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   List<int> toBuffer() {
@@ -17607,27 +17834,21 @@
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
-    fb.Offset offset_node;
+    fb.Offset offset_libraries;
     fb.Offset offset_references;
-    fb.Offset offset_tokens;
-    if (_node != null) {
-      offset_node = _node.finish(fbBuilder);
+    if (!(_libraries == null || _libraries.isEmpty)) {
+      offset_libraries = fbBuilder
+          .writeList(_libraries.map((b) => b.finish(fbBuilder)).toList());
     }
     if (_references != null) {
       offset_references = _references.finish(fbBuilder);
     }
-    if (_tokens != null) {
-      offset_tokens = _tokens.finish(fbBuilder);
-    }
     fbBuilder.startTable();
-    if (offset_node != null) {
-      fbBuilder.addOffset(2, offset_node);
+    if (offset_libraries != null) {
+      fbBuilder.addOffset(1, offset_libraries);
     }
     if (offset_references != null) {
-      fbBuilder.addOffset(1, offset_references);
-    }
-    if (offset_tokens != null) {
-      fbBuilder.addOffset(0, offset_tokens);
+      fbBuilder.addOffset(0, offset_references);
     }
     return fbBuilder.endTable();
   }
@@ -17654,55 +17875,206 @@
 
   _LinkedNodeBundleImpl(this._bc, this._bcOffset);
 
-  idl.LinkedNode _node;
-  idl.LinkedNodeReference _references;
-  idl.UnlinkedTokens _tokens;
+  List<idl.LinkedNodeLibrary> _libraries;
+  idl.LinkedNodeReferences _references;
 
   @override
-  idl.LinkedNode get node {
-    _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
-    return _node;
+  List<idl.LinkedNodeLibrary> get libraries {
+    _libraries ??= const fb.ListReader<idl.LinkedNodeLibrary>(
+            const _LinkedNodeLibraryReader())
+        .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeLibrary>[]);
+    return _libraries;
   }
 
   @override
-  idl.LinkedNodeReference get references {
+  idl.LinkedNodeReferences get references {
     _references ??=
-        const _LinkedNodeReferenceReader().vTableGet(_bc, _bcOffset, 1, null);
+        const _LinkedNodeReferencesReader().vTableGet(_bc, _bcOffset, 0, null);
     return _references;
   }
-
-  @override
-  idl.UnlinkedTokens get tokens {
-    _tokens ??=
-        const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 0, null);
-    return _tokens;
-  }
 }
 
 abstract class _LinkedNodeBundleMixin implements idl.LinkedNodeBundle {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
-    if (node != null) _result["node"] = node.toJson();
+    if (libraries.isNotEmpty)
+      _result["libraries"] =
+          libraries.map((_value) => _value.toJson()).toList();
     if (references != null) _result["references"] = references.toJson();
-    if (tokens != null) _result["tokens"] = tokens.toJson();
     return _result;
   }
 
   @override
   Map<String, Object> toMap() => {
-        "node": node,
+        "libraries": libraries,
         "references": references,
-        "tokens": tokens,
       };
 
   @override
   String toString() => convert.json.encode(toJson());
 }
 
-class LinkedNodeReferenceBuilder extends Object
-    with _LinkedNodeReferenceMixin
-    implements idl.LinkedNodeReference {
+class LinkedNodeLibraryBuilder extends Object
+    with _LinkedNodeLibraryMixin
+    implements idl.LinkedNodeLibrary {
+  List<int> _exports;
+  List<LinkedNodeUnitBuilder> _units;
+  String _uriStr;
+
+  @override
+  List<int> get exports => _exports ??= <int>[];
+
+  void set exports(List<int> value) {
+    assert(value == null || value.every((e) => e >= 0));
+    this._exports = value;
+  }
+
+  @override
+  List<LinkedNodeUnitBuilder> get units => _units ??= <LinkedNodeUnitBuilder>[];
+
+  void set units(List<LinkedNodeUnitBuilder> value) {
+    this._units = value;
+  }
+
+  @override
+  String get uriStr => _uriStr ??= '';
+
+  void set uriStr(String value) {
+    this._uriStr = value;
+  }
+
+  LinkedNodeLibraryBuilder(
+      {List<int> exports, List<LinkedNodeUnitBuilder> units, String uriStr})
+      : _exports = exports,
+        _units = units,
+        _uriStr = uriStr;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _units?.forEach((b) => b.flushInformative());
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._uriStr ?? '');
+    if (this._units == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._units.length);
+      for (var x in this._units) {
+        x?.collectApiSignature(signature);
+      }
+    }
+    if (this._exports == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._exports.length);
+      for (var x in this._exports) {
+        signature.addInt(x);
+      }
+    }
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_exports;
+    fb.Offset offset_units;
+    fb.Offset offset_uriStr;
+    if (!(_exports == null || _exports.isEmpty)) {
+      offset_exports = fbBuilder.writeListUint32(_exports);
+    }
+    if (!(_units == null || _units.isEmpty)) {
+      offset_units =
+          fbBuilder.writeList(_units.map((b) => b.finish(fbBuilder)).toList());
+    }
+    if (_uriStr != null) {
+      offset_uriStr = fbBuilder.writeString(_uriStr);
+    }
+    fbBuilder.startTable();
+    if (offset_exports != null) {
+      fbBuilder.addOffset(2, offset_exports);
+    }
+    if (offset_units != null) {
+      fbBuilder.addOffset(1, offset_units);
+    }
+    if (offset_uriStr != null) {
+      fbBuilder.addOffset(0, offset_uriStr);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeLibraryReader extends fb.TableReader<_LinkedNodeLibraryImpl> {
+  const _LinkedNodeLibraryReader();
+
+  @override
+  _LinkedNodeLibraryImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeLibraryImpl(bc, offset);
+}
+
+class _LinkedNodeLibraryImpl extends Object
+    with _LinkedNodeLibraryMixin
+    implements idl.LinkedNodeLibrary {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeLibraryImpl(this._bc, this._bcOffset);
+
+  List<int> _exports;
+  List<idl.LinkedNodeUnit> _units;
+  String _uriStr;
+
+  @override
+  List<int> get exports {
+    _exports ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 2, const <int>[]);
+    return _exports;
+  }
+
+  @override
+  List<idl.LinkedNodeUnit> get units {
+    _units ??=
+        const fb.ListReader<idl.LinkedNodeUnit>(const _LinkedNodeUnitReader())
+            .vTableGet(_bc, _bcOffset, 1, const <idl.LinkedNodeUnit>[]);
+    return _units;
+  }
+
+  @override
+  String get uriStr {
+    _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _uriStr;
+  }
+}
+
+abstract class _LinkedNodeLibraryMixin implements idl.LinkedNodeLibrary {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (exports.isNotEmpty) _result["exports"] = exports;
+    if (units.isNotEmpty)
+      _result["units"] = units.map((_value) => _value.toJson()).toList();
+    if (uriStr != '') _result["uriStr"] = uriStr;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "exports": exports,
+        "units": units,
+        "uriStr": uriStr,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeReferencesBuilder extends Object
+    with _LinkedNodeReferencesMixin
+    implements idl.LinkedNodeReferences {
   List<String> _name;
   List<int> _parent;
 
@@ -17721,7 +18093,7 @@
     this._parent = value;
   }
 
-  LinkedNodeReferenceBuilder({List<String> name, List<int> parent})
+  LinkedNodeReferencesBuilder({List<String> name, List<int> parent})
       : _name = name,
         _parent = parent;
 
@@ -17773,22 +18145,22 @@
   }
 }
 
-class _LinkedNodeReferenceReader
-    extends fb.TableReader<_LinkedNodeReferenceImpl> {
-  const _LinkedNodeReferenceReader();
+class _LinkedNodeReferencesReader
+    extends fb.TableReader<_LinkedNodeReferencesImpl> {
+  const _LinkedNodeReferencesReader();
 
   @override
-  _LinkedNodeReferenceImpl createObject(fb.BufferContext bc, int offset) =>
-      new _LinkedNodeReferenceImpl(bc, offset);
+  _LinkedNodeReferencesImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeReferencesImpl(bc, offset);
 }
 
-class _LinkedNodeReferenceImpl extends Object
-    with _LinkedNodeReferenceMixin
-    implements idl.LinkedNodeReference {
+class _LinkedNodeReferencesImpl extends Object
+    with _LinkedNodeReferencesMixin
+    implements idl.LinkedNodeReferences {
   final fb.BufferContext _bc;
   final int _bcOffset;
 
-  _LinkedNodeReferenceImpl(this._bc, this._bcOffset);
+  _LinkedNodeReferencesImpl(this._bc, this._bcOffset);
 
   List<String> _name;
   List<int> _parent;
@@ -17808,7 +18180,7 @@
   }
 }
 
-abstract class _LinkedNodeReferenceMixin implements idl.LinkedNodeReference {
+abstract class _LinkedNodeReferencesMixin implements idl.LinkedNodeReferences {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
@@ -17842,7 +18214,7 @@
   List<int> get functionFormalParameters =>
       _functionFormalParameters ??= <int>[];
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   void set functionFormalParameters(List<int> value) {
     assert(value == null || value.every((e) => e >= 0));
     this._functionFormalParameters = value;
@@ -17858,7 +18230,7 @@
   @override
   List<int> get functionTypeParameters => _functionTypeParameters ??= <int>[];
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   void set functionTypeParameters(List<int> value) {
     assert(value == null || value.every((e) => e >= 0));
     this._functionTypeParameters = value;
@@ -17867,7 +18239,7 @@
   @override
   int get interfaceClass => _interfaceClass ??= 0;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   void set interfaceClass(int value) {
     assert(value == null || value >= 0);
     this._interfaceClass = value;
@@ -17891,7 +18263,7 @@
   @override
   int get typeParameterParameter => _typeParameterParameter ??= 0;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   void set typeParameterParameter(int value) {
     assert(value == null || value >= 0);
     this._typeParameterParameter = value;
@@ -18113,6 +18485,302 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class LinkedNodeUnitBuilder extends Object
+    with _LinkedNodeUnitMixin
+    implements idl.LinkedNodeUnit {
+  LinkedNodeBuilder _node;
+  UnlinkedTokensBuilder _tokens;
+  String _uriStr;
+
+  @override
+  LinkedNodeBuilder get node => _node;
+
+  void set node(LinkedNodeBuilder value) {
+    this._node = value;
+  }
+
+  @override
+  UnlinkedTokensBuilder get tokens => _tokens;
+
+  void set tokens(UnlinkedTokensBuilder value) {
+    this._tokens = value;
+  }
+
+  @override
+  String get uriStr => _uriStr ??= '';
+
+  void set uriStr(String value) {
+    this._uriStr = value;
+  }
+
+  LinkedNodeUnitBuilder(
+      {LinkedNodeBuilder node, UnlinkedTokensBuilder tokens, String uriStr})
+      : _node = node,
+        _tokens = tokens,
+        _uriStr = uriStr;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _node?.flushInformative();
+    _tokens?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._uriStr ?? '');
+    signature.addBool(this._tokens != null);
+    this._tokens?.collectApiSignature(signature);
+    signature.addBool(this._node != null);
+    this._node?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_node;
+    fb.Offset offset_tokens;
+    fb.Offset offset_uriStr;
+    if (_node != null) {
+      offset_node = _node.finish(fbBuilder);
+    }
+    if (_tokens != null) {
+      offset_tokens = _tokens.finish(fbBuilder);
+    }
+    if (_uriStr != null) {
+      offset_uriStr = fbBuilder.writeString(_uriStr);
+    }
+    fbBuilder.startTable();
+    if (offset_node != null) {
+      fbBuilder.addOffset(2, offset_node);
+    }
+    if (offset_tokens != null) {
+      fbBuilder.addOffset(1, offset_tokens);
+    }
+    if (offset_uriStr != null) {
+      fbBuilder.addOffset(0, offset_uriStr);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeUnitReader extends fb.TableReader<_LinkedNodeUnitImpl> {
+  const _LinkedNodeUnitReader();
+
+  @override
+  _LinkedNodeUnitImpl createObject(fb.BufferContext bc, int offset) =>
+      new _LinkedNodeUnitImpl(bc, offset);
+}
+
+class _LinkedNodeUnitImpl extends Object
+    with _LinkedNodeUnitMixin
+    implements idl.LinkedNodeUnit {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeUnitImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNode _node;
+  idl.UnlinkedTokens _tokens;
+  String _uriStr;
+
+  @override
+  idl.LinkedNode get node {
+    _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
+    return _node;
+  }
+
+  @override
+  idl.UnlinkedTokens get tokens {
+    _tokens ??=
+        const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 1, null);
+    return _tokens;
+  }
+
+  @override
+  String get uriStr {
+    _uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _uriStr;
+  }
+}
+
+abstract class _LinkedNodeUnitMixin implements idl.LinkedNodeUnit {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (node != null) _result["node"] = node.toJson();
+    if (tokens != null) _result["tokens"] = tokens.toJson();
+    if (uriStr != '') _result["uriStr"] = uriStr;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "node": node,
+        "tokens": tokens,
+        "uriStr": uriStr,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
+class LinkedNodeVariablesDeclarationBuilder extends Object
+    with _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  LinkedNodeBuilder _comment;
+  bool _isConst;
+  bool _isFinal;
+  bool _isStatic;
+
+  @override
+  LinkedNodeBuilder get comment => _comment;
+
+  void set comment(LinkedNodeBuilder value) {
+    this._comment = value;
+  }
+
+  @override
+  bool get isConst => _isConst ??= false;
+
+  void set isConst(bool value) {
+    this._isConst = value;
+  }
+
+  @override
+  bool get isFinal => _isFinal ??= false;
+
+  void set isFinal(bool value) {
+    this._isFinal = value;
+  }
+
+  @override
+  bool get isStatic => _isStatic ??= false;
+
+  void set isStatic(bool value) {
+    this._isStatic = value;
+  }
+
+  LinkedNodeVariablesDeclarationBuilder(
+      {LinkedNodeBuilder comment, bool isConst, bool isFinal, bool isStatic})
+      : _comment = comment,
+        _isConst = isConst,
+        _isFinal = isFinal,
+        _isStatic = isStatic;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _comment?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addBool(this._isConst == true);
+    signature.addBool(this._isFinal == true);
+    signature.addBool(this._isStatic == true);
+    signature.addBool(this._comment != null);
+    this._comment?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_comment;
+    if (_comment != null) {
+      offset_comment = _comment.finish(fbBuilder);
+    }
+    fbBuilder.startTable();
+    if (offset_comment != null) {
+      fbBuilder.addOffset(3, offset_comment);
+    }
+    if (_isConst == true) {
+      fbBuilder.addBool(0, true);
+    }
+    if (_isFinal == true) {
+      fbBuilder.addBool(1, true);
+    }
+    if (_isStatic == true) {
+      fbBuilder.addBool(2, true);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeVariablesDeclarationReader
+    extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
+  const _LinkedNodeVariablesDeclarationReader();
+
+  @override
+  _LinkedNodeVariablesDeclarationImpl createObject(
+          fb.BufferContext bc, int offset) =>
+      new _LinkedNodeVariablesDeclarationImpl(bc, offset);
+}
+
+class _LinkedNodeVariablesDeclarationImpl extends Object
+    with _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNode _comment;
+  bool _isConst;
+  bool _isFinal;
+  bool _isStatic;
+
+  @override
+  idl.LinkedNode get comment {
+    _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 3, null);
+    return _comment;
+  }
+
+  @override
+  bool get isConst {
+    _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 0, false);
+    return _isConst;
+  }
+
+  @override
+  bool get isFinal {
+    _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
+    return _isFinal;
+  }
+
+  @override
+  bool get isStatic {
+    _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
+    return _isStatic;
+  }
+}
+
+abstract class _LinkedNodeVariablesDeclarationMixin
+    implements idl.LinkedNodeVariablesDeclaration {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (comment != null) _result["comment"] = comment.toJson();
+    if (isConst != false) _result["isConst"] = isConst;
+    if (isFinal != false) _result["isFinal"] = isFinal;
+    if (isStatic != false) _result["isStatic"] = isStatic;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "comment": comment,
+        "isConst": isConst,
+        "isFinal": isFinal,
+        "isStatic": isStatic,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class LinkedReferenceBuilder extends Object
     with _LinkedReferenceMixin
     implements idl.LinkedReference {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index bb8bc6b..56e0d73 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1791,19 +1791,30 @@
   variantField_20:string (id: 20);
 
   variantField_22:string (id: 22);
+
+  variantField_32:LinkedNodeVariablesDeclaration (id: 32);
 }
 
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
 table LinkedNodeBundle {
-  node:LinkedNode (id: 2);
+  libraries:[LinkedNodeLibrary] (id: 1);
 
-  references:LinkedNodeReference (id: 1);
+  /// The shared list of references used in the [libraries].
+  references:LinkedNodeReferences (id: 0);
+}
 
-  tokens:UnlinkedTokens (id: 0);
+/// Information about a single library in a [LinkedNodeBundle].
+table LinkedNodeLibrary {
+  exports:[uint] (id: 2);
+
+  units:[LinkedNodeUnit] (id: 1);
+
+  uriStr:string (id: 0);
 }
 
 /// Flattened tree of declarations referenced from [LinkedNode]s.
-table LinkedNodeReference {
+table LinkedNodeReferences {
   name:[string] (id: 1);
 
   parent:[uint] (id: 0);
@@ -1811,25 +1822,46 @@
 
 /// Information about a Dart type.
 table LinkedNodeType {
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   functionFormalParameters:[uint] (id: 0);
 
   functionReturnType:LinkedNodeType (id: 1);
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   functionTypeParameters:[uint] (id: 2);
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   interfaceClass:uint (id: 3);
 
   interfaceTypeArguments:[LinkedNodeType] (id: 4);
 
   kind:LinkedNodeTypeKind (id: 5);
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   typeParameterParameter:uint (id: 6);
 }
 
+/// Information about a single library in a [LinkedNodeLibrary].
+table LinkedNodeUnit {
+  node:LinkedNode (id: 2);
+
+  tokens:UnlinkedTokens (id: 1);
+
+  uriStr:string (id: 0);
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+table LinkedNodeVariablesDeclaration {
+  comment:LinkedNode (id: 3);
+
+  isConst:bool (id: 0);
+
+  isFinal:bool (id: 1);
+
+  isStatic:bool (id: 2);
+}
+
 /// Information about the resolution of an [UnlinkedReference].
 table LinkedReference {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index b25b830..94b4c25 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1338,6 +1338,9 @@
   @VariantId(6, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_type;
 
+  @VariantId(24, variant: LinkedNodeKind.fieldFormalParameter)
+  LinkedNodeType get fieldFormalParameter_type2;
+
   @VariantId(7, variant: LinkedNodeKind.fieldFormalParameter)
   LinkedNode get fieldFormalParameter_typeParameters;
 
@@ -1459,6 +1462,9 @@
   @VariantId(7, variant: LinkedNodeKind.functionDeclaration)
   LinkedNode get functionDeclaration_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.functionDeclaration)
+  LinkedNodeType get functionDeclaration_returnType2;
+
   @VariantId(6, variant: LinkedNodeKind.functionDeclarationStatement)
   LinkedNode get functionDeclarationStatement_functionDeclaration;
 
@@ -1696,6 +1702,9 @@
   @VariantId(7, variant: LinkedNodeKind.mapLiteralEntry)
   LinkedNode get mapLiteralEntry_value;
 
+  @VariantId(19, variant: LinkedNodeKind.methodDeclaration)
+  int get methodDeclaration_actualProperty;
+
   @VariantId(6, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_body;
 
@@ -1720,6 +1729,9 @@
   @VariantId(8, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_returnType;
 
+  @VariantId(24, variant: LinkedNodeKind.methodDeclaration)
+  LinkedNodeType get methodDeclaration_returnType2;
+
   @VariantId(9, variant: LinkedNodeKind.methodDeclaration)
   LinkedNode get methodDeclaration_typeParameters;
 
@@ -1804,6 +1816,13 @@
   ])
   LinkedNode get normalFormalParameter_identifier;
 
+  @VariantId(27, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+  ])
+  bool get normalFormalParameter_isCovariant;
+
   @VariantId(4, variantList: [
     LinkedNodeKind.fieldFormalParameter,
     LinkedNodeKind.functionTypedFormalParameter,
@@ -1931,6 +1950,9 @@
   @VariantId(6, variant: LinkedNodeKind.simpleFormalParameter)
   LinkedNode get simpleFormalParameter_type;
 
+  @VariantId(24, variant: LinkedNodeKind.simpleFormalParameter)
+  LinkedNodeType get simpleFormalParameter_type2;
+
   @VariantId(15, variant: LinkedNodeKind.simpleIdentifier)
   int get simpleIdentifier_element;
 
@@ -2140,6 +2162,9 @@
   ])
   int get uriBasedDirective_uriElement;
 
+  @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
+
   @VariantId(15, variant: LinkedNodeKind.variableDeclaration)
   int get variableDeclaration_equals;
 
@@ -2149,6 +2174,9 @@
   @VariantId(7, variant: LinkedNodeKind.variableDeclaration)
   LinkedNode get variableDeclaration_name;
 
+  @VariantId(24, variant: LinkedNodeKind.variableDeclaration)
+  LinkedNodeType get variableDeclaration_type2;
+
   @VariantId(15, variant: LinkedNodeKind.variableDeclarationList)
   int get variableDeclarationList_keyword;
 
@@ -2198,20 +2226,19 @@
   int get yieldStatement_yieldKeyword;
 }
 
-/// TODO(scheglov) extend to support multiple libraries or remove
+/// Information about a group of libraries linked together, for example because
+/// they form a single cycle, or because they represent a single build artifact.
 @TopLevel('LNBn')
 abstract class LinkedNodeBundle extends base.SummaryClass {
   factory LinkedNodeBundle.fromBuffer(List<int> buffer) =>
       generated.readLinkedNodeBundle(buffer);
 
-  @Id(2)
-  LinkedNode get node;
-
   @Id(1)
-  LinkedNodeReference get references;
+  List<LinkedNodeLibrary> get libraries;
 
+  /// The shared list of references used in the [libraries].
   @Id(0)
-  UnlinkedTokens get tokens;
+  LinkedNodeReferences get references;
 }
 
 /// Types of comments.
@@ -2344,8 +2371,20 @@
   yieldStatement,
 }
 
+/// Information about a single library in a [LinkedNodeBundle].
+abstract class LinkedNodeLibrary extends base.SummaryClass {
+  @Id(2)
+  List<int> get exports;
+
+  @Id(1)
+  List<LinkedNodeUnit> get units;
+
+  @Id(0)
+  String get uriStr;
+}
+
 /// Flattened tree of declarations referenced from [LinkedNode]s.
-abstract class LinkedNodeReference extends base.SummaryClass {
+abstract class LinkedNodeReferences extends base.SummaryClass {
   @Id(1)
   List<String> get name;
 
@@ -2355,18 +2394,18 @@
 
 /// Information about a Dart type.
 abstract class LinkedNodeType extends base.SummaryClass {
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   @Id(0)
   List<int> get functionFormalParameters;
 
   @Id(1)
   LinkedNodeType get functionReturnType;
 
-  /// References to [LinkedNodeReference].
+  /// References to [LinkedNodeReferences].
   @Id(2)
   List<int> get functionTypeParameters;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   @Id(3)
   int get interfaceClass;
 
@@ -2376,7 +2415,7 @@
   @Id(5)
   LinkedNodeTypeKind get kind;
 
-  /// Reference to a [LinkedNodeReference].
+  /// Reference to a [LinkedNodeReferences].
   @Id(6)
   int get typeParameterParameter;
 }
@@ -2391,6 +2430,34 @@
   void_
 }
 
+/// Information about a single library in a [LinkedNodeLibrary].
+abstract class LinkedNodeUnit extends base.SummaryClass {
+  @Id(2)
+  LinkedNode get node;
+
+  @Id(1)
+  UnlinkedTokens get tokens;
+
+  @Id(0)
+  String get uriStr;
+}
+
+/// Information about a top-level declaration, or a field declaration that
+/// contributes information to [LinkedNodeKind.variableDeclaration].
+abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
+  @Id(3)
+  LinkedNode get comment;
+
+  @Id(0)
+  bool get isConst;
+
+  @Id(1)
+  bool get isFinal;
+
+  @Id(2)
+  bool get isStatic;
+}
+
 /// Information about the resolution of an [UnlinkedReference].
 abstract class LinkedReference extends base.SummaryClass {
   /// If this [LinkedReference] doesn't have an associated [UnlinkedReference],
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index f8490e1..f68c463 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -18,7 +18,7 @@
 /// Deserializer of fully resolved ASTs from flat buffers.
 class AstBinaryReader {
   final Reference _nameRoot;
-  final LinkedNodeReference _linkedReferences;
+  final LinkedNodeReferences _linkedReferences;
   final List<Reference> _references;
 
   final UnlinkedTokens _tokensBinary;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 185370e..8a9076d 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -19,13 +19,18 @@
 /// Serializer of fully resolved ASTs into flat buffers.
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
   final referenceRoot = Reference.root();
-  final referenceBuilder = LinkedNodeReferenceBuilder();
+  final referencesBuilder = LinkedNodeReferencesBuilder();
   final _references = <Reference>[];
 
   final UnlinkedTokensBuilder tokens = UnlinkedTokensBuilder();
   final Map<Token, int> _tokenMap = Map.identity();
   int _tokenIndex = 0;
 
+  /// This field is set temporary while visiting [FieldDeclaration] or
+  /// [TopLevelVariableDeclaration] to store data shared among all variables
+  /// in these declarations.
+  LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
+
   AstBinaryWriter() {
     _references.add(referenceRoot);
     _addToken(
@@ -452,6 +457,10 @@
 
   @override
   LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
+    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
+      isStatic: node.isStatic,
+    );
+
     var builder = LinkedNodeBuilder.fieldDeclaration(
       fieldDeclaration_covariantKeyword: _getToken(node.covariantKeyword),
       fieldDeclaration_fields: node.fields.accept(this),
@@ -459,6 +468,10 @@
       fieldDeclaration_staticKeyword: _getToken(node.staticKeyword),
     );
     _storeClassMember(builder, node);
+
+    _variablesDeclaration.comment = builder.annotatedNode_comment;
+    _variablesDeclaration = null;
+
     return builder;
   }
 
@@ -1133,11 +1146,17 @@
   @override
   LinkedNodeBuilder visitTopLevelVariableDeclaration(
       TopLevelVariableDeclaration node) {
+    _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
+
     var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
       topLevelVariableDeclaration_semicolon: _getToken(node.semicolon),
       topLevelVariableDeclaration_variableList: node.variables?.accept(this),
     );
     _storeCompilationUnitMember(builder, node);
+
+    _variablesDeclaration.comment = builder.annotatedNode_comment;
+    _variablesDeclaration = null;
+
     return builder;
   }
 
@@ -1196,11 +1215,17 @@
       variableDeclaration_equals: _getToken(node.equals),
       variableDeclaration_initializer: node.initializer?.accept(this),
       variableDeclaration_name: node.name.accept(this),
+      variableDeclaration_declaration: _variablesDeclaration,
     );
   }
 
   @override
   LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
+    if (_variablesDeclaration != null) {
+      _variablesDeclaration.isConst = node.isConst;
+      _variablesDeclaration.isFinal = node.isFinal;
+    }
+
     var builder = LinkedNodeBuilder.variableDeclarationList(
       variableDeclarationList_keyword: _getToken(node.keyword),
       variableDeclarationList_type: node.type?.accept(this),
@@ -1255,11 +1280,11 @@
     return node.accept(this);
   }
 
-  /// Write [referenceRoot] and all its children into [referenceBuilder].
+  /// Write [referenceRoot] and all its children into [referencesBuilder].
   void writeReferences() {
     for (var reference in _references) {
-      referenceBuilder.parent.add(reference.parent?.index ?? 0);
-      referenceBuilder.name.add(reference.name);
+      referencesBuilder.parent.add(reference.parent?.index ?? 0);
+      referencesBuilder.name.add(reference.name);
     }
   }
 
@@ -1298,12 +1323,17 @@
 
     Reference result;
     if (element is ClassElement) {
-      var containerRef = _getReference(element.library).getChild('@class');
+      var enclosingRef = _getReference(element.enclosingElement);
+      var containerRef = enclosingRef.getChild('@class');
       _ensureReferenceIndex(containerRef);
 
       result = containerRef.getChild(element.name);
     } else if (element is CompilationUnitElement) {
-      return _getReference(element.enclosingElement);
+      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');
@@ -1319,13 +1349,14 @@
 
       result = containerRef.getChild(element.name);
     } else if (element is FunctionElement) {
-      var containerRef = _getReference(element.library).getChild('@function');
+      var enclosingRef = _getReference(element.enclosingElement);
+      var containerRef = enclosingRef.getChild('@function');
       _ensureReferenceIndex(containerRef);
 
       result = containerRef.getChild(element.name ?? '');
     } else if (element is FunctionTypeAliasElement) {
-      var libraryRef = _getReference(element.library);
-      var containerRef = libraryRef.getChild('@functionTypeAlias');
+      var enclosingRef = _getReference(element.enclosingElement);
+      var containerRef = enclosingRef.getChild('@functionTypeAlias');
       _ensureReferenceIndex(containerRef);
 
       result = containerRef.getChild(element.name);
@@ -1333,15 +1364,16 @@
       if (element.enclosingElement is GenericTypeAliasElement) {
         return _getReference(element.enclosingElement);
       } else {
-        var libraryRef = _getReference(element.library);
-        var containerRef = libraryRef.getChild('@functionType');
+        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 containerRef = _getReference(element.library).getChild('@typeAlias');
+      var enclosingRef = _getReference(element.enclosingElement);
+      var containerRef = enclosingRef.getChild('@typeAlias');
       _ensureReferenceIndex(containerRef);
 
       result = containerRef.getChild(element.name);
@@ -1374,8 +1406,7 @@
     } else if (element is MultiplyDefinedElement) {
       return referenceRoot;
     } else if (element is ParameterElement) {
-      var enclosing = element.enclosingElement;
-      var enclosingRef = _getReference(enclosing);
+      var enclosingRef = _getReference(element.enclosingElement);
       var containerRef = enclosingRef.getChild('@parameter');
       _ensureReferenceIndex(containerRef);
 
@@ -1386,7 +1417,7 @@
 
       result = containerRef.getChild(element.name);
     } else if (element is PropertyAccessorElement) {
-      var enclosingRef = _getReference(element.library);
+      var enclosingRef = _getReference(element.enclosingElement);
       var containerRef = enclosingRef.getChild(
         element.isGetter ? '@getter' : '@setter',
       );
@@ -1394,7 +1425,7 @@
 
       result = containerRef.getChild(element.displayName);
     } else if (element is TopLevelVariableElement) {
-      var enclosingRef = _getReference(element.library);
+      var enclosingRef = _getReference(element.enclosingElement);
       var containerRef = enclosingRef.getChild('@variable');
       _ensureReferenceIndex(containerRef);
 
@@ -1658,7 +1689,7 @@
       _addToken(
         isSynthetic: token.isSynthetic,
         kind: UnlinkedTokenKind.keyword,
-        lexeme: '',
+        lexeme: token.lexeme,
         offset: token.offset,
         length: token.length,
         precedingComment: commentIndex,
diff --git a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
deleted file mode 100644
index a816247..0000000
--- a/pkg/analyzer/lib/src/summary2/builder/library_builder.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
-import 'package:analyzer/src/summary2/declaration.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
-import 'package:analyzer/src/summary2/reference.dart';
-import 'package:analyzer/src/summary2/scope.dart';
-
-class LibraryBuilder {
-  final Uri uri;
-  final Reference reference;
-  final List<UnitBuilder> units = [];
-
-  /// The import scope of the library.
-  final Scope importScope;
-
-  /// Local declarations, enclosed by [importScope].
-  final Scope scope;
-
-  /// The export scope of the library.
-  final Scope exportScope = Scope.top();
-
-  LibraryBuilder(Uri uri, Reference reference)
-      : this._(uri, reference, Scope.top());
-
-  LibraryBuilder._(this.uri, this.reference, this.importScope)
-      : scope = Scope(importScope, <String, Declaration>{});
-
-  /// Add top-level declaration of the library units to the local scope.
-  void addLocalDeclarations() {
-    for (var unit in units) {
-      for (var node in unit.node.compilationUnit_declarations) {
-        if (node.kind == LinkedNodeKind.classDeclaration) {
-          var name = unit.context.getUnitMemberName(node);
-          var reference = this.reference.getChild('@class').getChild(name);
-          reference.node = node;
-          var declaration = Declaration(name, reference);
-          scope.declare(name, declaration);
-        } else {
-          // TODO(scheglov) implement
-          throw UnimplementedError();
-        }
-      }
-    }
-  }
-
-  /// Return `true` if the export scope was modified.
-  bool addToExportScope(String name, Declaration declaration) {
-    if (name.startsWith('_')) return false;
-    if (declaration is PrefixBuilder) return false;
-
-    var existing = exportScope.map[name];
-    if (existing == declaration) return false;
-
-    // Ambiguous declaration detected.
-    if (existing != null) return false;
-
-    exportScope.map[name] = declaration;
-    return true;
-  }
-
-  void addUnit(LinkedUnitContext context, LinkedNode node) {
-    units.add(UnitBuilder(context, node));
-  }
-
-  void buildInitialExportScope() {
-    // TODO(scheglov) Maybe store export scopes in summaries?
-    scope.forEach((name, declaration) {
-      addToExportScope(name, declaration);
-    });
-  }
-}
-
-class UnitBuilder {
-  final LinkedUnitContext context;
-  final LinkedNode node;
-
-  UnitBuilder(this.context, this.node);
-}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index c676b9b..ed07f63 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -4,25 +4,46 @@
 
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
+import 'package:analyzer/src/summary2/builder/prefix_builder.dart';
+import 'package:analyzer/src/summary2/declaration.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
+import 'package:analyzer/src/summary2/reference_resolver.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+import 'package:analyzer/src/summary2/top_level_inference.dart';
 
-class SourceLibraryBuilder extends LibraryBuilder {
+class SourceLibraryBuilder {
   final Linker linker;
-  final LinkedBundleContext bundleContext;
+  final LinkedElementFactory elementFactory;
+  final Uri uri;
   final Reference reference;
+  final LinkedNodeLibraryBuilder node;
+  final List<UnitBuilder> units = [];
 
-  SourceLibraryBuilder(this.linker, this.bundleContext, Uri uri, this.reference)
-      : super(uri, reference);
+  /// The import scope of the library.
+  final Scope importScope;
+
+  /// Local declarations, enclosed by [importScope].
+  final Scope scope;
+
+  /// The export scope of the library.
+  final Scope exportScope = Scope.top();
+
+  SourceLibraryBuilder(Linker linker, LinkedElementFactory elementFactory,
+      Uri uri, Reference reference, LinkedNodeLibraryBuilder node)
+      : this._(linker, elementFactory, uri, reference, node, Scope.top());
+
+  SourceLibraryBuilder._(this.linker, this.elementFactory, this.uri,
+      this.reference, this.node, this.importScope)
+      : scope = Scope(importScope, <String, Declaration>{});
 
   void addSyntheticConstructors() {
     for (var declaration in scope.map.values) {
       var reference = declaration.reference;
       var node = reference.node;
-
+      if (node == null) continue;
       if (node.kind != LinkedNodeKind.classDeclaration) continue;
 
       // Skip the class if it already has a constructor.
@@ -35,75 +56,140 @@
         LinkedNodeBuilder.constructorDeclaration(
           constructorDeclaration_parameters:
               LinkedNodeBuilder.formalParameterList(),
+          constructorDeclaration_body: LinkedNodeBuilder.emptyFunctionBody(),
         )..isSynthetic = true,
       );
     }
   }
 
+  void performTopLevelInference() {
+    for (var unit in units) {
+      TopLevelInference(linker, reference, unit).infer();
+    }
+  }
+
   void resolveTypes() {
     for (var unit in units) {
+      ReferenceResolver(linker, unit, scope).resolve();
+    }
+  }
+
+  void addImportsToScope() {
+    // TODO
+    var hasDartCore = false;
+    for (var directive in units[0].node.compilationUnit_directives) {
+      if (directive.kind == LinkedNodeKind.importDirective) {
+        var uriStr = directive.uriBasedDirective_uriContent;
+        var importedLibrary = reference.parent.getChild(uriStr);
+        // TODO(scheglov) resolve URI as relative
+        // TODO(scheglov) prefix
+        // TODO(scheglov) combinators
+      }
+    }
+    if (!hasDartCore) {
+      var references = elementFactory.exportsOfLibrary('dart:core');
+      for (var reference in references) {
+        var name = reference.name;
+        importScope.declare(name, Declaration(name, reference));
+      }
+    }
+  }
+
+  /// Add top-level declaration of the library units to the local scope.
+  void addLocalDeclarations() {
+    for (var unit in units) {
+      var unitRef = reference.getChild('@unit').getChild('${unit.uri}');
+      var classRef = unitRef.getChild('@class');
+      var functionRef = unitRef.getChild('@function');
+      var getterRef = unitRef.getChild('@getter');
+      var setterRef = unitRef.getChild('@setter');
+      var variableRef = unitRef.getChild('@variable');
       for (var node in unit.node.compilationUnit_declarations) {
-        if (node.kind == LinkedNodeKind.classDeclaration) {
-          var extendsClause = node.classDeclaration_extendsClause;
-          if (extendsClause != null) {
-            _resolveTypeName(
-              unit.context,
-              extendsClause.extendsClause_superclass,
-            );
+        if (node.kind == LinkedNodeKind.classDeclaration ||
+            node.kind == LinkedNodeKind.classTypeAlias) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = classRef.getChild(name);
+          reference.node = node;
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+          var name = unit.context.getUnitMemberName(node);
+
+          Reference containerRef;
+          if (unit.context.isGetterFunction(node)) {
+            containerRef = getterRef;
+          } else if (unit.context.isSetterFunction(node)) {
+            containerRef = setterRef;
+          } else {
+            containerRef = functionRef;
           }
 
-          var withClause = node.classDeclaration_withClause;
-          if (withClause != null) {
-            for (var typeName in withClause.withClause_mixinTypes) {
-              _resolveTypeName(unit.context, typeName);
+          var reference = containerRef.getChild(name);
+          reference.node = node;
+
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+          var variableList = node.topLevelVariableDeclaration_variableList;
+          for (var variable in variableList.variableDeclarationList_variables) {
+            var name = unit.context.getVariableName(variable);
+
+            var reference = variableRef.getChild(name);
+            reference.node = node;
+
+            var getter = getterRef.getChild(name);
+            scope.declare(name, Declaration(name, getter));
+
+            if (!unit.context.isFinal(variable)) {
+              var setter = setterRef.getChild(name);
+              scope.declare('$name=', Declaration(name, setter));
             }
           }
-
-          var implementsClause = node.classOrMixinDeclaration_implementsClause;
-          if (implementsClause != null) {
-            for (var typeName in implementsClause.implementsClause_interfaces) {
-              _resolveTypeName(unit.context, typeName);
-            }
-          }
-
-          // TODO(scheglov) type parameters
-          assert(node.classOrMixinDeclaration_typeParameters == null);
         } else {
           // TODO(scheglov) implement
-          throw UnimplementedError();
+          throw UnimplementedError('${node.kind}');
         }
       }
     }
   }
 
-  int _referenceIndex(Reference reference) {
-    if (reference.index == null) {
-      reference.index = linker.references.length;
-      linker.references.add(reference);
-    }
-    return reference.index;
+  /// Return `true` if the export scope was modified.
+  bool addToExportScope(String name, Declaration declaration) {
+    if (name.startsWith('_')) return false;
+    if (declaration is PrefixBuilder) return false;
+
+    var existing = exportScope.map[name];
+    if (existing == declaration) return false;
+
+    // Ambiguous declaration detected.
+    if (existing != null) return false;
+
+    exportScope.map[name] = declaration;
+    return true;
   }
 
-  void _resolveTypeName(LinkedUnitContext context, LinkedNodeBuilder typeName) {
-    var identifier = typeName.typeName_name;
-    if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
-      var name = context.getSimpleName(identifier);
-      var reference = exportScope.lookup(name).reference;
-      var referenceIndex = _referenceIndex(reference);
-      identifier.simpleIdentifier_element = referenceIndex;
-      if (reference.isClass) {
-        typeName.typeName_type = LinkedNodeTypeBuilder(
-          kind: LinkedNodeTypeKind.interface,
-          interfaceClass: referenceIndex,
-        );
-        // TODO(scheglov) type arguments
-      } else {
-        // TODO(scheglov) set Object? keep unresolved?
-        throw UnimplementedError();
-      }
-    } else {
-      // TODO(scheglov) implement
-      throw UnimplementedError();
+  void addUnit(Uri uri, LinkedUnitContext context, LinkedNode node) {
+    units.add(UnitBuilder(uri, context, node));
+  }
+
+  void buildInitialExportScope() {
+    scope.forEach((name, declaration) {
+      addToExportScope(name, declaration);
+    });
+  }
+
+  void storeExportScope() {
+    for (var declaration in exportScope.map.values) {
+      var index = linker.indexOfReference(declaration.reference);
+      node.exports.add(index);
     }
   }
 }
+
+class UnitBuilder {
+  final Uri uri;
+  final LinkedUnitContext context;
+  final LinkedNode node;
+
+  UnitBuilder(this.uri, this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e24fc84..24c6b70 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -2,94 +2,156 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/ast_binary_writer.dart';
-import 'package:analyzer/src/summary2/builder/library_builder.dart';
 import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 LinkResult link(
+  AnalysisContext analysisContext,
+  AnalysisSession analysisSession,
   Reference rootReference,
+  List<LinkedNodeBundle> inputs,
   Map<Source, Map<Source, CompilationUnit>> unitMap,
 ) {
-  var linker = Linker(rootReference);
-  linker.link(unitMap);
-  return LinkResult(linker.references, linker.libraryResults);
-}
-
-class LibraryLinkResult {
-  final Source source;
-  final Map<Source, UnitLinkResult> units;
-
-  LibraryLinkResult(this.source, this.units);
+  var linker = Linker(analysisContext, analysisSession, rootReference);
+  linker.link(inputs, unitMap);
+  return LinkResult(linker.linkingBundle);
 }
 
 class Linker {
+  final AnalysisContext analysisContext;
+  final AnalysisSession analysisSession;
   final Reference rootReference;
+  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 output results.
-  var libraryResults = <Source, LibraryLinkResult>{};
+  /// The references of the [linkingBundle].
+  final LinkedNodeReferencesBuilder referencesBuilder =
+      LinkedNodeReferencesBuilder(
+    parent: [0],
+    name: [''],
+  );
 
-  /// Libraries that are being linked, or are already linked.
-  final Map<Uri, LibraryBuilder> builders = {};
+  LinkedNodeBundleBuilder linkingBundle;
 
-  Linker(this.rootReference);
+  /// Libraries that are being linked.
+  final List<SourceLibraryBuilder> builders = [];
 
-  void addBuilder(LibraryBuilder builder) {
-    builders[builder.uri] = builder;
+  TypeProvider typeProvider;
+  Dart2TypeSystem typeSystem;
+
+  Linker(this.analysisContext, this.analysisSession, this.rootReference) {
+    elementFactory = LinkedElementFactory(
+      analysisContext,
+      analysisSession,
+      rootReference,
+    );
   }
 
   void addSyntheticConstructors() {
-    for (var library in builders.values) {
-      if (library is SourceLibraryBuilder) {
-        library.addSyntheticConstructors();
-      }
+    for (var library in builders) {
+      library.addSyntheticConstructors();
     }
   }
 
   void buildOutlines() {
     computeLibraryScopes();
-    resolveTypes();
     addSyntheticConstructors();
+    createTypeSystem();
+    resolveTypes();
+    performTopLevelInference();
   }
 
   void computeLibraryScopes() {
-    for (var uri in builders.keys) {
-      var library = builders[uri];
+    for (var library in builders) {
+      library.addLocalDeclarations();
+    }
+
+    for (var library in builders) {
       library.buildInitialExportScope();
     }
 
+    for (var library in builders) {
+      library.addImportsToScope();
+    }
+
+    for (var library in builders) {
+      library.storeExportScope();
+    }
+
     // TODO(scheglov) process imports and exports
   }
 
-  void link(Map<Source, Map<Source, CompilationUnit>> unitMap) {
-    var linkedBundleContext = LinkedBundleContext(references);
+  void createTypeSystem() {
+    var coreRef = rootReference.getChild('dart:core');
+    var coreLib = elementFactory.elementOfReference(coreRef);
+    typeProvider = SummaryTypeProvider()..initializeCore(coreLib);
+
+    typeSystem = Dart2TypeSystem(typeProvider);
+  }
+
+  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) {
+      elementFactory.addBundle(input);
+    }
+
+    var linkingLibraries = <LinkedNodeLibraryBuilder>[];
+    linkingBundle = LinkedNodeBundleBuilder(
+      references: referencesBuilder,
+      libraries: linkingLibraries,
+    );
+    var bundleContext = LinkedBundleContext(
+      elementFactory,
+      linkingBundle.references,
+    );
+
     for (var librarySource in unitMap.keys) {
       var libraryUriStr = librarySource.uri.toString();
       var libraryReference = rootReference.getChild(libraryUriStr);
 
-      var unitResults = <Source, UnitLinkResult>{};
-      libraryResults[librarySource] = LibraryLinkResult(
-        librarySource,
-        unitResults,
+      var units = <LinkedNodeUnitBuilder>[];
+      var libraryNode = LinkedNodeLibraryBuilder(
+        units: units,
+        uriStr: libraryUriStr,
       );
 
       var libraryBuilder = SourceLibraryBuilder(
         this,
-        linkedBundleContext,
+        elementFactory,
         librarySource.uri,
         libraryReference,
+        libraryNode,
       );
-      addBuilder(libraryBuilder);
+      builders.add(libraryBuilder);
 
       var libraryUnits = unitMap[librarySource];
       for (var unitSource in libraryUnits.keys) {
@@ -98,44 +160,41 @@
         var writer = AstBinaryWriter();
         var unitData = writer.writeNode(unit);
 
-        var unitLinkResult = UnitLinkResult(writer.tokens, unitData);
-        unitResults[unitSource] = unitLinkResult;
+        var unitContext = LinkedUnitContext(bundleContext, writer.tokens);
+        libraryBuilder.addUnit(unitSource.uri, unitContext, unitData);
 
-        var linkedUnitContext = LinkedUnitContext(
-          linkedBundleContext,
-          writer.tokens,
+        libraryNode.units.add(
+          LinkedNodeUnitBuilder(
+            uriStr: '${unitSource.uri}',
+            tokens: writer.tokens,
+            node: unitData,
+          ),
         );
-        libraryBuilder.addUnit(linkedUnitContext, unitData);
       }
-
-      libraryBuilder.addLocalDeclarations();
+      linkingLibraries.add(libraryNode);
     }
 
+    // Add libraries being linked, so we can ask for their elements as well.
+    elementFactory.addBundle(linkingBundle, context: bundleContext);
+
     buildOutlines();
   }
 
+  void performTopLevelInference() {
+    for (var library in builders) {
+      library.performTopLevelInference();
+    }
+  }
+
   void resolveTypes() {
-    for (var uri in builders.keys) {
-      var library = builders[uri];
-      if (library is SourceLibraryBuilder) {
-        library.resolveTypes();
-      }
+    for (var library in builders) {
+      library.resolveTypes();
     }
   }
 }
 
 class LinkResult {
-  /// Element references in [LinkedNode]s are indexes in this list.
-  final List<Reference> references;
+  final LinkedNodeBundleBuilder bundle;
 
-  final Map<Source, LibraryLinkResult> libraries;
-
-  LinkResult(this.references, this.libraries);
-}
-
-class UnitLinkResult {
-  final UnlinkedTokensBuilder tokens;
-  final LinkedNodeBuilder node;
-
-  UnitLinkResult(this.tokens, this.node);
+  LinkResult(this.bundle);
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index 2b1d0ed..38c43ff 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -2,24 +2,63 @@
 // 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/type.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 
 /// The context of a linked bundle, with shared references.
 class LinkedBundleContext {
-  final List<Reference> references;
+  final LinkedElementFactory elementFactory;
+  final LinkedNodeReferences referencesData;
+  final List<Reference> _references;
 
-  LinkedBundleContext(this.references);
+  LinkedBundleContext(this.elementFactory, this.referencesData)
+      : _references = List<Reference>(referencesData.name.length);
 
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
-    if (linkedType.kind == LinkedNodeTypeKind.interface) {
-      var element = references[linkedType.interfaceClass].element;
-      // TODO(scheglov) type arguments
-      assert(linkedType.interfaceTypeArguments.isEmpty);
-      return InterfaceTypeImpl.explicit(element, []);
-    }
+    var type = getType(linkedType);
+    if (type is InterfaceType) return type;
     return null;
   }
+
+  DartType getType(LinkedNodeType linkedType) {
+    var kind = linkedType.kind;
+    if (kind == LinkedNodeTypeKind.dynamic_) {
+      return DynamicTypeImpl.instance;
+    } else if (kind == LinkedNodeTypeKind.interface) {
+      var reference = referenceOfIndex(linkedType.interfaceClass);
+      Element element = elementFactory.elementOfReference(reference);
+      return InterfaceTypeImpl.explicit(
+        element,
+        linkedType.interfaceTypeArguments.map(getType).toList(),
+      );
+    } else if (kind == LinkedNodeTypeKind.void_) {
+      return VoidTypeImpl.instance;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  Reference referenceOfIndex(int index) {
+    var reference = _references[index];
+    if (reference != null) return reference;
+
+    if (index == 0) {
+      _references[index] = elementFactory.rootReference;
+      return elementFactory.rootReference;
+    }
+
+    var parentIndex = referencesData.parent[index];
+    var parent = referenceOfIndex(parentIndex);
+    if (parent == null) return null;
+
+    var name = referencesData.name[index];
+    reference = parent.getChild(name);
+    _references[index] = reference;
+
+    return reference;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
new file mode 100644
index 0000000..e99dd4e
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+class LinkedElementFactory {
+  final AnalysisContext analysisContext;
+  final AnalysisSession analysisSession;
+  final Reference rootReference;
+  final Map<String, _Library> libraryMap = {};
+
+  LinkedElementFactory(
+      this.analysisContext, this.analysisSession, this.rootReference);
+
+  void addBundle(LinkedNodeBundle bundle, {LinkedBundleContext context}) {
+    context ??= LinkedBundleContext(this, bundle.references);
+    for (var library in bundle.libraries) {
+      libraryMap[library.uriStr] = _Library(context, library);
+    }
+  }
+
+  LinkedBundleContext bundleContextOfLibrary(String uriStr) {
+    return libraryMap[uriStr].context;
+  }
+
+  Element elementOfReference(Reference reference) {
+    if (reference.element != null) {
+      return reference.element;
+    }
+
+    return _ElementRequest(this, reference).elementOfReference(reference);
+  }
+
+  List<Reference> exportsOfLibrary(String uriStr) {
+    var library = libraryMap[uriStr];
+    var exportIndexList = library.node.exports;
+    var exportReferences = List<Reference>(exportIndexList.length);
+    for (var i = 0; i < exportIndexList.length; ++i) {
+      var index = exportIndexList[i];
+      var reference = library.context.referenceOfIndex(index);
+      exportReferences[i] = reference;
+    }
+    return exportReferences;
+  }
+}
+
+class _ElementRequest {
+  final LinkedElementFactory elementFactory;
+  final Reference input;
+
+  _ElementRequest(this.elementFactory, this.input);
+
+  ClassElementImpl createClassElement(
+      CompilationUnitElementImpl unit, Reference reference) {
+    if (reference.node == null) {
+      indexUnitDeclarations(unit);
+      assert(reference.node != 0, '$reference');
+    }
+    return reference.element = ClassElementImpl.forLinkedNode(
+      unit,
+      reference,
+      reference.node,
+    );
+  }
+
+  LibraryElementImpl createLibraryElement(Reference reference) {
+    // TODO(scheglov) use actual values
+    var libraryElement = LibraryElementImpl(elementFactory.analysisContext,
+        elementFactory.analysisSession, '', -1, 0);
+
+    var uriStr = reference.name;
+    var sourceFactory = elementFactory.analysisContext.sourceFactory;
+    var libraryData = elementFactory.libraryMap[uriStr];
+    var librarySource = sourceFactory.forUri(uriStr);
+
+    var units = <CompilationUnitElementImpl>[];
+    var unitContainerRef = reference.getChild('@unit');
+    for (var unitData in libraryData.node.units) {
+      var unitSource = sourceFactory.forUri(unitData.uriStr);
+      var unitElement = CompilationUnitElementImpl.forLinkedNode(
+        libraryElement,
+        LinkedUnitContext(libraryData.context, unitData.tokens),
+        unitContainerRef.getChild(unitData.uriStr),
+        unitData.node,
+      );
+      unitElement.source = unitSource;
+      unitElement.librarySource = librarySource;
+      units.add(unitElement);
+      unitContainerRef.getChild(unitData.uriStr).element = unitElement;
+    }
+
+    libraryElement.definingCompilationUnit = units[0];
+    libraryElement.parts = units.skip(1).toList();
+    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 == '@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');
+  }
+
+  void indexUnitDeclarations(CompilationUnitElementImpl unit) {
+    var context = unit.linkedContext;
+    var classRef = unit.reference.getChild('@class');
+    for (var declaration in unit.linkedNode.compilationUnit_declarations) {
+      var kind = declaration.kind;
+      if (kind == LinkedNodeKind.classDeclaration ||
+          kind == LinkedNodeKind.classTypeAlias) {
+        var name = context.getUnitMemberName(declaration);
+        classRef.getChild(name).node = declaration;
+      } else {
+        // TODO(scheglov) support other elements
+        throw UnimplementedError('$kind');
+      }
+    }
+  }
+}
+
+class _Library {
+  final LinkedBundleContext context;
+  final LinkedNodeLibrary node;
+
+  _Library(this.context, this.node);
+}
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index f7869e1..3a8e6ce 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -2,9 +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/element/type.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/ast_binary_reader.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
+import 'package:analyzer/src/summary2/reference.dart';
 
 /// The context of a unit - the context of the bundle, and the unit tokens.
 class LinkedUnitContext {
@@ -13,6 +16,23 @@
 
   LinkedUnitContext(this.bundleContext, this.tokens);
 
+  Iterable<LinkedNode> classFields(LinkedNode class_) sync* {
+    for (var declaration in class_.classOrMixinDeclaration_members) {
+      if (declaration.kind == LinkedNodeKind.fieldDeclaration) {
+        var variableList = declaration.fieldDeclaration_fields;
+        for (var field in variableList.variableDeclarationList_variables) {
+          yield field;
+        }
+      }
+    }
+  }
+
+  String getCommentText(LinkedNode comment) {
+    if (comment == null) return null;
+
+    return comment.comment_tokens.map(getTokenLexeme).join('\n');
+  }
+
   String getConstructorDeclarationName(LinkedNode node) {
     var name = node.constructorDeclaration_name;
     if (name != null) {
@@ -21,15 +41,282 @@
     return '';
   }
 
+  String getFormalParameterName(LinkedNode node) {
+    return getSimpleName(node.normalFormalParameter_identifier);
+  }
+
+  List<LinkedNode> getFormalParameters(LinkedNode node) {
+    LinkedNode parameterList;
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.constructorDeclaration) {
+      parameterList = node.constructorDeclaration_parameters;
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      parameterList = node.functionDeclaration_functionExpression
+          .functionExpression_formalParameters;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      parameterList = node.methodDeclaration_formalParameters;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+    return parameterList?.formalParameterList_parameters;
+  }
+
+  LinkedNode getImplementsClause(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.classDeclaration) {
+      return node.classOrMixinDeclaration_implementsClause;
+    } else if (kind == LinkedNodeKind.classTypeAlias) {
+      return node.classTypeAlias_implementsClause;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
     return bundleContext.getInterfaceType(linkedType);
   }
 
+  String getMethodName(LinkedNode node) {
+    return getSimpleName(node.methodDeclaration_name);
+  }
+
+  DartType getReturnType(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.functionDeclaration) {
+      return getType(node.functionDeclaration_returnType2);
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return getType(node.methodDeclaration_returnType2);
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
   String getSimpleName(LinkedNode node) {
-    return tokens.lexeme[node.simpleIdentifier_token];
+    return getTokenLexeme(node.simpleIdentifier_token);
+  }
+
+  int getSimpleOffset(LinkedNode node) {
+    return tokens.offset[node.simpleIdentifier_token];
+  }
+
+  String getTokenLexeme(int token) {
+    return tokens.lexeme[token];
+  }
+
+  DartType getType(LinkedNodeType linkedType) {
+    return bundleContext.getType(linkedType);
+  }
+
+  List<LinkedNode> getTypeParameters(LinkedNode node) {
+    LinkedNode typeParameterList;
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.classTypeAlias) {
+      typeParameterList = node.classTypeAlias_typeParameters;
+    } else if (kind == LinkedNodeKind.classDeclaration ||
+        kind == LinkedNodeKind.mixinDeclaration) {
+      typeParameterList = node.classOrMixinDeclaration_typeParameters;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+    return typeParameterList?.typeParameterList_typeParameters;
   }
 
   String getUnitMemberName(LinkedNode node) {
     return getSimpleName(node.namedCompilationUnitMember_name);
   }
+
+  String getVariableName(LinkedNode node) {
+    return getSimpleName(node.variableDeclaration_name);
+  }
+
+  bool isAbstract(LinkedNode node) {
+    return node.kind == LinkedNodeKind.methodDeclaration &&
+        node.methodDeclaration_body.kind == LinkedNodeKind.emptyFunctionBody;
+  }
+
+  bool isAsynchronous(LinkedNode node) {
+    LinkedNode body = _getFunctionBody(node);
+    if (body.kind == LinkedNodeKind.blockFunctionBody) {
+      return body.blockFunctionBody_keyword != 0;
+    } else if (body.kind == LinkedNodeKind.emptyFunctionBody) {
+      return false;
+    } else {
+      return body.expressionFunctionBody_keyword != 0;
+    }
+  }
+
+  bool isConst(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.variableDeclaration) {
+      return node.variableDeclaration_declaration.isConst;
+    }
+    throw UnimplementedError('$kind');
+  }
+
+  bool isConstKeyword(int token) {
+    return getTokenLexeme(token) == 'const';
+  }
+
+  bool isConstVariableList(LinkedNode node) {
+    return isConstKeyword(node.variableDeclarationList_keyword);
+  }
+
+  bool isExternal(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.constructorDeclaration) {
+      return node.constructorDeclaration_externalKeyword != 0;
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      return node.functionDeclaration_externalKeyword != 0;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return node.methodDeclaration_externalKeyword != 0;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  bool isFinal(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.variableDeclaration) {
+      return node.variableDeclaration_declaration.isFinal;
+    }
+    throw UnimplementedError('$kind');
+  }
+
+  bool isFinalKeyword(int token) {
+    return getTokenLexeme(token) == 'final';
+  }
+
+  bool isFinalVariableList(LinkedNode node) {
+    return isFinalKeyword(node.variableDeclarationList_keyword);
+  }
+
+  bool isFunction(LinkedNode node) {
+    return node.kind == LinkedNodeKind.functionDeclaration;
+  }
+
+  bool isGenerator(LinkedNode node) {
+    LinkedNode body = _getFunctionBody(node);
+    if (body.kind == LinkedNodeKind.blockFunctionBody) {
+      return body.blockFunctionBody_star != 0;
+    }
+    return false;
+  }
+
+  bool isGetter(LinkedNode node) {
+    return isGetterMethod(node) || isGetterFunction(node);
+  }
+
+  bool isGetterFunction(LinkedNode node) {
+    return isFunction(node) &&
+        _isGetToken(node.functionDeclaration_propertyKeyword);
+  }
+
+  bool isGetterMethod(LinkedNode node) {
+    return isMethod(node) &&
+        _isGetToken(node.methodDeclaration_propertyKeyword);
+  }
+
+  bool isMethod(LinkedNode node) {
+    return node.kind == LinkedNodeKind.methodDeclaration;
+  }
+
+  bool isSetter(LinkedNode node) {
+    return isSetterMethod(node) || isSetterFunction(node);
+  }
+
+  bool isSetterFunction(LinkedNode node) {
+    return isFunction(node) &&
+        _isSetToken(node.functionDeclaration_propertyKeyword);
+  }
+
+  bool isSetterMethod(LinkedNode node) {
+    return isMethod(node) &&
+        _isSetToken(node.methodDeclaration_propertyKeyword);
+  }
+
+  bool isStatic(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.functionDeclaration) {
+      return true;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return node.methodDeclaration_modifierKeyword != 0;
+    } else if (kind == LinkedNodeKind.variableDeclaration) {
+      return node.variableDeclaration_declaration.isStatic;
+    }
+    throw UnimplementedError('$kind');
+  }
+
+  void loadClassMemberReferences(Reference reference) {
+    var node = reference.node;
+    if (node.kind != LinkedNodeKind.classDeclaration &&
+        node.kind != LinkedNodeKind.mixinDeclaration) {
+      return;
+    }
+
+    var fieldContainerRef = reference.getChild('@field');
+    var methodContainerRef = reference.getChild('@method');
+    var getterContainerRef = reference.getChild('@getter');
+    var setterContainerRef = reference.getChild('@setter');
+    for (var member in node.classOrMixinDeclaration_members) {
+      if (member.kind == LinkedNodeKind.fieldDeclaration) {
+        var variableList = member.fieldDeclaration_fields;
+        for (var field in variableList.variableDeclarationList_variables) {
+          var name = getSimpleName(field.variableDeclaration_name);
+          fieldContainerRef.getChild(name).node = field;
+        }
+      } else if (member.kind == LinkedNodeKind.methodDeclaration) {
+        var name = getSimpleName(member.methodDeclaration_name);
+        var propertyKeyword = member.methodDeclaration_propertyKeyword;
+        if (_isGetToken(propertyKeyword)) {
+          getterContainerRef.getChild(name).node = member;
+        } else if (_isSetToken(propertyKeyword)) {
+          setterContainerRef.getChild(name).node = member;
+        } else {
+          methodContainerRef.getChild(name).node = member;
+        }
+      }
+    }
+  }
+
+  Expression readInitializer(LinkedNode linkedNode) {
+    var reader = AstBinaryReader(
+      bundleContext.elementFactory.rootReference,
+      bundleContext.referencesData,
+      tokens,
+    );
+    return reader.readNode(linkedNode.variableDeclaration_initializer);
+  }
+
+  Iterable<LinkedNode> topLevelVariables(LinkedNode unit) sync* {
+    for (var declaration in unit.compilationUnit_declarations) {
+      if (declaration.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+        var variableList = declaration.topLevelVariableDeclaration_variableList;
+        for (var variable in variableList.variableDeclarationList_variables) {
+          yield variable;
+        }
+      }
+    }
+  }
+
+  LinkedNode _getFunctionBody(LinkedNode node) {
+    var kind = node.kind;
+    if (kind == LinkedNodeKind.constructorDeclaration) {
+      return node.constructorDeclaration_body;
+    } else if (kind == LinkedNodeKind.functionDeclaration) {
+      return node
+          .functionDeclaration_functionExpression.functionExpression_body;
+    } else if (kind == LinkedNodeKind.methodDeclaration) {
+      return node.methodDeclaration_body;
+    } else {
+      throw UnimplementedError('$kind');
+    }
+  }
+
+  bool _isGetToken(int token) {
+    return tokens.type[token] == UnlinkedTokenType.GET;
+  }
+
+  bool _isSetToken(int token) {
+    return tokens.type[token] == UnlinkedTokenType.SET;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
new file mode 100644
index 0000000..b507621
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -0,0 +1,303 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/scope.dart';
+
+/// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
+/// in outlines.  This includes resolving element references in identifiers
+/// in type annotation, and setting [LinkedNodeType]s for corresponding type
+/// annotation nodes.
+///
+/// Declarations that have type annotations, e.g. return types of methods, get
+/// the corresponding type set (so, if there is an explicit type annotation,
+/// the type is set, otherwise we keep it empty, so we will attempt to infer
+/// it later).
+class ReferenceResolver {
+  final Linker linker;
+  final UnitBuilder unit;
+
+  /// TODO(scheglov) Update scope with local scopes (formal / type parameters).
+  Scope scope;
+
+  ReferenceResolver(this.linker, this.unit, this.scope);
+
+  void resolve() {
+    _node(unit.node);
+  }
+
+  void _classDeclaration(LinkedNodeBuilder node) {
+    _node(node.classOrMixinDeclaration_typeParameters);
+
+    var extendsClause = node.classDeclaration_extendsClause;
+    if (extendsClause != null) {
+      _typeName(extendsClause.extendsClause_superclass);
+    } else {
+      // TODO(scheglov) add synthetic
+    }
+
+    _nodeList(
+      node.classDeclaration_withClause?.withClause_mixinTypes,
+    );
+
+    _nodeList(
+      node.classOrMixinDeclaration_implementsClause
+          ?.implementsClause_interfaces,
+    );
+
+    for (var field in node.classOrMixinDeclaration_members) {
+      if (field.kind != LinkedNodeKind.constructorDeclaration) {
+        _node(field);
+      }
+    }
+    for (var field in node.classOrMixinDeclaration_members) {
+      if (field.kind == LinkedNodeKind.constructorDeclaration) {
+        _node(field);
+      }
+    }
+  }
+
+  void _classTypeAlias(LinkedNodeBuilder node) {
+    _node(node.classTypeAlias_typeParameters);
+
+    var superclass = node.classTypeAlias_superclass;
+    if (superclass != null) {
+      _typeName(superclass);
+    } else {
+      // TODO(scheglov) add synthetic
+    }
+
+    _nodeList(
+      node.classTypeAlias_withClause?.withClause_mixinTypes,
+    );
+
+    _nodeList(
+      node.classTypeAlias_implementsClause?.implementsClause_interfaces,
+    );
+  }
+
+  void _compilationUnit(LinkedNodeBuilder node) {
+    _nodeList(node.compilationUnit_directives);
+    _nodeList(node.compilationUnit_declarations);
+  }
+
+  void _constructorDeclaration(LinkedNodeBuilder node) {
+    _node(node.constructorDeclaration_parameters);
+  }
+
+  void _fieldDeclaration(LinkedNodeBuilder node) {
+    _node(node.fieldDeclaration_fields);
+  }
+
+  void _fieldFormalParameter(LinkedNodeBuilder node) {
+    var typeNode = node.fieldFormalParameter_type;
+    if (typeNode != null) {
+      _node(typeNode);
+      node.fieldFormalParameter_type2 = typeNode.typeName_type;
+    }
+
+    var formalParameters = node.fieldFormalParameter_formalParameters;
+    if (formalParameters != null) {
+      _node(formalParameters);
+      throw 'incomplete';
+    }
+  }
+
+  void _formalParameters(LinkedNodeBuilder node) {
+    for (var parameter in node.formalParameterList_parameters) {
+      _node(parameter);
+    }
+  }
+
+  void _functionDeclaration(LinkedNodeBuilder node) {
+    var returnType = node.functionDeclaration_returnType;
+    if (returnType != null) {
+      _typeName(returnType);
+      // TODO(scheglov) type annotation?
+      node.functionDeclaration_returnType2 = returnType.typeName_type;
+    } else {
+      node.functionDeclaration_returnType2 = LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.dynamic_,
+      );
+    }
+
+    _node(node.functionDeclaration_functionExpression);
+  }
+
+  void _functionExpression(LinkedNodeBuilder node) {
+    _node(node.functionExpression_typeParameters);
+    _node(node.functionExpression_formalParameters);
+  }
+
+  void _methodDeclaration(LinkedNodeBuilder node) {
+    _node(node.methodDeclaration_typeParameters);
+
+    var returnType = node.methodDeclaration_returnType;
+    if (returnType != null) {
+      _node(returnType);
+      // TODO(scheglov) might be an not TypeName
+      node.methodDeclaration_returnType2 = returnType.typeName_type;
+    }
+
+    _node(node.methodDeclaration_formalParameters);
+  }
+
+  void _node(LinkedNodeBuilder node) {
+    if (node == null) return;
+
+    if (node.kind == LinkedNodeKind.classDeclaration) {
+      _classDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.classTypeAlias) {
+      _classTypeAlias(node);
+    } else if (node.kind == LinkedNodeKind.compilationUnit) {
+      _compilationUnit(node);
+    } else if (node.kind == LinkedNodeKind.constructorDeclaration) {
+      _constructorDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.fieldDeclaration) {
+      _fieldDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.fieldFormalParameter) {
+      _fieldFormalParameter(node);
+    } else if (node.kind == LinkedNodeKind.formalParameterList) {
+      _formalParameters(node);
+    } else if (node.kind == LinkedNodeKind.functionDeclaration) {
+      _functionDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.functionExpression) {
+      _functionExpression(node);
+    } else if (node.kind == LinkedNodeKind.methodDeclaration) {
+      _methodDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.simpleFormalParameter) {
+      _simpleFormalParameter(node);
+    } else if (node.kind == LinkedNodeKind.topLevelVariableDeclaration) {
+      _topLevelVariableDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.typeArgumentList) {
+      _typeArgumentList(node);
+    } else if (node.kind == LinkedNodeKind.typeName) {
+      _typeName(node);
+    } else if (node.kind == LinkedNodeKind.typeParameter) {
+      _typeParameter(node);
+    } else if (node.kind == LinkedNodeKind.typeParameterList) {
+      _typeParameterList(node);
+    } else if (node.kind == LinkedNodeKind.variableDeclarationList) {
+      _variableDeclarationList(node);
+    } else {
+      // TODO(scheglov) implement
+      throw UnimplementedError('${node.kind}');
+    }
+  }
+
+  void _nodeList(List<LinkedNode> nodeList) {
+    if (nodeList == null) return;
+
+    for (var i = 0; i < nodeList.length; ++i) {
+      var node = nodeList[i];
+      _node(node);
+    }
+  }
+
+  void _simpleFormalParameter(LinkedNodeBuilder node) {
+    var typeNode = node.simpleFormalParameter_type;
+    if (typeNode != null) {
+      _node(typeNode);
+      node.simpleFormalParameter_type2 = typeNode.typeName_type;
+    } else {
+      // TODO(scheglov) might be inferred
+      node.simpleFormalParameter_type2 = LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.dynamic_,
+      );
+    }
+
+    if (node.normalFormalParameter_covariantKeyword != 0) {
+      node.normalFormalParameter_isCovariant = true;
+    } else {
+      // TODO(scheglov) might be inferred
+    }
+  }
+
+  void _topLevelVariableDeclaration(LinkedNodeBuilder node) {
+    _node(node.topLevelVariableDeclaration_variableList);
+  }
+
+  void _typeArgumentList(LinkedNodeBuilder node) {
+    for (var typeArgument in node.typeArgumentList_arguments) {
+      _typeName(typeArgument);
+    }
+  }
+
+  void _typeName(LinkedNodeBuilder node) {
+    if (node == null) return;
+
+    var identifier = node.typeName_name;
+    if (identifier.kind == LinkedNodeKind.simpleIdentifier) {
+      var name = unit.context.getSimpleName(identifier);
+
+      if (name == 'void') {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.void_,
+        );
+        return;
+      }
+
+      var declaration = scope.lookup(name);
+      if (declaration == null) {
+        identifier.simpleIdentifier_element = 0;
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.dynamic_,
+        );
+        return;
+      }
+
+      var reference = declaration.reference;
+      var referenceIndex = linker.indexOfReference(reference);
+      identifier.simpleIdentifier_element = referenceIndex;
+
+      var typeArguments = const <LinkedNodeTypeBuilder>[];
+      var typeArgumentList = node.typeName_typeArguments;
+      if (typeArgumentList != null) {
+        _node(typeArgumentList);
+        typeArguments = typeArgumentList.typeArgumentList_arguments
+            .map((node) => node.typeName_type)
+            .toList();
+      }
+
+      if (reference.isClass) {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.interface,
+          interfaceClass: referenceIndex,
+          interfaceTypeArguments: typeArguments,
+        );
+        // TODO(scheglov) type arguments
+      } else {
+        // TODO(scheglov) set Object? keep unresolved?
+        throw UnimplementedError();
+      }
+    } else {
+      // TODO(scheglov) implement
+      throw UnimplementedError();
+    }
+  }
+
+  void _typeParameter(LinkedNodeBuilder node) {
+    _node(node.typeParameter_bound);
+    // TODO(scheglov) set Object bound if no explicit?
+  }
+
+  void _typeParameterList(LinkedNodeBuilder node) {
+    for (var typeParameter in node.typeParameterList_typeParameters) {
+      _node(typeParameter);
+    }
+  }
+
+  void _variableDeclarationList(LinkedNodeBuilder node) {
+    var typeNode = node.variableDeclarationList_type;
+    if (typeNode != null) {
+      _node(typeNode);
+      for (var field in node.variableDeclarationList_variables) {
+        field.variableDeclaration_type2 = typeNode.typeName_type;
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/scope.dart b/pkg/analyzer/lib/src/summary2/scope.dart
index 6917dea..30f7419 100644
--- a/pkg/analyzer/lib/src/summary2/scope.dart
+++ b/pkg/analyzer/lib/src/summary2/scope.dart
@@ -21,6 +21,10 @@
   }
 
   Declaration lookup(String name) {
-    return map[name];
+    var declaration = map[name];
+    if (declaration != null) return declaration;
+
+    if (parent == null) return null;
+    return parent.lookup(name);
   }
 }
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
new file mode 100644
index 0000000..51dfa9f
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -0,0 +1,230 @@
+// 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/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/builder/source_library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/reference.dart';
+
+DartType _dynamicIfNull(DartType type) {
+  if (type == null || type.isBottom || type.isDartCoreNull) {
+    return DynamicTypeImpl.instance;
+  }
+  return type;
+}
+
+class TopLevelInference {
+  final Linker linker;
+  final Reference libraryRef;
+  final UnitBuilder unit;
+
+  TopLevelInference(this.linker, this.libraryRef, this.unit);
+
+  void infer() {
+    _inferFieldsTemporary();
+    _inferConstructorFieldFormals();
+  }
+
+  void _inferConstructorFieldFormals() {
+    _visitClassList((unitDeclaration) {
+      var members = unitDeclaration.classOrMixinDeclaration_members;
+
+      var fields = <String, LinkedNodeType>{};
+      _visitClassFields(unitDeclaration, (field) {
+        var name = unit.context.getVariableName(field);
+        var type = field.variableDeclaration_type2;
+        if (type == null) {
+          throw StateError('Field $name should have a type.');
+        }
+        fields[name] = type;
+      });
+
+      for (var member in members) {
+        if (member.kind == LinkedNodeKind.constructorDeclaration) {
+          for (var parameter in member.constructorDeclaration_parameters
+              .formalParameterList_parameters) {
+            if (parameter.kind == LinkedNodeKind.fieldFormalParameter &&
+                parameter.fieldFormalParameter_type2 == null) {
+              var name = unit.context.getSimpleName(
+                parameter.normalFormalParameter_identifier,
+              );
+              var type = fields[name];
+              if (type == null) {
+                type = LinkedNodeTypeBuilder(
+                  kind: LinkedNodeTypeKind.dynamic_,
+                );
+              }
+              parameter.fieldFormalParameter_type2 = type;
+            }
+          }
+        }
+      }
+    });
+  }
+
+  void _inferFieldsTemporary() {
+    var unitDeclarations = unit.node.compilationUnit_declarations;
+    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+      if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
+        _visitClassFields(unitDeclaration, (field) {
+          var name = unit.context.getVariableName(field);
+          // TODO(scheglov) Use inheritance
+          if (field.variableDeclaration_type2 == null) {
+            field.variableDeclaration_type2 = LinkedNodeTypeBuilder(
+              kind: LinkedNodeTypeKind.dynamic_,
+            );
+          }
+        });
+
+        var members = unitDeclaration.classOrMixinDeclaration_members;
+        for (var member in members) {
+          if (member.kind == LinkedNodeKind.methodDeclaration) {
+            // TODO(scheglov) Use inheritance
+            if (member.methodDeclaration_returnType2 == null) {
+              if (unit.context.isSetter(member)) {
+                member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
+                  kind: LinkedNodeTypeKind.void_,
+                );
+              } else {
+                member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
+                  kind: LinkedNodeTypeKind.dynamic_,
+                );
+              }
+            }
+          }
+        }
+      } else if (unitDeclaration.kind == LinkedNodeKind.functionDeclaration) {
+        if (unit.context.isSetter(unitDeclaration)) {
+          unitDeclaration.functionDeclaration_returnType2 =
+              LinkedNodeTypeBuilder(
+            kind: LinkedNodeTypeKind.void_,
+          );
+        }
+      } else if (unitDeclaration.kind ==
+          LinkedNodeKind.topLevelVariableDeclaration) {
+        var variableList =
+            unitDeclaration.topLevelVariableDeclaration_variableList;
+        for (var variable in variableList.variableDeclarationList_variables) {
+          // TODO(scheglov) infer in the correct order
+          if (variable.variableDeclaration_type2 == null) {
+            _inferVariableTypeFromInitializerTemporary(variable);
+          }
+        }
+      }
+    }
+  }
+
+  void _inferVariableTypeFromInitializerTemporary(LinkedNodeBuilder node) {
+    var storedInitializer = node.variableDeclaration_initializer;
+
+    if (storedInitializer == null) {
+      node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.dynamic_,
+      );
+      return;
+    }
+
+    var reader = AstBinaryReader(
+      unit.context.bundleContext.elementFactory.rootReference,
+      unit.context.bundleContext.referencesData,
+      unit.context.tokens,
+    );
+
+    // TODO(scheglov) This duplicates `readInitializer` in LinkedUnitContext
+    Expression initializer = reader.readNode(storedInitializer);
+
+    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 bundleContext = unit.context.bundleContext;
+    var library = bundleContext.elementFactory.elementOfReference(libraryRef);
+    var inheritance = InheritanceManager2(linker.typeSystem);
+
+    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_,
+      );
+    } 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}');
+    }
+  }
+
+  void _visitClassFields(
+      LinkedNode class_, void Function(LinkedNodeBuilder) f) {
+    var members = class_.classOrMixinDeclaration_members;
+
+    for (var member in members) {
+      if (member.kind == LinkedNodeKind.fieldDeclaration) {
+        var variableList = member.fieldDeclaration_fields;
+        for (var field in variableList.variableDeclarationList_variables) {
+          f(field);
+        }
+      }
+    }
+  }
+
+  void _visitClassList(void Function(LinkedNodeBuilder) f) {
+    var unitDeclarations = unit.node.compilationUnit_declarations;
+    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
+      if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
+        f(unitDeclaration);
+      }
+    }
+  }
+
+  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 63c0599..38fa6ff 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -316,6 +316,10 @@
       buffer.write('<null>');
     } else if (e is SimpleIdentifier && e.name == '#invalidConst') {
       buffer.write('#invalidConst');
+    } else if (e is AdjacentStrings) {
+      writeList("'", "'", e.strings, '',
+          (StringLiteral s) => buffer.write(s.stringValue),
+          includeEmpty: true);
     } else if (e is Annotation) {
       buffer.write('@');
       writeExpression(e.name);
@@ -802,16 +806,13 @@
 
     if (!e.isSynthetic) {
       expect(e.getter, isNotNull);
-      expect(e.getter.isSynthetic, isTrue);
-      expect(e.getter.variable, same(e));
-      expect(e.getter.enclosingElement, same(e.enclosingElement));
+      _assertSyntheticAccessorEnclosing(e, e.getter);
+
       if (e.isFinal || e.isConst) {
         expect(e.setter, isNull);
       } else {
         expect(e.setter, isNotNull);
-        expect(e.setter.isSynthetic, isTrue);
-        expect(e.setter.variable, same(e.getter.variable));
-        expect(e.setter.enclosingElement, same(e.enclosingElement));
+        _assertSyntheticAccessorEnclosing(e, e.getter);
       }
     }
 
@@ -922,6 +923,23 @@
     }
   }
 
+  /// Assert that the [accessor] of the [property] is correctly linked to
+  /// the same enclosing element as the [property].
+  void _assertSyntheticAccessorEnclosing(
+      PropertyInducingElement property, PropertyAccessorElement accessor) {
+    expect(accessor.isSynthetic, isTrue);
+    expect(accessor.variable, same(property));
+
+    var propertyEnclosing = property.enclosingElement;
+    expect(accessor.enclosingElement, same(propertyEnclosing));
+
+    if (propertyEnclosing is CompilationUnitElement) {
+      expect(propertyEnclosing.accessors, contains(accessor));
+    } else if (propertyEnclosing is ClassElement) {
+      expect(propertyEnclosing.accessors, contains(accessor));
+    }
+  }
+
   String _getElementLocationString(Element element) {
     if (element == null) {
       return 'null';
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index efbdbf9..002ff8c 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -3,9 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_bundle_context.dart';
-import 'package:analyzer/src/summary2/linked_unit_context.dart';
+import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -25,6 +27,43 @@
   @override
   Future<LibraryElementImpl> checkLibrary(String text,
       {bool allowErrors = false, bool dumpSummaries = false}) async {
+    var dartCoreSource = sourceFactory.forUri('dart:core');
+    var dartCoreCode = getFile(dartCoreSource.fullName).readAsStringSync();
+    dartCoreCode = r'''
+abstract class Comparable<T> {
+  int compareTo(T other);
+}
+
+class Iterable<T> {}
+
+class Iterator<T> {}
+
+class List<T> {}
+
+class Map<K, V> {}
+
+abstract class Null {}
+
+class Object {
+  const Object();
+}
+
+abstract class String {}
+
+abstract class Type {}
+
+abstract class bool {}
+
+abstract class double extends num {}
+
+abstract class int extends num {}
+
+abstract class num implements Comparable<num> {}
+''';
+
+    var rootReference = Reference.root();
+    var dartCoreResult = _link(rootReference, dartCoreSource, dartCoreCode);
+
     var source = addTestSource(text);
 
     var unit = parseText(text, experimentStatus: experimentStatus);
@@ -34,66 +73,25 @@
       source: {source: unit},
     };
 
-    var rootReference = Reference.root();
-    var linkResult = link(rootReference, libraryUnitMap);
-
-    var libraryLinkResult = linkResult.libraries[source];
-    var defaultUnitResult = libraryLinkResult.units[source];
-
-    var linkedBundleContext = LinkedBundleContext(linkResult.references);
-    var linkedUnitContext = LinkedUnitContext(
-      linkedBundleContext,
-      defaultUnitResult.tokens,
+    var linkResult = link(
+      _FakeAnalysisContext(sourceFactory, null),
+      null,
+      rootReference,
+      [dartCoreResult.bundle],
+      libraryUnitMap,
     );
 
-    // TODO(scheglov) use actual names
-    // TODO(scheglov) support parts
-    var libraryElement = LibraryElementImpl(null, null, '', -1, 0);
-    var unitElement = CompilationUnitElementImpl.forLinkedNode(
-      libraryElement,
-      linkedUnitContext,
-      rootReference.getChild('${libraryLinkResult.source.uri}'),
-      defaultUnitResult.node,
+    var rootReference2 = Reference.root();
+    var elementFactory = LinkedElementFactory(
+      _FakeAnalysisContext(sourceFactory, null),
+      null,
+      rootReference2,
     );
-    libraryElement.definingCompilationUnit = unitElement;
-
-    return libraryElement;
-  }
-
-  @override
-  @failingTest
-  test_class_alias() async {
-    await super.test_class_alias();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_abstract() async {
-    await super.test_class_alias_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_documented() async {
-    await super.test_class_alias_documented();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_documented_tripleSlash() async {
-    await super.test_class_alias_documented_tripleSlash();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_documented_withLeadingNonDocumentation() async {
-    await super.test_class_alias_documented_withLeadingNonDocumentation();
-  }
-
-  @override
-  @failingTest
-  test_class_alias_generic() async {
-    await super.test_class_alias_generic();
+    elementFactory.addBundle(dartCoreResult.bundle);
+    elementFactory.addBundle(linkResult.bundle);
+    return elementFactory.elementOfReference(
+      rootReference2.getChild('${source.uri}'),
+    );
   }
 
   @override
@@ -118,36 +116,6 @@
 
   @override
   @failingTest
-  test_class_alias_with_mixin_members() async {
-    await super.test_class_alias_with_mixin_members();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_explicit_type_params() async {
-    await super.test_class_constructor_explicit_type_params();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_dynamic_dynamic() async {
-    await super.test_class_constructor_field_formal_dynamic_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_dynamic_typed() async {
-    await super.test_class_constructor_field_formal_dynamic_typed();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_dynamic_untyped() async {
-    await super.test_class_constructor_field_formal_dynamic_untyped();
-  }
-
-  @override
-  @failingTest
   test_class_constructor_field_formal_functionTyped_noReturnType() async {
     await super
         .test_class_constructor_field_formal_functionTyped_noReturnType();
@@ -168,48 +136,6 @@
 
   @override
   @failingTest
-  test_class_constructor_field_formal_no_matching_field() async {
-    await super.test_class_constructor_field_formal_no_matching_field();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_typed_dynamic() async {
-    await super.test_class_constructor_field_formal_typed_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_typed_typed() async {
-    await super.test_class_constructor_field_formal_typed_typed();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_typed_untyped() async {
-    await super.test_class_constructor_field_formal_typed_untyped();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_untyped_dynamic() async {
-    await super.test_class_constructor_field_formal_untyped_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_untyped_typed() async {
-    await super.test_class_constructor_field_formal_untyped_typed();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_field_formal_untyped_untyped() async {
-    await super.test_class_constructor_field_formal_untyped_untyped();
-  }
-
-  @override
-  @failingTest
   test_class_constructor_fieldFormal_named_noDefault() async {
     await super.test_class_constructor_fieldFormal_named_noDefault();
   }
@@ -234,252 +160,24 @@
 
   @override
   @failingTest
-  test_class_constructor_implicit_type_params() async {
-    await super.test_class_constructor_implicit_type_params();
-  }
-
-  @override
-  @failingTest
-  test_class_constructor_params() async {
-    await super.test_class_constructor_params();
-  }
-
-  @override
-  @failingTest
-  test_class_documented() async {
-    await super.test_class_documented();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_mix() async {
-    await super.test_class_documented_mix();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_tripleSlash() async {
-    await super.test_class_documented_tripleSlash();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_with_references() async {
-    await super.test_class_documented_with_references();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_with_windows_line_endings() async {
-    await super.test_class_documented_with_windows_line_endings();
-  }
-
-  @override
-  @failingTest
-  test_class_documented_withLeadingNotDocumentation() async {
-    await super.test_class_documented_withLeadingNotDocumentation();
-  }
-
-  @override
-  @failingTest
   test_class_documented_withMetadata() async {
     await super.test_class_documented_withMetadata();
   }
 
   @override
   @failingTest
-  test_class_field_const() async {
-    await super.test_class_field_const();
-  }
-
-  @override
-  @failingTest
-  test_class_field_implicit_type() async {
-    await super.test_class_field_implicit_type();
-  }
-
-  @override
-  @failingTest
-  test_class_field_static() async {
-    await super.test_class_field_static();
-  }
-
-  @override
-  @failingTest
-  test_class_fields() async {
-    await super.test_class_fields();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_abstract() async {
-    await super.test_class_getter_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_external() async {
-    await super.test_class_getter_external();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_implicit_return_type() async {
-    await super.test_class_getter_implicit_return_type();
-  }
-
-  @override
-  @failingTest
-  test_class_getter_static() async {
-    await super.test_class_getter_static();
-  }
-
-  @override
-  @failingTest
-  test_class_getters() async {
-    await super.test_class_getters();
-  }
-
-  @override
-  @failingTest
-  test_class_implicitField_getterFirst() async {
-    await super.test_class_implicitField_getterFirst();
-  }
-
-  @override
-  @failingTest
-  test_class_implicitField_setterFirst() async {
-    await super.test_class_implicitField_setterFirst();
-  }
-
-  @override
-  @failingTest
-  test_class_interfaces_unresolved() async {
-    await super.test_class_interfaces_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_class_method_abstract() async {
-    await super.test_class_method_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_method_external() async {
-    await super.test_class_method_external();
-  }
-
-  @override
-  @failingTest
-  test_class_method_params() async {
-    await super.test_class_method_params();
-  }
-
-  @override
-  @failingTest
-  test_class_method_static() async {
-    await super.test_class_method_static();
-  }
-
-  @override
-  @failingTest
-  test_class_methods() async {
-    await super.test_class_methods();
-  }
-
-  @override
-  @failingTest
-  test_class_mixins_generic() async {
-    await super.test_class_mixins_generic();
-  }
-
-  @override
-  @failingTest
-  test_class_mixins_unresolved() async {
-    await super.test_class_mixins_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_abstract() async {
-    await super.test_class_setter_abstract();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_external() async {
-    await super.test_class_setter_external();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_implicit_param_type() async {
-    await super.test_class_setter_implicit_param_type();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_implicit_return_type() async {
-    await super.test_class_setter_implicit_return_type();
-  }
-
-  @override
-  @failingTest
   test_class_setter_invalid_named_parameter() async {
     await super.test_class_setter_invalid_named_parameter();
   }
 
   @override
   @failingTest
-  test_class_setter_invalid_no_parameter() async {
-    await super.test_class_setter_invalid_no_parameter();
-  }
-
-  @override
-  @failingTest
   test_class_setter_invalid_optional_parameter() async {
     await super.test_class_setter_invalid_optional_parameter();
   }
 
   @override
   @failingTest
-  test_class_setter_invalid_too_many_parameters() async {
-    await super.test_class_setter_invalid_too_many_parameters();
-  }
-
-  @override
-  @failingTest
-  test_class_setter_static() async {
-    await super.test_class_setter_static();
-  }
-
-  @override
-  @failingTest
-  test_class_setters() async {
-    await super.test_class_setters();
-  }
-
-  @override
-  @failingTest
-  test_class_supertype_typeArguments() async {
-    await super.test_class_supertype_typeArguments();
-  }
-
-  @override
-  @failingTest
-  test_class_supertype_unresolved() async {
-    await super.test_class_supertype_unresolved();
-  }
-
-  @override
-  @failingTest
-  test_class_type_parameters() async {
-    await super.test_class_type_parameters();
-  }
-
-  @override
-  @failingTest
   test_class_type_parameters_bound() async {
     await super.test_class_type_parameters_bound();
   }
@@ -498,12 +196,6 @@
 
   @override
   @failingTest
-  test_closure_executable_with_return_type_from_closure() async {
-    await super.test_closure_executable_with_return_type_from_closure();
-  }
-
-  @override
-  @failingTest
   test_closure_generic() async {
     await super.test_closure_generic();
   }
@@ -612,12 +304,6 @@
 
   @override
   @failingTest
-  test_const_invalid_intLiteral() async {
-    await super.test_const_invalid_intLiteral();
-  }
-
-  @override
-  @failingTest
   test_const_invalid_topLevel() async {
     await super.test_const_invalid_topLevel();
   }
@@ -698,12 +384,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_unresolved2() async {
-    await super.test_const_invokeConstructor_named_unresolved2();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_named_unresolved3() async {
     await super.test_const_invokeConstructor_named_unresolved3();
   }
@@ -716,12 +396,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_unresolved5() async {
-    await super.test_const_invokeConstructor_named_unresolved5();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_named_unresolved6() async {
     await super.test_const_invokeConstructor_named_unresolved6();
   }
@@ -746,24 +420,12 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed_unresolved() async {
-    await super.test_const_invokeConstructor_unnamed_unresolved();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_unnamed_unresolved2() async {
     await super.test_const_invokeConstructor_unnamed_unresolved2();
   }
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed_unresolved3() async {
-    await super.test_const_invokeConstructor_unnamed_unresolved3();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofClassConstField() async {
     await super.test_const_length_ofClassConstField();
   }
@@ -958,12 +620,6 @@
 
   @override
   @failingTest
-  test_const_reference_unresolved_prefix0() async {
-    await super.test_const_reference_unresolved_prefix0();
-  }
-
-  @override
-  @failingTest
   test_const_reference_unresolved_prefix1() async {
     await super.test_const_reference_unresolved_prefix1();
   }
@@ -1018,18 +674,6 @@
 
   @override
   @failingTest
-  test_const_topLevel_super() async {
-    await super.test_const_topLevel_super();
-  }
-
-  @override
-  @failingTest
-  test_const_topLevel_this() async {
-    await super.test_const_topLevel_this();
-  }
-
-  @override
-  @failingTest
   test_const_topLevel_throw() async {
     await super.test_const_topLevel_throw();
   }
@@ -1102,12 +746,6 @@
 
   @override
   @failingTest
-  test_constructor_documented() async {
-    await super.test_constructor_documented();
-  }
-
-  @override
-  @failingTest
   test_constructor_initializers_assertInvocation() async {
     await super.test_constructor_initializers_assertInvocation();
   }
@@ -1217,19 +855,6 @@
 
   @override
   @failingTest
-  test_constructor_redirected_factory_named_unresolved_class() async {
-    await super.test_constructor_redirected_factory_named_unresolved_class();
-  }
-
-  @override
-  @failingTest
-  test_constructor_redirected_factory_named_unresolved_constructor() async {
-    await super
-        .test_constructor_redirected_factory_named_unresolved_constructor();
-  }
-
-  @override
-  @failingTest
   test_constructor_redirected_factory_unnamed() async {
     await super.test_constructor_redirected_factory_unnamed();
   }
@@ -1266,12 +891,6 @@
 
   @override
   @failingTest
-  test_constructor_redirected_factory_unnamed_unresolved() async {
-    await super.test_constructor_redirected_factory_unnamed_unresolved();
-  }
-
-  @override
-  @failingTest
   test_constructor_redirected_thisInvocation_named() async {
     await super.test_constructor_redirected_thisInvocation_named();
   }
@@ -1302,12 +921,6 @@
 
   @override
   @failingTest
-  test_constructor_withCycles_nonConst() async {
-    await super.test_constructor_withCycles_nonConst();
-  }
-
-  @override
-  @failingTest
   test_defaultValue_genericFunction() async {
     await super.test_defaultValue_genericFunction();
   }
@@ -1494,36 +1107,18 @@
 
   @override
   @failingTest
-  test_expr_invalid_typeParameter_asPrefix() async {
-    await super.test_expr_invalid_typeParameter_asPrefix();
-  }
-
-  @override
-  @failingTest
   test_field_covariant() async {
     await super.test_field_covariant();
   }
 
   @override
   @failingTest
-  test_field_documented() async {
-    await super.test_field_documented();
-  }
-
-  @override
-  @failingTest
   test_field_formal_param_inferred_type_implicit() async {
     await super.test_field_formal_param_inferred_type_implicit();
   }
 
   @override
   @failingTest
-  test_field_inferred_type_nonStatic_explicit_initialized() async {
-    await super.test_field_inferred_type_nonStatic_explicit_initialized();
-  }
-
-  @override
-  @failingTest
   test_field_inferred_type_nonStatic_implicit_initialized() async {
     await super.test_field_inferred_type_nonStatic_implicit_initialized();
   }
@@ -1578,12 +1173,6 @@
 
   @override
   @failingTest
-  test_field_typed() async {
-    await super.test_field_typed();
-  }
-
-  @override
-  @failingTest
   test_field_untyped() async {
     await super.test_field_untyped();
   }
@@ -1602,18 +1191,6 @@
 
   @override
   @failingTest
-  test_function_documented() async {
-    await super.test_function_documented();
-  }
-
-  @override
-  @failingTest
-  test_function_entry_point() async {
-    await super.test_function_entry_point();
-  }
-
-  @override
-  @failingTest
   test_function_entry_point_in_export() async {
     await super.test_function_entry_point_in_export();
   }
@@ -1632,18 +1209,6 @@
 
   @override
   @failingTest
-  test_function_external() async {
-    await super.test_function_external();
-  }
-
-  @override
-  @failingTest
-  test_function_parameter_final() async {
-    await super.test_function_parameter_final();
-  }
-
-  @override
-  @failingTest
   test_function_parameter_kind_named() async {
     await super.test_function_parameter_kind_named();
   }
@@ -1656,12 +1221,6 @@
 
   @override
   @failingTest
-  test_function_parameter_kind_required() async {
-    await super.test_function_parameter_kind_required();
-  }
-
-  @override
-  @failingTest
   test_function_parameter_parameters() async {
     await super.test_function_parameter_parameters();
   }
@@ -1680,36 +1239,6 @@
 
   @override
   @failingTest
-  test_function_parameter_type() async {
-    await super.test_function_parameter_type();
-  }
-
-  @override
-  @failingTest
-  test_function_parameters() async {
-    await super.test_function_parameters();
-  }
-
-  @override
-  @failingTest
-  test_function_return_type() async {
-    await super.test_function_return_type();
-  }
-
-  @override
-  @failingTest
-  test_function_return_type_implicit() async {
-    await super.test_function_return_type_implicit();
-  }
-
-  @override
-  @failingTest
-  test_function_return_type_void() async {
-    await super.test_function_return_type_void();
-  }
-
-  @override
-  @failingTest
   test_function_type_parameter() async {
     await super.test_function_type_parameter();
   }
@@ -1728,12 +1257,6 @@
 
   @override
   @failingTest
-  test_functions() async {
-    await super.test_functions();
-  }
-
-  @override
-  @failingTest
   test_futureOr() async {
     await super.test_futureOr();
   }
@@ -1794,42 +1317,12 @@
 
   @override
   @failingTest
-  test_getter_documented() async {
-    await super.test_getter_documented();
-  }
-
-  @override
-  @failingTest
-  test_getter_external() async {
-    await super.test_getter_external();
-  }
-
-  @override
-  @failingTest
   test_getter_inferred_type_nonStatic_implicit_return() async {
     await super.test_getter_inferred_type_nonStatic_implicit_return();
   }
 
   @override
   @failingTest
-  test_getters() async {
-    await super.test_getters();
-  }
-
-  @override
-  @failingTest
-  test_implicitTopLevelVariable_getterFirst() async {
-    await super.test_implicitTopLevelVariable_getterFirst();
-  }
-
-  @override
-  @failingTest
-  test_implicitTopLevelVariable_setterFirst() async {
-    await super.test_implicitTopLevelVariable_setterFirst();
-  }
-
-  @override
-  @failingTest
   test_import_configurations_useDefault() async {
     await super.test_import_configurations_useDefault();
   }
@@ -1938,18 +1431,6 @@
 
   @override
   @failingTest
-  test_inferred_function_type_in_generic_class_constructor() async {
-    await super.test_inferred_function_type_in_generic_class_constructor();
-  }
-
-  @override
-  @failingTest
-  test_inferred_function_type_in_generic_class_getter() async {
-    await super.test_inferred_function_type_in_generic_class_getter();
-  }
-
-  @override
-  @failingTest
   test_inferred_function_type_in_generic_class_in_generic_method() async {
     await super
         .test_inferred_function_type_in_generic_class_in_generic_method();
@@ -1957,12 +1438,6 @@
 
   @override
   @failingTest
-  test_inferred_function_type_in_generic_class_setter() async {
-    await super.test_inferred_function_type_in_generic_class_setter();
-  }
-
-  @override
-  @failingTest
   test_inferred_function_type_in_generic_closure() async {
     await super.test_inferred_function_type_in_generic_closure();
   }
@@ -2059,12 +1534,6 @@
 
   @override
   @failingTest
-  test_inheritance_errors() async {
-    await super.test_inheritance_errors();
-  }
-
-  @override
-  @failingTest
   test_initializer_executable_with_return_type_from_closure() async {
     await super.test_initializer_executable_with_return_type_from_closure();
   }
@@ -2106,13 +1575,6 @@
 
   @override
   @failingTest
-  test_initializer_executable_with_return_type_from_closure_local() async {
-    await super
-        .test_initializer_executable_with_return_type_from_closure_local();
-  }
-
-  @override
-  @failingTest
   test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
     await super.test_instantiateToBounds_boundRefersToEarlierTypeArgument();
   }
@@ -2233,42 +1695,6 @@
 
   @override
   @failingTest
-  test_localFunctions() async {
-    await super.test_localFunctions();
-  }
-
-  @override
-  @failingTest
-  test_localFunctions_inMethod() async {
-    await super.test_localFunctions_inMethod();
-  }
-
-  @override
-  @failingTest
-  test_localFunctions_inTopLevelGetter() async {
-    await super.test_localFunctions_inTopLevelGetter();
-  }
-
-  @override
-  @failingTest
-  test_localLabels_inMethod() async {
-    await super.test_localLabels_inMethod();
-  }
-
-  @override
-  @failingTest
-  test_localLabels_inTopLevelFunction() async {
-    await super.test_localLabels_inTopLevelFunction();
-  }
-
-  @override
-  @failingTest
-  test_main_class_alias() async {
-    await super.test_main_class_alias();
-  }
-
-  @override
-  @failingTest
   test_main_class_alias_via_export() async {
     await super.test_main_class_alias_via_export();
   }
@@ -2281,12 +1707,6 @@
 
   @override
   @failingTest
-  test_main_getter() async {
-    await super.test_main_getter();
-  }
-
-  @override
-  @failingTest
   test_main_getter_via_export() async {
     await super.test_main_getter_via_export();
   }
@@ -2305,12 +1725,6 @@
 
   @override
   @failingTest
-  test_main_variable() async {
-    await super.test_main_variable();
-  }
-
-  @override
-  @failingTest
   test_main_variable_via_export() async {
     await super.test_main_variable_via_export();
   }
@@ -2551,12 +1965,6 @@
 
   @override
   @failingTest
-  test_method_documented() async {
-    await super.test_method_documented();
-  }
-
-  @override
-  @failingTest
   test_method_inferred_type_nonStatic_implicit_param() async {
     await super.test_method_inferred_type_nonStatic_implicit_param();
   }
@@ -2657,60 +2065,6 @@
 
   @override
   @failingTest
-  test_operator() async {
-    await super.test_operator();
-  }
-
-  @override
-  @failingTest
-  test_operator_equal() async {
-    await super.test_operator_equal();
-  }
-
-  @override
-  @failingTest
-  test_operator_external() async {
-    await super.test_operator_external();
-  }
-
-  @override
-  @failingTest
-  test_operator_greater_equal() async {
-    await super.test_operator_greater_equal();
-  }
-
-  @override
-  @failingTest
-  test_operator_index() async {
-    await super.test_operator_index();
-  }
-
-  @override
-  @failingTest
-  test_operator_index_set() async {
-    await super.test_operator_index_set();
-  }
-
-  @override
-  @failingTest
-  test_operator_less_equal() async {
-    await super.test_operator_less_equal();
-  }
-
-  @override
-  @failingTest
-  test_parameter() async {
-    await super.test_parameter();
-  }
-
-  @override
-  @failingTest
-  test_parameter_covariant() async {
-    await super.test_parameter_covariant();
-  }
-
-  @override
-  @failingTest
   test_parameter_covariant_inherited() async {
     await super.test_parameter_covariant_inherited();
   }
@@ -2783,60 +2137,12 @@
 
   @override
   @failingTest
-  test_propagated_type_refers_to_closure() async {
-    await super.test_propagated_type_refers_to_closure();
-  }
-
-  @override
-  @failingTest
-  test_setter_covariant() async {
-    await super.test_setter_covariant();
-  }
-
-  @override
-  @failingTest
-  test_setter_documented() async {
-    await super.test_setter_documented();
-  }
-
-  @override
-  @failingTest
-  test_setter_external() async {
-    await super.test_setter_external();
-  }
-
-  @override
-  @failingTest
-  test_setter_inferred_type_conflictingInheritance() async {
-    await super.test_setter_inferred_type_conflictingInheritance();
-  }
-
-  @override
-  @failingTest
   test_setter_inferred_type_nonStatic_implicit_param() async {
     await super.test_setter_inferred_type_nonStatic_implicit_param();
   }
 
   @override
   @failingTest
-  test_setter_inferred_type_static_implicit_return() async {
-    await super.test_setter_inferred_type_static_implicit_return();
-  }
-
-  @override
-  @failingTest
-  test_setter_inferred_type_top_level_implicit_return() async {
-    await super.test_setter_inferred_type_top_level_implicit_return();
-  }
-
-  @override
-  @failingTest
-  test_setters() async {
-    await super.test_setters();
-  }
-
-  @override
-  @failingTest
   test_syntheticFunctionType_genericClosure() async {
     await super.test_syntheticFunctionType_genericClosure();
   }
@@ -2873,42 +2179,12 @@
 
   @override
   @failingTest
-  test_type_arguments_explicit_dynamic_dynamic() async {
-    await super.test_type_arguments_explicit_dynamic_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_type_arguments_explicit_dynamic_int() async {
-    await super.test_type_arguments_explicit_dynamic_int();
-  }
-
-  @override
-  @failingTest
-  test_type_arguments_explicit_String_dynamic() async {
-    await super.test_type_arguments_explicit_String_dynamic();
-  }
-
-  @override
-  @failingTest
-  test_type_arguments_explicit_String_int() async {
-    await super.test_type_arguments_explicit_String_int();
-  }
-
-  @override
-  @failingTest
   test_type_arguments_implicit() async {
     await super.test_type_arguments_implicit();
   }
 
   @override
   @failingTest
-  test_type_dynamic() async {
-    await super.test_type_dynamic();
-  }
-
-  @override
-  @failingTest
   test_type_inference_based_on_loadLibrary() async {
     await super.test_type_inference_based_on_loadLibrary();
   }
@@ -2999,18 +2275,6 @@
 
   @override
   @failingTest
-  test_type_reference_to_class() async {
-    await super.test_type_reference_to_class();
-  }
-
-  @override
-  @failingTest
-  test_type_reference_to_class_with_type_arguments() async {
-    await super.test_type_reference_to_class_with_type_arguments();
-  }
-
-  @override
-  @failingTest
   test_type_reference_to_class_with_type_arguments_implicit() async {
     await super.test_type_reference_to_class_with_type_arguments_implicit();
   }
@@ -3095,12 +2359,6 @@
 
   @override
   @failingTest
-  test_type_unresolved() async {
-    await super.test_type_unresolved();
-  }
-
-  @override
-  @failingTest
   test_type_unresolved_prefixed() async {
     await super.test_type_unresolved_prefixed();
   }
@@ -3233,12 +2491,6 @@
 
   @override
   @failingTest
-  test_typedefs() async {
-    await super.test_typedefs();
-  }
-
-  @override
-  @failingTest
   test_unresolved_annotation_instanceCreation_argument_this() async {
     await super.test_unresolved_annotation_instanceCreation_argument_this();
   }
@@ -3340,30 +2592,6 @@
 
   @override
   @failingTest
-  test_variable() async {
-    await super.test_variable();
-  }
-
-  @override
-  @failingTest
-  test_variable_const() async {
-    await super.test_variable_const();
-  }
-
-  @override
-  @failingTest
-  test_variable_documented() async {
-    await super.test_variable_documented();
-  }
-
-  @override
-  @failingTest
-  test_variable_final() async {
-    await super.test_variable_final();
-  }
-
-  @override
-  @failingTest
   test_variable_getterInLib_setterInPart() async {
     await super.test_variable_getterInLib_setterInPart();
   }
@@ -3382,48 +2610,6 @@
 
   @override
   @failingTest
-  test_variable_implicit_type() async {
-    await super.test_variable_implicit_type();
-  }
-
-  @override
-  @failingTest
-  test_variable_inferred_type_implicit_initialized() async {
-    await super.test_variable_inferred_type_implicit_initialized();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer() async {
-    await super.test_variable_initializer();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer_final() async {
-    await super.test_variable_initializer_final();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer_final_untyped() async {
-    await super.test_variable_initializer_final_untyped();
-  }
-
-  @override
-  @failingTest
-  test_variable_initializer_untyped() async {
-    await super.test_variable_initializer_untyped();
-  }
-
-  @override
-  @failingTest
-  test_variable_propagatedType_const_noDep() async {
-    await super.test_variable_propagatedType_const_noDep();
-  }
-
-  @override
-  @failingTest
   test_variable_propagatedType_final_dep_inLib() async {
     await super.test_variable_propagatedType_final_dep_inLib();
   }
@@ -3436,12 +2622,6 @@
 
   @override
   @failingTest
-  test_variable_propagatedType_final_noDep() async {
-    await super.test_variable_propagatedType_final_noDep();
-  }
-
-  @override
-  @failingTest
   test_variable_propagatedType_implicit_dep() async {
     await super.test_variable_propagatedType_implicit_dep();
   }
@@ -3452,9 +2632,46 @@
     await super.test_variable_setterInPart_getterInPart();
   }
 
-  @override
-  @failingTest
-  test_variables() async {
-    await super.test_variables();
+  LinkResult _link(Reference root, Source source, String code) {
+    var unit = parseText(code, experimentStatus: experimentStatus);
+
+    // TODO(scheglov) add other libraries
+    var libraryUnitMap = {
+      source: {source: unit},
+    };
+
+    var rootReference = Reference.root();
+    var linkResult = link(
+      _FakeAnalysisContext(sourceFactory, null),
+      null,
+      rootReference,
+      [],
+      libraryUnitMap,
+    );
+    return linkResult;
+//    var linkResult = link(rootReference, libraryUnitMap);
+
+//    var libraryLinkResult = linkResult.libraries[source];
+//    var defaultUnitResult = libraryLinkResult.units[source];
+//
+//    var linkedBundleContext = LinkedBundleContext(linkResult.references);
+//    var linkedUnitContext = LinkedUnitContext(
+//      linkedBundleContext,
+//      defaultUnitResult.tokens,
+//    );
   }
 }
+
+class _FakeAnalysisContext implements AnalysisContext {
+  final SourceFactory sourceFactory;
+  final Dart2TypeSystem typeSystem;
+
+  _FakeAnalysisContext(this.sourceFactory, this.typeSystem);
+
+  @override
+  AnalysisOptions get analysisOptions {
+    return AnalysisOptionsImpl();
+  }
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
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 f97c7a7..8d1ad46 100644
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
@@ -128,7 +128,7 @@
 
     var reader = AstBinaryReader(
       Reference.root(),
-      writer.referenceBuilder,
+      writer.referencesBuilder,
       writer.tokens,
     );
     var deserializedUnit = reader.readNode(builder);