[analyzer] Dot shorthands: FunctionReferences have dot shorthand flag.

`FunctionReference`s like `.foo<T>` can also be dot shorthands. This CL adds the flag onto that AST.

Unit test added and co19 tests that have function references are now passing.

Bug: https://github.com/dart-lang/sdk/issues/59835
Change-Id: I8c85e7915b665de5c4de2b249b22c6e8d8fc364d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426001
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
Kallen Tu
2025-05-02 11:07:31 -07:00
committed by Commit Queue
parent 57bfb6abd6
commit d7b3562cf4
3 changed files with 49 additions and 4 deletions
+4 -2
View File
@@ -8700,9 +8700,10 @@ abstract final class FunctionReference
///
/// In error-free code, this is either a [SimpleIdentifier] (indicating a
/// function that is in scope), a [PrefixedIdentifier] (indicating a either
/// function imported via prefix or a static method in a class), or a
/// function imported via prefix or a static method in a class), a
/// [PropertyAccess] (indicating a static method in a class imported via
/// prefix). In code with errors, this could be other kinds of expressions.
/// prefix), or a [DotShorthandPropertyAccess] (indicating a static method in
/// a class). In code with errors, this could be other kinds of expressions.
/// For example, `(...)<int>` parses as a [FunctionReference] whose referent
/// is a [ParenthesizedExpression].
Expression get function;
@@ -8720,6 +8721,7 @@ abstract final class FunctionReference
}
final class FunctionReferenceImpl extends CommentReferableExpressionImpl
with DotShorthandMixin
implements FunctionReference {
ExpressionImpl _function;
+13 -2
View File
@@ -2967,11 +2967,22 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
@override
void visitFunctionReference(
FunctionReference node, {
covariant FunctionReferenceImpl node, {
TypeImpl contextType = UnknownInferredType.instance,
}) {
inferenceLogWriter?.enterExpression(node, contextType);
_functionReferenceResolver.resolve(node as FunctionReferenceImpl);
// If [isDotShorthand] is set, cache the context type for resolution.
if (isDotShorthand(node)) {
pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
}
_functionReferenceResolver.resolve(node);
if (isDotShorthand(node)) {
popDotShorthandContext();
}
inferenceLogWriter?.exitExpression(node);
}
@@ -398,6 +398,38 @@ DotShorthandPropertyAccess
''');
}
test_functionReference() async {
await assertNoErrorsInCode(r'''
class C<T> {
static String foo<X>() => "C<$X>";
@override
bool operator ==(Object other) {
return false;
}
}
void test<T extends num>() {
C() == .foo<T>;
}
main() {
test<int>();
}
''');
var identifier = findNode.singleDotShorthandPropertyAccess;
assertResolvedNodeText(identifier, r'''
DotShorthandPropertyAccess
period: .
propertyName: SimpleIdentifier
token: foo
element: <testLibraryFragment>::@class::C::@method::foo#element
staticType: String Function<X>()
staticType: String Function<X>()
''');
}
test_futureOr() async {
await assertNoErrorsInCode('''
import 'dart:async';