mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:39:48 +00:00
Resolve call method when defined by an extension
Change-Id: Ic1bc90241207bad2c0c0338dae4b1d2f32c0b021 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111310 Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
bd049f5b53
commit
0639908ecc
|
@ -705,6 +705,13 @@ class MethodInvocationResolver {
|
|||
|
||||
if (type is InterfaceType) {
|
||||
var call = _inheritance.getMember(type, _nameCall);
|
||||
if (call == null) {
|
||||
var extension = _extensionMemberResolver.findExtension(
|
||||
type, _nameCall.name, node.methodName);
|
||||
if (extension != null) {
|
||||
call = extension.getMethod(_nameCall.name);
|
||||
}
|
||||
}
|
||||
if (call != null && call.kind == ElementKind.METHOD) {
|
||||
type = call.type;
|
||||
}
|
||||
|
|
|
@ -420,7 +420,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
|
|||
node.staticInvokeType = staticInvokeType;
|
||||
|
||||
List<ParameterElement> parameters =
|
||||
_computeCorrespondingParameters(node.argumentList, staticInvokeType);
|
||||
_computeCorrespondingParameters(node, staticInvokeType);
|
||||
if (parameters != null) {
|
||||
node.argumentList.correspondingStaticParameters = parameters;
|
||||
}
|
||||
|
@ -999,10 +999,10 @@ class ElementResolver extends SimpleAstVisitor<void> {
|
|||
* arguments, or `null` if no correspondence could be computed.
|
||||
*/
|
||||
List<ParameterElement> _computeCorrespondingParameters(
|
||||
ArgumentList argumentList, DartType type) {
|
||||
FunctionExpressionInvocation invocation, DartType type) {
|
||||
ArgumentList argumentList = invocation.argumentList;
|
||||
if (type is InterfaceType) {
|
||||
MethodElement callMethod =
|
||||
type.lookUpMethod(FunctionElement.CALL_METHOD_NAME, _definingLibrary);
|
||||
MethodElement callMethod = invocation.staticElement;
|
||||
if (callMethod != null) {
|
||||
return _resolveArgumentsToFunction(false, argumentList, callMethod);
|
||||
}
|
||||
|
@ -1083,16 +1083,17 @@ class ElementResolver extends SimpleAstVisitor<void> {
|
|||
/**
|
||||
* Check for a generic method & apply type arguments if any were passed.
|
||||
*/
|
||||
DartType _instantiateGenericMethod(
|
||||
DartType invokeType, TypeArgumentList typeArguments, AstNode node) {
|
||||
DartType _instantiateGenericMethod(DartType invokeType,
|
||||
TypeArgumentList typeArguments, FunctionExpressionInvocation invocation) {
|
||||
DartType parameterizableType;
|
||||
List<TypeParameterElement> parameters;
|
||||
if (invokeType is FunctionType) {
|
||||
parameterizableType = invokeType;
|
||||
parameters = invokeType.typeFormals;
|
||||
} else if (invokeType is InterfaceType) {
|
||||
MethodElement callMethod = invokeType.lookUpMethod(
|
||||
FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
|
||||
MethodElement callMethod =
|
||||
_lookUpCallMethod(invokeType, invocation.function);
|
||||
invocation.staticElement = callMethod;
|
||||
parameterizableType = callMethod?.type;
|
||||
parameters = (parameterizableType as FunctionType)?.typeFormals;
|
||||
}
|
||||
|
@ -1102,7 +1103,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
|
|||
if (arguments != null && arguments.length != parameters.length) {
|
||||
_resolver.errorReporter.reportErrorForNode(
|
||||
StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
|
||||
node,
|
||||
invocation,
|
||||
[parameterizableType, parameters.length, arguments?.length ?? 0]);
|
||||
// Wrong number of type arguments. Ignore them.
|
||||
arguments = null;
|
||||
|
@ -1211,7 +1212,25 @@ class ElementResolver extends SimpleAstVisitor<void> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Look up the getter with the given [name] in the given [type]. Return
|
||||
* Return the element representing the `call` method that is defined for the
|
||||
* given [type]. If there are multiple `call` methods defined by extensions,
|
||||
* use the given [node] to report the error.
|
||||
*/
|
||||
MethodElement _lookUpCallMethod(InterfaceType type, Expression node) {
|
||||
MethodElement callMethod = type.lookUpMethod(
|
||||
FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
|
||||
if (callMethod == null) {
|
||||
var extension = _extensionMemberResolver.findExtension(
|
||||
type, FunctionElement.CALL_METHOD_NAME, node);
|
||||
if (extension != null) {
|
||||
callMethod = extension.getMethod(FunctionElement.CALL_METHOD_NAME);
|
||||
}
|
||||
}
|
||||
return callMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the getter with the given [getterName] in the given [type]. Return
|
||||
* the element representing the getter that was found, or `null` if there is
|
||||
* no getter with the given name. The [target] is the target of the
|
||||
* invocation, or `null` if there is no target.
|
||||
|
|
|
@ -911,6 +911,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
|
|||
if (!_checkForNullableDereference(functionExpression) &&
|
||||
!_checkForUseOfVoidResult(functionExpression) &&
|
||||
!_checkForUseOfNever(functionExpression) &&
|
||||
node.staticElement == null &&
|
||||
!_isFunctionType(expressionType)) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
|
||||
|
|
|
@ -168,7 +168,6 @@ f(C c) {
|
|||
assertInvokeType(invocation, 'int Function(int)');
|
||||
}
|
||||
|
||||
@failingTest
|
||||
test_instance_call_fromExtension() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class C {}
|
||||
|
@ -217,6 +216,22 @@ f(C c) {
|
|||
assertElement(assignment, findElement.method('+', of: 'E'));
|
||||
}
|
||||
|
||||
test_instance_call_fromExtension_int() async {
|
||||
await assertNoErrorsInCode('''
|
||||
extension E on int {
|
||||
int call(int x) => 0;
|
||||
}
|
||||
|
||||
f() {
|
||||
1(2);
|
||||
}
|
||||
''');
|
||||
var invocation = findNode.functionExpressionInvocation('1(2)');
|
||||
expect(invocation.staticInvokeType.element,
|
||||
same(findElement.method('call', of: 'E')));
|
||||
assertInvokeType(invocation, 'int Function(int)');
|
||||
}
|
||||
|
||||
test_instance_getter_methodInvocation() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class C {}
|
||||
|
@ -874,7 +889,6 @@ f() {
|
|||
/// by code internal to (within) the extension declaration.
|
||||
@reflectiveTest
|
||||
class ExtensionMethodsInternalReferenceTest extends BaseExtensionMethodsTest {
|
||||
@failingTest
|
||||
test_instance_call() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class C {}
|
||||
|
|
Loading…
Reference in a new issue