Skip to content

Commit b024af0

Browse files
kallentuCommit Queue
authored and
Commit Queue
committed
[analyzer] Dot shorthands: Add support for call() and getter executions.
Follow up to comment: https://dart-review.googlesource.com/c/sdk/+/422544/comment/36fb49ba_f9f3c908/ Invocations are rewritten to `FunctionExpressionInvocation`s with a `DotShorthandPropertyAccess` as its `function`. Any actual static method invocations are kept as is. Added some special handling of dot shorthands in the `method_invocation_resolver` to rewrite an invocation to a property access with a function expression invocation as a parent. The static type is set for later usage in the `function_expression_invocation_resolver`. `language/dot_shorthands/simple/call_test` passing and unit tests added. Bug: #59835 Change-Id: I42649cefab54f80dc96357a03e208ad374183d09 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/423211 Reviewed-by: Paul Berry <[email protected]> Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
1 parent 4146134 commit b024af0

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,16 @@ class MethodInvocationResolver with ScopeHelpers {
13151315

13161316
ExpressionImpl functionExpression;
13171317
if (target == null) {
1318-
functionExpression = methodName;
1318+
if (node is DotShorthandInvocationImpl) {
1319+
functionExpression = DotShorthandPropertyAccessImpl(
1320+
period: node.period,
1321+
propertyName: node.memberName,
1322+
);
1323+
functionExpression.setPseudoExpressionStaticType(targetType);
1324+
} else {
1325+
functionExpression = methodName;
1326+
}
1327+
13191328
var element = methodName.element;
13201329
if (element is ExecutableElement2 &&
13211330
element.enclosingElement2 is InstanceElement2 &&

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -2434,7 +2434,8 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
24342434
);
24352435
switch (rewrittenExpression) {
24362436
case null:
2437-
// TODO(kallentu): Report an error here.
2437+
// In this case, we didn't rewrite anything. The [node] is a static
2438+
// method invocation.
24382439
break;
24392440
case FunctionExpressionInvocationImpl():
24402441
_resolveRewrittenFunctionExpressionInvocation(

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

+94
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analyzer/src/error/codes.dart';
56
import 'package:test_reflective_loader/test_reflective_loader.dart';
67

78
import 'context_collection_resolution.dart';
@@ -128,6 +129,99 @@ DotShorthandInvocation
128129
''');
129130
}
130131

132+
test_call_getter() async {
133+
await assertNoErrorsInCode(r'''
134+
class C {
135+
const C();
136+
static C get id1 => const C();
137+
C call() => const C();
138+
}
139+
140+
void main() {
141+
C c1 = .id1();
142+
print(c1);
143+
}
144+
''');
145+
146+
// The [DotShorthandInvocation] is rewritten to a
147+
// [FunctionExpressionInvocation].
148+
var node = findNode.singleFunctionExpressionInvocation;
149+
assertResolvedNodeText(node, r'''
150+
FunctionExpressionInvocation
151+
function: DotShorthandPropertyAccess
152+
period: .
153+
propertyName: SimpleIdentifier
154+
token: id1
155+
element: <testLibraryFragment>::@class::C::@getter::id1#element
156+
staticType: C
157+
staticType: C
158+
argumentList: ArgumentList
159+
leftParenthesis: (
160+
rightParenthesis: )
161+
element: <testLibraryFragment>::@class::C::@method::call#element
162+
staticInvokeType: C Function()
163+
staticType: C
164+
''');
165+
}
166+
167+
test_call_noCallMethod() async {
168+
await assertErrorsInCode(
169+
r'''
170+
class C {
171+
const C();
172+
static C id1 = const C();
173+
}
174+
175+
void main() {
176+
C c1 = .id1();
177+
print(c1);
178+
}
179+
''',
180+
[
181+
error(
182+
CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
183+
77,
184+
4,
185+
),
186+
],
187+
);
188+
}
189+
190+
test_call_property() async {
191+
await assertNoErrorsInCode(r'''
192+
class C {
193+
const C();
194+
static C id1 = const C();
195+
C call() => const C();
196+
}
197+
198+
void main() {
199+
C c1 = .id1();
200+
print(c1);
201+
}
202+
''');
203+
204+
// The [DotShorthandInvocation] is rewritten to a
205+
// [FunctionExpressionInvocation].
206+
var node = findNode.singleFunctionExpressionInvocation;
207+
assertResolvedNodeText(node, r'''
208+
FunctionExpressionInvocation
209+
function: DotShorthandPropertyAccess
210+
period: .
211+
propertyName: SimpleIdentifier
212+
token: id1
213+
element: <testLibraryFragment>::@class::C::@getter::id1#element
214+
staticType: C
215+
staticType: C
216+
argumentList: ArgumentList
217+
leftParenthesis: (
218+
rightParenthesis: )
219+
element: <testLibraryFragment>::@class::C::@method::call#element
220+
staticInvokeType: C Function()
221+
staticType: C
222+
''');
223+
}
224+
131225
test_equality() async {
132226
await assertNoErrorsInCode('''
133227
class C {

0 commit comments

Comments
 (0)