Report INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR instead of INSTANTIATE_ENUM when enhanced-enums.
Change-Id: I634b3e50641b2b696b4d9e164266b43fdc72f137 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231063 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
committed by
Commit Bot
parent
0d5eec26f1
commit
22a8295295
@@ -258,6 +258,7 @@ const List<ErrorCode> errorCodeValues = [
|
||||
CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR,
|
||||
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
|
||||
CompileTimeErrorCode.INVALID_OVERRIDE,
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS,
|
||||
CompileTimeErrorCode.INVALID_SUPER_FORMAL_PARAMETER_LOCATION,
|
||||
CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST,
|
||||
|
||||
@@ -14,6 +14,12 @@ extension ClassElementExtension on ClassElement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ConstructorElementExtension on ConstructorElement {
|
||||
bool get isGenerative {
|
||||
return !isFactory;
|
||||
}
|
||||
}
|
||||
|
||||
extension ElementAnnotationExtensions on ElementAnnotation {
|
||||
static final Map<String, TargetKind> _targetKindsByName = {
|
||||
for (final kind in TargetKind.values) kind.toString(): kind,
|
||||
|
||||
@@ -6568,6 +6568,7 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
||||
// instantiated:
|
||||
//
|
||||
// ```dart
|
||||
// // @dart = 2.16
|
||||
// enum E {a}
|
||||
//
|
||||
// var e = [!E!]();
|
||||
@@ -6579,6 +6580,7 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
||||
// constants defined in the enum:
|
||||
//
|
||||
// ```dart
|
||||
// // @dart = 2.16
|
||||
// enum E {a}
|
||||
//
|
||||
// var e = E.a;
|
||||
@@ -7499,6 +7501,13 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
||||
hasPublishedDocs: true,
|
||||
);
|
||||
|
||||
static const CompileTimeErrorCode
|
||||
INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR = CompileTimeErrorCode(
|
||||
'INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR',
|
||||
"Generative enum constructors can only be used as targets of redirection.",
|
||||
correctionMessage: "Try using a factory constructor, or an enum constant.",
|
||||
);
|
||||
|
||||
/**
|
||||
* No parameters.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@ import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/ast/extensions.dart';
|
||||
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/extensions.dart';
|
||||
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/type_provider.dart';
|
||||
@@ -534,6 +535,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
@override
|
||||
void visitConstructorReference(ConstructorReference node) {
|
||||
_typeArgumentsVerifier.checkConstructorReference(node);
|
||||
_checkForInvalidGenerativeConstructorReference(node.constructorName);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -842,7 +844,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
DartType type = namedType.typeOrThrow;
|
||||
if (type is InterfaceType) {
|
||||
_checkForConstOrNewWithAbstractClass(node, namedType, type);
|
||||
_checkForConstOrNewWithEnum(node, namedType, type);
|
||||
_checkForInvalidGenerativeConstructorReference(constructorName);
|
||||
_checkForConstOrNewWithMixin(node, namedType, type);
|
||||
_requiredParametersVerifier.visitInstanceCreationExpression(node);
|
||||
if (node.isConst) {
|
||||
@@ -2149,21 +2151,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify that the given instance creation [expression] is not being invoked
|
||||
/// on an enum. The [namedType] is the [NamedType] of the [ConstructorName] from
|
||||
/// the [InstanceCreationExpression], this is the AST node that the error is
|
||||
/// attached to. The [type] is the type being constructed with this
|
||||
/// [InstanceCreationExpression].
|
||||
///
|
||||
/// See [CompileTimeErrorCode.INSTANTIATE_ENUM].
|
||||
void _checkForConstOrNewWithEnum(InstanceCreationExpression expression,
|
||||
NamedType namedType, InterfaceType type) {
|
||||
if (type.element.isEnum) {
|
||||
errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.INSTANTIATE_ENUM, namedType);
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify that the given [expression] is not a mixin instantiation.
|
||||
void _checkForConstOrNewWithMixin(InstanceCreationExpression expression,
|
||||
NamedType namedType, InterfaceType type) {
|
||||
@@ -2902,6 +2889,25 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
}
|
||||
}
|
||||
|
||||
void _checkForInvalidGenerativeConstructorReference(ConstructorName node) {
|
||||
var constructorElement = node.staticElement;
|
||||
if (constructorElement != null &&
|
||||
constructorElement.isGenerative &&
|
||||
constructorElement.enclosingElement.isEnum) {
|
||||
if (_currentLibrary.featureSet.isEnabled(Feature.enhanced_enums)) {
|
||||
errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
node,
|
||||
);
|
||||
} else {
|
||||
errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.INSTANTIATE_ENUM,
|
||||
node.type2,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify that if the given [identifier] is part of a constructor
|
||||
/// initializer, then it does not implicitly reference 'this' expression.
|
||||
///
|
||||
|
||||
@@ -5713,6 +5713,7 @@ CompileTimeErrorCode:
|
||||
instantiated:
|
||||
|
||||
```dart
|
||||
// @dart = 2.16
|
||||
enum E {a}
|
||||
|
||||
var e = [!E!]();
|
||||
@@ -5724,6 +5725,7 @@ CompileTimeErrorCode:
|
||||
constants defined in the enum:
|
||||
|
||||
```dart
|
||||
// @dart = 2.16
|
||||
enum E {a}
|
||||
|
||||
var e = E.a;
|
||||
@@ -6504,6 +6506,9 @@ CompileTimeErrorCode:
|
||||
void m2(String s) {}
|
||||
}
|
||||
```
|
||||
INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR:
|
||||
problemMessage: Generative enum constructors can only be used as targets of redirection.
|
||||
correctionMessage: Try using a factory constructor, or an enum constant.
|
||||
INVALID_REFERENCE_TO_THIS:
|
||||
problemMessage: "Invalid reference to 'this' expression."
|
||||
hasPublishedDocs: true
|
||||
|
||||
@@ -440,6 +440,11 @@ mixin WithoutConstructorTearoffsMixin on PubPackageResolutionTest {
|
||||
String? get testPackageLanguageVersion => '2.14';
|
||||
}
|
||||
|
||||
mixin WithoutEnhancedEnumsMixin on PubPackageResolutionTest {
|
||||
@override
|
||||
String? get testPackageLanguageVersion => '2.16';
|
||||
}
|
||||
|
||||
mixin WithoutNullSafetyMixin on PubPackageResolutionTest {
|
||||
@override
|
||||
String? get testPackageLanguageVersion => '2.9';
|
||||
|
||||
@@ -14,7 +14,8 @@ main() {
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class InstantiateEnumTest extends PubPackageResolutionTest {
|
||||
class InstantiateEnumTest extends PubPackageResolutionTest
|
||||
with WithoutEnhancedEnumsMixin {
|
||||
test_const() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E { ONE }
|
||||
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
// 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(InvalidReferenceToGenerativeEnumConstructorTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class InvalidReferenceToGenerativeEnumConstructorTest
|
||||
extends PubPackageResolutionTest {
|
||||
test_factory_named() async {
|
||||
await assertNoErrorsInCode('''
|
||||
enum E {
|
||||
v();
|
||||
|
||||
factory E.named() => v;
|
||||
}
|
||||
|
||||
void f() {
|
||||
E.named;
|
||||
E.named();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_factory_unnamed() async {
|
||||
await assertNoErrorsInCode('''
|
||||
enum E {
|
||||
v.named();
|
||||
|
||||
const E.named();
|
||||
factory E() => v;
|
||||
}
|
||||
|
||||
void f() {
|
||||
E.new;
|
||||
E();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_generative_named_constructorReference() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E {
|
||||
v.named();
|
||||
|
||||
const E.named();
|
||||
}
|
||||
|
||||
void f() {
|
||||
E.named;
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
58,
|
||||
7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_generative_named_instanceCreation_implicitNew() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E {
|
||||
v.named();
|
||||
|
||||
const E.named();
|
||||
}
|
||||
|
||||
void f() {
|
||||
E.named();
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
58,
|
||||
7),
|
||||
]);
|
||||
}
|
||||
|
||||
test_generative_named_redirectingConstructorInvocation() async {
|
||||
await assertNoErrorsInCode('''
|
||||
enum E {
|
||||
v;
|
||||
|
||||
const E() : this.named();
|
||||
const E.named();
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_generative_unnamed_constructorReference() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E {
|
||||
v
|
||||
}
|
||||
|
||||
void f() {
|
||||
E.new;
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
29,
|
||||
5),
|
||||
]);
|
||||
}
|
||||
|
||||
test_generative_unnamed_instanceCreation_explicitConst() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E {
|
||||
v
|
||||
}
|
||||
|
||||
void f() {
|
||||
const E();
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
35,
|
||||
1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_generative_unnamed_instanceCreation_explicitNew() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E {
|
||||
v
|
||||
}
|
||||
|
||||
void f() {
|
||||
new E();
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
33,
|
||||
1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_generative_unnamed_instanceCreation_implicitNew() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E {
|
||||
v
|
||||
}
|
||||
|
||||
void f() {
|
||||
E();
|
||||
}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.INVALID_REFERENCE_TO_GENERATIVE_ENUM_CONSTRUCTOR,
|
||||
29,
|
||||
1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_generative_unnamed_redirectingConstructorInvocation() async {
|
||||
await assertNoErrorsInCode('''
|
||||
enum E {
|
||||
v;
|
||||
|
||||
const E();
|
||||
const E.named() : this();
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
||||
@@ -341,6 +341,8 @@ import 'invalid_override_different_default_values_positional_test.dart'
|
||||
import 'invalid_override_of_non_virtual_member_test.dart'
|
||||
as invalid_override_of_non_virtual_member;
|
||||
import 'invalid_override_test.dart' as invalid_override;
|
||||
import 'invalid_reference_to_generative_enum_constructor_test.dart'
|
||||
as invalid_reference_to_generative_enum_constructor;
|
||||
import 'invalid_reference_to_this_test.dart' as invalid_reference_to_this;
|
||||
import 'invalid_required_named_param_test.dart' as invalid_required_named_param;
|
||||
import 'invalid_required_optional_positional_param_test.dart'
|
||||
@@ -976,6 +978,7 @@ main() {
|
||||
invalid_override_different_default_values_positional.main();
|
||||
invalid_override_of_non_virtual_member.main();
|
||||
invalid_override.main();
|
||||
invalid_reference_to_generative_enum_constructor.main();
|
||||
invalid_reference_to_this.main();
|
||||
invalid_required_named_param.main();
|
||||
invalid_required_optional_positional_param.main();
|
||||
|
||||
@@ -6616,6 +6616,7 @@ The following code produces this diagnostic because the enum `E` is being
|
||||
instantiated:
|
||||
|
||||
{% prettify dart tag=pre+code %}
|
||||
// @dart = 2.16
|
||||
enum E {a}
|
||||
|
||||
var e = [!E!]();
|
||||
@@ -6627,6 +6628,7 @@ If you intend to use an instance of the enum, then reference one of the
|
||||
constants defined in the enum:
|
||||
|
||||
{% prettify dart tag=pre+code %}
|
||||
// @dart = 2.16
|
||||
enum E {a}
|
||||
|
||||
var e = E.a;
|
||||
|
||||
Reference in New Issue
Block a user