Resynthesize typedef(s) and generic function types.

R=brianwilkerson@google.com

Change-Id: I3ee3014ffc615052ef077dbf58947330e4ca5e17
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97420
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 5cf726d..6c9fb86 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1780,7 +1780,9 @@
       var context = enclosingUnit.linkedContext;
       var containerRef = reference.getChild('@typeAlias');
       _typeAliases = linkedNode.compilationUnit_declarations
-          .where((node) => node.kind == LinkedNodeKind.functionTypeAlias)
+          .where((node) =>
+              node.kind == LinkedNodeKind.functionTypeAlias ||
+              node.kind == LinkedNodeKind.genericTypeAlias)
           .map((node) {
         var name = context.getUnitMemberName(node);
         var reference = containerRef.getChild(name);
@@ -4372,32 +4374,12 @@
         var context = enclosingUnit.linkedContext;
         var containerRef = reference.getChild('@parameter');
         var formalParameters = context.getFormalParameters(linkedNode);
-        if (formalParameters != null) {
-          _parameters = formalParameters.map((node) {
-            if (node.kind == LinkedNodeKind.defaultFormalParameter) {
-              var parameterNode = node.defaultFormalParameter_parameter;
-              var name = context.getFormalParameterName(parameterNode);
-              var reference = containerRef.getChild(name);
-              reference.node = node;
-              return DefaultParameterElementImpl.forLinkedNode(
-                this,
-                reference,
-                node,
-              );
-            } else {
-              var name = context.getFormalParameterName(node);
-              var reference = containerRef.getChild(name);
-              reference.node = node;
-              return ParameterElementImpl.forLinkedNodeFactory(
-                this,
-                reference,
-                node,
-              );
-            }
-          }).toList();
-        } else {
-          _parameters = const [];
-        }
+        _parameters = ParameterElementImpl.forLinkedNodeList(
+          this,
+          context,
+          containerRef,
+          formalParameters,
+        );
       }
       if (serializedExecutable != null) {
         _parameters = ParameterElementImpl.resynthesizeList(
@@ -5143,6 +5125,10 @@
   /// The type defined by this element.
   FunctionType _type;
 
+  GenericFunctionTypeElementImpl.forLinkedNode(
+      ElementImpl enclosingElement, Reference reference, LinkedNode linkedNode)
+      : super.forLinkedNode(enclosingElement, reference, linkedNode);
+
   /// Initialize a newly created function element to have no name and the given
   /// [nameOffset]. This is used for function expressions, that have no name.
   GenericFunctionTypeElementImpl.forOffset(int nameOffset)
@@ -5167,6 +5153,15 @@
   @override
   List<ParameterElement> get parameters {
     if (_parameters == null) {
+      if (linkedNode != null) {
+        var context = enclosingUnit.linkedContext;
+        return _parameters = ParameterElementImpl.forLinkedNodeList(
+          this,
+          context,
+          reference.getChild('@parameter'),
+          context.getFormalParameters(linkedNode),
+        );
+      }
       if (_entityRef != null) {
         _parameters = ParameterElementImpl.resynthesizeList(
             _entityRef.syntheticParams, this);
@@ -5188,6 +5183,10 @@
   @override
   DartType get returnType {
     if (_returnType == null) {
+      if (linkedNode != null) {
+        var context = enclosingUnit.linkedContext;
+        return _returnType = context.getReturnType(linkedNode);
+      }
       if (_entityRef != null) {
         _returnType = enclosingUnit.resynthesizerContext.resolveTypeRef(
             this, _entityRef.syntheticReturnType,
@@ -5217,6 +5216,16 @@
     _type = type;
   }
 
+  @override
+  List<TypeParameterElement> get typeParameters {
+    if (linkedNode != null) {
+      if (linkedNode.kind == LinkedNodeKind.functionTypeAlias) {
+        return const <TypeParameterElement>[];
+      }
+    }
+    return super.typeParameters;
+  }
+
   /// Set the type parameters defined by this function type element to the given
   /// [typeParameters].
   void set typeParameters(List<TypeParameterElement> typeParameters) {
@@ -5362,24 +5371,19 @@
     if (_function != null) return _function;
 
     if (linkedNode != null) {
-      var context = enclosingUnit.linkedContext;
-      _function = new GenericFunctionTypeElementImpl.forOffset(-1);
-      _function.enclosingElement = this;
-      _function.returnType = context.getType(
-        linkedNode.functionTypeAlias_returnType2,
-      );
-      var containerRef = reference.getChild('@parameter');
-      var formalParameters = context.getFormalParameters(linkedNode);
-      _function.parameters = formalParameters.map((node) {
-        var name = context.getFormalParameterName(node);
-        var reference = containerRef.getChild(name);
-        reference.node = node;
-        return ParameterElementImpl.forLinkedNodeFactory(
+      if (linkedNode.kind == LinkedNodeKind.genericTypeAlias) {
+        _function = GenericFunctionTypeElementImpl.forLinkedNode(
           this,
-          reference,
-          node,
+          reference.getChild('@function'),
+          linkedNode.genericTypeAlias_functionType,
         );
-      }).toList();
+      } else {
+        return _function = GenericFunctionTypeElementImpl.forLinkedNode(
+          this,
+          reference.getChild('@function'),
+          linkedNode,
+        );
+      }
       return _function;
     }
 
@@ -8080,6 +8084,39 @@
     }
   }
 
+  static List<ParameterElement> forLinkedNodeList(
+      ElementImpl enclosing,
+      LinkedUnitContext context,
+      Reference containerRef,
+      List<LinkedNode> formalParameters) {
+    if (formalParameters == null) {
+      return const [];
+    }
+
+    return formalParameters.map((node) {
+      if (node.kind == LinkedNodeKind.defaultFormalParameter) {
+        var parameterNode = node.defaultFormalParameter_parameter;
+        var name = context.getFormalParameterName(parameterNode);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return DefaultParameterElementImpl.forLinkedNode(
+          enclosing,
+          reference,
+          node,
+        );
+      } else {
+        var name = context.getFormalParameterName(node);
+        var reference = containerRef.getChild(name);
+        reference.node = node;
+        return ParameterElementImpl.forLinkedNodeFactory(
+          enclosing,
+          reference,
+          node,
+        );
+      }
+    }).toList();
+  }
+
   /// Create and return [ParameterElement]s for the given [unlinkedParameters].
   static List<ParameterElement> resynthesizeList(
       List<UnlinkedParam> unlinkedParameters, ElementImpl enclosingElement,
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 38784fc..ce7fd72 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -9433,6 +9433,12 @@
     return _variantField_25;
   }
 
+  @override
+  LinkedNodeTypeBuilder get genericFunctionType_type {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    return _variantField_25;
+  }
+
   void set expression_type(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.adjacentStrings ||
         kind == idl.LinkedNodeKind.assignmentExpression ||
@@ -9469,6 +9475,11 @@
     _variantField_25 = value;
   }
 
+  void set genericFunctionType_type(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_25 = value;
+  }
+
   @override
   idl.LinkedNodeFormalParameterKind get formalParameter_kind {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
@@ -10715,13 +10726,15 @@
     LinkedNodeBuilder genericFunctionType_formalParameters,
     int genericFunctionType_question,
     LinkedNodeTypeBuilder genericFunctionType_returnType2,
+    LinkedNodeTypeBuilder genericFunctionType_type,
   })  : _kind = idl.LinkedNodeKind.genericFunctionType,
         _variantField_6 = genericFunctionType_typeParameters,
         _variantField_15 = genericFunctionType_functionKeyword,
         _variantField_7 = genericFunctionType_returnType,
         _variantField_8 = genericFunctionType_formalParameters,
         _variantField_16 = genericFunctionType_question,
-        _variantField_24 = genericFunctionType_returnType2;
+        _variantField_24 = genericFunctionType_returnType2,
+        _variantField_25 = genericFunctionType_type;
 
   LinkedNodeBuilder.ifElement({
     LinkedNodeBuilder ifMixin_condition,
@@ -14876,6 +14889,14 @@
   }
 
   @override
+  idl.LinkedNodeType get genericFunctionType_type {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _variantField_25 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 25, null);
+    return _variantField_25;
+  }
+
+  @override
   idl.LinkedNodeFormalParameterKind get formalParameter_kind {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
         kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
@@ -16275,6 +16296,8 @@
       if (genericFunctionType_returnType2 != null)
         _result["genericFunctionType_returnType2"] =
             genericFunctionType_returnType2.toJson();
+      if (genericFunctionType_type != null)
+        _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
     }
     if (kind == idl.LinkedNodeKind.ifElement) {
       if (ifMixin_condition != null)
@@ -17618,6 +17641,7 @@
             genericFunctionType_formalParameters,
         "genericFunctionType_question": genericFunctionType_question,
         "genericFunctionType_returnType2": genericFunctionType_returnType2,
+        "genericFunctionType_type": genericFunctionType_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18540,21 +18564,22 @@
 class LinkedNodeTypeBuilder extends Object
     with _LinkedNodeTypeMixin
     implements idl.LinkedNodeType {
-  List<int> _functionFormalParameters;
+  List<LinkedNodeTypeFormalParameterBuilder> _functionFormalParameters;
   LinkedNodeTypeBuilder _functionReturnType;
   List<int> _functionTypeParameters;
+  int _genericTypeAliasReference;
+  List<LinkedNodeTypeBuilder> _genericTypeAliasTypeArguments;
   int _interfaceClass;
   List<LinkedNodeTypeBuilder> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
   int _typeParameterParameter;
 
   @override
-  List<int> get functionFormalParameters =>
-      _functionFormalParameters ??= <int>[];
+  List<LinkedNodeTypeFormalParameterBuilder> get functionFormalParameters =>
+      _functionFormalParameters ??= <LinkedNodeTypeFormalParameterBuilder>[];
 
-  /// References to [LinkedNodeReferences].
-  void set functionFormalParameters(List<int> value) {
-    assert(value == null || value.every((e) => e >= 0));
+  void set functionFormalParameters(
+      List<LinkedNodeTypeFormalParameterBuilder> value) {
     this._functionFormalParameters = value;
   }
 
@@ -18575,6 +18600,22 @@
   }
 
   @override
+  int get genericTypeAliasReference => _genericTypeAliasReference ??= 0;
+
+  void set genericTypeAliasReference(int value) {
+    assert(value == null || value >= 0);
+    this._genericTypeAliasReference = value;
+  }
+
+  @override
+  List<LinkedNodeTypeBuilder> get genericTypeAliasTypeArguments =>
+      _genericTypeAliasTypeArguments ??= <LinkedNodeTypeBuilder>[];
+
+  void set genericTypeAliasTypeArguments(List<LinkedNodeTypeBuilder> value) {
+    this._genericTypeAliasTypeArguments = value;
+  }
+
+  @override
   int get interfaceClass => _interfaceClass ??= 0;
 
   /// Reference to a [LinkedNodeReferences].
@@ -18608,9 +18649,11 @@
   }
 
   LinkedNodeTypeBuilder(
-      {List<int> functionFormalParameters,
+      {List<LinkedNodeTypeFormalParameterBuilder> functionFormalParameters,
       LinkedNodeTypeBuilder functionReturnType,
       List<int> functionTypeParameters,
+      int genericTypeAliasReference,
+      List<LinkedNodeTypeBuilder> genericTypeAliasTypeArguments,
       int interfaceClass,
       List<LinkedNodeTypeBuilder> interfaceTypeArguments,
       idl.LinkedNodeTypeKind kind,
@@ -18618,6 +18661,8 @@
       : _functionFormalParameters = functionFormalParameters,
         _functionReturnType = functionReturnType,
         _functionTypeParameters = functionTypeParameters,
+        _genericTypeAliasReference = genericTypeAliasReference,
+        _genericTypeAliasTypeArguments = genericTypeAliasTypeArguments,
         _interfaceClass = interfaceClass,
         _interfaceTypeArguments = interfaceTypeArguments,
         _kind = kind,
@@ -18627,7 +18672,9 @@
    * Flush [informative] data recursively.
    */
   void flushInformative() {
+    _functionFormalParameters?.forEach((b) => b.flushInformative());
     _functionReturnType?.flushInformative();
+    _genericTypeAliasTypeArguments?.forEach((b) => b.flushInformative());
     _interfaceTypeArguments?.forEach((b) => b.flushInformative());
   }
 
@@ -18640,7 +18687,7 @@
     } else {
       signature.addInt(this._functionFormalParameters.length);
       for (var x in this._functionFormalParameters) {
-        signature.addInt(x);
+        x?.collectApiSignature(signature);
       }
     }
     signature.addBool(this._functionReturnType != null);
@@ -18664,17 +18711,27 @@
     }
     signature.addInt(this._kind == null ? 0 : this._kind.index);
     signature.addInt(this._typeParameterParameter ?? 0);
+    signature.addInt(this._genericTypeAliasReference ?? 0);
+    if (this._genericTypeAliasTypeArguments == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._genericTypeAliasTypeArguments.length);
+      for (var x in this._genericTypeAliasTypeArguments) {
+        x?.collectApiSignature(signature);
+      }
+    }
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
     fb.Offset offset_functionFormalParameters;
     fb.Offset offset_functionReturnType;
     fb.Offset offset_functionTypeParameters;
+    fb.Offset offset_genericTypeAliasTypeArguments;
     fb.Offset offset_interfaceTypeArguments;
     if (!(_functionFormalParameters == null ||
         _functionFormalParameters.isEmpty)) {
-      offset_functionFormalParameters =
-          fbBuilder.writeListUint32(_functionFormalParameters);
+      offset_functionFormalParameters = fbBuilder.writeList(
+          _functionFormalParameters.map((b) => b.finish(fbBuilder)).toList());
     }
     if (_functionReturnType != null) {
       offset_functionReturnType = _functionReturnType.finish(fbBuilder);
@@ -18683,6 +18740,13 @@
       offset_functionTypeParameters =
           fbBuilder.writeListUint32(_functionTypeParameters);
     }
+    if (!(_genericTypeAliasTypeArguments == null ||
+        _genericTypeAliasTypeArguments.isEmpty)) {
+      offset_genericTypeAliasTypeArguments = fbBuilder.writeList(
+          _genericTypeAliasTypeArguments
+              .map((b) => b.finish(fbBuilder))
+              .toList());
+    }
     if (!(_interfaceTypeArguments == null || _interfaceTypeArguments.isEmpty)) {
       offset_interfaceTypeArguments = fbBuilder.writeList(
           _interfaceTypeArguments.map((b) => b.finish(fbBuilder)).toList());
@@ -18697,6 +18761,12 @@
     if (offset_functionTypeParameters != null) {
       fbBuilder.addOffset(2, offset_functionTypeParameters);
     }
+    if (_genericTypeAliasReference != null && _genericTypeAliasReference != 0) {
+      fbBuilder.addUint32(7, _genericTypeAliasReference);
+    }
+    if (offset_genericTypeAliasTypeArguments != null) {
+      fbBuilder.addOffset(8, offset_genericTypeAliasTypeArguments);
+    }
     if (_interfaceClass != null && _interfaceClass != 0) {
       fbBuilder.addUint32(3, _interfaceClass);
     }
@@ -18729,18 +18799,23 @@
 
   _LinkedNodeTypeImpl(this._bc, this._bcOffset);
 
-  List<int> _functionFormalParameters;
+  List<idl.LinkedNodeTypeFormalParameter> _functionFormalParameters;
   idl.LinkedNodeType _functionReturnType;
   List<int> _functionTypeParameters;
+  int _genericTypeAliasReference;
+  List<idl.LinkedNodeType> _genericTypeAliasTypeArguments;
   int _interfaceClass;
   List<idl.LinkedNodeType> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
   int _typeParameterParameter;
 
   @override
-  List<int> get functionFormalParameters {
+  List<idl.LinkedNodeTypeFormalParameter> get functionFormalParameters {
     _functionFormalParameters ??=
-        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 0, const <int>[]);
+        const fb.ListReader<idl.LinkedNodeTypeFormalParameter>(
+                const _LinkedNodeTypeFormalParameterReader())
+            .vTableGet(
+                _bc, _bcOffset, 0, const <idl.LinkedNodeTypeFormalParameter>[]);
     return _functionFormalParameters;
   }
 
@@ -18759,6 +18834,21 @@
   }
 
   @override
+  int get genericTypeAliasReference {
+    _genericTypeAliasReference ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 7, 0);
+    return _genericTypeAliasReference;
+  }
+
+  @override
+  List<idl.LinkedNodeType> get genericTypeAliasTypeArguments {
+    _genericTypeAliasTypeArguments ??=
+        const fb.ListReader<idl.LinkedNodeType>(const _LinkedNodeTypeReader())
+            .vTableGet(_bc, _bcOffset, 8, const <idl.LinkedNodeType>[]);
+    return _genericTypeAliasTypeArguments;
+  }
+
+  @override
   int get interfaceClass {
     _interfaceClass ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
     return _interfaceClass;
@@ -18792,11 +18882,18 @@
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
     if (functionFormalParameters.isNotEmpty)
-      _result["functionFormalParameters"] = functionFormalParameters;
+      _result["functionFormalParameters"] =
+          functionFormalParameters.map((_value) => _value.toJson()).toList();
     if (functionReturnType != null)
       _result["functionReturnType"] = functionReturnType.toJson();
     if (functionTypeParameters.isNotEmpty)
       _result["functionTypeParameters"] = functionTypeParameters;
+    if (genericTypeAliasReference != 0)
+      _result["genericTypeAliasReference"] = genericTypeAliasReference;
+    if (genericTypeAliasTypeArguments.isNotEmpty)
+      _result["genericTypeAliasTypeArguments"] = genericTypeAliasTypeArguments
+          .map((_value) => _value.toJson())
+          .toList();
     if (interfaceClass != 0) _result["interfaceClass"] = interfaceClass;
     if (interfaceTypeArguments.isNotEmpty)
       _result["interfaceTypeArguments"] =
@@ -18813,6 +18910,8 @@
         "functionFormalParameters": functionFormalParameters,
         "functionReturnType": functionReturnType,
         "functionTypeParameters": functionTypeParameters,
+        "genericTypeAliasReference": genericTypeAliasReference,
+        "genericTypeAliasTypeArguments": genericTypeAliasTypeArguments,
         "interfaceClass": interfaceClass,
         "interfaceTypeArguments": interfaceTypeArguments,
         "kind": kind,
@@ -18823,6 +18922,148 @@
   String toString() => convert.json.encode(toJson());
 }
 
+class LinkedNodeTypeFormalParameterBuilder extends Object
+    with _LinkedNodeTypeFormalParameterMixin
+    implements idl.LinkedNodeTypeFormalParameter {
+  idl.LinkedNodeFormalParameterKind _kind;
+  String _name;
+  LinkedNodeTypeBuilder _type;
+
+  @override
+  idl.LinkedNodeFormalParameterKind get kind =>
+      _kind ??= idl.LinkedNodeFormalParameterKind.required;
+
+  void set kind(idl.LinkedNodeFormalParameterKind value) {
+    this._kind = value;
+  }
+
+  @override
+  String get name => _name ??= '';
+
+  void set name(String value) {
+    this._name = value;
+  }
+
+  @override
+  LinkedNodeTypeBuilder get type => _type;
+
+  void set type(LinkedNodeTypeBuilder value) {
+    this._type = value;
+  }
+
+  LinkedNodeTypeFormalParameterBuilder(
+      {idl.LinkedNodeFormalParameterKind kind,
+      String name,
+      LinkedNodeTypeBuilder type})
+      : _kind = kind,
+        _name = name,
+        _type = type;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+    _type?.flushInformative();
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addInt(this._kind == null ? 0 : this._kind.index);
+    signature.addString(this._name ?? '');
+    signature.addBool(this._type != null);
+    this._type?.collectApiSignature(signature);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_name;
+    fb.Offset offset_type;
+    if (_name != null) {
+      offset_name = fbBuilder.writeString(_name);
+    }
+    if (_type != null) {
+      offset_type = _type.finish(fbBuilder);
+    }
+    fbBuilder.startTable();
+    if (_kind != null && _kind != idl.LinkedNodeFormalParameterKind.required) {
+      fbBuilder.addUint8(0, _kind.index);
+    }
+    if (offset_name != null) {
+      fbBuilder.addOffset(1, offset_name);
+    }
+    if (offset_type != null) {
+      fbBuilder.addOffset(2, offset_type);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _LinkedNodeTypeFormalParameterReader
+    extends fb.TableReader<_LinkedNodeTypeFormalParameterImpl> {
+  const _LinkedNodeTypeFormalParameterReader();
+
+  @override
+  _LinkedNodeTypeFormalParameterImpl createObject(
+          fb.BufferContext bc, int offset) =>
+      new _LinkedNodeTypeFormalParameterImpl(bc, offset);
+}
+
+class _LinkedNodeTypeFormalParameterImpl extends Object
+    with _LinkedNodeTypeFormalParameterMixin
+    implements idl.LinkedNodeTypeFormalParameter {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _LinkedNodeTypeFormalParameterImpl(this._bc, this._bcOffset);
+
+  idl.LinkedNodeFormalParameterKind _kind;
+  String _name;
+  idl.LinkedNodeType _type;
+
+  @override
+  idl.LinkedNodeFormalParameterKind get kind {
+    _kind ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
+        _bc, _bcOffset, 0, idl.LinkedNodeFormalParameterKind.required);
+    return _kind;
+  }
+
+  @override
+  String get name {
+    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
+    return _name;
+  }
+
+  @override
+  idl.LinkedNodeType get type {
+    _type ??= const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 2, null);
+    return _type;
+  }
+}
+
+abstract class _LinkedNodeTypeFormalParameterMixin
+    implements idl.LinkedNodeTypeFormalParameter {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (kind != idl.LinkedNodeFormalParameterKind.required)
+      _result["kind"] = kind.toString().split('.')[1];
+    if (name != '') _result["name"] = name;
+    if (type != null) _result["type"] = type.toJson();
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+        "kind": kind,
+        "name": name,
+        "type": type,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class LinkedNodeUnitBuilder extends Object
     with _LinkedNodeUnitMixin
     implements idl.LinkedNodeUnit {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 3d529d9..8b52c07 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1920,14 +1920,17 @@
 
 /// Information about a Dart type.
 table LinkedNodeType {
-  /// References to [LinkedNodeReferences].
-  functionFormalParameters:[uint] (id: 0);
+  functionFormalParameters:[LinkedNodeTypeFormalParameter] (id: 0);
 
   functionReturnType:LinkedNodeType (id: 1);
 
   /// References to [LinkedNodeReferences].
   functionTypeParameters:[uint] (id: 2);
 
+  genericTypeAliasReference:uint (id: 7);
+
+  genericTypeAliasTypeArguments:[LinkedNodeType] (id: 8);
+
   /// Reference to a [LinkedNodeReferences].
   interfaceClass:uint (id: 3);
 
@@ -1939,6 +1942,15 @@
   typeParameterParameter:uint (id: 6);
 }
 
+/// Information about a formal parameter in a function type.
+table LinkedNodeTypeFormalParameter {
+  kind:LinkedNodeFormalParameterKind (id: 0);
+
+  name:string (id: 1);
+
+  type:LinkedNodeType (id: 2);
+}
+
 /// Information about a single library in a [LinkedNodeLibrary].
 table LinkedNodeUnit {
   node:LinkedNode (id: 2);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 81731be..e214f9c 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1531,6 +1531,9 @@
   @VariantId(24, variant: LinkedNodeKind.genericFunctionType)
   LinkedNodeType get genericFunctionType_returnType2;
 
+  @VariantId(25, variant: LinkedNodeKind.genericFunctionType)
+  LinkedNodeType get genericFunctionType_type;
+
   @VariantId(6, variant: LinkedNodeKind.genericFunctionType)
   LinkedNode get genericFunctionType_typeParameters;
 
@@ -2433,9 +2436,8 @@
 
 /// Information about a Dart type.
 abstract class LinkedNodeType extends base.SummaryClass {
-  /// References to [LinkedNodeReferences].
   @Id(0)
-  List<int> get functionFormalParameters;
+  List<LinkedNodeTypeFormalParameter> get functionFormalParameters;
 
   @Id(1)
   LinkedNodeType get functionReturnType;
@@ -2444,6 +2446,12 @@
   @Id(2)
   List<int> get functionTypeParameters;
 
+  @Id(7)
+  int get genericTypeAliasReference;
+
+  @Id(8)
+  List<LinkedNodeType> get genericTypeAliasTypeArguments;
+
   /// Reference to a [LinkedNodeReferences].
   @Id(3)
   int get interfaceClass;
@@ -2459,6 +2467,18 @@
   int get typeParameterParameter;
 }
 
+/// Information about a formal parameter in a function type.
+abstract class LinkedNodeTypeFormalParameter extends base.SummaryClass {
+  @Id(0)
+  LinkedNodeFormalParameterKind get kind;
+
+  @Id(1)
+  String get name;
+
+  @Id(2)
+  LinkedNodeType get type;
+}
+
 /// Kinds of [LinkedNodeType]s.
 enum LinkedNodeTypeKind {
   bottom,
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 9b03ad2..93c7b51 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -28,6 +28,16 @@
     return node;
   }
 
+  ParameterKind _formalParameterKind(LinkedNodeFormalParameterKind kind) {
+    if (kind == LinkedNodeFormalParameterKind.optionalNamed) {
+      return ParameterKind.NAMED;
+    }
+    if (kind == LinkedNodeFormalParameterKind.optionalPositional) {
+      return ParameterKind.POSITIONAL;
+    }
+    return ParameterKind.REQUIRED;
+  }
+
   T _getElement<T extends Element>(int index) {
     var bundleContext = _unitContext.bundleContext;
     return bundleContext.elementOfIndex(index);
@@ -1434,7 +1444,10 @@
         return FunctionTypeImpl.synthetic(
           _readType(data.functionReturnType),
           _getElements(data.functionTypeParameters),
-          _getElements(data.functionFormalParameters),
+          data.functionFormalParameters
+              .map((p) => ParameterElementImpl.synthetic(
+                  p.name, _readType(p.type), _formalParameterKind(p.kind)))
+              .toList(),
         );
       case LinkedNodeTypeKind.interface:
         var element = _getElement(data.interfaceClass);
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index fbaf454..e0abe3a 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/reference.dart';
@@ -46,19 +47,21 @@
     var kind = linkedType.kind;
     if (kind == LinkedNodeTypeKind.dynamic_) {
       return DynamicTypeImpl.instance;
+    } else if (kind == LinkedNodeTypeKind.genericTypeAlias) {
+      var reference = referenceOfIndex(linkedType.genericTypeAliasReference);
+      return GenericTypeAliasElementImpl.typeAfterSubstitution(
+        elementFactory.elementOfReference(reference),
+        linkedType.genericTypeAliasTypeArguments.map(getType).toList(),
+      );
     } else if (kind == LinkedNodeTypeKind.function) {
       var returnType = getType(linkedType.functionReturnType);
-      var typeParameters = linkedType.functionTypeParameters
-          .map(referenceOfIndex)
-          .map(elementFactory.elementOfReference)
-          .cast<TypeParameterElement>()
-          .toList();
-      var formalParameters = linkedType.functionFormalParameters
-          .map(referenceOfIndex)
-          .map(elementFactory.elementOfReference)
-          .cast<ParameterElement>()
-          .toList();
-      // TODO(scheglov) Rework this to purely synthetic types.
+      var formalParameters = linkedType.functionFormalParameters.map((p) {
+        return ParameterElementImpl.synthetic(
+          p.name,
+          getType(p.type),
+          _formalParameterKind(p.kind),
+        );
+      }).toList();
       return FunctionElementImpl.synthetic(formalParameters, returnType).type;
     } else if (kind == LinkedNodeTypeKind.interface) {
       var reference = referenceOfIndex(linkedType.interfaceClass);
@@ -105,4 +108,14 @@
 
     return reference;
   }
+
+  ParameterKind _formalParameterKind(LinkedNodeFormalParameterKind kind) {
+    if (kind == LinkedNodeFormalParameterKind.optionalNamed) {
+      return ParameterKind.NAMED;
+    }
+    if (kind == LinkedNodeFormalParameterKind.optionalPositional) {
+      return ParameterKind.POSITIONAL;
+    }
+    return ParameterKind.REQUIRED;
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index b1bb1f4..a5fe43b 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -56,6 +56,8 @@
           .functionExpression_formalParameters;
     } else if (kind == LinkedNodeKind.functionTypeAlias) {
       parameterList = node.functionTypeAlias_formalParameters;
+    } else if (kind == LinkedNodeKind.genericFunctionType) {
+      parameterList = node.genericFunctionType_formalParameters;
     } else if (kind == LinkedNodeKind.methodDeclaration) {
       parameterList = node.methodDeclaration_formalParameters;
     } else {
@@ -109,6 +111,10 @@
     var kind = node.kind;
     if (kind == LinkedNodeKind.functionDeclaration) {
       return getType(node.functionDeclaration_returnType2);
+    } else if (kind == LinkedNodeKind.functionTypeAlias) {
+      return getType(node.functionTypeAlias_returnType2);
+    } else if (kind == LinkedNodeKind.genericFunctionType) {
+      return getType(node.genericFunctionType_returnType2);
     } else if (kind == LinkedNodeKind.methodDeclaration) {
       return getType(node.methodDeclaration_returnType2);
     } else {
@@ -161,6 +167,10 @@
       typeParameterList = node.functionExpression_typeParameters;
     } else if (kind == LinkedNodeKind.functionTypeAlias) {
       typeParameterList = node.functionTypeAlias_typeParameters;
+    } else if (kind == LinkedNodeKind.genericFunctionType) {
+      typeParameterList = node.genericFunctionType_typeParameters;
+    } else if (kind == LinkedNodeKind.genericTypeAlias) {
+      typeParameterList = node.genericTypeAlias_typeParameters;
     } else if (kind == LinkedNodeKind.methodDeclaration) {
       typeParameterList = node.methodDeclaration_typeParameters;
     } else {
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 50b9b92..c296437 100644
--- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/reference.dart';
@@ -56,7 +57,14 @@
     } else if (type is FunctionType) {
       return LinkedNodeTypeBuilder(
         kind: LinkedNodeTypeKind.function,
-        functionFormalParameters: _getReferences(type.parameters),
+        functionFormalParameters: type.parameters
+            .map((p) => LinkedNodeTypeFormalParameterBuilder(
+                  // ignore: deprecated_member_use_from_same_package
+                  kind: _formalParameterKind(p.parameterKind),
+                  name: p.name,
+                  type: writeType(p.type),
+                ))
+            .toList(),
         functionReturnType: writeType(type.returnType),
         functionTypeParameters: _getReferences(type.typeParameters),
       );
@@ -80,6 +88,16 @@
     }
   }
 
+  LinkedNodeFormalParameterKind _formalParameterKind(ParameterKind kind) {
+    if (kind == ParameterKind.NAMED) {
+      return LinkedNodeFormalParameterKind.optionalNamed;
+    }
+    if (kind == ParameterKind.POSITIONAL) {
+      return LinkedNodeFormalParameterKind.optionalPositional;
+    }
+    return LinkedNodeFormalParameterKind.required;
+  }
+
   int _getReferenceIndex(Element element) {
     if (element == null) return 0;
 
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 7ab1198..72ac0e4 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -203,13 +203,12 @@
       var returnType = node.genericFunctionType_returnType;
       if (returnType != null) {
         _node(returnType);
-        node.genericFunctionType_returnType2 =
-            _getTypeAnnotationType(returnType);
-      } else {
-        node.genericFunctionType_returnType2 = _dynamicType;
+        typesToBuild.declarations.add(node);
       }
 
       _node(node.genericFunctionType_formalParameters);
+
+      typesToBuild.typeAnnotations.add(node);
     });
 
     reference = reference.parent.parent;
@@ -229,15 +228,6 @@
     reference = reference.parent.parent;
   }
 
-  LinkedNodeTypeBuilder _getTypeAnnotationType(LinkedNodeBuilder node) {
-    var kind = node.kind;
-    if (kind == LinkedNodeKind.typeName) {
-      return node.typeName_type;
-    } else {
-      throw UnimplementedError('$kind');
-    }
-  }
-
   void _importDirective(LinkedNodeBuilder node) {}
 
   void _libraryDirective(LinkedNodeBuilder node) {}
@@ -385,7 +375,7 @@
         _node(typeArgumentList);
       }
 
-      typesToBuild.typeNames.add(node);
+      typesToBuild.typeAnnotations.add(node);
     } else {
       // TODO(scheglov) implement
       throw UnimplementedError();
@@ -445,12 +435,14 @@
 /// know this until we resolved `A` declaration, and we might have not yet.
 /// So, we remember [LinkedNodeKind.typeName] nodes to resolve them later.
 class TypesToBuild {
-  /// Nodes with [LinkedNodeKind.typeName], both with type arguments, and
-  /// without them.  These nodes will be resolved by [ReferenceResolver], so
-  /// that they have their references set, but their types will not be set yet.
+  /// Nodes with [LinkedNodeKind.typeName] (with type arguments, and without
+  /// them), and [LinkedNodeKind.genericFunctionType].  These nodes will be
+  /// resolved by [ReferenceResolver], so that they have their references set,
+  /// but their types will not be set yet.
   ///
-  /// Types arguments must be before the types that use them in this list.
-  final List<LinkedNodeBuilder> typeNames = [];
+  /// Types arguments, return types, and types of formal parameters must be
+  /// before the types that use them in this list.
+  final List<LinkedNodeBuilder> typeAnnotations = [];
 
   /// Nodes with type annotations, where we want not just resolve these types
   /// annotations, but also set additional types.  For example instance method
diff --git a/pkg/analyzer/lib/src/summary2/type_builder.dart b/pkg/analyzer/lib/src/summary2/type_builder.dart
index fcacd84..c2c6359 100644
--- a/pkg/analyzer/lib/src/summary2/type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/type_builder.dart
@@ -13,15 +13,53 @@
 
   TypeBuilder(this.bundleContext);
 
+  LinkedNodeTypeBuilder get _dynamicType {
+    return LinkedNodeTypeBuilder(
+      kind: LinkedNodeTypeKind.dynamic_,
+    );
+  }
+
   void build(TypesToBuild typesToBuild) {
-    for (var node in typesToBuild.typeNames) {
-      _buildTypeName(node);
+    for (var node in typesToBuild.typeAnnotations) {
+      var kind = node.kind;
+      if (kind == LinkedNodeKind.genericFunctionType) {
+        _buildGenericFunctionType(node);
+      } else if (kind == LinkedNodeKind.typeName) {
+        _buildTypeName(node);
+      } else {
+        throw StateError('$kind');
+      }
     }
     for (var node in typesToBuild.declarations) {
       _setTypesForDeclaration(node);
     }
   }
 
+  void _buildGenericFunctionType(LinkedNodeBuilder node) {
+    // TODO(scheglov) Type parameters?
+    LinkedNodeTypeBuilder returnType;
+    if (node.genericFunctionType_returnType != null) {
+      returnType = _getType(node.genericFunctionType_returnType);
+    } else {
+      returnType = _dynamicType;
+    }
+
+    var formalParameters = <LinkedNodeTypeFormalParameterBuilder>[];
+    for (var parameter in node
+        .genericFunctionType_formalParameters.formalParameterList_parameters) {
+      formalParameters.add(LinkedNodeTypeFormalParameterBuilder(
+        kind: parameter.formalParameter_kind,
+        type: _getType(parameter.simpleFormalParameter_type),
+      ));
+    }
+
+    node.genericFunctionType_type = LinkedNodeTypeBuilder(
+      kind: LinkedNodeTypeKind.function,
+      functionFormalParameters: formalParameters,
+      functionReturnType: returnType,
+    );
+  }
+
   void _buildTypeName(LinkedNodeBuilder node) {
     var referenceIndex = _typeNameElementIndex(node.typeName_name);
     var reference = bundleContext.referenceOfIndex(referenceIndex);
@@ -40,6 +78,12 @@
         interfaceClass: referenceIndex,
         interfaceTypeArguments: typeArguments,
       );
+    } else if (reference.isGenericTypeAlias) {
+      node.typeName_type = LinkedNodeTypeBuilder(
+        kind: LinkedNodeTypeKind.genericTypeAlias,
+        genericTypeAliasReference: referenceIndex,
+        genericTypeAliasTypeArguments: typeArguments,
+      );
     } else if (reference.isEnum) {
       node.typeName_type = LinkedNodeTypeBuilder(
         kind: LinkedNodeTypeKind.interface,
@@ -52,7 +96,7 @@
       );
     } else {
       // TODO(scheglov) set Object? keep unresolved?
-      throw UnimplementedError();
+      throw UnimplementedError('$reference');
     }
   }
 
@@ -70,6 +114,10 @@
       node.functionTypeAlias_returnType2 = _getType(
         node.functionTypeAlias_returnType,
       );
+    } else if (kind == LinkedNodeKind.genericFunctionType) {
+      node.genericFunctionType_returnType2 = _getType(
+        node.genericFunctionType_returnType,
+      );
     } else if (kind == LinkedNodeKind.methodDeclaration) {
       node.methodDeclaration_returnType2 = _getType(
         node.methodDeclaration_returnType,
@@ -90,7 +138,9 @@
 
   static LinkedNodeTypeBuilder _getType(LinkedNodeBuilder node) {
     var kind = node.kind;
-    if (kind == LinkedNodeKind.typeName) {
+    if (kind == LinkedNodeKind.genericFunctionType) {
+      return node.genericFunctionType_type;
+    } else if (kind == LinkedNodeKind.typeName) {
       return node.typeName_type;
     } else {
       throw UnimplementedError('$kind');
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 32edf88..087ef97 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -443,12 +443,6 @@
 
   @override
   @failingTest
-  test_const_reference_staticMethod_imported() async {
-    await super.test_const_reference_staticMethod_imported();
-  }
-
-  @override
-  @failingTest
   test_const_reference_staticMethod_imported_withPrefix() async {
     await super.test_const_reference_staticMethod_imported_withPrefix();
   }
@@ -750,12 +744,6 @@
 
   @override
   @failingTest
-  test_executable_parameter_type_typedef() async {
-    await super.test_executable_parameter_type_typedef();
-  }
-
-  @override
-  @failingTest
   test_export_class() async {
     await super.test_export_class();
   }
@@ -1014,42 +1002,12 @@
 
   @override
   @failingTest
-  test_genericFunction_asFunctionReturnType() async {
-    await super.test_genericFunction_asFunctionReturnType();
-  }
-
-  @override
-  @failingTest
   test_genericFunction_asFunctionTypedParameterReturnType() async {
     await super.test_genericFunction_asFunctionTypedParameterReturnType();
   }
 
   @override
   @failingTest
-  test_genericFunction_asGenericFunctionReturnType() async {
-    await super.test_genericFunction_asGenericFunctionReturnType();
-  }
-
-  @override
-  @failingTest
-  test_genericFunction_asMethodReturnType() async {
-    await super.test_genericFunction_asMethodReturnType();
-  }
-
-  @override
-  @failingTest
-  test_genericFunction_asParameterType() async {
-    await super.test_genericFunction_asParameterType();
-  }
-
-  @override
-  @failingTest
-  test_genericFunction_asTopLevelVariableType() async {
-    await super.test_genericFunction_asTopLevelVariableType();
-  }
-
-  @override
-  @failingTest
   test_getter_inferred_type_nonStatic_implicit_return() async {
     await super.test_getter_inferred_type_nonStatic_implicit_return();
   }
@@ -1683,12 +1641,6 @@
 
   @override
   @failingTest
-  test_type_reference_lib_to_lib() async {
-    await super.test_type_reference_lib_to_lib();
-  }
-
-  @override
-  @failingTest
   test_type_reference_lib_to_part() async {
     await super.test_type_reference_lib_to_part();
   }
@@ -1773,24 +1725,6 @@
 
   @override
   @failingTest
-  test_type_reference_to_typedef() async {
-    await super.test_type_reference_to_typedef();
-  }
-
-  @override
-  @failingTest
-  test_type_reference_to_typedef_with_type_arguments() async {
-    await super.test_type_reference_to_typedef_with_type_arguments();
-  }
-
-  @override
-  @failingTest
-  test_type_reference_to_typedef_with_type_arguments_implicit() async {
-    await super.test_type_reference_to_typedef_with_type_arguments_implicit();
-  }
-
-  @override
-  @failingTest
   test_type_unresolved_prefixed() async {
     await super.test_type_unresolved_prefixed();
   }
@@ -1827,12 +1761,6 @@
 
   @override
   @failingTest
-  test_typedef_parameters_named() async {
-    await super.test_typedef_parameters_named();
-  }
-
-  @override
-  @failingTest
   test_typedef_type_parameters_bound_recursive() async {
     await super.test_typedef_type_parameters_bound_recursive();
   }