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:
pq
2019-07-19 16:57:23 +00:00
committed by commit-bot@chromium.org
parent c6f3d972b8
commit 2faee21edb
4 changed files with 50 additions and 15 deletions
+1
View File
@@ -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);
+9
View File
@@ -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 { }