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