Add diagnostic for undefined getters and setters invoked on an extension override

Change-Id: Ib66f203836e3900e2e151dd3a8b6be1360e12d50
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109319
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Brian Wilkerson
2019-07-17 12:36:16 +00:00
parent 2b3336b51e
commit 6073489539
6 changed files with 151 additions and 10 deletions
+2
View File
@@ -290,7 +290,9 @@ const List<ErrorCode> errorCodeValues = const [
CompileTimeErrorCode.UNDEFINED_CLASS,
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER,
CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER,
CompileTimeErrorCode.URI_DOES_NOT_EXIST,
CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED,
+27 -3
View File
@@ -3115,15 +3115,39 @@ class CompileTimeErrorCode extends ErrorCode {
/**
* Parameters:
* 0: the name of the extension method that is undefined
* 0: the name of the getter that is undefined
* 1: the name of the extension that was explicitly specified
*/
static const CompileTimeErrorCode UNDEFINED_EXTENSION_GETTER =
const CompileTimeErrorCode('UNDEFINED_EXTENSION_GETTER',
"The getter '{0}' isn't defined for the extension '{1}'.",
correction:
"Try correcting the name to the name of an existing getter, or "
"defining a getter named '{0}'.");
/**
* Parameters:
* 0: the name of the method that is undefined
* 1: the name of the extension that was explicitly specified
*/
static const CompileTimeErrorCode UNDEFINED_EXTENSION_METHOD =
const CompileTimeErrorCode('UNDEFINED_EXTENSION_METHOD',
"The extension method '{0}' isn't defined for the extension '{1}'.",
"The method '{0}' isn't defined for the extension '{1}'.",
correction:
"Try correcting the name to the name of an existing method, or "
"defining an extension method named '{0}'.");
"defining a method named '{0}'.");
/**
* Parameters:
* 0: the name of the setter that is undefined
* 1: the name of the extension that was explicitly specified
*/
static const CompileTimeErrorCode UNDEFINED_EXTENSION_SETTER =
const CompileTimeErrorCode('UNDEFINED_EXTENSION_SETTER',
"The setter '{0}' isn't defined for the extension '{1}'.",
correction:
"Try correcting the name to the name of an existing setter, or "
"defining a setter named '{0}'.");
/**
* 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>,
@@ -685,25 +685,31 @@ class ElementResolver extends SimpleAstVisitor<void> {
if (propertyName.inSetterContext()) {
member = element.getSetter(propertyName.name);
if (member == null) {
// TODO(brianwilkerson) Report this error.
throw new UnsupportedError('extension override of missing setter');
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
propertyName,
[propertyName.name, element.name]);
}
if (propertyName.inGetterContext()) {
PropertyAccessorElement getter = element.getGetter(propertyName.name);
if (getter == null) {
// TODO(brianwilkerson) Report this error.
throw new UnsupportedError('extension override of missing getter');
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
propertyName,
[propertyName.name, element.name]);
}
propertyName.auxiliaryElements = AuxiliaryElements(getter, null);
}
} else if (propertyName.inGetterContext()) {
member = element.getGetter(propertyName.name);
if (member == null) {
// TODO(brianwilkerson) Report this error.
throw new UnsupportedError('extension override of missing getter');
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
propertyName,
[propertyName.name, element.name]);
}
}
if (member.isStatic) {
if (member != null && member.isStatic) {
// TODO(brianwilkerson) Report this error.
throw new UnsupportedError('extension override of static member');
}
@@ -185,7 +185,9 @@ import 'type_check_is_not_null_test.dart' as type_check_is_not_null;
import 'type_check_is_null_test.dart' as type_check_is_null;
import 'unchecked_use_of_nullable_value_test.dart'
as unchecked_use_of_nullable_value;
import 'undefined_extension_getter_test.dart' as undefined_extension_getter;
import 'undefined_extension_method_test.dart' as undefined_extension_method;
import 'undefined_extension_setter_test.dart' as undefined_extension_setter;
import 'undefined_getter_test.dart' as undefined_getter;
import 'undefined_hidden_name_test.dart' as undefined_hidden_name;
import 'undefined_identifier_test.dart' as undefined_identifier;
@@ -346,7 +348,9 @@ main() {
type_check_is_not_null.main();
type_check_is_null.main();
unchecked_use_of_nullable_value.main();
undefined_extension_getter.main();
undefined_extension_method.main();
undefined_extension_setter.main();
undefined_getter.main();
undefined_identifier.main();
undefined_hidden_name.main();
@@ -0,0 +1,59 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(UndefinedExtensionGetterTest);
});
}
@reflectiveTest
class UndefinedExtensionGetterTest extends DriverResolutionTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = new FeatureSet.forTesting(
sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
test_defined() {
assertNoErrorsInCode('''
extension E on String {
int get g => 0;
}
f() {
E('a').g;
}
''');
}
test_undefined() {
assertErrorsInCode('''
extension E on String {}
f() {
E('a').g;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 40, 1),
]);
}
test_undefined_withSetter() {
assertErrorsInCode('''
extension E on String {
void set s(int x) {}
}
f() {
E('a').s += 1;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 64, 1),
]);
}
}
@@ -0,0 +1,46 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(UndefinedExtensionSetterTest);
});
}
@reflectiveTest
class UndefinedExtensionSetterTest extends DriverResolutionTest {
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = new FeatureSet.forTesting(
sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
test_defined() {
assertNoErrorsInCode('''
extension E on String {
void set s(int x) {}
}
f() {
E('a').s = 1;
}
''');
}
test_undefined() {
assertErrorsInCode('''
extension E on String {}
f() {
E('a').s = 1;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER, 40, 1),
]);
}
}