diagnostic for static extension member access
Change-Id: I5380fa6240434ff398cdbd7efeae32b11336cf69 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109681 Commit-Queue: Phil Quitslund <pquitslund@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
c6f3d972b8
commit
2faee21edb
@@ -65,6 +65,7 @@ const List<ErrorCode> errorCodeValues = const [
|
||||
CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
|
||||
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
|
||||
CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
|
||||
CompileTimeErrorCode.ACCESS_STATIC_EXTENSION_MEMBER,
|
||||
CompileTimeErrorCode.AMBIGUOUS_EXPORT,
|
||||
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_METHOD_ACCESS,
|
||||
CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
|
||||
|
||||
@@ -299,6 +299,10 @@ class MethodInvocationResolver {
|
||||
return invokeType;
|
||||
}
|
||||
|
||||
/// Ask the type system to instantiate the given type to its bounds.
|
||||
DartType _instantiateToBounds(DartType type) =>
|
||||
_resolver.typeSystem.instantiateToBounds(type);
|
||||
|
||||
bool _isCoreFunction(DartType type) {
|
||||
// TODO(scheglov) Can we optimize this?
|
||||
return type is InterfaceType && type.isDartCoreFunction;
|
||||
@@ -413,6 +417,23 @@ class MethodInvocationResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
void _resolveExtension(MethodInvocation node, ExtensionElement extension,
|
||||
SimpleIdentifier nameNode, String name) {
|
||||
ExecutableElement member = extension.getMethod(name) ??
|
||||
extension.getGetter(name) ??
|
||||
extension.getSetter(name);
|
||||
if (member.isStatic) {
|
||||
_setDynamicResolution(node);
|
||||
_resolver.errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.ACCESS_STATIC_EXTENSION_MEMBER,
|
||||
nameNode,
|
||||
);
|
||||
return;
|
||||
}
|
||||
nameNode.staticElement = member;
|
||||
return;
|
||||
}
|
||||
|
||||
void _resolveExtensionOverride(MethodInvocation node,
|
||||
ExtensionOverride override, SimpleIdentifier nameNode, String name) {
|
||||
ExtensionElement element = override.extensionName.staticElement;
|
||||
@@ -499,12 +520,7 @@ class MethodInvocationResolver {
|
||||
List<ExtensionElement> extensions =
|
||||
_getApplicableExtensions(receiverType, name);
|
||||
if (extensions.length == 1) {
|
||||
var extension = extensions[0];
|
||||
Element member = extension.getMethod(name) ??
|
||||
extension.getGetter(name) ??
|
||||
extension.getSetter(name);
|
||||
nameNode.staticElement = member;
|
||||
return;
|
||||
return _resolveExtension(node, extensions[0], nameNode, name);
|
||||
} else if (extensions.length > 1) {
|
||||
ExtensionElement extension =
|
||||
_chooseMostSpecificExtension(extensions, receiverType);
|
||||
@@ -521,11 +537,7 @@ class MethodInvocationResolver {
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
ExecutableElement member = extension.getMethod(name) ??
|
||||
extension.getGetter(name) ??
|
||||
extension.getSetter(name);
|
||||
nameNode.staticElement = member;
|
||||
return;
|
||||
return _resolveExtension(node, extension, nameNode, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,10 +800,6 @@ class MethodInvocationResolver {
|
||||
_reportInvocationOfNonFunction(node);
|
||||
}
|
||||
|
||||
/// Ask the type system to instantiate the given type to its bounds.
|
||||
DartType _instantiateToBounds(DartType type) =>
|
||||
_resolver.typeSystem.instantiateToBounds(type);
|
||||
|
||||
/// Ask the type system for a subtype check.
|
||||
bool _subtypeOf(DartType type1, DartType type2) =>
|
||||
_resolver.typeSystem.isSubtypeOf(type1, type2);
|
||||
|
||||
@@ -125,6 +125,15 @@ class CompileTimeErrorCode extends ErrorCode {
|
||||
"The private fields of an enum can't be accessed, even within the "
|
||||
"same library.");
|
||||
|
||||
/**
|
||||
* No parameters.
|
||||
*/
|
||||
//todo (pq): refactor to reuse StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER.
|
||||
static const CompileTimeErrorCode ACCESS_STATIC_EXTENSION_MEMBER =
|
||||
const CompileTimeErrorCode('ACCESS_STATIC_EXTENSION_MEMBER',
|
||||
"Static extension members can't be accessed.",
|
||||
correction: "Try removing the static member access.");
|
||||
|
||||
/**
|
||||
* 14.2 Exports: It is a compile-time error if a name <i>N</i> is re-exported
|
||||
* by a library <i>L</i> and <i>N</i> is introduced into the export namespace
|
||||
|
||||
@@ -115,6 +115,23 @@ f() {
|
||||
expect(invocation.methodName.staticElement, declaration.declaredElement);
|
||||
}
|
||||
|
||||
test_method_resolvesToStatic() async {
|
||||
await assertErrorsInCode('''
|
||||
class A { }
|
||||
|
||||
extension A1_Ext on A {
|
||||
static void a() { }
|
||||
}
|
||||
|
||||
f() {
|
||||
A a = A();
|
||||
a.a();
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ACCESS_STATIC_EXTENSION_MEMBER, 85, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_method_specificSubtypeMatchLocal() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A { }
|
||||
|
||||
Reference in New Issue
Block a user