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:
Konstantin Shcheglov
2022-02-07 21:47:45 +00:00
committed by Commit Bot
parent ef66f47631
commit f15518dffc
8 changed files with 440 additions and 1 deletions
+2
View File
@@ -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,
+20
View File
@@ -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(
+9
View File
@@ -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();