analyzer: fix various issues for static extension member resolution

* Unqualified, out-of-scope static extension members are not
  accessible.
* Locally scoped extension members shadow others.
* Static and instance extension members do not conflict.

Fixes https://github.com/dart-lang/sdk/issues/41268

Fixes https://github.com/dart-lang/sdk/issues/55848

Cq-Include-Trybots: luci.dart.try:flutter-analyze-try,analyzer-win-release-try,pkg-win-release-try
Change-Id: Icd618d044b3857efa24f365c6835d42c0022c176
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370323
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Sam Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Sam Rawlins 2024-06-14 00:59:57 +00:00 committed by Commit Queue
parent b4e30d1b45
commit 50e4c576b9
16 changed files with 378 additions and 308 deletions

View file

@ -22,7 +22,7 @@ class AddExtensionOverride extends MultiCorrectionProducer {
if (target == null) return const [];
var extensions =
libraryElement.accessibleExtensions.hasMemberWithBaseName(node.name);
libraryElement.accessibleExtensions.havingMemberWithBaseName(node.name);
var producers = <ResolvedCorrectionProducer>[];
for (var extension in extensions) {
var name = extension.extension.name;

View file

@ -186,7 +186,7 @@ class ImportLibrary extends MultiCorrectionProducer {
}
foundImport = true;
var instantiatedExtensions = importedLibrary.exportedExtensions
.hasMemberWithBaseName(memberName)
.havingMemberWithBaseName(memberName)
.applicableTo(targetLibrary: libraryElement, targetType: targetType);
for (var instantiatedExtension in instantiatedExtensions) {
// If the import has a combinator that needs to be updated, then offer
@ -482,7 +482,7 @@ class _ImportLibraryContainingExtension extends ResolvedCorrectionProducer {
@override
Future<void> compute(ChangeBuilder builder) async {
var instantiatedExtensions = library.exportedExtensions
.hasMemberWithBaseName(memberName)
.havingMemberWithBaseName(memberName)
.applicableTo(targetLibrary: libraryElement, targetType: targetType);
if (instantiatedExtensions.isNotEmpty) {
await builder.addDartFileEdit(file, (builder) {

View file

@ -38,25 +38,6 @@ void f(A a) {
''');
}
Future<void> test_method_extension() async {
await resolveTestCode('''
extension E on int {
static void foo() {}
}
void f() {
0.foo();
}
''');
await assertHasFix('''
extension E on int {
static void foo() {}
}
void f() {
E.foo();
}
''');
}
Future<void> test_method_importType() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {

View file

@ -114,7 +114,9 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
.applicableTo(targetLibrary: targetLibrary, targetType: targetType);
}
List<_NotInstantiatedExtensionWithMember> hasMemberWithBaseName(
/// Returns the sublist of [ExtensionElement]s that have an instance member
/// named [baseName].
List<_NotInstantiatedExtensionWithMember> havingMemberWithBaseName(
String baseName,
) {
var result = <_NotInstantiatedExtensionWithMember>[];
@ -140,6 +142,9 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
}
} else {
for (var field in extension.augmented.fields) {
if (field.isStatic) {
continue;
}
if (field.name == baseName) {
result.add(
_NotInstantiatedExtensionWithMember(
@ -152,6 +157,9 @@ extension ExtensionsExtensions on Iterable<ExtensionElement> {
}
}
for (var method in extension.augmented.methods) {
if (method.isStatic) {
continue;
}
if (method.name == baseName) {
result.add(
_NotInstantiatedExtensionWithMember(

View file

@ -20,7 +20,6 @@ import 'package:analyzer/src/dart/resolver/applicable_extensions.dart';
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/util/either.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
class ExtensionMemberResolver {
@ -74,20 +73,17 @@ class ExtensionMemberResolver {
).substituteType(element.extendedType);
}
/// Return the most specific extension in the current scope for this [type],
/// Returns the most specific accessible extension, applicable to [type],
/// that defines the member with the given [name].
///
/// If no applicable extensions, return [ResolutionResult.none].
/// If no applicable extensions are found, returns [ResolutionResult.none].
///
/// If the match is ambiguous, report an error on the [nameEntity], and
/// return [ResolutionResult.ambiguous].
/// If the match is ambiguous, reports an error on the [nameEntity], and
/// returns [ResolutionResult.ambiguous].
ResolutionResult findExtension(
DartType type,
SyntacticEntity nameEntity,
String name,
) {
DartType type, SyntacticEntity nameEntity, String name) {
var extensions = _resolver.definingLibrary.accessibleExtensions
.hasMemberWithBaseName(name)
.havingMemberWithBaseName(name)
.applicableTo(
targetLibrary: _resolver.definingLibrary,
targetType: type,
@ -102,29 +98,27 @@ class ExtensionMemberResolver {
}
var mostSpecific = _chooseMostSpecific(extensions);
return mostSpecific.map(
(extension) {
return extension.asResolutionResult;
},
(noneMoreSpecific) {
_errorReporter.atEntity(
nameEntity,
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS,
arguments: [
name,
noneMoreSpecific.map((e) {
var name = e.extension.name;
if (name != null) {
return "extension '$name'";
}
var type = e.extension.extendedType.getDisplayString();
return "unnamed extension on '$type'";
}).commaSeparatedWithAnd,
],
);
return ResolutionResult.ambiguous;
},
if (mostSpecific.length == 1) {
return mostSpecific.first.asResolutionResult;
}
// The most specific extension is ambiguous.
_errorReporter.atEntity(
nameEntity,
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS,
arguments: [
name,
mostSpecific.map((e) {
var name = e.extension.name;
if (name != null) {
return "extension '$name'";
}
var type = e.extension.extendedType.getDisplayString();
return "unnamed extension on '$type'";
}).commaSeparatedWithAnd,
],
);
return ResolutionResult.ambiguous;
}
/// Resolve the [name] (without `=`) to the corresponding getter and setter
@ -260,11 +254,10 @@ class ExtensionMemberResolver {
}
}
/// Return either the most specific extension, or a list of the extensions
/// that are ambiguous.
Either2<InstantiatedExtensionWithMember,
List<InstantiatedExtensionWithMember>>
_chooseMostSpecific(List<InstantiatedExtensionWithMember> extensions) {
/// Returns a list with either the most specific extension, or, if the most
/// specific is ambiguous, then the extensions that are ambiguous.
List<InstantiatedExtensionWithMember> _chooseMostSpecific(
List<InstantiatedExtensionWithMember> extensions) {
InstantiatedExtensionWithMember? bestSoFar;
var noneMoreSpecific = <InstantiatedExtensionWithMember>[];
for (var candidate in extensions) {
@ -299,18 +292,17 @@ class ExtensionMemberResolver {
}
if (bestSoFar != null) {
return Either2.t1(bestSoFar);
} else {
return Either2.t2(noneMoreSpecific);
return [bestSoFar];
}
return noneMoreSpecific;
}
/// Given the generic [element] element, either return types specified
/// explicitly in [typeArguments], or infer type arguments from the given
/// [receiverType].
/// Given the generic [node], either returns types specified explicitly in its
/// type arguments, or infer type arguments from the given [receiverType].
///
/// If the number of explicit type arguments is different than the number
/// of extension's type parameters, or inference fails, return `dynamic`
/// of extension's type parameters, or inference fails, returns `dynamic`
/// for all type parameters.
List<DartType>? _inferTypeArguments(
ExtensionOverride node, DartType receiverType,

View file

@ -574,6 +574,39 @@ class MethodInvocationResolver with ScopeHelpers {
return null;
}
element = scopeLookupResult.setter;
if (element != null) {
// If the scope lookup reveals a setter, but no getter, then we may still
// find the getter by looking up the inheritence chain (via
// TypePropertyResolver, via `_resolveReceiverType`). However, if the
// setter that was found is either top-level, or declared in an extension,
// or is static, then we do not keep searching for the getter; this
// setter represents the property being accessed (erroneously).
var noGetterIsPossible =
element.enclosingElement is CompilationUnitElement ||
element.enclosingElement is ExtensionElement ||
(element is ExecutableElement && element.isStatic);
if (noGetterIsPossible) {
nameNode.staticElement = element;
_setInvalidTypeResolution(node,
setNameTypeToDynamic: false,
whyNotPromotedList: whyNotPromotedList,
contextType: contextType);
var receiverTypeName = switch (receiverType) {
InterfaceType() => receiverType.element.name,
FunctionType() => 'Function',
_ => '<unknown>',
};
_resolver.errorReporter.atNode(
nameNode,
CompileTimeErrorCode.UNDEFINED_METHOD,
arguments: [name, receiverTypeName],
);
return null;
}
}
return _resolveReceiverType(
node: node,
receiver: null,

View file

@ -2203,8 +2203,8 @@ extension E on int {
}
void f() {
0.foo;
0.foo = 0;
E.foo;
E.foo = 0;
}
''');
var getter = findElement.getter('foo');

View file

@ -484,6 +484,36 @@ FunctionExpressionInvocation
''');
}
test_getter_functionTyped_withSetterDeclaredLocally() async {
await assertNoErrorsInCode('''
class A {
Function get foo => () {};
}
class B extends A {
set foo(Function _) {}
void f() {
foo();
}
}
''');
var node = findNode.singleFunctionExpressionInvocation;
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: SimpleIdentifier
token: foo
staticElement: self::@class::A::@getter::foo
staticType: Function
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticElement: <null>
staticInvokeType: dynamic
staticType: dynamic
''');
}
test_invalidConst_topLevelVariable() async {
await assertErrorsInCode(r'''
const id = identical;

View file

@ -1030,15 +1030,11 @@ void bar() {
foo.m<int>;
}
extension on Function {
extension E on Function {
static void m<T>(T t) {}
}
''', [
error(
CompileTimeErrorCode
.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION,
40,
1),
error(CompileTimeErrorCode.UNDEFINED_GETTER, 40, 1),
]);
assertResolvedNodeText(findNode.functionReference('foo.m<int>;'), r'''
@ -1051,10 +1047,10 @@ FunctionReference
period: .
identifier: SimpleIdentifier
token: m
staticElement: self::@extension::0::@method::m
staticType: null
staticElement: self::@extension::0::@method::m
staticType: void Function<T>(T)
staticElement: <null>
staticType: InvalidType
staticElement: <null>
staticType: InvalidType
typeArguments: TypeArgumentList
leftBracket: <
arguments
@ -1063,9 +1059,7 @@ FunctionReference
element: dart:core::@class::int
type: int
rightBracket: >
staticType: void Function(int)
typeArgumentTypes
int
staticType: InvalidType
''');
}

View file

@ -347,6 +347,29 @@ int Function() foo(A? a) {
assertType(identifier, 'A?');
}
test_inClass_getterInherited_setterDeclaredLocally() async {
await assertNoErrorsInCode('''
class A {
int get foo => 7;
}
class B extends A {
set foo(int _) {}
void f() {
foo;
}
}
''');
var node = findNode.simple('foo;');
assertResolvedNodeText(node, r'''
SimpleIdentifier
token: foo
staticElement: self::@class::A::@getter::foo
staticType: int
''');
}
test_inClass_inDeclaration_augmentationDeclares() async {
newFile('$testPackageLibPath/a.dart', r'''
augment library 'test.dart'

View file

@ -65,6 +65,36 @@ PropertyAccess
''');
}
test_getter_getterStatic() async {
await assertNoErrorsInCode('''
extension E1 on int {
void get a => 1;
}
extension E2 on int {
static void get a => 2;
}
f() {
0.a;
}
''');
var node = findNode.propertyAccess('0.a');
assertResolvedNodeText(node, r'''
PropertyAccess
target: IntegerLiteral
literal: 0
staticType: int
operator: .
propertyName: SimpleIdentifier
token: a
staticElement: self::@extension::E1::@getter::a
staticType: void
staticType: void
''');
}
test_getter_method() async {
await assertErrorsInCode('''
extension E on int {

View file

@ -34,98 +34,6 @@ f(C c) {
);
}
test_extension_getter() async {
await assertErrorsInCode('''
class C {}
extension E on C {
static int get a => 0;
}
C g(C c) => C();
f(C c) {
g(c).a;
}
''', [
error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 92, 1,
correctionContains: "extension 'E'"),
]);
assertElement(
findNode.simple('a;'),
findElement.getter('a'),
);
}
test_extension_getter_unnamed() async {
await assertErrorsInCode('''
class C {}
extension on C {
static int get a => 0;
}
C g(C c) => C();
f(C c) {
g(c).a;
}
''', [
error(
CompileTimeErrorCode
.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION,
90,
1),
]);
assertElement(
findNode.simple('a;'),
findElement.getter('a'),
);
}
test_extension_method() async {
await assertErrorsInCode('''
class C {}
extension E on C {
static void a() {}
}
f(C c) {
c.a();
}
''', [
error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 68, 1,
correctionContains: "extension 'E'"),
]);
assertElement(
findNode.methodInvocation('a();'),
findElement.method('a'),
);
}
test_extension_method_unnamed() async {
await assertErrorsInCode('''
class C {}
extension on C {
static void a() {}
}
f(C c) {
c.a();
}
''', [
error(
CompileTimeErrorCode
.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION,
66,
1),
]);
assertElement(
findNode.methodInvocation('a();'),
findElement.method('a'),
);
}
test_extension_referring_to_class_member() async {
await assertErrorsInCode('''
class C {
@ -145,49 +53,6 @@ test(int i) {
]);
}
test_extension_setter() async {
await assertErrorsInCode('''
class C {}
extension E on C {
static set a(int v) {}
}
f(C c) {
c.a = 2;
}
''', [
error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 72, 1),
]);
assertResolvedNodeText(findNode.assignment('a ='), r'''
AssignmentExpression
leftHandSide: PrefixedIdentifier
prefix: SimpleIdentifier
token: c
staticElement: self::@function::f::@parameter::c
staticType: C
period: .
identifier: SimpleIdentifier
token: a
staticElement: <null>
staticType: null
staticElement: <null>
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 2
parameter: self::@extension::E::@setter::a::@parameter::v
staticType: int
readElement: <null>
readType: null
writeElement: self::@extension::E::@setter::a
writeType: int
staticElement: <null>
staticType: int
''');
}
test_method_reference() async {
await assertErrorsInCode(r'''
class A {
@ -211,25 +76,7 @@ f(int a) {
a.m<int>;
}
''', [
error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 57, 1,
correctionContains: "extension 'E'"),
]);
}
test_method_reference_extension_unnamed() async {
await assertErrorsInCode(r'''
extension on int {
static m<T>() {}
}
f(int a) {
a.m<int>;
}
''', [
error(
CompileTimeErrorCode
.INSTANCE_ACCESS_TO_STATIC_MEMBER_OF_UNNAMED_EXTENSION,
55,
1),
error(CompileTimeErrorCode.UNDEFINED_GETTER, 57, 1),
]);
}

View file

@ -481,6 +481,23 @@ f(var p) {
]);
}
test_static_extension_InstanceAccess() async {
await assertErrorsInCode('''
class C {}
extension E on C {
static int get a => 0;
}
C g(C c) => C();
f(C c) {
g(c).a;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_GETTER, 92, 1),
]);
}
test_static_undefined() async {
await assertErrorsInCode('''
class C {}

View file

@ -75,6 +75,42 @@ f(C c) {
]);
}
test_extensionMethodHiddenByStaticSetter() async {
await assertErrorsInCode('''
class C {
void f() {
foo();
}
static set foo(int x) {}
}
extension E on C {
int foo() => 1;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_METHOD, 27, 3),
]);
}
test_extensionMethodShadowingTopLevelSetter() async {
await assertErrorsInCode('''
class C {
void f() {
foo();
}
}
extension E on C {
int foo() => 1;
}
set foo(int x) {}
''', [
error(CompileTimeErrorCode.UNDEFINED_METHOD, 27, 3),
]);
}
test_functionAlias_notInstantiated() async {
await assertNoErrorsInCode('''
typedef Fn<T> = void Function(T);
@ -152,6 +188,26 @@ class C {
]);
}
test_localSetterShadowingExtensionMethod() async {
await assertErrorsInCode('''
class C {}
extension E1 on C {
int foo(int x) => 1;
}
extension E2 on C {
static set foo(int x) {}
void f() {
foo();
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_METHOD, 123, 3),
]);
}
test_method_undefined() async {
await assertErrorsInCode(r'''
class C {
@ -217,6 +273,22 @@ f() { A?.m(); }
]);
}
test_static_extension_instanceAccess() async {
await assertErrorsInCode('''
class C {}
extension E on C {
static void a() {}
}
f(C c) {
c.a();
}
''', [
error(CompileTimeErrorCode.UNDEFINED_METHOD, 68, 1),
]);
}
test_static_mixinApplication_superConstructorIsFactory() async {
await assertErrorsInCode(r'''
mixin M {}

View file

@ -232,6 +232,49 @@ f(var p) {
]);
}
test_static_extension_instanceAccess() async {
await assertErrorsInCode('''
class C {}
extension E on C {
static set a(int v) {}
}
f(C c) {
c.a = 2;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_SETTER, 72, 1),
]);
assertResolvedNodeText(findNode.assignment('a ='), r'''
AssignmentExpression
leftHandSide: PrefixedIdentifier
prefix: SimpleIdentifier
token: c
staticElement: self::@function::f::@parameter::c
staticType: C
period: .
identifier: SimpleIdentifier
token: a
staticElement: <null>
staticType: null
staticElement: <null>
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 2
parameter: <null>
staticType: int
readElement: <null>
readType: null
writeElement: <null>
writeType: InvalidType
staticElement: <null>
staticType: int
''');
}
test_static_undefined() async {
await assertErrorsInCode(r'''
class A {}

View file

@ -68,37 +68,37 @@ extension E2 on A2 {
void test() {
// The instance setter shadows the global getter
topLevelGetter = topLevelGetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelGetter'.
topLevelGetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelGetter'.
topLevelGetter;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelGetter'.
topLevelGetter = 3;
// The instance setter shadows the global field getter
topLevelField = topLevelField + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelField'.
topLevelField++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelField'.
topLevelField;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelField'.
// The instance setter shadows the global method
topLevelMethod(4);
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] Getter not found: 'topLevelMethod'.
}
}
@ -160,36 +160,36 @@ extension E4 on A4 {
void test() {
// The static setter shadows the global getter
topLevelGetter = topLevelGetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelGetter'.
topLevelGetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelGetter'.
topLevelGetter;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelGetter'.
// The static setter shadows the global field getter
topLevelField = topLevelField + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelField'.
topLevelField++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelField'.
topLevelField;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'topLevelField'.
// The static setter shadows the global method
topLevelMethod(4);
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] Getter not found: 'topLevelMethod'.
}
}
@ -276,22 +276,22 @@ extension E8 on A8 {
void test() {
// The instance setter shadows the other extension's getter
extensionGetter = extensionGetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
extensionGetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
extensionGetter;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
// The instance setter shadows the other extension's method.
extensionMethod(4);
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] Getter not found: 'extensionMethod'.
}
}
@ -306,22 +306,22 @@ class A9 extends A8 {
void test() {
// The instance setter shadows the other extension's getter
extensionGetter = extensionGetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] The getter 'extensionGetter' isn't defined for the class 'A9'.
extensionGetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] The getter 'extensionGetter' isn't defined for the class 'A9'.
extensionGetter;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] The getter 'extensionGetter' isn't defined for the class 'A9'.
// The instance setter shadows the other extension's method.
extensionMethod(4);
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] The method 'extensionMethod' isn't defined for the class 'A9'.
}
}
@ -356,16 +356,16 @@ extension E10 on A10 {
// The static field shadows the other extension's setter
extensionFieldSetter = extensionFieldSetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
// [cfe] Setter not found: 'extensionFieldSetter'.
extensionFieldSetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
// [cfe] Setter not found: 'extensionFieldSetter'.
extensionFieldSetter = 0;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
// [cfe] Setter not found: 'extensionFieldSetter'.
// The static getter shadows the other extensions method
@ -402,16 +402,16 @@ class A11 extends A10 {
// The static field shadows the other extension's setter
extensionFieldSetter = extensionFieldSetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
// [cfe] Setter not found: 'extensionFieldSetter'.
extensionFieldSetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
// [cfe] Setter not found: 'extensionFieldSetter'.
extensionFieldSetter = 0;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
// [cfe] Setter not found: 'extensionFieldSetter'.
// The static getter shadows the other extensions method
@ -437,22 +437,22 @@ extension E12 on A12 {
void test() {
// The static setter shadows the other extension's getter
extensionGetter = extensionGetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
extensionGetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
extensionGetter;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
// The static setter shadows the other extension's method.
extensionMethod(4);
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] Getter not found: 'extensionMethod'.
}
}
@ -467,22 +467,22 @@ class A13 extends A12 {
void test() {
// The static setter shadows the other extension's getter
extensionGetter = extensionGetter + 1;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
extensionGetter++;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
extensionGetter;
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// [cfe] Getter not found: 'extensionGetter'.
// The static setter shadows the other extension's method.
extensionMethod(4);
// ^^
// [analyzer] unspecified
// ^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] Getter not found: 'extensionMethod'.
}
}