mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:21:21 +00:00
Issue 49842. Resolve call() invocation without a receiver.
Bug: https://github.com/dart-lang/sdk/issues/49842 Change-Id: I44a274da4ca209b34710d6bfc3ae3d18ee62058c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/256704 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
36affd7014
commit
8e4dc26b2a
|
@ -175,13 +175,6 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
receiverType = _typeSystem.promoteToNonNull(receiverType);
|
||||
}
|
||||
|
||||
if (_typeSystem.isFunctionBounded(receiverType)) {
|
||||
_resolveReceiverFunctionBounded(
|
||||
node, receiver, receiverType, nameNode, name, whyNotPromotedList,
|
||||
contextType: contextType);
|
||||
return;
|
||||
}
|
||||
|
||||
if (receiver is TypeLiteralImpl &&
|
||||
receiver.type.typeArguments != null &&
|
||||
receiver.type.type is FunctionType) {
|
||||
|
@ -487,36 +480,6 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
.resolveInvocation(rawType: rawType);
|
||||
}
|
||||
|
||||
void _resolveReceiverFunctionBounded(
|
||||
MethodInvocationImpl node,
|
||||
Expression receiver,
|
||||
DartType receiverType,
|
||||
SimpleIdentifierImpl nameNode,
|
||||
String name,
|
||||
List<WhyNotPromotedGetter> whyNotPromotedList,
|
||||
{required DartType? contextType}) {
|
||||
if (name == FunctionElement.CALL_METHOD_NAME) {
|
||||
_setResolution(node, receiverType, whyNotPromotedList,
|
||||
contextType: contextType);
|
||||
// TODO(scheglov) Replace this with using FunctionType directly.
|
||||
// Here was erase resolution that _setResolution() sets.
|
||||
nameNode.staticElement = null;
|
||||
nameNode.staticType = _dynamicType;
|
||||
return;
|
||||
}
|
||||
|
||||
_resolveReceiverType(
|
||||
node: node,
|
||||
receiver: receiver,
|
||||
receiverType: receiverType,
|
||||
nameNode: nameNode,
|
||||
name: name,
|
||||
receiverErrorNode: nameNode,
|
||||
whyNotPromotedList: whyNotPromotedList,
|
||||
contextType: contextType,
|
||||
);
|
||||
}
|
||||
|
||||
void _resolveReceiverNever(MethodInvocationImpl node, Expression receiver,
|
||||
DartType receiverType, List<WhyNotPromotedGetter> whyNotPromotedList,
|
||||
{required DartType? contextType}) {
|
||||
|
@ -790,6 +753,18 @@ class MethodInvocationResolver with ScopeHelpers {
|
|||
nameErrorEntity: nameNode,
|
||||
);
|
||||
|
||||
final callFunctionType = result.callFunctionType;
|
||||
if (callFunctionType != null) {
|
||||
assert(name == FunctionElement.CALL_METHOD_NAME);
|
||||
_setResolution(node, callFunctionType, whyNotPromotedList,
|
||||
contextType: contextType);
|
||||
// TODO(scheglov) Replace this with using FunctionType directly.
|
||||
// Here was erase resolution that _setResolution() sets.
|
||||
nameNode.staticElement = null;
|
||||
nameNode.staticType = _dynamicType;
|
||||
return;
|
||||
}
|
||||
|
||||
var target = result.getter;
|
||||
if (target != null) {
|
||||
nameNode.staticElement = target;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
|
||||
/// The result of attempting to resolve an identifier to elements.
|
||||
class ResolutionResult {
|
||||
|
@ -43,6 +44,9 @@ class ResolutionResult {
|
|||
/// when `dynamicTarget.foo`).
|
||||
final bool needsSetterError;
|
||||
|
||||
/// The [FunctionType] referenced with `call`.
|
||||
final FunctionType? callFunctionType;
|
||||
|
||||
/// Initialize a newly created result to represent resolving a single
|
||||
/// reading and / or writing result.
|
||||
ResolutionResult({
|
||||
|
@ -50,6 +54,7 @@ class ResolutionResult {
|
|||
this.needsGetterError = true,
|
||||
this.setter,
|
||||
this.needsSetterError = true,
|
||||
this.callFunctionType,
|
||||
}) : state = _ResolutionResultState.single;
|
||||
|
||||
/// Initialize a newly created result with no elements and the given [state].
|
||||
|
@ -57,7 +62,8 @@ class ResolutionResult {
|
|||
: getter = null,
|
||||
needsGetterError = true,
|
||||
setter = null,
|
||||
needsSetterError = true;
|
||||
needsSetterError = true,
|
||||
callFunctionType = null;
|
||||
|
||||
/// Return `true` if this result represents the case where multiple ambiguous
|
||||
/// elements were found.
|
||||
|
|
|
@ -186,7 +186,13 @@ class TypePropertyResolver {
|
|||
|
||||
if (receiverTypeResolved is FunctionType &&
|
||||
_name == FunctionElement.CALL_METHOD_NAME) {
|
||||
return _toResult();
|
||||
return ResolutionResult(
|
||||
getter: null,
|
||||
needsGetterError: false,
|
||||
setter: null,
|
||||
needsSetterError: false,
|
||||
callFunctionType: receiverTypeResolved,
|
||||
);
|
||||
}
|
||||
|
||||
if (receiverTypeResolved is NeverType) {
|
||||
|
|
|
@ -7432,6 +7432,84 @@ MethodInvocation
|
|||
}
|
||||
}
|
||||
|
||||
test_noReceiver_call_extension_on_FunctionType() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
extension E on int Function() {
|
||||
void f() {
|
||||
call();
|
||||
}
|
||||
}
|
||||
''');
|
||||
|
||||
final node = findNode.methodInvocation('call()');
|
||||
if (isNullSafetyEnabled) {
|
||||
assertResolvedNodeText(node, r'''
|
||||
MethodInvocation
|
||||
methodName: SimpleIdentifier
|
||||
token: call
|
||||
staticElement: <null>
|
||||
staticType: dynamic
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
''');
|
||||
} else {
|
||||
assertResolvedNodeText(node, r'''
|
||||
MethodInvocation
|
||||
methodName: SimpleIdentifier
|
||||
token: call
|
||||
staticElement: <null>
|
||||
staticType: dynamic
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticInvokeType: int* Function()*
|
||||
staticType: int*
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
test_noReceiver_call_extension_on_FunctionType_bounded() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
extension E<T extends int Function()> on T {
|
||||
void f() {
|
||||
call();
|
||||
}
|
||||
}
|
||||
''');
|
||||
|
||||
final node = findNode.methodInvocation('call()');
|
||||
if (isNullSafetyEnabled) {
|
||||
assertResolvedNodeText(node, r'''
|
||||
MethodInvocation
|
||||
methodName: SimpleIdentifier
|
||||
token: call
|
||||
staticElement: <null>
|
||||
staticType: dynamic
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
''');
|
||||
} else {
|
||||
assertResolvedNodeText(node, r'''
|
||||
MethodInvocation
|
||||
methodName: SimpleIdentifier
|
||||
token: call
|
||||
staticElement: <null>
|
||||
staticType: dynamic
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticInvokeType: int* Function()*
|
||||
staticType: int*
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
test_noReceiver_getter_superClass() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
|
|
Loading…
Reference in a new issue