Adapt ResolutionApplier.visitFormalParameterList to handle function-typed formal parameters.

Fixes #33845.

Change-Id: I6de918d644e9a22b1a9f9cd384b972047078a472
Reviewed-on: https://dart-review.googlesource.com/65162
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 015946f..d326fcd 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -1220,7 +1220,7 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter() {
+  void endFunctionTypedFormalParameter(Token nameToken) {
     debugEvent("FunctionTypedFormalParameter");
 
     FormalParameterList formalParameters = pop();
diff --git a/pkg/analyzer/lib/src/fasta/resolution_applier.dart b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
index 2125919..7c73f73 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_applier.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
@@ -258,9 +258,19 @@
       }
       if (normalParameter is SimpleFormalParameter) {
         normalParameter.type?.accept(this);
+      } else if (normalParameter is FieldFormalParameter) {
+        normalParameter.type?.accept(this);
+      } else if (normalParameter is FunctionTypedFormalParameter) {
+        normalParameter.returnType?.accept(this);
+        normalParameter.typeParameters?.accept(this);
+        normalParameter.parameters?.accept(this);
+        var data = _get(normalParameter.identifier);
+        normalParameter.identifier.staticType = data.inferredType;
       } else {
-        // TODO(paulberry): handle function typed formal parameters
-        // (dartbug.com/33845)
+        // Now that DefaultFormalParameter has been handled, all parameters
+        // should be SimpleFormalParameter, FieldFormalParameter, or
+        // FunctionTypedFormalParameter.
+        throw new UnimplementedError('${normalParameter.runtimeType}');
       }
     }
   }
diff --git a/pkg/analyzer/lib/src/fasta/resolution_storer.dart b/pkg/analyzer/lib/src/fasta/resolution_storer.dart
index 72fdf19..218029f 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_storer.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_storer.dart
@@ -291,6 +291,11 @@
           ExpressionJudgment judgment, int location, DartType inferredType) =>
       genericExpression("functionExpression", location, inferredType);
 
+  @override
+  void functionTypedFormalParameter(int location, DartType type) {
+    _store(location, inferredType: type);
+  }
+
   void genericExpression(
       String expressionType, int location, DartType inferredType) {
     _store(location, inferredType: inferredType);
@@ -615,9 +620,10 @@
         isTypeReference: true);
   }
 
-  void typeVariableDeclaration(
+  void typeVariableDeclaration(int location,
       covariant TypeVariableBinder binder, TypeParameter typeParameter) {
     _storeTypeVariableDeclaration(binder.fileOffset, typeParameter);
+    _store(location, declaration: binder.fileOffset);
   }
 
   void variableAssign(
diff --git a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
index 73bce7e..6f40a3c 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
@@ -185,13 +185,6 @@
 
   @override
   @failingTest
-  test_forEach_genericFunctionType() {
-    // Bad state: Not found T in main() → dynamic
-    return super.test_forEach_genericFunctionType();
-  }
-
-  @override
-  @failingTest
   @FastaProblem('https://github.com/dart-lang/sdk/issues/33799')
   test_functionTypeAlias_scope_signature() async {
     // Caused by Bad state: Found 1 annotation nodes and 0 element annotations
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 9697a3c..daa3ac4 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -795,9 +795,9 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter() {
+  void endFunctionTypedFormalParameter(Token nameToken) {
     end('FunctionTypedFormalParameter');
-    super.endFunctionTypedFormalParameter();
+    super.endFunctionTypedFormalParameter(nameToken);
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/static_warning_code_kernel_test.dart b/pkg/analyzer/test/generated/static_warning_code_kernel_test.dart
index e8408a0..92bc27e 100644
--- a/pkg/analyzer/test/generated/static_warning_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_kernel_test.dart
@@ -1410,6 +1410,13 @@
 
   @override
   @failingTest
+  test_typeAnnotationDeferredClass_fieldFormalParameter() {
+    // Bad state: No data for A at 73 in /lib2.dart
+    return super.test_typeAnnotationDeferredClass_fieldFormalParameter();
+  }
+
+  @override
+  @failingTest
   @potentialAnalyzerProblem
   test_typeAnnotationDeferredClass_functionDeclaration_returnType() async {
     return super
@@ -1418,6 +1425,14 @@
 
   @override
   @failingTest
+  test_typeAnnotationDeferredClass_functionTypedFormalParameter_returnType() {
+    // Bad state: No data for A at 52 in /lib2.dart
+    return super
+        .test_typeAnnotationDeferredClass_functionTypedFormalParameter_returnType();
+  }
+
+  @override
+  @failingTest
   test_typeAnnotationDeferredClass_isExpression() {
     // Bad state: No data for A at 77 in /lib2.dart
     return super.test_typeAnnotationDeferredClass_isExpression();
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_kernel_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_kernel_test.dart
index e62131b..ab5a476 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_kernel_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_kernel_test.dart
@@ -156,6 +156,13 @@
     await super.test_getResult_doesNotExist();
   }
 
+  @override
+  @failingTest
+  test_getResult_functionTypeFormalParameter_withTypeParameter() {
+    // Failed assertion: 'element != null': is not true.
+    return super.test_getResult_functionTypeFormalParameter_withTypeParameter();
+  }
+
   @failingTest
   @potentialAnalyzerProblem
   @override
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index fdfdd7c..8f9e062 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -3967,6 +3967,32 @@
     }
   }
 
+  test_local_function_with_function_typed_parameter() async {
+    addTestFile('''
+class C {}
+class D {}
+class E {}
+void f() {
+  void g(C callback<T extends E>(D d)) {}
+}
+''');
+    await resolveTestFile();
+    var callback = findNode.simple('callback');
+    assertType(callback, '<T extends E>(D) → C');
+    var cReference = findNode.simple('C callback');
+    var cElement = findElement.class_('C');
+    assertType(cReference, 'C');
+    assertElement(cReference, cElement);
+    var dReference = findNode.simple('D d');
+    var dElement = findElement.class_('D');
+    assertType(dReference, 'D');
+    assertElement(dReference, dElement);
+    var eReference = findNode.simple('E>');
+    var eElement = findElement.class_('E');
+    assertType(eReference, 'E');
+    assertElement(eReference, eElement);
+  }
+
   test_local_parameter() async {
     String content = r'''
 void main(int p) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 3838ba4..6f75480 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2439,7 +2439,7 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter() {
+  void endFunctionTypedFormalParameter(Token nameToken) {
     debugEvent("FunctionTypedFormalParameter");
     if (inCatchClause || functionNestingLevel != 0) {
       exitLocalScope();
@@ -2448,6 +2448,7 @@
     DartType returnType = pop();
     List<TypeParameter> typeVariables = typeVariableBuildersToKernel(pop());
     FunctionType type = formals.toFunctionType(returnType, typeVariables);
+    _typeInferrer.functionTypedFormalParameter(nameToken.offset, type);
     exitLocalScope();
     push(type);
     functionNestingLevel--;
@@ -3811,7 +3812,6 @@
       variable.binder = _typeInferrer.binderForTypeVariable(
           variable, variable.charOffset, variable.name);
     }
-    storeTypeUse(offsetForToken(token), variable.target);
     if (annotations != null) {
       _typeInferrer.inferMetadata(this, factory, annotations);
       for (Expression annotation in annotations) {
@@ -3893,7 +3893,8 @@
     int i = 0;
     for (KernelTypeVariableBuilder builder in typeVariableBuilders) {
       var typeParameter = builder.target;
-      _typeInferrer.typeVariableDeclaration(builder.binder, typeParameter);
+      _typeInferrer.typeVariableDeclaration(
+          builder.charOffset, builder.binder, typeParameter);
       typeParameters[i++] = typeParameter;
     }
     return typeParameters;
diff --git a/pkg/front_end/lib/src/fasta/kernel/factory.dart b/pkg/front_end/lib/src/fasta/kernel/factory.dart
index 885c394..5ede5ca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/factory.dart
@@ -204,6 +204,8 @@
   Expression functionExpression(
       ExpressionJudgment judgment, int fileOffset, DartType inferredType);
 
+  Object functionTypedFormalParameter(int fileOffset, DartType type);
+
   Expression ifNull(
       ExpressionJudgment judgment,
       int fileOffset,
@@ -444,7 +446,7 @@
       DartType type);
 
   Object typeVariableDeclaration(
-      covariant Object binder, TypeParameter typeParameter);
+      int fileOffset, covariant Object binder, TypeParameter typeParameter);
 
   Expression variableAssign(
       ExpressionJudgment judgment,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart
index f474c5e..31c1598 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart
@@ -303,6 +303,9 @@
   }
 
   @override
+  void functionTypedFormalParameter(int fileOffset, DartType type) {}
+
+  @override
   Expression ifNull(
       ExpressionJudgment judgment,
       int fileOffset,
@@ -662,7 +665,7 @@
       DartType type) {}
 
   @override
-  TypeParameter typeVariableDeclaration(
+  TypeParameter typeVariableDeclaration(int fileOffset,
       covariant KernelTypeVariableBuilder binder, TypeParameter typeParameter) {
     return typeParameter;
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart b/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart
index 6aad140..60e7542 100644
--- a/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart
@@ -241,6 +241,9 @@
       ExpressionJudgment judgment, int fileOffset, DartType inferredType) {}
 
   @override
+  void functionTypedFormalParameter(int fileOffset, DartType type) {}
+
+  @override
   void ifNull(ExpressionJudgment judgment, int fileOffset, void leftOperand,
       Token operator, void rightOperand, DartType inferredType) {}
 
@@ -506,7 +509,7 @@
 
   @override
   void typeVariableDeclaration(
-      covariant void binder, TypeParameter typeParameter) {}
+      int fileOffset, covariant void binder, TypeParameter typeParameter) {}
 
   @override
   void variableAssign(
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 3af09ee..467e833 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -641,8 +641,8 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter() {
-    listener?.endFunctionTypedFormalParameter();
+  void endFunctionTypedFormalParameter(Token nameToken) {
+    listener?.endFunctionTypedFormalParameter(nameToken);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index c69cf17..1f6dd5c 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -996,7 +996,7 @@
   /// - type variables
   /// - return type
   /// - formal parameters
-  void endFunctionTypedFormalParameter() {
+  void endFunctionTypedFormalParameter(Token nameToken) {
     logEvent("FunctionTypedFormalParameter");
   }
 
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 861b15c..0c820a7 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1350,7 +1350,7 @@
       token = typeInfo.parseType(beforeType, this);
       endInlineFunctionType = parseFormalParametersRequiredOpt(
           endInlineFunctionType, MemberKind.FunctionTypedParameter);
-      listener.endFunctionTypedFormalParameter();
+      listener.endFunctionTypedFormalParameter(beforeInlineFunctionType);
 
       // Generalized function types don't allow inline function types.
       // The following isn't allowed:
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 8f8c5c1..597ecd0 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1016,7 +1016,7 @@
   }
 
   @override
-  void endFunctionTypedFormalParameter() {
+  void endFunctionTypedFormalParameter(Token nameToken) {
     debugEvent("FunctionTypedFormalParameter");
     List<FormalParameterBuilder> formals = pop();
     int formalsOffset = pop();
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
index 4b2a6db..17332eb 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
@@ -216,6 +216,8 @@
   void functionExpression(
       ExpressionJudgment judgment, Location location, DartType inferredType);
 
+  void functionTypedFormalParameter(Location location, DartType type);
+
   void ifNull(ExpressionJudgment judgment, Location location, void leftOperand,
       Token operator, void rightOperand, DartType inferredType);
 
@@ -451,7 +453,7 @@
       DartType type);
 
   void typeVariableDeclaration(
-      covariant Object binder, TypeParameter typeParameter);
+      Location location, covariant Object binder, TypeParameter typeParameter);
 
   void variableAssign(
       ExpressionJudgment judgment,
@@ -686,6 +688,8 @@
   void functionExpression(
       ExpressionJudgment judgment, location, DartType inferredType) {}
 
+  void functionTypedFormalParameter(int location, DartType type) {}
+
   @override
   void ifNull(ExpressionJudgment judgment, location, void leftOperand,
       Token operator, void rightOperand, DartType inferredType) {}
@@ -938,7 +942,7 @@
 
   @override
   void typeVariableDeclaration(
-      covariant void binder, TypeParameter typeParameter) {}
+      location, covariant void binder, TypeParameter typeParameter) {}
 
   @override
   void variableAssign(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index e03c017..afe2bbe 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -342,6 +342,8 @@
   Object binderForTypeVariable(
       KernelTypeVariableBuilder builder, int fileOffset, String name);
 
+  void functionTypedFormalParameter(int offset, DartType type);
+
   /// Performs full type inference on the given field initializer.
   void inferFieldInitializer<Expression, Statement, Initializer, Type>(
       InferenceHelper helper,
@@ -390,7 +392,8 @@
 
   void storeTypeUse(int offset, Node node);
 
-  void typeVariableDeclaration(Object binder, TypeParameter typeParameter);
+  void typeVariableDeclaration(
+      int offset, Object binder, TypeParameter typeParameter);
 
   void voidType(int offset, Token token, DartType type);
 }
@@ -415,6 +418,8 @@
   void binderForTypeVariable(
       KernelTypeVariableBuilder builder, int fileOffset, String name) {}
 
+  void functionTypedFormalParameter(int offset, DartType type) {}
+
   @override
   void inferFieldInitializer<Expression, Statement, Initializer, Type>(
       InferenceHelper helper,
@@ -465,7 +470,8 @@
   void storeTypeUse(int offset, Node node) {}
 
   @override
-  void typeVariableDeclaration(Object binder, TypeParameter typeParameter) {}
+  void typeVariableDeclaration(
+      int offset, Object binder, TypeParameter typeParameter) {}
 
   @override
   void voidType(int offset, Token token, DartType type) {}
@@ -541,6 +547,10 @@
     return listener.binderForTypeVariable(builder, fileOffset, name);
   }
 
+  void functionTypedFormalParameter(int offset, DartType type) {
+    listener.functionTypedFormalParameter(offset, type);
+  }
+
   bool isAssignable(DartType expectedType, DartType actualType) {
     return typeSchemaEnvironment.isSubtypeOf(expectedType, actualType) ||
         typeSchemaEnvironment.isSubtypeOf(actualType, expectedType);
@@ -1758,8 +1768,9 @@
   }
 
   @override
-  void typeVariableDeclaration(Object binder, TypeParameter typeParameter) {
-    return listener.typeVariableDeclaration(binder, typeParameter);
+  void typeVariableDeclaration(
+      int offset, Object binder, TypeParameter typeParameter) {
+    return listener.typeVariableDeclaration(offset, binder, typeParameter);
   }
 
   @override