Version 2.14.0-372.0.dev

Merge commit 'a4afb06b215eb9b40cb9cb17a6c69d03e413d8a0' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
new file mode 100644
index 0000000..cf4574c
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -0,0 +1,152 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// A resolver for [InstanceCreationExpression] nodes.
+///
+/// This resolver is responsible for rewriting a given
+/// [InstanceCreationExpression] as a [MethodInvocation] if the parsed
+/// [ConstructorName]'s `type` resolves to a [FunctionReference] or
+/// [ConstructorReference], instead of a [TypeName].
+class InstanceCreationExpressionResolver {
+  /// The resolver driving this participant.
+  final ResolverVisitor _resolver;
+
+  InstanceCreationExpressionResolver(this._resolver);
+
+  void resolve(InstanceCreationExpressionImpl node) {
+    // The parser can parse certain code as [InstanceCreationExpression] when it
+    // might be an invocation of a method on a [FunctionReference] or
+    // [ConstructorReference]. In such a case, it is this resolver's
+    // responsibility to rewrite. For example, given:
+    //
+    //     a.m<int>.apply();
+    //
+    // the parser will give an InstanceCreationExpression (`a.m<int>.apply()`)
+    // with a name of `a.m<int>.apply` (ConstructorName) with a type of
+    // `a.m<int>` (TypeName with a name of `a.m` (PrefixedIdentifier) and
+    // typeArguments of `<int>`) and a name of `apply` (SimpleIdentifier). If
+    // `a.m<int>` is actually a function reference, then the
+    // InstanceCreationExpression needs to be rewritten as a MethodInvocation
+    // with a target of `a.m<int>` (a FunctionReference) and a name of `apply`.
+    if (node.keyword == null) {
+      var typeNameTypeArguments = node.constructorName.type.typeArguments;
+      if (typeNameTypeArguments != null) {
+        // This could be a method call on a function reference or a constructor
+        // reference.
+        _resolveWithTypeNameWithTypeArguments(node, typeNameTypeArguments);
+        return;
+      }
+    }
+
+    _resolveInstanceCreationExpression(node);
+  }
+
+  void _inferArgumentTypes(covariant InstanceCreationExpressionImpl node) {
+    var constructorName = node.constructorName;
+    var typeName = constructorName.type;
+    var typeArguments = typeName.typeArguments;
+    var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
+      constructorName: constructorName,
+      definingLibrary: _resolver.definingLibrary,
+    );
+    FunctionType? inferred;
+
+    // If the constructor is generic, we'll have a ConstructorMember that
+    // substitutes in type arguments (possibly `dynamic`) from earlier in
+    // resolution.
+    //
+    // Otherwise we'll have a ConstructorElement, and we can skip inference
+    // because there's nothing to infer in a non-generic type.
+    if (elementToInfer != null) {
+      // TODO(leafp): Currently, we may re-infer types here, since we
+      // sometimes resolve multiple times.  We should really check that we
+      // have not already inferred something.  However, the obvious ways to
+      // check this don't work, since we may have been instantiated
+      // to bounds in an earlier phase, and we *do* want to do inference
+      // in that case.
+
+      // Get back to the uninstantiated generic constructor.
+      // TODO(jmesserly): should we store this earlier in resolution?
+      // Or look it up, instead of jumping backwards through the Member?
+      var rawElement = elementToInfer.element;
+      var constructorType = elementToInfer.asType;
+
+      inferred = _resolver.inferenceHelper.inferArgumentTypesForGeneric(
+          node, constructorType, typeArguments,
+          isConst: node.isConst, errorNode: node.constructorName);
+
+      if (inferred != null) {
+        var arguments = node.argumentList;
+        InferenceContext.setType(arguments, inferred);
+        // Fix up the parameter elements based on inferred method.
+        arguments.correspondingStaticParameters =
+            ResolverVisitor.resolveArgumentsToParameters(
+                arguments, inferred.parameters, null);
+
+        constructorName.type.type = inferred.returnType;
+
+        // Update the static element as well. This is used in some cases, such
+        // as computing constant values. It is stored in two places.
+        var constructorElement = ConstructorMember.from(
+          rawElement,
+          inferred.returnType as InterfaceType,
+        );
+        constructorName.staticElement = constructorElement;
+      }
+    }
+
+    if (inferred == null) {
+      var constructorElement = constructorName.staticElement;
+      if (constructorElement != null) {
+        var type = constructorElement.type;
+        type = _resolver.toLegacyTypeIfOptOut(type) as FunctionType;
+        InferenceContext.setType(node.argumentList, type);
+      }
+    }
+  }
+
+  void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node) {
+    var whyNotPromotedList = <WhyNotPromotedGetter>[];
+    node.constructorName.accept(_resolver);
+    _inferArgumentTypes(node);
+    _resolver.visitArgumentList(node.argumentList,
+        whyNotPromotedList: whyNotPromotedList);
+    node.accept(_resolver.elementResolver);
+    node.accept(_resolver.typeAnalyzer);
+    _resolver.checkForArgumentTypesNotAssignableInList(
+        node.argumentList, whyNotPromotedList);
+  }
+
+  /// Resolve [node] which has a [TypeName] with type arguments (given as
+  /// [typeNameTypeArguments]).
+  ///
+  /// The instance creation expression may actually be a method call on a
+  /// type-instantiated function reference or constructor reference.
+  void _resolveWithTypeNameWithTypeArguments(
+    InstanceCreationExpressionImpl node,
+    TypeArgumentListImpl typeNameTypeArguments,
+  ) {
+    var typeNameName = node.constructorName.type.name;
+    if (typeNameName is SimpleIdentifierImpl) {
+      // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+      // [MethodInvocation].
+      _resolveInstanceCreationExpression(node);
+      return;
+    } else if (typeNameName is PrefixedIdentifierImpl) {
+      // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+      // [MethodInvocation].
+      _resolveInstanceCreationExpression(node);
+    } else {
+      assert(
+          false, 'Unexpected typeNameName type: ${typeNameName.runtimeType}');
+      _resolveInstanceCreationExpression(node);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 112f2e7..c175e24 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -21,8 +21,7 @@
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart'
-    show ConstructorMember, Member;
+import 'package:analyzer/src/dart/element/member.dart' show Member;
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/scope.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -38,6 +37,7 @@
 import 'package:analyzer/src/dart/resolver/function_expression_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/function_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
+import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
@@ -253,6 +253,9 @@
 
   late final FunctionReferenceResolver _functionReferenceResolver;
 
+  late final InstanceCreationExpressionResolver
+      _instanceCreationExpressionResolver;
+
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
   /// The [definingLibrary] is the element for the library containing the node
@@ -373,6 +376,8 @@
     typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
     _functionReferenceResolver =
         FunctionReferenceResolver(this, _isNonNullableByDefault);
+    _instanceCreationExpressionResolver =
+        InstanceCreationExpressionResolver(this);
   }
 
   /// Return the element representing the function containing the current node,
@@ -1677,15 +1682,7 @@
   @override
   void visitInstanceCreationExpression(
       covariant InstanceCreationExpressionImpl node) {
-    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
-    node.constructorName.accept(this);
-    _inferArgumentTypesForInstanceCreate(node);
-    visitArgumentList(node.argumentList,
-        whyNotPromotedList: whyNotPromotedList);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-    checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedList);
+    _instanceCreationExpressionResolver.resolve(node);
   }
 
   @override
@@ -2176,72 +2173,6 @@
     return typeProvider.futureOrType(type);
   }
 
-  void _inferArgumentTypesForInstanceCreate(
-      covariant InstanceCreationExpressionImpl node) {
-    var constructorName = node.constructorName;
-
-    var typeName = constructorName.type;
-    var typeArguments = typeName.typeArguments;
-
-    var elementToInfer = inferenceHelper.constructorElementToInfer(
-      constructorName: constructorName,
-      definingLibrary: definingLibrary,
-    );
-
-    FunctionType? inferred;
-    // If the constructor is generic, we'll have a ConstructorMember that
-    // substitutes in type arguments (possibly `dynamic`) from earlier in
-    // resolution.
-    //
-    // Otherwise we'll have a ConstructorElement, and we can skip inference
-    // because there's nothing to infer in a non-generic type.
-    if (elementToInfer != null) {
-      // TODO(leafp): Currently, we may re-infer types here, since we
-      // sometimes resolve multiple times.  We should really check that we
-      // have not already inferred something.  However, the obvious ways to
-      // check this don't work, since we may have been instantiated
-      // to bounds in an earlier phase, and we *do* want to do inference
-      // in that case.
-
-      // Get back to the uninstantiated generic constructor.
-      // TODO(jmesserly): should we store this earlier in resolution?
-      // Or look it up, instead of jumping backwards through the Member?
-      var rawElement = elementToInfer.element;
-      var constructorType = elementToInfer.asType;
-
-      inferred = inferenceHelper.inferArgumentTypesForGeneric(
-          node, constructorType, typeArguments,
-          isConst: node.isConst, errorNode: node.constructorName);
-
-      if (inferred != null) {
-        var arguments = node.argumentList;
-        InferenceContext.setType(arguments, inferred);
-        // Fix up the parameter elements based on inferred method.
-        arguments.correspondingStaticParameters =
-            resolveArgumentsToParameters(arguments, inferred.parameters, null);
-
-        constructorName.type.type = inferred.returnType;
-
-        // Update the static element as well. This is used in some cases, such
-        // as computing constant values. It is stored in two places.
-        var constructorElement = ConstructorMember.from(
-          rawElement,
-          inferred.returnType as InterfaceType,
-        );
-        constructorName.staticElement = constructorElement;
-      }
-    }
-
-    if (inferred == null) {
-      var constructorElement = constructorName.staticElement;
-      if (constructorElement != null) {
-        var type = constructorElement.type;
-        type = toLegacyTypeIfOptOut(type) as FunctionType;
-        InferenceContext.setType(node.argumentList, type);
-      }
-    }
-  }
-
   /// Continues resolution of a [FunctionExpressionInvocation] that was created
   /// from a rewritten [MethodInvocation]. The target function is already
   /// resolved.
diff --git a/tools/VERSION b/tools/VERSION
index 2713250..38834f5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 371
+PRERELEASE 372
 PRERELEASE_PATCH 0
\ No newline at end of file