mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 13:57:58 +00:00
Extension types. It is not an error to invoke members of nullable extension type.
1. It is not allowed to write a nullable type in `implements`. 2. Any methods of the extension type itself are OK to invoke. I start to doubt what is the meaning of isNonNullable() to extension types. For now I will add a workaround, to be reconsidered if isNonNullable() is clarified. Change-Id: I8a9543a6b0e942ae4de3ce673eeee1aa9b0a5230 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319862 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Phil Quitslund <pquitslund@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
3c75002cee
commit
00b59bd878
|
@ -11,6 +11,10 @@ import 'package:collection/collection.dart';
|
|||
import 'package:meta/meta_meta.dart';
|
||||
|
||||
extension DartTypeExtension on DartType {
|
||||
bool get isExtensionType {
|
||||
return element is ExtensionTypeElement;
|
||||
}
|
||||
|
||||
/// If `this` is an [InterfaceType] that is an instantiation of an extension
|
||||
/// type, returns its representation type erasure. Otherwise, returns self.
|
||||
DartType get representationTypeErasureOrSelf {
|
||||
|
|
|
@ -92,7 +92,8 @@ class TypePropertyResolver {
|
|||
}
|
||||
|
||||
if (_isNonNullableByDefault &&
|
||||
_typeSystem.isPotentiallyNullable(receiverType)) {
|
||||
_typeSystem.isPotentiallyNullable(receiverType) &&
|
||||
!receiverType.isExtensionType) {
|
||||
_lookupInterfaceType(_typeProvider.objectType);
|
||||
if (_hasGetterOrSetter) {
|
||||
return _toResult();
|
||||
|
|
|
@ -817,6 +817,37 @@ extension type A(int it) {
|
|||
void foo() {}
|
||||
}
|
||||
|
||||
void f(A a) {
|
||||
a.foo();
|
||||
}
|
||||
''');
|
||||
|
||||
final node = findNode.singleMethodInvocation;
|
||||
assertResolvedNodeText(node, r'''
|
||||
MethodInvocation
|
||||
target: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: A
|
||||
operator: .
|
||||
methodName: SimpleIdentifier
|
||||
token: foo
|
||||
staticElement: self::@extensionType::A::@method::foo
|
||||
staticType: void Function()
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticInvokeType: void Function()
|
||||
staticType: void
|
||||
''');
|
||||
}
|
||||
|
||||
test_hasReceiver_interfaceType_extensionType_declared_nullableRepresentation() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
extension type A(int? it) {
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
void f(A a) {
|
||||
a.foo();
|
||||
}
|
||||
|
|
|
@ -549,6 +549,34 @@ extension type A(int it) {
|
|||
int get foo => 0;
|
||||
}
|
||||
|
||||
void f(A a) {
|
||||
a.foo;
|
||||
}
|
||||
''');
|
||||
|
||||
final node = findNode.singlePrefixedIdentifier;
|
||||
assertResolvedNodeText(node, r'''
|
||||
PrefixedIdentifier
|
||||
prefix: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: A
|
||||
period: .
|
||||
identifier: SimpleIdentifier
|
||||
token: foo
|
||||
staticElement: self::@extensionType::A::@getter::foo
|
||||
staticType: int
|
||||
staticElement: self::@extensionType::A::@getter::foo
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_ofExtensionType_read_nullableRepresentation() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
extension type A(int? it) {
|
||||
int get foo => 0;
|
||||
}
|
||||
|
||||
void f(A a) {
|
||||
a.foo;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue