Use formal parameters location to access function expression types.

There is still an issue with using type parameters inside function
expression bodies. https://github.com/dart-lang/sdk/issues/33722

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

Change-Id: I9c1a4f8b6d6545a22de1b67953a7d833bf96df03
Reviewed-on: https://dart-review.googlesource.com/63365
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/resolution_applier.dart b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
index 39bf30a..2ba57bf 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_applier.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
@@ -313,7 +313,7 @@
     parameterList.accept(this);
 
     node.body.accept(this);
-    _storeFunctionType(_get(node).inferredType, element);
+    _storeFunctionType(_get(node.parameters).inferredType, element);
 
     // Associate the elements with the nodes.
     if (element != null) {
diff --git a/pkg/analyzer/test/generated/hint_code_kernel_test.dart b/pkg/analyzer/test/generated/hint_code_kernel_test.dart
index 14b0e84..6d58259 100644
--- a/pkg/analyzer/test/generated/hint_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_kernel_test.dart
@@ -274,20 +274,6 @@
     return super.test_strongMode_downCastCompositeWarn();
   }
 
-  @override
-  @failingTest
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke() {
-    return super
-        .test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke();
-  }
-
-  @override
-  @failingTest
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke_explicit_type_params() {
-    return super
-        .test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke_explicit_type_params();
-  }
-
   @failingTest
   @override
   test_undefinedOperator_binaryExpression() async {
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index e49e2fb..ed684ec 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -285,7 +285,7 @@
 }
 
 class List<E> implements Iterable<E> {
-  List();
+  List([int length]);
   factory List.from(Iterable elements, {bool growable: true}) => null;
   void add(E value) {}
   void addAll(Iterable<E> iterable) {}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
index 4121a0b..e1153f2 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
@@ -29,6 +29,24 @@
   @override
   @failingTest
   @potentialAnalyzerProblem
+  test_closure_generic() async {
+    // Bad state: Not found T in main() → dynamic
+    // https://github.com/dart-lang/sdk/issues/33722
+    await super.test_closure_generic();
+  }
+
+  @override
+  @failingTest
+  @potentialAnalyzerProblem
+  test_local_function_generic() async {
+    // Bad state: Not found T in main() → void
+    // https://github.com/dart-lang/sdk/issues/33722
+    await super.test_local_function_generic();
+  }
+
+  @override
+  @failingTest
+  @potentialAnalyzerProblem
   test_unresolved_assignment_left_identifier_compound() async {
     await super.test_unresolved_assignment_left_identifier_compound();
   }
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 76bb3ff..6007a37 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -1750,6 +1750,38 @@
     }
   }
 
+  test_closure_generic() async {
+    addTestFile(r'''
+main() {
+  foo(<T>() => new List<T>(4));
+}
+
+void foo(List<T> Function<T>() createList) {}
+''');
+    await resolveTestFile();
+
+    var closure = findNode.functionExpression('<T>() =>');
+    assertType(closure, '<T>() → List<T>');
+
+    FunctionElementImpl closureElement = closure.element;
+    expect(closureElement.enclosingElement, findElement.function('main'));
+    expect(closureElement.returnType.toString(), 'List<T>');
+    expect(closureElement.parameters, isEmpty);
+
+    var typeParameters = closureElement.typeParameters;
+    expect(typeParameters, hasLength(1));
+
+    TypeParameterElement tElement = typeParameters[0];
+    expect(tElement.name, 'T');
+    expect(tElement.nameOffset, 16);
+
+    var creation = findNode.instanceCreation('new List');
+    assertType(creation, 'List<T>');
+
+    var tRef = findNode.simple('T>(4)');
+    assertElement(tRef, tElement);
+  }
+
   test_closure_inField() async {
     addTestFile(r'''
 class C {
@@ -3074,7 +3106,10 @@
   test_local_function_generic() async {
     addTestFile(r'''
 void main() {
-  T f<T, U>(T a, U b) {}
+  T f<T, U>(T a, U b) {
+    a;
+    b;
+  }
   var v = f(1, '2');
 }
 ''');
@@ -3118,23 +3153,31 @@
     expect(fExpression.element, same(fElement));
 
     {
-      List<ParameterElement> elements = fElement.parameters;
-      expect(elements, hasLength(2));
+      List<ParameterElement> parameters = fElement.parameters;
+      expect(parameters, hasLength(2));
 
       List<FormalParameter> nodes = fExpression.parameters.parameters;
       expect(nodes, hasLength(2));
 
-      _assertSimpleParameter(nodes[0], elements[0],
+      _assertSimpleParameter(nodes[0], parameters[0],
           name: 'a',
           offset: 28,
           kind: ParameterKind.REQUIRED,
           type: tElement.type);
 
-      _assertSimpleParameter(nodes[1], elements[1],
+      _assertSimpleParameter(nodes[1], parameters[1],
           name: 'b',
           offset: 33,
           kind: ParameterKind.REQUIRED,
           type: uElement.type);
+
+      var aRef = findNode.simple('a;');
+      assertElement(aRef, parameters[0]);
+      assertType(aRef, 'T');
+
+      var bRef = findNode.simple('b;');
+      assertElement(bRef, parameters[1]);
+      assertType(bRef, 'U');
     }
 
     VariableDeclarationStatement vStatement = mainStatements[1];
@@ -7315,6 +7358,15 @@
     fail('Not found class field: $name');
   }
 
+  FunctionElement function(String name) {
+    for (var function in unitElement.functions) {
+      if (function.name == name) {
+        return function;
+      }
+    }
+    fail('Not found top-level function: $name');
+  }
+
   PropertyAccessorElement getter(String name) {
     for (var class_ in unitElement.types) {
       for (var accessor in class_.accessors) {
@@ -7385,6 +7437,18 @@
     return _node(search).getAncestor((n) => n is CascadeExpression);
   }
 
+  FunctionExpression functionExpression(String search) {
+    return _node(search).getAncestor((n) => n is FunctionExpression);
+  }
+
+  InstanceCreationExpression instanceCreation(String search) {
+    return _node(search).getAncestor((n) => n is InstanceCreationExpression);
+  }
+
+  MethodInvocation methodInvocation(String search) {
+    return _node(search).getAncestor((n) => n is MethodInvocation);
+  }
+
   SimpleIdentifier simple(String search) {
     return _node(search);
   }
@@ -7396,6 +7460,6 @@
       fail('The pattern |$search| is not unique in:\n$content');
     }
     expect(index, greaterThanOrEqualTo(0));
-    return new NodeLocator(index).searchWithin(result.unit);
+    return new NodeLocator2(index).searchWithin(result.unit);
   }
 }