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..400db3640f37ef72eda3825f9bb161b936f73aa6 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,34 @@ 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 = |
Brian Wilkerson
2016/01/06 21:57:34
If the propagatedInvokeType is not `null` and is n
Jennifer Messerly
2016/01/06 22:25:51
Yeah that's a good point. I think we get this for
Brian Wilkerson
2016/01/06 22:47:01
Unfortunately, no. It's perfectly valid for both t
Jennifer Messerly
2016/01/06 22:52:48
Ah that makes sense. Does something like this look
Brian Wilkerson
2016/01/07 00:24:22
See ResolverVisitor.recordPropagatedTypeIfBetter.
Jennifer Messerly
2016/01/07 00:33:29
Ah, nice! Looking through there, I think the logic
|
+ _computeMethodInvokeType(node, propagatedElement); |
+ |
// |
// Record the results. |
// |
methodName.staticElement = staticElement; |
methodName.propagatedElement = propagatedElement; |
+ |
+ node.staticInvokeType = staticInvokeType; |
+ 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 +1304,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 +1454,50 @@ 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): should we support for generic "call" methods on |
Brian Wilkerson
2016/01/06 21:57:34
"should we support for"?
Jennifer Messerly
2016/01/06 22:25:51
DOH. Good catch! It got stuck halfway between an e
|
+ // 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]); |
+ } |
+ 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. |
*/ |
@@ -1973,77 +1957,9 @@ class ElementResolver extends SimpleAstVisitor<Object> { |
*/ |
List<ParameterElement> _resolveArgumentsToParameters(bool reportError, |
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, |
+ reportError: reportError); |
} |
void _resolveBinaryExpression(BinaryExpression node, String methodName) { |