Remove hack that builds FunctionExpressionInvocation with synthetic arguments.

Now that we have an AST and visitor support for the FunctionReference
structure (which represents `Expression<TypeArguments>` for various
kinds of expressions), we no longer need to error recover this as a
FunctionExpressionInvocation with synthetic arguments.  The resolver
still doesn't resolve the syntax properly, but that's ok because it's
not permitted in valid code (for now we just treat it as having type
`dynamic`).

Fixes #46150.

Change-Id: I357175cc16bcf2f9027be2e1da66bb6ca70a9400
Bug: https://github.com/dart-lang/sdk/issues/46020
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/199682
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
index 2b66120..a09335c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
@@ -305,6 +305,13 @@
   }
 
   @override
+  bool visitFunctionReference(FunctionReference node) {
+    // Note: `node.function` could be a reference to a method
+    // (`Target.methodName`) so we need to visit it in case the target exits.
+    return node.function.accept(this)!;
+  }
+
+  @override
   bool visitGenericFunctionType(GenericFunctionType node) => false;
 
   @override
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index a4f9b42..29d755d 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -3532,14 +3532,6 @@
         typeArguments.leftBracket,
         typeArguments.rightBracket,
       );
-      // Since analyzer visitors don't yet support constructor tear-offs, create
-      // a FunctionExpressionInvocation with a synthetic argument list instead.
-      // TODO(paulberry): once we have visitor support for constructor
-      // tear-offs, fall through and return a FunctionReference instead since
-      // that should lead to better quality error recovery.
-      push(ast.functionExpressionInvocation(receiver, typeArguments,
-          _syntheticArgumentList(typeArguments.rightBracket)));
-      return;
     }
     push(ast.functionReference(
         function: receiver, typeArguments: typeArguments));
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 54b29b2..43750b2 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -163,6 +163,12 @@
   @override
   void visitFunctionExpression(FunctionExpression node) {}
 
+  @override
+  void visitFunctionReference(covariant FunctionReferenceImpl node) {
+    // TODO(paulberry): implement
+    node.staticType = _dynamicType;
+  }
+
   /// The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
   /// either the form <i>new T.id(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> or the form <i>new
   /// T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>.</blockquote>
diff --git a/pkg/analyzer/test/generated/function_reference_parser_test.dart b/pkg/analyzer/test/generated/function_reference_parser_test.dart
index fe9091f..13d0d82 100644
--- a/pkg/analyzer/test/generated/function_reference_parser_test.dart
+++ b/pkg/analyzer/test/generated/function_reference_parser_test.dart
@@ -36,23 +36,9 @@
   }
 
   void test_feature_disabled() {
-    var expression =
-        (parseStatement('f<a, b>;', featureSet: preConstructorTearoffs)
-                as ExpressionStatement)
-            .expression;
-    // TODO(paulberry): once we have visitor support for FunctionReference, this
-    // should be parsed as a FunctionReference, so we should be able to validate
-    // it using `expect_f_a_b`.  But for now it's parsed as a
-    // FunctionExpressionInvocation with synthetic arguments.
-    var functionExpressionInvocation =
-        expression as FunctionExpressionInvocation;
-    expect(
-        (functionExpressionInvocation.function as SimpleIdentifier).name, 'f');
-    expect(functionExpressionInvocation.argumentList.arguments, isEmpty);
-    var typeArgs = functionExpressionInvocation.typeArguments!.arguments;
-    expect(typeArgs, hasLength(2));
-    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
-    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+    expect_f_a_b((parseStatement('f<a, b>;', featureSet: preConstructorTearoffs)
+            as ExpressionStatement)
+        .expression);
     listener.assertErrors([
       expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 1, 6),
     ]);
diff --git a/pkg/analyzer/test/generated/simple_parser_test.dart b/pkg/analyzer/test/generated/simple_parser_test.dart
index 0198aa1..3a52b79 100644
--- a/pkg/analyzer/test/generated/simple_parser_test.dart
+++ b/pkg/analyzer/test/generated/simple_parser_test.dart
@@ -1449,8 +1449,8 @@
     expect(body.expression, isMethodInvocation);
     var methodInvocation = body.expression as MethodInvocationImpl;
     var target = methodInvocation.target!;
-    expect(target, isFunctionExpressionInvocation);
-    expect(target.toSource(), 'C<E>()');
+    expect(target, isFunctionReference);
+    expect(target.toSource(), 'C<E>');
     expect(methodInvocation.methodName.name, 'n');
     expect(methodInvocation.argumentList, isNotNull);
     expect(methodInvocation.typeArguments!.arguments, hasLength(1));
diff --git a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
index bb0999a..a24235f 100644
--- a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
@@ -2,8 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/resolver/exit_detector.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -143,6 +145,11 @@
 /// See [ExitDetectorResolvedStatementTest] for tests that require the AST to be resolved.
 @reflectiveTest
 class ExitDetectorParsedStatementTest extends ParseBase {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.13', additionalFeatures: [Feature.constructor_tearoffs]);
+
   test_asExpression() async {
     _assertFalse('a as Object;');
   }
@@ -514,6 +521,18 @@
     _assertTrue("(throw 42)(g);");
   }
 
+  test_functionReference() async {
+    _assertFalse('a<int>;');
+  }
+
+  test_functionReference_method() async {
+    _assertFalse('(a).m<int>;');
+  }
+
+  test_functionReference_method_throw() async {
+    _assertTrue('(throw 42).m<int>;');
+  }
+
   test_identifier_prefixedIdentifier() async {
     _assertFalse('a.b;');
   }
diff --git a/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart b/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
index e1037ea..c0ecd09 100644
--- a/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/context_collection_resolution.dart';
@@ -26,10 +25,6 @@
   Foo<int>.bar.baz();
 }
 ''', [
-      // TODO(paulberry): the INVOCATION_OF_NON_FUNCTION_EXPRESSION error is
-      // bogus, and should go away once we implement visitor and resolution
-      // support for constructor tearoffs.
-      error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 67, 3),
       error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 70, 5),
     ]);
   }
@@ -45,10 +40,6 @@
   Foo<int>.bar.baz();
 }
 ''', [
-      // TODO(paulberry): the INVOCATION_OF_NON_FUNCTION_EXPRESSION error is
-      // bogus, and should go away once we implement visitor and resolution
-      // support for constructor tearoffs.
-      error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 80, 3),
       error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 83, 5),
     ]);
   }
diff --git a/tests/language/constructor/reference_test.dart b/tests/language/constructor/reference_test.dart
index f57a26f..d781ab1 100644
--- a/tests/language/constructor/reference_test.dart
+++ b/tests/language/constructor/reference_test.dart
@@ -92,8 +92,6 @@
   Foo<int>();
   Foo<int>.bar();
   Foo<int>.bar.baz();
-//^^^
-// [analyzer] COMPILE_TIME_ERROR.INVOCATION_OF_NON_FUNCTION_EXPRESSION
   // ^^^^^
   // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
   // [cfe] This requires the 'constructor-tearoffs' language feature to be enabled.
diff --git a/tests/language_2/constructor/reference_test.dart b/tests/language_2/constructor/reference_test.dart
index 73abdb9..ee1aa67 100644
--- a/tests/language_2/constructor/reference_test.dart
+++ b/tests/language_2/constructor/reference_test.dart
@@ -94,8 +94,6 @@
   Foo<int>();
   Foo<int>.bar();
   Foo<int>.bar.baz();
-//^^^
-// [analyzer] COMPILE_TIME_ERROR.INVOCATION_OF_NON_FUNCTION_EXPRESSION
   // ^^^^^
   // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
   // [cfe] This requires the 'constructor-tearoffs' language feature to be enabled.