Resolve Class.staticGetter<A> as ImplicitCallReference.
Change-Id: I66e6f4005d4adc24355da5a17089c98032552d39
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233961
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index cf14dd4..0aa5a1e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -453,22 +453,26 @@
return;
}
- var functionType = _resolveTypeProperty(
+ var propertyType = _resolveTypeProperty(
receiver: function.prefix,
name: function.identifier,
nameErrorEntity: function,
);
- if (functionType != null) {
- if (functionType is FunctionType) {
- function.staticType = functionType;
- _resolve(
- node: node,
- rawType: functionType,
- name: functionName,
- );
- return;
- }
+ var callMethod = _getCallMethod(node, propertyType);
+ if (callMethod is MethodElement) {
+ _resolveAsImplicitCallReference(node, callMethod);
+ return;
+ }
+
+ if (propertyType is FunctionType) {
+ function.staticType = propertyType;
+ _resolve(
+ node: node,
+ rawType: propertyType,
+ name: functionName,
+ );
+ return;
}
function.accept(_resolver);
@@ -823,17 +827,13 @@
if (receiverElement is ClassElement) {
var element = _resolveStaticElement(receiverElement, name);
name.staticElement = element;
- // TODO(srawlins): Should this use referenceType? E.g. if `element`
- // is a function-typed static getter.
- return element?.type;
+ return element?.referenceType;
} else if (receiverElement is TypeAliasElement) {
var aliasedType = receiverElement.aliasedType;
if (aliasedType is InterfaceType) {
var element = _resolveStaticElement(aliasedType.element, name);
name.staticElement = element;
- // TODO(srawlins): Should this use referenceType? E.g. if `element`
- // is a function-typed static getter.
- return element?.type;
+ return element?.referenceType;
} else {
return null;
}
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 3456bd6..a5d8a32 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -1723,6 +1723,51 @@
findElement.method('call'), 'int Function(int)');
}
+ test_implicitCallTearoff_class_staticGetter() async {
+ await assertNoErrorsInCode('''
+class C {
+ static const v = C();
+ const C();
+ T call<T>(T t) => t;
+}
+
+void f() {
+ C.v<int>;
+}
+''');
+
+ var node = findNode.implicitCallReference('C.v<int>');
+ assertResolvedNodeText(node, r'''
+ImplicitCallReference
+ expression: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: C
+ staticElement: self::@class::C
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: v
+ staticElement: self::@class::C::@getter::v
+ staticType: null
+ staticElement: self::@class::C::@getter::v
+ staticType: null
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ staticElement: self::@class::C::@method::call
+ staticType: int Function(int)
+ typeArgumentTypes
+ int
+''');
+ }
+
test_implicitCallTearoff_extensionOnNullable() async {
await assertNoErrorsInCode('''
Object? v = null;
@@ -1741,6 +1786,62 @@
'void Function(int, String)');
}
+ test_implicitCallTearoff_prefix_class_staticGetter() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class C {
+ static const v = C();
+ const C();
+ T call<T>(T t) => t;
+}
+''');
+
+ await assertNoErrorsInCode('''
+import 'a.dart' as prefix;
+
+void f() {
+ prefix.C.v<int>;
+}
+''');
+
+ var node = findNode.implicitCallReference('C.v<int>');
+ assertResolvedNodeText(node, r'''
+ImplicitCallReference
+ expression: PropertyAccess
+ target: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: C
+ staticElement: package:test/a.dart::@class::C
+ staticType: null
+ staticElement: package:test/a.dart::@class::C
+ staticType: null
+ operator: .
+ propertyName: SimpleIdentifier
+ token: v
+ staticElement: package:test/a.dart::@class::C::@getter::v
+ staticType: C
+ staticType: C
+ typeArguments: TypeArgumentList
+ leftBracket: <
+ arguments
+ NamedType
+ name: SimpleIdentifier
+ token: int
+ staticElement: dart:core::@class::int
+ staticType: null
+ type: int
+ rightBracket: >
+ staticElement: package:test/a.dart::@class::C::@method::call
+ staticType: int Function(int)
+ typeArgumentTypes
+ int
+''');
+ }
+
test_implicitCallTearoff_prefixed() async {
newFile('$testPackageLibPath/a.dart', content: '''
class C {
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 8978bb1..107d0d6 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -684,6 +684,7 @@
_writeln('ImplicitCallReference');
_withIndent(() {
_writeNamedChildEntities(node);
+ _writeElement('staticElement', node.staticElement);
_writeType('staticType', node.staticType);
_writeTypeList('typeArgumentTypes', node.typeArgumentTypes);
});
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index bc151cc..9e41564 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -21963,6 +21963,7 @@
token: c @68
staticElement: c@52
staticType: C
+ staticElement: self::@class::C::@method::call
staticType: void Function()
rightParenthesis: ) @69
staticElement: self::@class::D::@constructor::named