Skip to content

Commit ca31f1d

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Refactor FunctionExpressionInvocationResolver to support Never.
Bug: dart-lang/sdk#40055 Change-Id: Ic53b23178441a32d9de6fe0d2b6d5f4c646de75b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131401 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 4495c2b commit ca31f1d

File tree

2 files changed

+113
-49
lines changed

2 files changed

+113
-49
lines changed

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

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,33 @@ class FunctionExpressionInvocationResolver {
3636
ExtensionMemberResolver get _extensionResolver => _resolver.extensionResolver;
3737

3838
void resolve(FunctionExpressionInvocationImpl node) {
39-
var rawType = _resolveCallElement(node);
39+
var function = node.function;
4040

41-
if (rawType == null) {
42-
_setExplicitTypeArgumentTypes(node);
43-
_resolveArguments(node);
44-
node.staticInvokeType = DynamicTypeImpl.instance;
45-
node.staticType = DynamicTypeImpl.instance;
41+
if (function is ExtensionOverride) {
42+
_resolveReceiverExtensionOverride(node, function);
43+
return;
44+
}
45+
46+
var receiverType = function.staticType;
47+
if (receiverType is FunctionType) {
48+
_resolve(node, receiverType);
4649
return;
4750
}
4851

52+
if (receiverType is InterfaceType) {
53+
_resolveReceiverInterfaceType(node, function, receiverType);
54+
return;
55+
}
56+
57+
if (identical(receiverType, NeverTypeImpl.instance)) {
58+
_unresolved(node, NeverTypeImpl.instance);
59+
return;
60+
}
61+
62+
_unresolved(node, DynamicTypeImpl.instance);
63+
}
64+
65+
void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType) {
4966
_inferenceHelper.resolveFunctionExpressionInvocation(
5067
node: node,
5168
rawType: rawType,
@@ -62,60 +79,66 @@ class FunctionExpressionInvocationResolver {
6279
node.argumentList.accept(_resolver);
6380
}
6481

65-
FunctionType _resolveCallElement(FunctionExpressionInvocation node) {
66-
Expression function = node.function;
82+
void _resolveReceiverExtensionOverride(
83+
FunctionExpressionInvocation node,
84+
ExtensionOverride function,
85+
) {
86+
var result = _extensionResolver.getOverrideMember(
87+
function,
88+
FunctionElement.CALL_METHOD_NAME,
89+
);
90+
var callElement = result.getter;
91+
node.staticElement = callElement;
6792

68-
if (function is ExtensionOverride) {
69-
var result = _extensionResolver.getOverrideMember(
93+
if (callElement == null) {
94+
_errorReporter.reportErrorForNode(
95+
CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
7096
function,
71-
FunctionElement.CALL_METHOD_NAME,
97+
[function.extensionName.name],
7298
);
73-
var callElement = result.getter;
74-
node.staticElement = callElement;
75-
76-
if (callElement == null) {
77-
_errorReporter.reportErrorForNode(
78-
CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
79-
function,
80-
[function.extensionName.name],
81-
);
82-
return null;
83-
}
84-
85-
if (callElement.isStatic) {
86-
_errorReporter.reportErrorForNode(
87-
CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
88-
node.argumentList,
89-
);
90-
}
91-
92-
return _elementTypeProvider.getExecutableType(callElement);
99+
return _unresolved(node, DynamicTypeImpl.instance);
93100
}
94101

95-
var receiverType = function.staticType;
96-
if (receiverType is FunctionType) {
97-
return receiverType;
102+
if (callElement.isStatic) {
103+
_errorReporter.reportErrorForNode(
104+
CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
105+
node.argumentList,
106+
);
98107
}
99108

100-
if (receiverType is InterfaceType) {
101-
var result = _typePropertyResolver.resolve(
102-
receiver: function,
103-
receiverType: receiverType,
104-
name: FunctionElement.CALL_METHOD_NAME,
105-
receiverErrorNode: function,
106-
nameErrorNode: function,
107-
);
108-
var callElement = result.getter;
109+
var rawType = _elementTypeProvider.getExecutableType(callElement);
110+
_resolve(node, rawType);
111+
}
109112

110-
if (callElement?.kind != ElementKind.METHOD) {
111-
return null;
112-
}
113+
void _resolveReceiverInterfaceType(
114+
FunctionExpressionInvocationImpl node,
115+
Expression function,
116+
InterfaceType receiverType,
117+
) {
118+
var result = _typePropertyResolver.resolve(
119+
receiver: function,
120+
receiverType: receiverType,
121+
name: FunctionElement.CALL_METHOD_NAME,
122+
receiverErrorNode: function,
123+
nameErrorNode: function,
124+
);
125+
var callElement = result.getter;
113126

114-
node.staticElement = callElement;
115-
return _elementTypeProvider.getExecutableType(callElement);
127+
if (callElement?.kind != ElementKind.METHOD) {
128+
_unresolved(node, DynamicTypeImpl.instance);
129+
return;
116130
}
117131

118-
return null;
132+
node.staticElement = callElement;
133+
var rawType = _elementTypeProvider.getExecutableType(callElement);
134+
_resolve(node, rawType);
135+
}
136+
137+
void _unresolved(FunctionExpressionInvocationImpl node, DartType type) {
138+
_setExplicitTypeArgumentTypes(node);
139+
_resolveArguments(node);
140+
node.staticInvokeType = DynamicTypeImpl.instance;
141+
node.staticType = type;
119142
}
120143

121144
/// Inference cannot be done, we still want to fill type argument types.

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analyzer/src/dart/analysis/experiments.dart';
6+
import 'package:analyzer/src/error/codes.dart';
67
import 'package:analyzer/src/generated/engine.dart';
78
import 'package:test_reflective_loader/test_reflective_loader.dart';
89

@@ -145,4 +146,44 @@ main(A a) {
145146
type: 'int',
146147
);
147148
}
149+
150+
test_never() async {
151+
await assertErrorsInCode(r'''
152+
main(Never x) {
153+
x<int>(1 + 2);
154+
}
155+
''', [
156+
error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 18, 1),
157+
]);
158+
159+
assertFunctionExpressionInvocation(
160+
findNode.functionExpressionInvocation('x<int>(1 + 2)'),
161+
element: null,
162+
typeArgumentTypes: ['int'],
163+
invokeType: 'dynamic',
164+
type: 'Never',
165+
);
166+
167+
assertType(findNode.binary('1 + 2'), 'int');
168+
}
169+
170+
test_neverQ() async {
171+
await assertErrorsInCode(r'''
172+
main(Never? x) {
173+
x<int>(1 + 2);
174+
}
175+
''', [
176+
error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
177+
]);
178+
179+
assertFunctionExpressionInvocation(
180+
findNode.functionExpressionInvocation('x<int>(1 + 2)'),
181+
element: null,
182+
typeArgumentTypes: ['int'],
183+
invokeType: 'dynamic',
184+
type: 'dynamic',
185+
);
186+
187+
assertType(findNode.binary('1 + 2'), 'int');
188+
}
148189
}

0 commit comments

Comments
 (0)