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>
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index b234142..c43d2d6 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -486,6 +486,7 @@
   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,
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index 9758ede..16f20e9 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -15895,6 +15895,19 @@
 
   /**
    * 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
    * 1: the number of type parameters that were declared
    * 2: the number of type arguments provided
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 1488253..db01b0b 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -91,6 +91,55 @@
     }
   }
 
+  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,
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 36d3095..1acd7b1 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -560,6 +560,7 @@
   @override
   void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     _requiredParametersVerifier.visitEnumConstantDeclaration(node);
+    _typeArgumentsVerifier.checkEnumConstantDeclaration(node);
     super.visitEnumConstantDeclaration(node);
   }
 
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 8682035..3c90ccd 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -13632,6 +13632,13 @@
       }
       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.
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 3fddbed..a98026b 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -776,6 +776,8 @@
     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 @@
     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();
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 3149899..2aea194 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -431,6 +431,35 @@
 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> {}
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_enum_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_enum_test.dart
new file mode 100644
index 0000000..60e12c9
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_enum_test.dart
@@ -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),
+    ]);
+  }
+}