Report ILLEGAL_ENUM_VALUES_DECLARATION/INHERITANCE
Change-Id: I31a02b7c0fe50362ed6d9cb66159db3386f3b56e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232020 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
committed by
Commit Bot
parent
ef66f47631
commit
f15518dffc
@@ -212,6 +212,8 @@ const List<ErrorCode> errorCodeValues = [
|
||||
CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
|
||||
CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
|
||||
CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE,
|
||||
CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION,
|
||||
CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE,
|
||||
CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
|
||||
CompileTimeErrorCode.ILLEGAL_NON_ABSTRACT_ENUM_INDEX,
|
||||
CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
|
||||
|
||||
@@ -5737,6 +5737,26 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
||||
hasPublishedDocs: true,
|
||||
);
|
||||
|
||||
static const CompileTimeErrorCode ILLEGAL_ENUM_VALUES_DECLARATION =
|
||||
CompileTimeErrorCode(
|
||||
'ILLEGAL_ENUM_VALUES_DECLARATION',
|
||||
"An instance member named 'values' can't be declared in a class that "
|
||||
"implements 'Enum'.",
|
||||
correctionMessage: "Try using a different name.",
|
||||
);
|
||||
|
||||
/**
|
||||
* Parameters:
|
||||
* 0: the name of the class that declares 'values'
|
||||
*/
|
||||
static const CompileTimeErrorCode ILLEGAL_ENUM_VALUES_INHERITANCE =
|
||||
CompileTimeErrorCode(
|
||||
'ILLEGAL_ENUM_VALUES_INHERITANCE',
|
||||
"An instance member named 'values' can't be inherited from '{0}' in a "
|
||||
"class that implements 'Enum'.",
|
||||
correctionMessage: "Try using a different name.",
|
||||
);
|
||||
|
||||
static const CompileTimeErrorCode ILLEGAL_LANGUAGE_VERSION_OVERRIDE =
|
||||
CompileTimeErrorCode(
|
||||
'ILLEGAL_LANGUAGE_VERSION_OVERRIDE',
|
||||
|
||||
@@ -107,7 +107,7 @@ class DuplicateDefinitionVerifier {
|
||||
var baseName = accessor.displayName;
|
||||
if (accessor.isStatic) {
|
||||
var instance = _getInterfaceMember(enumElement, baseName);
|
||||
if (instance != null) {
|
||||
if (instance != null && baseName != 'values') {
|
||||
_errorReporter.reportErrorForElement(
|
||||
CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
|
||||
accessor,
|
||||
|
||||
@@ -199,6 +199,7 @@ class _ClassVerifier {
|
||||
_checkDeclaredMember(field.name, libraryUri, fieldElement.setter);
|
||||
if (!member.isStatic) {
|
||||
_checkIllegalNonAbstractEnumIndex(field.name);
|
||||
_checkIllegalEnumValuesDeclaration(field.name);
|
||||
}
|
||||
}
|
||||
} else if (member is MethodDeclaration) {
|
||||
@@ -209,12 +210,17 @@ class _ClassVerifier {
|
||||
|
||||
_checkDeclaredMember(member.name, libraryUri, member.declaredElement,
|
||||
methodParameterNodes: member.parameters?.parameters);
|
||||
if (!member.isStatic) {
|
||||
_checkIllegalEnumValuesDeclaration(member.name);
|
||||
}
|
||||
if (!(member.isStatic || member.isAbstract || member.isSetter)) {
|
||||
_checkIllegalNonAbstractEnumIndex(member.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_checkIllegalEnumValuesInheritance();
|
||||
|
||||
GetterSetterTypesVerifier(
|
||||
typeSystem: typeSystem,
|
||||
errorReporter: reporter,
|
||||
@@ -625,6 +631,36 @@ class _ClassVerifier {
|
||||
return false;
|
||||
}
|
||||
|
||||
void _checkIllegalEnumValuesDeclaration(SimpleIdentifier name) {
|
||||
if (implementsDartCoreEnum && name.name == 'values') {
|
||||
reporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION,
|
||||
name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _checkIllegalEnumValuesInheritance() {
|
||||
if (implementsDartCoreEnum) {
|
||||
var getter = inheritance.getInherited2(
|
||||
classElement,
|
||||
Name(libraryUri, 'values'),
|
||||
);
|
||||
var setter = inheritance.getInherited2(
|
||||
classElement,
|
||||
Name(libraryUri, 'values='),
|
||||
);
|
||||
var inherited = getter ?? setter;
|
||||
if (inherited != null) {
|
||||
reporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE,
|
||||
classNameNode,
|
||||
[inherited.enclosingElement.name!],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _checkIllegalNonAbstractEnumIndex(SimpleIdentifier name) {
|
||||
if (implementsDartCoreEnum && name.name == 'index') {
|
||||
reporter.reportErrorForNode(
|
||||
|
||||
@@ -5018,6 +5018,15 @@ CompileTimeErrorCode:
|
||||
```dart
|
||||
int f() => 0;
|
||||
```
|
||||
ILLEGAL_ENUM_VALUES_DECLARATION:
|
||||
problemMessage: An instance member named 'values' can't be declared in a class that implements 'Enum'.
|
||||
correctionMessage: Try using a different name.
|
||||
ILLEGAL_ENUM_VALUES_INHERITANCE:
|
||||
problemMessage: An instance member named 'values' can't be inherited from '{0}' in a class that implements 'Enum'.
|
||||
correctionMessage: Try using a different name.
|
||||
comment: |-
|
||||
Parameters:
|
||||
0: the name of the class that declares 'values'
|
||||
ILLEGAL_LANGUAGE_VERSION_OVERRIDE:
|
||||
problemMessage: The language version must be {0}.
|
||||
correctionMessage: Try removing the language version override and migrating the code.
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
// Copyright (c) 2022, 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/src/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(IllegalEnumValuesDeclarationTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class IllegalEnumValuesDeclarationTest extends PubPackageResolutionTest {
|
||||
test_class_field() async {
|
||||
await assertErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
int values = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 41, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_field_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
static int values = 0;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_getter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
int get values => 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 45, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_getter_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
static int get values => 0;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_method() async {
|
||||
await assertErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
void values() {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 42, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_method_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
static void values() {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_setter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
set values(int _) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 41, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_setter_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A implements Enum {
|
||||
static set values(int _) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_field() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E {
|
||||
v;
|
||||
int values = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 20, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
/// TODO(scheglov) this is wrong, we should get an error
|
||||
test_enum_field_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
enum E {
|
||||
v;
|
||||
static int values = 0;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_getter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E {
|
||||
v;
|
||||
int get values => 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 24, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_enum_method() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E {
|
||||
v;
|
||||
void values() {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 21, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_enum_setter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E {
|
||||
v;
|
||||
set values(int _) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 20, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_field() async {
|
||||
await assertErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
int values = 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 24, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_field_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
static int values = 0;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_mixin_getter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
int get values => 0;
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 28, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_getter_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
static int get values => 0;
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_mixin_method() async {
|
||||
await assertErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
void values() {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 25, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_method_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
static void values() {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_mixin_setter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
set values(int _) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_DECLARATION, 24, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_setter_static() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
mixin M on Enum {
|
||||
static set values(int _) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2022, 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/src/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(IllegalEnumValuesInheritanceTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class IllegalEnumValuesInheritanceTest extends PubPackageResolutionTest {
|
||||
test_class_field_fromExtends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
int values = 0;
|
||||
}
|
||||
|
||||
abstract class B extends A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 46, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_field_fromImplements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
int values = 0;
|
||||
}
|
||||
|
||||
abstract class B implements A, Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 46, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_field_fromWith() async {
|
||||
await assertErrorsInCode(r'''
|
||||
mixin M {
|
||||
int values = 0;
|
||||
}
|
||||
|
||||
abstract class B with M implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 46, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_getter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
int get values => 0;
|
||||
}
|
||||
|
||||
abstract class B extends A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 51, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_method() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
void values() {}
|
||||
}
|
||||
|
||||
abstract class B extends A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 47, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_setter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
set values(int _) {}
|
||||
}
|
||||
|
||||
abstract class B extends A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 51, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_enum_method() async {
|
||||
await assertErrorsInCode(r'''
|
||||
mixin M {
|
||||
int values() => 0;
|
||||
}
|
||||
|
||||
enum E with M {
|
||||
v
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 39, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_field() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
int values = 0;
|
||||
}
|
||||
|
||||
mixin M on A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 37, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_getter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
int get values => 0;
|
||||
}
|
||||
|
||||
mixin M on A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 42, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_method() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
int values() => 0;
|
||||
}
|
||||
|
||||
mixin M on A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 40, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_setter() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
set values(int _) {}
|
||||
}
|
||||
|
||||
mixin M on A implements Enum {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.ILLEGAL_ENUM_VALUES_INHERITANCE, 42, 1),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -253,6 +253,10 @@ import 'if_element_condition_from_deferred_library_test.dart'
|
||||
import 'illegal_async_generator_return_type_test.dart'
|
||||
as illegal_async_generator_return_type;
|
||||
import 'illegal_async_return_type_test.dart' as illegal_async_return_type;
|
||||
import 'illegal_enum_values_declaration_test.dart'
|
||||
as illegal_enum_values_declaration;
|
||||
import 'illegal_enum_values_inheritance_test.dart'
|
||||
as illegal_enum_values_inheritance;
|
||||
import 'illegal_language_version_override_test.dart'
|
||||
as illegal_language_version_override;
|
||||
import 'illegal_non_abstract_enum_index_test.dart'
|
||||
@@ -945,6 +949,8 @@ main() {
|
||||
if_element_condition_from_deferred_library.main();
|
||||
illegal_async_generator_return_type.main();
|
||||
illegal_async_return_type.main();
|
||||
illegal_enum_values_declaration.main();
|
||||
illegal_enum_values_inheritance.main();
|
||||
illegal_language_version_override.main();
|
||||
illegal_non_abstract_enum_index.main();
|
||||
illegal_sync_generator_return_type.main();
|
||||
|
||||
Reference in New Issue
Block a user