Skip to content

Commit 0864980

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Resolve the call method when used with an extension override
Change-Id: I2bf310abb3b8c3f4fc5eb9179bd60df4539d241f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109888 Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 17e15ee commit 0864980

File tree

5 files changed

+157
-5
lines changed

5 files changed

+157
-5
lines changed

pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class MethodInvocationResolver {
9696

9797
if (receiver is ExtensionOverride) {
9898
_resolveExtensionOverride(node, receiver, nameNode, name);
99+
return;
99100
}
100101

101102
ClassElement typeReference = getTypeReference(receiver);

pkg/analyzer/lib/src/generated/element_resolver.dart

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,23 @@ class ElementResolver extends SimpleAstVisitor<void> {
392392
@override
393393
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
394394
Expression function = node.function;
395-
DartType staticInvokeType = _instantiateGenericMethod(
396-
function.staticType, node.typeArguments, node);
395+
DartType functionType;
396+
if (function is ExtensionOverride) {
397+
ExtensionElement element = function.extensionName.staticElement;
398+
MethodElement member = element.getMethod('call');
399+
if (member != null && member.isStatic) {
400+
_resolver.errorReporter.reportErrorForNode(
401+
CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
402+
node.argumentList);
403+
}
404+
node.staticElement = member;
405+
functionType = member.type;
406+
} else {
407+
functionType = function.staticType;
408+
}
409+
410+
DartType staticInvokeType =
411+
_instantiateGenericMethod(functionType, node.typeArguments, node);
397412

398413
node.staticInvokeType = staticInvokeType;
399414

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,9 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
363363

364364
@override
365365
void visitArgumentList(ArgumentList node) {
366-
_checkForArgumentTypesNotAssignableInList(node);
366+
if (node.parent is! ExtensionOverride) {
367+
_checkForArgumentTypesNotAssignableInList(node);
368+
}
367369
super.visitArgumentList(node);
368370
}
369371

@@ -873,6 +875,12 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
873875
@override
874876
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
875877
Expression functionExpression = node.function;
878+
if (functionExpression is ExtensionOverride) {
879+
// TODO(brianwilkerson) Update `_checkTypeArguments` to handle extension
880+
// overrides.
881+
// _checkTypeArguments(node);
882+
return super.visitFunctionExpressionInvocation(node);
883+
}
876884
DartType expressionType = functionExpression.staticType;
877885
if (!_checkForNullableDereference(functionExpression) &&
878886
!_checkForUseOfVoidResult(functionExpression) &&
@@ -884,7 +892,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
884892
_checkTypeArguments(node);
885893
}
886894
_checkForImplicitDynamicInvoke(node);
887-
_checkForNullableDereference(node.function);
895+
_checkForNullableDereference(functionExpression);
888896
_checkForMissingRequiredParam(
889897
node.staticInvokeType, node.argumentList, node);
890898
super.visitFunctionExpressionInvocation(node);

pkg/analyzer/test/src/dart/resolution/extension_override_test.dart

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,82 @@ class ExtensionOverrideTest extends DriverResolutionTest {
4444
extensionOverride = findNode.extensionOverride(overrideSearch);
4545
}
4646

47+
test_call_noPrefix_noTypeArguments() async {
48+
await assertNoErrorsInCode('''
49+
class A {}
50+
extension E on A {
51+
int call(String s) => 0;
52+
}
53+
void f(A a) {
54+
E(a)('');
55+
}
56+
''');
57+
findDeclarationAndOverride(declarationName: 'E ', overrideSearch: 'E(a)');
58+
validateOverride();
59+
validateCall();
60+
}
61+
62+
@failingTest
63+
test_call_noPrefix_typeArguments() async {
64+
// The test is failing because we're not yet doing type inference.
65+
await assertNoErrorsInCode('''
66+
class A {}
67+
extension E<T> on A {
68+
int call(T s) => 0;
69+
}
70+
void f(A a) {
71+
E<String>(a)('');
72+
}
73+
''');
74+
findDeclarationAndOverride(declarationName: 'E<T>', overrideSearch: 'E<S');
75+
validateOverride(typeArguments: [stringType]);
76+
validateCall();
77+
}
78+
79+
test_call_prefix_noTypeArguments() async {
80+
newFile('/test/lib/lib.dart', content: '''
81+
class A {}
82+
extension E on A {
83+
int call(String s) => 0;
84+
}
85+
''');
86+
await assertNoErrorsInCode('''
87+
import 'lib.dart' as p;
88+
void f(p.A a) {
89+
p.E(a)('');
90+
}
91+
''');
92+
findDeclarationAndOverride(
93+
declarationName: 'E',
94+
declarationUri: 'package:test/lib.dart',
95+
overrideSearch: 'E(a)');
96+
validateOverride();
97+
validateCall();
98+
}
99+
100+
@failingTest
101+
test_call_prefix_typeArguments() async {
102+
// The test is failing because we're not yet doing type inference.
103+
newFile('/test/lib/lib.dart', content: '''
104+
class A {}
105+
extension E<T> on A {
106+
int call(T s) => 0;
107+
}
108+
''');
109+
await assertNoErrorsInCode('''
110+
import 'lib.dart' as p;
111+
void f(p.A a) {
112+
p.E<String>(a)('');
113+
}
114+
''');
115+
findDeclarationAndOverride(
116+
declarationName: 'E',
117+
declarationUri: 'package:test/lib.dart',
118+
overrideSearch: 'E<S');
119+
validateOverride(typeArguments: [stringType]);
120+
validateCall();
121+
}
122+
47123
test_getter_noPrefix_noTypeArguments() async {
48124
await assertNoErrorsInCode('''
49125
class A {}
@@ -414,10 +490,27 @@ void f(p.A a) {
414490
expect(resolvedElement, extension.getMethod('+'));
415491
}
416492

493+
void validateCall() {
494+
FunctionExpressionInvocation invocation =
495+
extensionOverride.parent as FunctionExpressionInvocation;
496+
Element resolvedElement = invocation.staticElement;
497+
expect(resolvedElement, extension.getMethod('call'));
498+
499+
NodeList<Expression> arguments = invocation.argumentList.arguments;
500+
for (int i = 0; i < arguments.length; i++) {
501+
expect(arguments[i].staticParameterElement, isNotNull);
502+
}
503+
}
504+
417505
void validateInvocation() {
418506
MethodInvocation invocation = extensionOverride.parent as MethodInvocation;
419507
Element resolvedElement = invocation.methodName.staticElement;
420508
expect(resolvedElement, extension.getMethod('m'));
509+
510+
NodeList<Expression> arguments = invocation.argumentList.arguments;
511+
for (int i = 0; i < arguments.length; i++) {
512+
expect(arguments[i].staticParameterElement, isNotNull);
513+
}
421514
}
422515

423516
void validateOverride({List<DartType> typeArguments}) {

pkg/analyzer/test/src/diagnostics/extension_override_argument_not_assignable_test.dart

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import '../dart/resolution/driver_resolution.dart';
1111

1212
main() {
1313
defineReflectiveSuite(() {
14-
defineReflectiveTests(ExtensionDeclaresAbstractMethodTest);
14+
// defineReflectiveTests(ExtensionDeclaresAbstractMethodTest);
15+
defineReflectiveTests(ExtensionDeclaresAbstractMethodWithNNBDTest);
1516
});
1617
}
1718

@@ -65,3 +66,37 @@ void f(B b) {
6566
]);
6667
}
6768
}
69+
70+
@reflectiveTest
71+
class ExtensionDeclaresAbstractMethodWithNNBDTest extends DriverResolutionTest {
72+
@override
73+
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
74+
..contextFeatures = new FeatureSet.forTesting(
75+
sdkVersion: '2.3.0',
76+
additionalFeatures: [Feature.extension_methods, Feature.non_nullable]);
77+
78+
test_override_onNonNullable() async {
79+
await assertErrorsInCode(r'''
80+
extension E on String {
81+
void m() {}
82+
}
83+
f() {
84+
E(null).m();
85+
}
86+
''', [
87+
error(CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE, 50,
88+
4),
89+
]);
90+
}
91+
92+
test_override_onNullable() async {
93+
await assertNoErrorsInCode(r'''
94+
extension E on String? {
95+
void m() {}
96+
}
97+
f() {
98+
E(null).m();
99+
}
100+
''');
101+
}
102+
}

0 commit comments

Comments
 (0)