Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(938)

Unified Diff: pkg/analyzer/lib/src/generated/element_resolver.dart

Issue 1568643002: clean up generic methods in resolution (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/generated/ast.dart ('k') | pkg/analyzer/lib/src/generated/error_verifier.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/element_resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 9f0cda01242452fad472655826b09be07e19b09d..f3fb282e41d7d0cbaac736acd459af7a871001f5 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -9,14 +9,12 @@ import 'dart:collection';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/scanner.dart' as sc;
-import 'package:analyzer/src/generated/utilities_dart.dart';
/**
* An object used by instances of [ResolverVisitor] to resolve references within
@@ -639,64 +637,41 @@ class ElementResolver extends SimpleAstVisitor<Object> {
}
}
}
- //
- // Check for a generic method & apply type arguments if any were passed.
- //
- if (staticElement is MethodElement || staticElement is FunctionElement) {
- FunctionType type = (staticElement as ExecutableElement).type;
- List<TypeParameterElement> parameters = type.boundTypeParameters;
-
- NodeList<TypeName> arguments = node.typeArguments?.arguments;
- if (arguments != null && arguments.length != parameters.length) {
- // Wrong number of type arguments. Ignore them
- arguments = null;
- _resolver.reportErrorForNode(
- StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
- methodName,
- [type, parameters.length, arguments.length]);
- }
- if (parameters.isNotEmpty) {
- List<DartType> typeArgs;
- if (arguments == null) {
- typeArgs = new List<DartType>.filled(
- parameters.length, DynamicTypeImpl.instance);
- } else {
- typeArgs = new List<DartType>.from(arguments.map((n) => n.type));
- }
- type = type.instantiate(typeArgs);
-
- if (staticElement is MethodMember) {
- MethodMember member = staticElement;
- staticElement =
- new MethodMember(member.baseElement, member.definingType, type);
- } else if (staticElement is MethodElement) {
- ClassElement clazz = staticElement.enclosingElement;
- staticElement = new MethodMember(staticElement, clazz.type, type);
- } else {
- staticElement =
- new FunctionMember(staticElement as FunctionElement, type);
- }
- }
- }
staticElement = _convertSetterToGetter(staticElement);
propagatedElement = _convertSetterToGetter(propagatedElement);
+
+ DartType staticInvokeType = _computeMethodInvokeType(node, staticElement);
+ DartType propagatedInvokeType =
+ _computeMethodInvokeType(node, propagatedElement);
+
//
// Record the results.
//
methodName.staticElement = staticElement;
methodName.propagatedElement = propagatedElement;
+
+ node.staticInvokeType = staticInvokeType;
+ if (propagatedInvokeType != null &&
+ propagatedInvokeType.isMoreSpecificThan(staticInvokeType)) {
+ // Don't store the propagated invoke type unless it's more specific than
+ // the static type. We still need to record the propagated parameter
+ // elements however, as that is used for the propagatedType downwards
+ // inference of lambda parameters.
+ node.propagatedInvokeType = propagatedInvokeType;
+ }
+
ArgumentList argumentList = node.argumentList;
- if (staticElement != null) {
+ if (staticInvokeType != null) {
List<ParameterElement> parameters =
- _computeCorrespondingParameters(argumentList, staticElement);
+ _computeCorrespondingParameters(argumentList, staticInvokeType);
if (parameters != null) {
argumentList.correspondingStaticParameters = parameters;
}
}
- if (propagatedElement != null) {
+ if (propagatedInvokeType != null) {
List<ParameterElement> parameters =
- _computeCorrespondingParameters(argumentList, propagatedElement);
+ _computeCorrespondingParameters(argumentList, propagatedInvokeType);
if (parameters != null) {
argumentList.correspondingPropagatedParameters = parameters;
}
@@ -1336,44 +1311,16 @@ class ElementResolver extends SimpleAstVisitor<Object> {
* arguments, or `null` if no correspondence could be computed.
*/
List<ParameterElement> _computeCorrespondingParameters(
- ArgumentList argumentList, Element element) {
- if (element is PropertyAccessorElement) {
- //
- // This is an invocation of the call method defined on the value returned
- // by the getter.
- //
- FunctionType getterType = element.type;
- if (getterType != null) {
- DartType getterReturnType = getterType.returnType;
- if (getterReturnType is InterfaceType) {
- MethodElement callMethod = getterReturnType.lookUpMethod(
- FunctionElement.CALL_METHOD_NAME, _definingLibrary);
- if (callMethod != null) {
- return _resolveArgumentsToFunction(false, argumentList, callMethod);
- }
- } else if (getterReturnType is FunctionType) {
- List<ParameterElement> parameters = getterReturnType.parameters;
- return _resolveArgumentsToParameters(false, argumentList, parameters);
- }
- }
- } else if (element is ExecutableElement) {
- return _resolveArgumentsToFunction(false, argumentList, element);
- } else if (element is VariableElement) {
- VariableElement variable = element;
- DartType type = _promoteManager.getStaticType(variable);
- if (type is FunctionType) {
- FunctionType functionType = type;
- List<ParameterElement> parameters = functionType.parameters;
- return _resolveArgumentsToParameters(false, argumentList, parameters);
- } else if (type is InterfaceType) {
- // "call" invocation
- MethodElement callMethod = type.lookUpMethod(
- FunctionElement.CALL_METHOD_NAME, _definingLibrary);
- if (callMethod != null) {
- List<ParameterElement> parameters = callMethod.parameters;
- return _resolveArgumentsToParameters(false, argumentList, parameters);
- }
+ ArgumentList argumentList, DartType type) {
+ if (type is InterfaceType) {
+ MethodElement callMethod =
+ type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _definingLibrary);
+ if (callMethod != null) {
+ return _resolveArgumentsToFunction(false, argumentList, callMethod);
}
+ } else if (type is FunctionType) {
+ return _resolveArgumentsToParameters(
+ false, argumentList, type.parameters);
}
return null;
}
@@ -1514,6 +1461,49 @@ class ElementResolver extends SimpleAstVisitor<Object> {
return staticType;
}
+ DartType _computeMethodInvokeType(MethodInvocation node, Element element) {
+ if (element == null) {
+ return null;
+ }
+
+ DartType invokeType;
+ if (element is PropertyAccessorElement) {
+ invokeType = element.returnType;
+ } else if (element is ExecutableElement) {
+ invokeType = element.type;
+ } else if (element is VariableElement) {
+ invokeType = _promoteManager.getStaticType(element);
+ }
+
+ //
+ // Check for a generic method & apply type arguments if any were passed.
+ //
+ // TODO(jmesserly): support generic "call" methods on InterfaceType.
+ if (invokeType is FunctionType) {
+ FunctionType type = invokeType;
+ List<TypeParameterElement> parameters = type.typeFormals;
+
+ NodeList<TypeName> arguments = node.typeArguments?.arguments;
+ if (arguments != null && arguments.length != parameters.length) {
+ // Wrong number of type arguments. Ignore them
+ arguments = null;
+ _resolver.reportErrorForNode(
+ StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+ node.methodName,
+ [type, parameters.length, arguments?.length ?? 0]);
+ }
+ if (parameters.isNotEmpty) {
+ if (arguments == null) {
+ invokeType = _resolver.typeSystem.instantiateToBounds(type);
+ } else {
+ invokeType = type.instantiate(arguments.map((n) => n.type).toList());
+ }
+ }
+ }
+
+ return invokeType;
+ }
+
/**
* Return `true` if the given [expression] is a prefix for a deferred import.
*/
@@ -1948,102 +1938,35 @@ class ElementResolver extends SimpleAstVisitor<Object> {
* Given an [argumentList] and the [executableElement] that will be invoked
* using those argument, compute the list of parameters that correspond to the
* list of arguments. An error will be reported if any of the arguments cannot
- * be matched to a parameter. The flag [reportError] should be `true` if a
+ * be matched to a parameter. The flag [reportAsError] should be `true` if a
* compile-time error should be reported; or `false` if a compile-time warning
* should be reported. Return the parameters that correspond to the arguments,
* or `null` if no correspondence could be computed.
*/
- List<ParameterElement> _resolveArgumentsToFunction(bool reportError,
+ List<ParameterElement> _resolveArgumentsToFunction(bool reportAsError,
ArgumentList argumentList, ExecutableElement executableElement) {
if (executableElement == null) {
return null;
}
List<ParameterElement> parameters = executableElement.parameters;
- return _resolveArgumentsToParameters(reportError, argumentList, parameters);
+ return _resolveArgumentsToParameters(
+ reportAsError, argumentList, parameters);
}
/**
* Given an [argumentList] and the [parameters] related to the element that
* will be invoked using those arguments, compute the list of parameters that
* correspond to the list of arguments. An error will be reported if any of
- * the arguments cannot be matched to a parameter. The flag [reportError]
+ * the arguments cannot be matched to a parameter. The flag [reportAsError]
* should be `true` if a compile-time error should be reported; or `false` if
* a compile-time warning should be reported. Return the parameters that
* correspond to the arguments.
*/
- List<ParameterElement> _resolveArgumentsToParameters(bool reportError,
+ List<ParameterElement> _resolveArgumentsToParameters(bool reportAsError,
ArgumentList argumentList, List<ParameterElement> parameters) {
- List<ParameterElement> requiredParameters = new List<ParameterElement>();
- List<ParameterElement> positionalParameters = new List<ParameterElement>();
- HashMap<String, ParameterElement> namedParameters =
- new HashMap<String, ParameterElement>();
- for (ParameterElement parameter in parameters) {
- ParameterKind kind = parameter.parameterKind;
- if (kind == ParameterKind.REQUIRED) {
- requiredParameters.add(parameter);
- } else if (kind == ParameterKind.POSITIONAL) {
- positionalParameters.add(parameter);
- } else {
- namedParameters[parameter.name] = parameter;
- }
- }
- List<ParameterElement> unnamedParameters =
- new List<ParameterElement>.from(requiredParameters);
- unnamedParameters.addAll(positionalParameters);
- int unnamedParameterCount = unnamedParameters.length;
- int unnamedIndex = 0;
- NodeList<Expression> arguments = argumentList.arguments;
- int argumentCount = arguments.length;
- List<ParameterElement> resolvedParameters =
- new List<ParameterElement>(argumentCount);
- int positionalArgumentCount = 0;
- HashSet<String> usedNames = new HashSet<String>();
- bool noBlankArguments = true;
- for (int i = 0; i < argumentCount; i++) {
- Expression argument = arguments[i];
- if (argument is NamedExpression) {
- SimpleIdentifier nameNode = argument.name.label;
- String name = nameNode.name;
- ParameterElement element = namedParameters[name];
- if (element == null) {
- ErrorCode errorCode = (reportError
- ? CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER
- : StaticWarningCode.UNDEFINED_NAMED_PARAMETER);
- _resolver.reportErrorForNode(errorCode, nameNode, [name]);
- } else {
- resolvedParameters[i] = element;
- nameNode.staticElement = element;
- }
- if (!usedNames.add(name)) {
- _resolver.reportErrorForNode(
- CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode, [name]);
- }
- } else {
- if (argument is SimpleIdentifier && argument.name.isEmpty) {
- noBlankArguments = false;
- }
- positionalArgumentCount++;
- if (unnamedIndex < unnamedParameterCount) {
- resolvedParameters[i] = unnamedParameters[unnamedIndex++];
- }
- }
- }
- if (positionalArgumentCount < requiredParameters.length &&
- noBlankArguments) {
- ErrorCode errorCode = (reportError
- ? CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS
- : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS);
- _resolver.reportErrorForNode(errorCode, argumentList,
- [requiredParameters.length, positionalArgumentCount]);
- } else if (positionalArgumentCount > unnamedParameterCount &&
- noBlankArguments) {
- ErrorCode errorCode = (reportError
- ? CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS
- : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS);
- _resolver.reportErrorForNode(errorCode, argumentList,
- [unnamedParameterCount, positionalArgumentCount]);
- }
- return resolvedParameters;
+ return ResolverVisitor.resolveArgumentsToParameters(
+ argumentList, parameters, _resolver.reportErrorForNode,
+ reportAsError: reportAsError);
}
void _resolveBinaryExpression(BinaryExpression node, String methodName) {
« no previous file with comments | « pkg/analyzer/lib/src/generated/ast.dart ('k') | pkg/analyzer/lib/src/generated/error_verifier.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698