error code for ambiguous extension method accesses
Change-Id: I97b0bc8ba32d1cb0ee3b361525f4c161845f1d01 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109463 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
63120303a7
commit
6dfd5766de
@@ -66,6 +66,7 @@ const List<ErrorCode> errorCodeValues = const [
|
||||
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
|
||||
CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
|
||||
CompileTimeErrorCode.AMBIGUOUS_EXPORT,
|
||||
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_METHOD_ACCESS,
|
||||
CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
|
||||
CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER,
|
||||
CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
|
||||
|
||||
@@ -158,13 +158,12 @@ class MethodInvocationResolver {
|
||||
var t1 = e1.extendedType;
|
||||
var t2 = e2.extendedType;
|
||||
|
||||
// todo(pq): broaden platform beyond dart:core
|
||||
if (t2.element.library.isDartCore) {
|
||||
if (t2.element.library.isInSdk) {
|
||||
// 1. T2 is declared in a platform library, and T1 is not
|
||||
if (!t1.element.library.isDartCore) {
|
||||
if (!t1.element.library.isInSdk) {
|
||||
return -1;
|
||||
}
|
||||
} else if (t1.element.library.isDartCore) {
|
||||
} else if (t1.element.library.isInSdk) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -504,7 +503,17 @@ class MethodInvocationResolver {
|
||||
ExtensionElement extension =
|
||||
_chooseMostSpecificExtension(extensions, receiverType);
|
||||
if (extension == null) {
|
||||
// todo(pq): report an error
|
||||
_setDynamicResolution(node);
|
||||
_resolver.errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.AMBIGUOUS_EXTENSION_METHOD_ACCESS,
|
||||
nameNode,
|
||||
[
|
||||
name,
|
||||
extensions[0].name,
|
||||
extensions[1].name,
|
||||
],
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
Element member = extension.getMethod(name) ??
|
||||
extension.getGetter(name) ??
|
||||
|
||||
@@ -142,6 +142,24 @@ class CompileTimeErrorCode extends ErrorCode {
|
||||
correction: "Try removing the export of one of the libraries, or "
|
||||
"explicitly hiding the name in one of the export directives.");
|
||||
|
||||
/**
|
||||
* It is a compile time error if there are two applicable extensions defining
|
||||
* the same member and neither is more specific than the other.
|
||||
*
|
||||
* Parameters:
|
||||
* 0: the name of the member
|
||||
* 1: the name of the first declaring extension
|
||||
* 2: the name of the second declaring extension
|
||||
*/
|
||||
static const CompileTimeErrorCode AMBIGUOUS_EXTENSION_METHOD_ACCESS =
|
||||
const CompileTimeErrorCode(
|
||||
'AMBIGUOUS_EXTENSION_METHOD_ACCESS',
|
||||
"A member named '{0}' is defined in extensions '{1}' and '{2}' and "
|
||||
"neither is more specific.",
|
||||
correction:
|
||||
"Try using an extension override to specify the extension "
|
||||
"you want to to be chosen.");
|
||||
|
||||
/**
|
||||
* No parameters.
|
||||
*/
|
||||
|
||||
@@ -60,10 +60,6 @@ f() {
|
||||
expect(invocation.methodName.staticElement.library.isDartCore, isFalse);
|
||||
}
|
||||
|
||||
test_multi_match_ambiguous() async {
|
||||
// todo(pq): implement
|
||||
}
|
||||
|
||||
test_multipleExtensions() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A {}
|
||||
@@ -87,6 +83,27 @@ f() {
|
||||
''', [StaticTypeWarningCode.UNDEFINED_METHOD]);
|
||||
}
|
||||
|
||||
test_noMostSpecificExtension() async {
|
||||
await assertErrorsInCode('''
|
||||
class A { }
|
||||
|
||||
extension A1_Ext on A {
|
||||
void a() { }
|
||||
}
|
||||
|
||||
extension A2_Ext on A {
|
||||
void a() { }
|
||||
}
|
||||
|
||||
f() {
|
||||
A a = A();
|
||||
a.a();
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.AMBIGUOUS_EXTENSION_METHOD_ACCESS, 120, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_one_match() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class B { }
|
||||
|
||||
Reference in New Issue
Block a user