Report WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM and TYPE_ARGUMENT_NOT_MATCHING_BOUNDS for enums.
Change-Id: Icac828fa09d7565974727521c27b5cd4daa7e0f4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232089 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
committed by
Commit Bot
parent
10bcd86677
commit
d8e2cdaeec
@@ -486,6 +486,7 @@ const List<ErrorCode> errorCodeValues = [
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM,
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION,
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD,
|
||||
|
||||
@@ -15893,6 +15893,19 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
||||
hasPublishedDocs: true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Parameters:
|
||||
* 0: the number of type parameters that were declared
|
||||
* 1: the number of type arguments provided
|
||||
*/
|
||||
static const CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM =
|
||||
CompileTimeErrorCode(
|
||||
'WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM',
|
||||
"The enum is declared with {0} type parameters, but {1} type arguments "
|
||||
"were given.",
|
||||
correctionMessage: "Try adjusting the number of type arguments.",
|
||||
);
|
||||
|
||||
/**
|
||||
* Parameters:
|
||||
* 0: the name of the extension being referenced
|
||||
|
||||
@@ -91,6 +91,55 @@ class TypeArgumentsVerifier {
|
||||
}
|
||||
}
|
||||
|
||||
void checkEnumConstantDeclaration(EnumConstantDeclaration node) {
|
||||
var constructorElement = node.constructorElement;
|
||||
if (constructorElement == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var enumElement = constructorElement.enclosingElement;
|
||||
var typeParameters = enumElement.typeParameters;
|
||||
|
||||
var typeArgumentList = node.arguments?.typeArguments;
|
||||
var typeArgumentNodes = typeArgumentList?.arguments;
|
||||
if (typeArgumentList != null &&
|
||||
typeArgumentNodes != null &&
|
||||
typeArgumentNodes.length != typeParameters.length) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM,
|
||||
typeArgumentList,
|
||||
[typeParameters.length, typeArgumentNodes.length],
|
||||
);
|
||||
}
|
||||
|
||||
if (typeParameters.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that type arguments are regular-bounded.
|
||||
var typeArguments = constructorElement.returnType.typeArguments;
|
||||
var substitution = Substitution.fromPairs(typeParameters, typeArguments);
|
||||
for (var i = 0; i < typeArguments.length; i++) {
|
||||
var typeParameter = typeParameters[i];
|
||||
var typeArgument = typeArguments[i];
|
||||
|
||||
var bound = typeParameter.bound;
|
||||
if (bound == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bound = substitution.substituteType(bound);
|
||||
|
||||
if (!_typeSystem.isSubtypeOf(typeArgument, bound)) {
|
||||
_errorReporter.reportErrorForNode(
|
||||
CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
|
||||
typeArgumentNodes?[i] ?? node.name,
|
||||
[typeArgument, typeParameter.name, bound],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkFunctionExpressionInvocation(FunctionExpressionInvocation node) {
|
||||
_checkInvocationTypeArguments(
|
||||
node.typeArguments?.arguments,
|
||||
|
||||
@@ -560,6 +560,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
||||
@override
|
||||
void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
|
||||
_requiredParametersVerifier.visitEnumConstantDeclaration(node);
|
||||
_typeArgumentsVerifier.checkEnumConstantDeclaration(node);
|
||||
super.visitEnumConstantDeclaration(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -13632,6 +13632,13 @@ CompileTimeErrorCode:
|
||||
}
|
||||
C f() => C.named();
|
||||
```
|
||||
WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM:
|
||||
problemMessage: The enum is declared with {0} type parameters, but {1} type arguments were given.
|
||||
correctionMessage: Try adjusting the number of type arguments.
|
||||
comment: |-
|
||||
Parameters:
|
||||
0: the number of type parameters that were declared
|
||||
1: the number of type arguments provided
|
||||
WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION:
|
||||
problemMessage: "The extension '{0}' is declared with {1} type parameters, but {2} type arguments were given."
|
||||
correctionMessage: Try adjusting the number of type arguments.
|
||||
|
||||
@@ -776,6 +776,8 @@ import 'wrong_number_of_parameters_for_operator_test.dart'
|
||||
as wrong_number_of_parameters_for_operator;
|
||||
import 'wrong_number_of_parameters_for_setter_test.dart'
|
||||
as wrong_number_of_parameters_for_setter;
|
||||
import 'wrong_number_of_type_arguments_enum_test.dart'
|
||||
as wrong_number_of_type_arguments_enum;
|
||||
import 'wrong_number_of_type_arguments_extension_test.dart'
|
||||
as wrong_number_of_type_arguments_extension;
|
||||
import 'wrong_number_of_type_arguments_test.dart'
|
||||
@@ -1306,6 +1308,7 @@ main() {
|
||||
void_with_type_arguments_test.main();
|
||||
wrong_number_of_parameters_for_operator.main();
|
||||
wrong_number_of_parameters_for_setter.main();
|
||||
wrong_number_of_type_arguments_enum.main();
|
||||
wrong_number_of_type_arguments_extension.main();
|
||||
wrong_number_of_type_arguments.main();
|
||||
wrong_type_parameter_variance_in_superinterface.main();
|
||||
|
||||
@@ -431,6 +431,35 @@ class C extends Object with G<B>{}
|
||||
class TypeArgumentNotMatchingBoundsWithNullSafetyTest
|
||||
extends PubPackageResolutionTest
|
||||
with TypeArgumentNotMatchingBoundsTestCases {
|
||||
test_enum_inferred() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E<T extends int> {
|
||||
v('');
|
||||
const E(T t);
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 26, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_enum_superBounded() async {
|
||||
await assertNoErrorsInCode('''
|
||||
enum E<T extends E<T>> {
|
||||
v<Never>()
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_withTypeArguments() async {
|
||||
await assertErrorsInCode('''
|
||||
enum E<T extends int> {
|
||||
v<String>()
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 28, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
test_extends_optIn_fromOptOut_Null() async {
|
||||
newFile('$testPackageLibPath/a.dart', content: r'''
|
||||
class A<X extends int> {}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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(WrongNumberOfTypeArgumentsEnumTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class WrongNumberOfTypeArgumentsEnumTest extends PubPackageResolutionTest {
|
||||
test_tooFew() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E<T, U> {
|
||||
v<int>()
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM, 18, 5),
|
||||
]);
|
||||
}
|
||||
|
||||
test_tooMany() async {
|
||||
await assertErrorsInCode(r'''
|
||||
enum E<T> {
|
||||
v<int, int>()
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ENUM, 15, 10),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user