Fix reporting of INSTANCE_ACCESS_TO_STATIC_MEMBER from within an extension.
Previously, if a piece of code inside an extension tried erroneously
to refer to a static class member using instance access, the error
CompileTimeError.UNQUALIFIED_ACCESS_TO_STATIC_MEMBER_OF_EXTENDED_TYPE
would be reported. This change corrects the error to
CompileTimeError.INSTANCE_ACCESS_TO_STATIC_MEMBER.
In addition, the responsibility to report the error
CompileTimeError.INSTANCE_ACCESS_TO_STATIC_MEMBER is shifted fully to
the resolver (previously, it was split between the resolver and the
error verifier).
Change-Id: Idcd1a3b8a1e226fed692900838c3d2d3c0585d4f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/217020
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@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 6ec3f7e..386da13 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -149,19 +149,21 @@
required bool implicitReceiver,
}) {
var enclosingElement = element.enclosingElement;
- if (_resolver.enclosingExtension != null) {
- _resolver.errorReporter.reportErrorForNode(
- CompileTimeErrorCode
- .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
- nameNode,
- [enclosingElement.displayName],
- );
- } else if (implicitReceiver) {
- _resolver.errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
- nameNode,
- [enclosingElement.displayName],
- );
+ if (implicitReceiver) {
+ if (_resolver.enclosingExtension != null) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode
+ .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+ nameNode,
+ [enclosingElement.displayName],
+ );
+ } else {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+ nameNode,
+ [enclosingElement.displayName],
+ );
+ }
} else {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 3d1d725..e75d2be 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -219,19 +219,21 @@
bool nullReceiver,
) {
var enclosingElement = element.enclosingElement;
- if (_resolver.enclosingExtension != null) {
- _resolver.errorReporter.reportErrorForNode(
- CompileTimeErrorCode
- .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
- nameNode,
- [enclosingElement.displayName],
- );
- } else if (nullReceiver) {
- _resolver.errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
- nameNode,
- [enclosingElement.displayName],
- );
+ if (nullReceiver) {
+ if (_resolver.enclosingExtension != null) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode
+ .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+ nameNode,
+ [enclosingElement.displayName],
+ );
+ } else {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+ nameNode,
+ [enclosingElement.displayName],
+ );
+ }
} else {
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index e8f3c35..787d963 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -248,18 +248,6 @@
);
}
- void _checkExtensionOverrideStaticMember(
- SimpleIdentifier propertyName,
- ExecutableElement? element,
- ) {
- if (element != null && element.isStatic) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
- propertyName,
- );
- }
- }
-
/// If the [element] is not static, report the error on the [identifier].
void _checkForStaticAccessToInstanceMember(
SimpleIdentifier identifier,
@@ -274,6 +262,33 @@
);
}
+ void _checkForStaticMember(
+ Expression target,
+ SimpleIdentifier propertyName,
+ ExecutableElement? element,
+ ) {
+ if (element != null && element.isStatic) {
+ if (target is ExtensionOverride) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+ propertyName,
+ );
+ } else {
+ var enclosingElement = element.enclosingElement;
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+ propertyName, [
+ propertyName,
+ element.kind.displayName,
+ enclosingElement.name ?? '<unnamed>',
+ enclosingElement is ClassElement && enclosingElement.isMixin
+ ? 'mixin'
+ : enclosingElement.kind.displayName,
+ ]);
+ }
+ }
+ }
+
DartType? _computeIndexContextType({
required ExecutableElement? readElement,
required ExecutableElement? writeElement,
@@ -417,21 +432,27 @@
result.getter,
result.getter?.returnType ?? _typeSystem.typeProvider.dynamicType);
- if (hasRead && result.needsGetterError) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_GETTER,
- propertyName,
- [propertyName.name, targetType],
- );
+ if (hasRead) {
+ _checkForStaticMember(target, propertyName, result.getter);
+ if (result.needsGetterError) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_GETTER,
+ propertyName,
+ [propertyName.name, targetType],
+ );
+ }
}
- if (hasWrite && result.needsSetterError) {
- AssignmentVerifier(_definingLibrary, _errorReporter).verify(
- node: propertyName,
- requested: null,
- recovery: result.getter,
- receiverTypeObject: targetType,
- );
+ if (hasWrite) {
+ _checkForStaticMember(target, propertyName, result.setter);
+ if (result.needsSetterError) {
+ AssignmentVerifier(_definingLibrary, _errorReporter).verify(
+ node: propertyName,
+ requested: null,
+ recovery: result.getter,
+ receiverTypeObject: targetType,
+ );
+ }
}
return PropertyElementResolverResult(
@@ -591,7 +612,7 @@
[memberName, element.name],
);
}
- _checkExtensionOverrideStaticMember(propertyName, readElement);
+ _checkForStaticMember(target, propertyName, readElement);
}
ExecutableElement? writeElement;
@@ -604,7 +625,7 @@
[memberName, element.name],
);
}
- _checkExtensionOverrideStaticMember(propertyName, writeElement);
+ _checkForStaticMember(target, propertyName, writeElement);
}
return PropertyElementResolverResult(
@@ -670,6 +691,7 @@
if (readElement != null) {
readElement = _resolver.toLegacyElement(readElement);
+ _checkForStaticMember(target, propertyName, readElement);
} else {
// We were not able to find the concrete dispatch target.
// But we would like to give the user at least some resolution.
@@ -708,6 +730,7 @@
if (writeElement != null) {
writeElement = _resolver.toLegacyElement(writeElement);
+ _checkForStaticMember(target, propertyName, writeElement);
} else {
// We were not able to find the concrete dispatch target.
// But we would like to give the user at least some resolution.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index a4f8ff7..2b6b30d 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2658,15 +2658,6 @@
return;
}
}
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, name, [
- name.name,
- _getKind(element),
- enclosingElement.name ?? '<unnamed>',
- enclosingElement is ClassElement && enclosingElement.isMixin
- ? 'mixin'
- : enclosingElement.kind.displayName
- ]);
}
}
@@ -4856,30 +4847,6 @@
return null;
}
- /// Return a human-readable representation of the kind of the [element].
- String _getKind(ExecutableElement element) {
- if (element is MethodElement) {
- return 'method';
- } else if (element is PropertyAccessorElement) {
- if (element.isSynthetic) {
- PropertyInducingElement variable = element.variable;
- if (variable is FieldElement) {
- return 'field';
- }
- return 'variable';
- } else if (element.isGetter) {
- return 'getter';
- } else {
- return 'setter';
- }
- } else if (element is ConstructorElement) {
- return 'constructor';
- } else if (element is FunctionElement) {
- return 'function';
- }
- return 'member';
- }
-
/// Return the name of the library that defines given [element].
String _getLibraryName(Element? element) {
if (element == null) {
diff --git a/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart b/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
index 470dbc7..1142a36 100644
--- a/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
@@ -98,6 +98,25 @@
);
}
+ test_extension_referring_to_class_member() async {
+ await assertErrorsInCode('''
+class C {
+ static void m() {}
+}
+extension on int {
+ foo(C c) {
+ c.m(); // ERROR
+ }
+}
+test(int i) {
+ i.foo(C());
+}
+''', [
+ error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 71, 1,
+ correctionContains: "class 'C'"),
+ ]);
+ }
+
test_extension_setter() async {
await assertErrorsInCode('''
class C {}
diff --git a/tests/language/getter/no_setter_test.dart b/tests/language/getter/no_setter_test.dart
index 260b5fc..6fa7014 100644
--- a/tests/language/getter/no_setter_test.dart
+++ b/tests/language/getter/no_setter_test.dart
@@ -15,7 +15,6 @@
// [cfe] Setter not found: 'nextVar'.
this.nextVar = 1;
// ^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.INSTANCE_ACCESS_TO_STATIC_MEMBER
// [cfe] The setter 'nextVar' isn't defined for the class 'Example'.
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_NO_SETTER
@@ -30,8 +29,6 @@
// [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_THIS
// [cfe] Expected identifier, but got 'this'.
// ^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.INSTANCE_ACCESS_TO_STATIC_MEMBER
-// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_NO_SETTER
}
}
diff --git a/tests/language_2/getter/no_setter_test.dart b/tests/language_2/getter/no_setter_test.dart
index 02bc833..9690f56 100644
--- a/tests/language_2/getter/no_setter_test.dart
+++ b/tests/language_2/getter/no_setter_test.dart
@@ -17,7 +17,6 @@
// [cfe] Setter not found: 'nextVar'.
this.nextVar = 1;
// ^^^^^^^
- // [analyzer] COMPILE_TIME_ERROR.INSTANCE_ACCESS_TO_STATIC_MEMBER
// [cfe] The setter 'nextVar' isn't defined for the class 'Example'.
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_NO_SETTER
@@ -32,8 +31,6 @@
// [analyzer] COMPILE_TIME_ERROR.INVALID_REFERENCE_TO_THIS
// [cfe] Expected identifier, but got 'this'.
// ^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.INSTANCE_ACCESS_TO_STATIC_MEMBER
-// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_NO_SETTER
}
}