Build more import scopes, support for enums.

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

Change-Id: I78c7a8be5b5d4ea9c9ecbc82f0c1101d7819dd30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96460
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 639bd5d..7323e95 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1707,6 +1707,19 @@
 
   @override
   List<ClassElement> get enums {
+    if (linkedNode != null) {
+      if (_enums != null) return _enums;
+      var context = enclosingUnit.linkedContext;
+      var containerRef = reference.getChild('@enum');
+      _enums = linkedNode.compilationUnit_declarations
+          .where((node) => node.kind == LinkedNodeKind.enumDeclaration)
+          .map((node) {
+        var name = context.getUnitMemberName(node);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return EnumElementImpl.forLinkedNode(this, reference, node);
+      }).toList();
+    }
     if (_unlinkedUnit != null) {
       _enums ??= _unlinkedUnit.enums
           .map((e) => new EnumElementImpl.forSerialized(e, this))
@@ -2188,8 +2201,21 @@
       EnumElementImpl enumElement, this._unlinkedEnumValue, this._index)
       : super(enumElement);
 
+  ConstFieldElementImpl_EnumValue.forLinkedNode(EnumElementImpl enumElement,
+      Reference reference, LinkedNode linkedNode, this._index)
+      : _unlinkedEnumValue = null,
+        super.forLinkedNode(enumElement, reference, linkedNode);
+
+  @override
+  Expression get constantInitializer => null;
+
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedEnumValue != null) {
       return _unlinkedEnumValue.documentationComment?.text;
     }
@@ -2221,6 +2247,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedEnumValue != null) {
       return _unlinkedEnumValue.name;
     }
@@ -2229,9 +2258,16 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getSimpleOffset(
+        linkedNode.enumConstantDeclaration_name,
+      );
+    }
     int offset = super.nameOffset;
-    if (offset == -1 && _unlinkedEnumValue != null) {
-      return _unlinkedEnumValue.nameOffset;
+    if (offset == -1) {
+      if (_unlinkedEnumValue != null) {
+        return _unlinkedEnumValue.nameOffset;
+      }
     }
     return offset;
   }
@@ -2283,6 +2319,10 @@
     enclosingElement = _enum;
   }
 
+  ConstFieldElementImpl_ofEnum.forLinkedNode(
+      this._enum, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(_enum, reference, linkedNode);
+
   @override
   void set evaluationResult(_) {
     assert(false);
@@ -3062,7 +3102,7 @@
   /// root of the element structure.
   ElementImpl _enclosingElement;
 
-  final Reference reference;
+  Reference reference;
   final LinkedNode linkedNode;
 
   /// The name of this element.
@@ -3105,7 +3145,7 @@
   /// Initialize from linked node.
   ElementImpl.forLinkedNode(
       this._enclosingElement, this.reference, this.linkedNode) {
-    reference.element = this;
+    reference?.element = this;
   }
 
   /// Initialize a newly created element to have the given [name].
@@ -3816,6 +3856,11 @@
       : _unlinkedEnum = null,
         super(name, offset);
 
+  EnumElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
+      Reference reference, LinkedNode linkedNode)
+      : _unlinkedEnum = null,
+        super.forLinkedNode(enclosing, reference, linkedNode);
+
   /// Initialize a newly created class element to have the given [name].
   EnumElementImpl.forNode(Identifier name)
       : _unlinkedEnum = null,
@@ -3834,6 +3879,9 @@
   @override
   List<PropertyAccessorElement> get accessors {
     if (_accessors == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3877,6 +3925,11 @@
 
   @override
   String get documentationComment {
+    if (linkedNode != null) {
+      return enclosingUnit.linkedContext.getCommentText(
+        linkedNode.annotatedNode_comment,
+      );
+    }
     if (_unlinkedEnum != null) {
       return _unlinkedEnum.documentationComment?.text;
     }
@@ -3886,6 +3939,9 @@
   @override
   List<FieldElement> get fields {
     if (_fields == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3944,6 +4000,9 @@
   @override
   List<MethodElement> get methods {
     if (_methods == null) {
+      if (linkedNode != null) {
+        _resynthesizeMembers2();
+      }
       if (_unlinkedEnum != null) {
         _resynthesizeMembers();
       }
@@ -3956,6 +4015,9 @@
 
   @override
   String get name {
+    if (linkedNode != null) {
+      return reference.name;
+    }
     if (_unlinkedEnum != null) {
       return _unlinkedEnum.name;
     }
@@ -4006,11 +4068,14 @@
   void createToStringMethodElement() {
     var method = new MethodElementImpl('toString', -1);
     method.isSynthetic = true;
-    if (_unlinkedEnum != null) {
+    if (linkedNode != null || _unlinkedEnum != null) {
       method.returnType = context.typeProvider.stringType;
       method.type = new FunctionTypeImpl(method);
     }
     method.enclosingElement = this;
+    if (linkedNode != null) {
+      method.reference = reference.getChild('@method').getChild('toString');
+    }
     _methods = <MethodElement>[method];
   }
 
@@ -4045,6 +4110,51 @@
         .toList(growable: false);
     createToStringMethodElement();
   }
+
+  void _resynthesizeMembers2() {
+    var fields = <FieldElementImpl>[];
+    var getters = <PropertyAccessorElementImpl>[];
+
+    // Build the 'index' field.
+    {
+      var field = FieldElementImpl('index', -1)
+        ..enclosingElement = this
+        ..isSynthetic = true
+        ..isFinal = true
+        ..type = context.typeProvider.intType;
+      fields.add(field);
+      getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+          reference: reference.getChild('@getter').getChild('index'))
+        ..enclosingElement = this);
+    }
+
+    // Build the 'values' field.
+    {
+      var field = ConstFieldElementImpl_EnumValues(this);
+      fields.add(field);
+      getters.add(PropertyAccessorElementImpl_ImplicitGetter(field,
+          reference: reference.getChild('@getter').getChild('values'))
+        ..enclosingElement = this);
+    }
+
+    // Build fields for all enum constants.
+    var constants = linkedNode.enumDeclaration_constants;
+    for (var i = 0; i < constants.length; ++i) {
+      var constant = constants[i];
+      var name = enclosingUnit.linkedContext.getSimpleName(
+        constant.enumConstantDeclaration_name,
+      );
+      var reference = this.reference.getChild('@constant').getChild(name);
+      var field = new ConstFieldElementImpl_EnumValue.forLinkedNode(
+          this, reference, constant, i);
+      fields.add(field);
+      getters.add(field.getter);
+    }
+
+    _fields = fields;
+    _accessors = getters;
+    createToStringMethodElement();
+  }
 }
 
 /// A base class for concrete implementations of an [ExecutableElement].
@@ -5527,6 +5637,12 @@
         _linkedDependency = null,
         super(null, offset);
 
+  ImportElementImpl.forLinkedNode(
+      LibraryElementImpl enclosing, LinkedNode linkedNode)
+      : _unlinkedImport = null,
+        _linkedDependency = null,
+        super.forLinkedNode(enclosing, null, linkedNode);
+
   /// Initialize using the given serialized information.
   ImportElementImpl.forSerialized(this._unlinkedImport, this._linkedDependency,
       LibraryElementImpl enclosingLibrary)
@@ -5554,10 +5670,28 @@
   }
 
   @override
+  CompilationUnitElementImpl get enclosingUnit {
+    LibraryElementImpl enclosingLibrary = enclosingElement;
+    return enclosingLibrary._definingCompilationUnit;
+  }
+
+  @override
   String get identifier => "${importedLibrary.identifier}@$nameOffset";
 
   @override
   LibraryElement get importedLibrary {
+    if (_importedLibrary != null) return _importedLibrary;
+
+    if (linkedNode != null) {
+      var context = enclosingUnit.linkedContext;
+      var relativeUriStr = context.getStringContent(
+        linkedNode.uriBasedDirective_uri,
+      );
+      var relativeUri = Uri.parse(relativeUriStr);
+      var uri = resolveRelativeUri(librarySource.uri, relativeUri);
+      var elementFactory = context.bundleContext.elementFactory;
+      return _importedLibrary = elementFactory.libraryOfUri('$uri');
+    }
     if (_linkedDependency != null) {
       if (_importedLibrary == null) {
         LibraryElementImpl library = enclosingElement as LibraryElementImpl;
@@ -5598,6 +5732,11 @@
 
   @override
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      var metadata = enclosingUnit.linkedContext.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     if (_metadata == null) {
       if (_unlinkedImport != null) {
         return _metadata = _buildAnnotations(
@@ -5805,6 +5944,9 @@
 
   final UnlinkedUnit unlinkedDefiningUnit;
 
+  /// The context of the defining unit.
+  final LinkedUnitContext linkedContext;
+
   /// The compilation unit that defines this library.
   CompilationUnitElement _definingCompilationUnit;
 
@@ -5859,14 +6001,32 @@
       this.context, this.session, String name, int offset, this.nameLength)
       : resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        linkedContext = null,
         super(name, offset);
 
+  LibraryElementImpl.forLinkedNode(
+      this.context,
+      this.session,
+      String name,
+      int offset,
+      this.nameLength,
+      this.linkedContext,
+      Reference reference,
+      LinkedNode linkedNode)
+      : resynthesizerContext = null,
+        unlinkedDefiningUnit = null,
+        super.forLinkedNode(null, reference, linkedNode) {
+    _name = name;
+    _nameOffset = offset;
+  }
+
   /// Initialize a newly created library element in the given [context] to have
   /// the given [name].
   LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name)
       : nameLength = name != null ? name.length : 0,
         resynthesizerContext = null,
         unlinkedDefiningUnit = null,
+        linkedContext = null,
         super.forNode(name);
 
   /// Initialize using the given serialized information.
@@ -5878,7 +6038,8 @@
       this.nameLength,
       this.resynthesizerContext,
       this.unlinkedDefiningUnit)
-      : super.forSerialized(null) {
+      : linkedContext = null,
+        super.forSerialized(null) {
     _name = name;
     _nameOffset = offset;
     setResolutionCapability(
@@ -6052,6 +6213,13 @@
   @override
   List<ImportElement> get imports {
     if (_imports == null) {
+      if (linkedNode != null) {
+        return _imports = linkedNode.compilationUnit_directives
+            .where((node) => node.kind == LinkedNodeKind.importDirective)
+            .map((node) {
+          return ImportElementImpl.forLinkedNode(this, node);
+        }).toList();
+      }
       if (unlinkedDefiningUnit != null) {
         _imports = buildImportsFromSummary(this, unlinkedDefiningUnit.imports,
             resynthesizerContext.linkedLibrary.importDependencies);
@@ -6219,6 +6387,13 @@
 
   @override
   List<ElementAnnotation> get metadata {
+    if (linkedNode != null) {
+      if (_metadata != null) return _metadata;
+      CompilationUnitElementImpl enclosingUnit = _definingCompilationUnit;
+      var context = enclosingUnit.linkedContext;
+      var metadata = context.getMetadataOrEmpty(linkedNode);
+      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+    }
     if (_metadata == null) {
       if (unlinkedDefiningUnit != null) {
         _metadata = _buildAnnotations(
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 ff64ff6..f4436fd 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/ast_binary_writer.dart';
@@ -45,21 +46,31 @@
   void addImportsToScope() {
     // TODO
     var hasDartCore = false;
+    var unitContext = units[0].context;
     for (var directive in units[0].node.compilationUnit_directives) {
       if (directive.kind == LinkedNodeKind.importDirective) {
-        var uriStr = directive.uriBasedDirective_uriContent;
-        var importedLibrary = reference.parent.getChild(uriStr);
-        // TODO(scheglov) resolve URI as relative
+        var relativeUriStr = unitContext.getStringContent(
+          directive.uriBasedDirective_uri,
+        );
+        var relativeUri = Uri.parse(relativeUriStr);
+        var uri = resolveRelativeUri(this.uri, relativeUri);
+        var builder = linker.builders[uri];
+        if (builder != null) {
+          builder.exportScope.forEach((name, declaration) {
+            importScope.declare(name, declaration);
+          });
+        } else {
+          var references = linker.elementFactory.exportsOfLibrary('$uri');
+          _importExportedReferences(references);
+        }
         // TODO(scheglov) prefix
         // TODO(scheglov) combinators
       }
     }
     if (!hasDartCore) {
+      // TODO(scheglov) This works only when dart:core is linked
       var references = linker.elementFactory.exportsOfLibrary('dart:core');
-      for (var reference in references) {
-        var name = reference.name;
-        importScope.declare(name, Declaration(name, reference));
-      }
+      _importExportedReferences(references);
     }
   }
 
@@ -68,6 +79,7 @@
     for (var unit in units) {
       var unitRef = reference.getChild('@unit').getChild('${unit.uri}');
       var classRef = unitRef.getChild('@class');
+      var enumRef = unitRef.getChild('@enum');
       var functionRef = unitRef.getChild('@function');
       var typeAliasRef = unitRef.getChild('@typeAlias');
       var getterRef = unitRef.getChild('@getter');
@@ -81,6 +93,12 @@
           reference.node = node;
           var declaration = Declaration(name, reference);
           scope.declare(name, declaration);
+        } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+          var name = unit.context.getUnitMemberName(node);
+          var reference = enumRef.getChild(name);
+          reference.node = node;
+          var declaration = Declaration(name, reference);
+          scope.declare(name, declaration);
         } else if (node.kind == LinkedNodeKind.functionDeclaration) {
           var name = unit.context.getUnitMemberName(node);
 
@@ -214,6 +232,13 @@
     }
   }
 
+  void _importExportedReferences(List<Reference> exportedReferences) {
+    for (var reference in exportedReferences) {
+      var name = reference.name;
+      importScope.declare(name, Declaration(name, reference));
+    }
+  }
+
   static void build(Linker linker, Source librarySource,
       Map<Source, ast.CompilationUnit> libraryUnits) {
     var libraryUriStr = librarySource.uri.toString();
@@ -286,7 +311,7 @@
     }
 
     linker.linkingLibraries.add(libraryNode);
-    linker.builders.add(builder);
+    linker.builders[builder.uri] = builder;
   }
 }
 
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 2819b16..aec825a 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -40,7 +41,7 @@
   LinkedBundleContext bundleContext;
 
   /// Libraries that are being linked.
-  final List<SourceLibraryBuilder> builders = [];
+  final Map<Uri, SourceLibraryBuilder> builders = {};
 
   _AnalysisContextForLinking analysisContext;
   TypeProvider typeProvider;
@@ -92,7 +93,7 @@
   }
 
   void _addSyntheticConstructors() {
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.addSyntheticConstructors();
     }
   }
@@ -107,19 +108,19 @@
   }
 
   void _computeLibraryScopes() {
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.addLocalDeclarations();
     }
 
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.buildInitialExportScope();
     }
 
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.addImportsToScope();
     }
 
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.storeExportScope();
     }
 
@@ -139,19 +140,19 @@
   }
 
   void _performTopLevelInference() {
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.performTopLevelInference();
     }
   }
 
   void _resolveMetadata() {
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.resolveMetadata();
     }
   }
 
   void _resolveTypes() {
-    for (var library in builders) {
+    for (var library in builders.values) {
       library.resolveTypes();
     }
   }
@@ -163,7 +164,7 @@
   LinkResult(this.bundle);
 }
 
-class _AnalysisContextForLinking implements AnalysisContext {
+class _AnalysisContextForLinking implements InternalAnalysisContext {
   @override
   final AnalysisOptions analysisOptions;
 
@@ -178,6 +179,13 @@
 
   _AnalysisContextForLinking(this.analysisOptions, this.sourceFactory);
 
+  @override
+  Namespace getPublicNamespace(LibraryElement library) {
+    // TODO(scheglov) Not sure if this method of AnalysisContext is useful.
+    var builder = new NamespaceBuilder();
+    return builder.createPublicNamespaceForLibrary(library);
+  }
+
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index 6eb53de..d814b26a 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -21,7 +21,9 @@
 
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
     var type = getType(linkedType);
-    if (type is InterfaceType) return type;
+    if (type is InterfaceType && !type.element.isEnum) {
+      return type;
+    }
     return null;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 6ec9523..aa95877 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -80,11 +80,30 @@
       return _class(unit, reference);
     }
 
+    if (parentName == '@constructor') {
+      var class_ = elementOfReference(parent2);
+      return _constructor(class_, reference);
+    }
+
+    if (parentName == '@function') {
+      CompilationUnitElementImpl enclosing = elementOfReference(parent2);
+      enclosing.functions;
+      assert(reference.element != null);
+      return reference.element;
+    }
+
     if (parentName == '@getter') {
       var enclosing = elementOfReference(parent2);
       return _getter(enclosing, reference);
     }
 
+    if (parentName == '@parameter') {
+      ExecutableElementImpl enclosing = elementOfReference(parent2);
+      enclosing.parameters;
+      assert(reference.element != null);
+      return reference.element;
+    }
+
     if (parentName == '@typeAlias') {
       var unit = elementOfReference(parent2);
       return _typeAlias(unit, reference);
@@ -122,6 +141,15 @@
     );
   }
 
+  ConstructorElementImpl _constructor(
+      ClassElementImpl class_, Reference reference) {
+    return reference.element = ConstructorElementImpl.forLinkedNode(
+      reference,
+      reference.node,
+      class_,
+    );
+  }
+
   LibraryElementImpl _createLibraryElement(Reference reference) {
     var uriStr = reference.name;
 
@@ -131,12 +159,22 @@
     var libraryData = elementFactory.libraryMap[uriStr];
     var node = libraryData.node;
     var hasName = node.name.isNotEmpty;
-    var libraryElement = LibraryElementImpl(
+
+    var definingUnitData = node.units[0];
+    var definingUnitContext = LinkedUnitContext(
+      libraryData.context,
+      TokensContext(definingUnitData.tokens),
+    );
+
+    var libraryElement = LibraryElementImpl.forLinkedNode(
       elementFactory.analysisContext,
       elementFactory.analysisSession,
       node.name,
       hasName ? node.nameOffset : -1,
       node.name.length,
+      definingUnitContext,
+      reference,
+      definingUnitData.node,
     );
 
     var units = <CompilationUnitElementImpl>[];
@@ -183,18 +221,32 @@
     var context = unit.linkedContext;
     var unitRef = unit.reference;
     var classRef = unitRef.getChild('@class');
+    var enumRef = unitRef.getChild('@class');
+    var functionRef = unitRef.getChild('@function');
     var typeAliasRef = unitRef.getChild('@typeAlias');
+    var variableRef = unitRef.getChild('@variable');
     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 if (kind == LinkedNodeKind.enumDeclaration) {
+        var name = context.getUnitMemberName(declaration);
+        enumRef.getChild(name).node = declaration;
+      } else if (kind == LinkedNodeKind.functionDeclaration) {
+        var name = context.getUnitMemberName(declaration);
+        functionRef.getChild(name).node = declaration;
       } else if (kind == LinkedNodeKind.functionTypeAlias) {
         var name = context.getUnitMemberName(declaration);
         typeAliasRef.getChild(name).node = declaration;
+      } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
+        var variables = declaration.topLevelVariableDeclaration_variableList;
+        for (var variable in variables.variableDeclarationList_variables) {
+          var name = context.getSimpleName(variable.variableDeclaration_name);
+          variableRef.getChild(name).node = variable;
+        }
       } else {
-        // TODO(scheglov) support other elements
         throw UnimplementedError('$kind');
       }
     }
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 13d7e09..fcaac18 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -84,6 +84,8 @@
     if (kind == LinkedNodeKind.classDeclaration ||
         kind == LinkedNodeKind.classTypeAlias ||
         kind == LinkedNodeKind.constructorDeclaration ||
+        kind == LinkedNodeKind.enumConstantDeclaration ||
+        kind == LinkedNodeKind.enumDeclaration ||
         kind == LinkedNodeKind.functionDeclaration ||
         kind == LinkedNodeKind.functionTypeAlias ||
         kind == LinkedNodeKind.methodDeclaration ||
@@ -117,6 +119,10 @@
     return tokensContext.offset(node.simpleIdentifier_token);
   }
 
+  String getStringContent(LinkedNode node) {
+    return node.simpleStringLiteral_value;
+  }
+
   String getTokenLexeme(int token) {
     return tokensContext.lexeme(token);
   }
@@ -211,6 +217,9 @@
 
   bool isFinal(LinkedNode node) {
     var kind = node.kind;
+    if (kind == LinkedNodeKind.enumConstantDeclaration) {
+      return false;
+    }
     if (kind == LinkedNodeKind.variableDeclaration) {
       return node.variableDeclaration_declaration.isFinal;
     }
@@ -292,12 +301,16 @@
       return;
     }
 
+    var constructorContainerRef = reference.getChild('@constructor');
     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) {
+      if (member.kind == LinkedNodeKind.constructorDeclaration) {
+        var name = getConstructorDeclarationName(member);
+        constructorContainerRef.getChild(name).node = member;
+      } else if (member.kind == LinkedNodeKind.fieldDeclaration) {
         var variableList = member.fieldDeclaration_fields;
         for (var field in variableList.variableDeclarationList_variables) {
           var name = getSimpleName(field.variableDeclaration_name);
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 4c400d6..50b9b92 100644
--- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -58,7 +58,7 @@
         kind: LinkedNodeTypeKind.function,
         functionFormalParameters: _getReferences(type.parameters),
         functionReturnType: writeType(type.returnType),
-        functionTypeParameters: _getReferences(type.parameters),
+        functionTypeParameters: _getReferences(type.typeParameters),
       );
     } else if (type is InterfaceType) {
       return LinkedNodeTypeBuilder(
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
index e73ceeb1..8c36981 100644
--- a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -32,6 +32,8 @@
       }
       if (kind == LinkedNodeKind.classDeclaration) {
         _class(unit, unitDeclaration);
+      } else if (kind == LinkedNodeKind.enumDeclaration) {
+        _enumDeclaration(unit, unitDeclaration);
       } else if (kind == LinkedNodeKind.topLevelVariableDeclaration) {
         _variables(
           unit,
@@ -65,6 +67,15 @@
     }
   }
 
+  void _enumDeclaration(UnitBuilder unit, LinkedNodeBuilder node) {
+    for (var constant in node.enumDeclaration_constants) {
+      var kind = constant.kind;
+      if (kind == LinkedNodeKind.enumConstantDeclaration) {
+        _annotatedNode(unit, constant);
+      }
+    }
+  }
+
   List<LinkedNodeBuilder> _list(UnitBuilder unit, List<LinkedNode> unresolved) {
     var resolved = List<LinkedNodeBuilder>(unresolved.length);
     for (var i = 0; i < unresolved.length; ++i) {
@@ -98,6 +109,7 @@
     return kind == LinkedNodeKind.classDeclaration ||
         kind == LinkedNodeKind.classTypeAlias ||
         kind == LinkedNodeKind.constructorDeclaration ||
+        kind == LinkedNodeKind.enumDeclaration ||
         kind == LinkedNodeKind.functionDeclaration ||
         kind == LinkedNodeKind.functionTypeAlias ||
         kind == LinkedNodeKind.methodDeclaration;
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index b647ad3..c89239d 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -48,6 +48,8 @@
 
   bool get isClass => parent != null && parent.name == '@class';
 
+  bool get isEnum => parent != null && parent.name == '@enum';
+
   bool get isGenericTypeAlias => parent != null && parent.name == '@typeAlias';
 
   bool get isTypeParameter => parent != null && parent.name == '@typeParameter';
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 43f1011..75c798f 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -112,6 +112,12 @@
     _node(node.constructorDeclaration_parameters);
   }
 
+  void _enumConstantDeclaration(LinkedNodeBuilder node) {}
+
+  void _enumDeclaration(LinkedNodeBuilder node) {
+    _nodeList(node.enumDeclaration_constants);
+  }
+
   void _fieldDeclaration(LinkedNodeBuilder node) {
     _node(node.fieldDeclaration_fields);
   }
@@ -226,6 +232,8 @@
     }
   }
 
+  void _importDirective(LinkedNodeBuilder node) {}
+
   void _libraryDirective(LinkedNodeBuilder node) {}
 
   void _methodDeclaration(LinkedNodeBuilder node) {
@@ -257,6 +265,10 @@
       _compilationUnit(node);
     } else if (node.kind == LinkedNodeKind.constructorDeclaration) {
       _constructorDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.enumDeclaration) {
+      _enumDeclaration(node);
+    } else if (node.kind == LinkedNodeKind.enumConstantDeclaration) {
+      _enumConstantDeclaration(node);
     } else if (node.kind == LinkedNodeKind.fieldDeclaration) {
       _fieldDeclaration(node);
     } else if (node.kind == LinkedNodeKind.fieldFormalParameter) {
@@ -273,6 +285,8 @@
       _genericFunctionType(node);
     } else if (node.kind == LinkedNodeKind.genericTypeAlias) {
       _genericTypeAlias(node);
+    } else if (node.kind == LinkedNodeKind.importDirective) {
+      _importDirective(node);
     } else if (node.kind == LinkedNodeKind.libraryDirective) {
       _libraryDirective(node);
     } else if (node.kind == LinkedNodeKind.methodDeclaration) {
@@ -373,6 +387,11 @@
           interfaceClass: referenceIndex,
           interfaceTypeArguments: typeArguments,
         );
+      } else if (reference.isEnum) {
+        node.typeName_type = LinkedNodeTypeBuilder(
+          kind: LinkedNodeTypeKind.interface,
+          interfaceClass: referenceIndex,
+        );
       } else if (reference.isTypeParameter) {
         node.typeName_type = LinkedNodeTypeBuilder(
           kind: LinkedNodeTypeKind.typeParameter,
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 9dd8833..2d1397a 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -72,7 +72,6 @@
     var dartCoreResult = _link(dartCoreSource, dartCoreCode);
 
     var source = addTestSource(text);
-
     var unit = parseText(text, experimentStatus: experimentStatus);
 
     // TODO(scheglov) add other libraries
@@ -80,6 +79,12 @@
       source: {source: unit},
     };
 
+    for (var otherLibrarySource in otherLibrarySources) {
+      var text = getFile(otherLibrarySource.fullName).readAsStringSync();
+      var unit = parseText(text, experimentStatus: experimentStatus);
+      libraryUnitMap[otherLibrarySource] = {otherLibrarySource: unit};
+    }
+
     var linkResult = link(
       AnalysisOptionsImpl(),
       sourceFactory,
@@ -175,12 +180,6 @@
 
   @override
   @failingTest
-  test_class_documented_withMetadata() async {
-    await super.test_class_documented_withMetadata();
-  }
-
-  @override
-  @failingTest
   test_class_setter_invalid_named_parameter() async {
     await super.test_class_setter_invalid_named_parameter();
   }
@@ -313,12 +312,6 @@
 
   @override
   @failingTest
-  test_const_invalid_topLevel() async {
-    await super.test_const_invalid_topLevel();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_generic_named() async {
     await super.test_const_invokeConstructor_generic_named();
   }
@@ -369,12 +362,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_named_imported() async {
-    await super.test_const_invokeConstructor_named_imported();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_named_imported_withPrefix() async {
     await super.test_const_invokeConstructor_named_imported_withPrefix();
   }
@@ -405,12 +392,6 @@
 
   @override
   @failingTest
-  test_const_invokeConstructor_unnamed_imported() async {
-    await super.test_const_invokeConstructor_unnamed_imported();
-  }
-
-  @override
-  @failingTest
   test_const_invokeConstructor_unnamed_imported_withPrefix() async {
     await super.test_const_invokeConstructor_unnamed_imported_withPrefix();
   }
@@ -423,24 +404,12 @@
 
   @override
   @failingTest
-  test_const_length_ofClassConstField_imported() async {
-    await super.test_const_length_ofClassConstField_imported();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofClassConstField_imported_withPrefix() async {
     await super.test_const_length_ofClassConstField_imported_withPrefix();
   }
 
   @override
   @failingTest
-  test_const_length_ofTopLevelVariable_imported() async {
-    await super.test_const_length_ofTopLevelVariable_imported();
-  }
-
-  @override
-  @failingTest
   test_const_length_ofTopLevelVariable_imported_withPrefix() async {
     await super.test_const_length_ofTopLevelVariable_imported_withPrefix();
   }
@@ -491,12 +460,6 @@
 
   @override
   @failingTest
-  test_const_reference_staticField_imported() async {
-    await super.test_const_reference_staticField_imported();
-  }
-
-  @override
-  @failingTest
   test_const_reference_staticField_imported_withPrefix() async {
     await super.test_const_reference_staticField_imported_withPrefix();
   }
@@ -635,12 +598,6 @@
 
   @override
   @failingTest
-  test_const_topLevel_typedList_imported() async {
-    await super.test_const_topLevel_typedList_imported();
-  }
-
-  @override
-  @failingTest
   test_const_topLevel_typedList_importedWithPrefix() async {
     await super.test_const_topLevel_typedList_importedWithPrefix();
   }
@@ -659,18 +616,6 @@
 
   @override
   @failingTest
-  test_constExpr_pushReference_enum_field() async {
-    await super.test_constExpr_pushReference_enum_field();
-  }
-
-  @override
-  @failingTest
-  test_constExpr_pushReference_enum_method() async {
-    await super.test_constExpr_pushReference_enum_method();
-  }
-
-  @override
-  @failingTest
   test_constExpr_pushReference_field_simpleIdentifier() async {
     await super.test_constExpr_pushReference_field_simpleIdentifier();
   }
@@ -900,36 +845,6 @@
 
   @override
   @failingTest
-  test_enum_documented() async {
-    await super.test_enum_documented();
-  }
-
-  @override
-  @failingTest
-  test_enum_value_documented() async {
-    await super.test_enum_value_documented();
-  }
-
-  @override
-  @failingTest
-  test_enum_values() async {
-    await super.test_enum_values();
-  }
-
-  @override
-  @failingTest
-  test_enums() async {
-    await super.test_enums();
-  }
-
-  @override
-  @failingTest
-  test_error_extendsEnum() async {
-    await super.test_error_extendsEnum();
-  }
-
-  @override
-  @failingTest
   test_executable_parameter_type_typedef() async {
     await super.test_executable_parameter_type_typedef();
   }
@@ -1254,12 +1169,6 @@
 
   @override
   @failingTest
-  test_import_configurations_useDefault() async {
-    await super.test_import_configurations_useDefault();
-  }
-
-  @override
-  @failingTest
   test_import_configurations_useFirst() async {
     await super.test_import_configurations_useFirst();
   }
@@ -1308,24 +1217,12 @@
 
   @override
   @failingTest
-  test_import_short_absolute() async {
-    await super.test_import_short_absolute();
-  }
-
-  @override
-  @failingTest
   test_import_show() async {
     await super.test_import_show();
   }
 
   @override
   @failingTest
-  test_imports() async {
-    await super.test_imports();
-  }
-
-  @override
-  @failingTest
   test_infer_generic_typedef_simple() async {
     await super.test_infer_generic_typedef_simple();
   }
@@ -1517,12 +1414,6 @@
 
   @override
   @failingTest
-  test_invalid_annotation_unprefixed_constructor() async {
-    await super.test_invalid_annotation_unprefixed_constructor();
-  }
-
-  @override
-  @failingTest
   test_invalid_importPrefix_asTypeArgument() async {
     await super.test_invalid_importPrefix_asTypeArgument();
   }
@@ -1643,18 +1534,6 @@
 
   @override
   @failingTest
-  test_metadata_enumConstantDeclaration() async {
-    await super.test_metadata_enumConstantDeclaration();
-  }
-
-  @override
-  @failingTest
-  test_metadata_enumDeclaration() async {
-    await super.test_metadata_enumDeclaration();
-  }
-
-  @override
-  @failingTest
   test_metadata_exportDirective() async {
     await super.test_metadata_exportDirective();
   }
@@ -1987,12 +1866,6 @@
 
   @override
   @failingTest
-  test_type_reference_to_enum() async {
-    await super.test_type_reference_to_enum();
-  }
-
-  @override
-  @failingTest
   test_type_reference_to_import() async {
     await super.test_type_reference_to_import();
   }
@@ -2224,12 +2097,6 @@
 
   @override
   @failingTest
-  test_variable_propagatedType_implicit_dep() async {
-    await super.test_variable_propagatedType_implicit_dep();
-  }
-
-  @override
-  @failingTest
   test_variable_setterInPart_getterInPart() async {
     await super.test_variable_setterInPart_getterInPart();
   }