diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart index 5992a08094f..a40e27e598f 100644 --- a/pkg/analyzer/lib/src/dart/element/extensions.dart +++ b/pkg/analyzer/lib/src/dart/element/extensions.dart @@ -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 { diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart index fc638df4fce..970e0711d7b 100644 --- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart +++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart @@ -92,7 +92,8 @@ class TypePropertyResolver { } if (_isNonNullableByDefault && - _typeSystem.isPotentiallyNullable(receiverType)) { + _typeSystem.isPotentiallyNullable(receiverType) && + !receiverType.isExtensionType) { _lookupInterfaceType(_typeProvider.objectType); if (_hasGetterOrSetter) { return _toResult(); diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart index a67ae1ba7c0..b3b7a5e9412 100644 --- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart @@ -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(); } diff --git a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart index 3b546667b51..df172ce2bf9 100644 --- a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart @@ -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; }