[wildcard-variables] More language tests on declarations - classes, enums, extension types.

Bug: https://github.com/dart-lang/sdk/issues/55652
Change-Id: Id1c48c3f6345d13c9c5f88224085a863e30f5aaf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/367985
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
diff --git a/tests/language/wildcard_variables/declarations/class_generic_type_parameter_test.dart b/tests/language/wildcard_variables/declarations/class_generic_type_parameter_test.dart
new file mode 100644
index 0000000..81ca9a6
--- /dev/null
+++ b/tests/language/wildcard_variables/declarations/class_generic_type_parameter_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2024, 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.
+
+// Tests using wildcards in class generic type parameters.
+
+// SharedOptions=--enable-experiment=wildcard-variables
+
+import 'package:expect/expect.dart';
+
+typedef _ = BB;
+
+class AA {}
+
+class BB extends AA {}
+
+class A<T, U extends AA> {}
+
+class B<_, _ extends AA> extends A<_, _> {
+  int foo<_ extends _>([int _ = 2]) => 1;
+}
+
+class C<_, _ extends _> extends A<_, _> {
+  static const int _ = 1;
+}
+
+void main() {
+  var b = B();
+  Expect.equals(1, b.foo());
+  Expect.type<A<BB, BB>>(b);
+  Expect.type<B<Object?, AA>>(b);
+
+  Expect.equals(1, C._);
+  Expect.type<C<dynamic, BB>>(C());
+}
diff --git a/tests/language/wildcard_variables/declarations/class_member_test.dart b/tests/language/wildcard_variables/declarations/class_member_test.dart
new file mode 100644
index 0000000..2875608
--- /dev/null
+++ b/tests/language/wildcard_variables/declarations/class_member_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2024, 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.
+
+// Class methods and getters and setters can still be named `_`.
+
+// SharedOptions=--enable-experiment=wildcard-variables
+
+import 'package:expect/expect.dart';
+
+class A<_> {
+  int _<_ extends num>([int _ = 2]) => 1;
+}
+
+class B {
+  int x = 1;
+
+  int get _ => x;
+  void set _(int y) {
+    x = y;
+  }
+}
+
+void main() {
+  var a = A();
+  Expect.equals(1, a._());
+
+  var b = B();
+  Expect.equals(1, b._);
+  b._ = 2;
+  Expect.equals(2, b._);
+}
diff --git a/tests/language/wildcard_variables/declarations/enum_test.dart b/tests/language/wildcard_variables/declarations/enum_test.dart
new file mode 100644
index 0000000..a57a586
--- /dev/null
+++ b/tests/language/wildcard_variables/declarations/enum_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2024, 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.
+
+// Tests the usage of wildcards in enum constructors and fields.
+
+// SharedOptions=--enable-experiment=wildcard-variables
+
+import 'package:expect/expect.dart';
+
+enum A { _ }
+
+enum B {
+  e(2);
+
+  const B(int _) : _ = 1;
+
+  final int _;
+}
+
+void main() {
+  A._;
+  Expect.equals(1, B.e._);
+}
diff --git a/tests/language/wildcard_variables/declarations/extension_type_test.dart b/tests/language/wildcard_variables/declarations/extension_type_test.dart
new file mode 100644
index 0000000..8558124
--- /dev/null
+++ b/tests/language/wildcard_variables/declarations/extension_type_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2024, 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.
+
+// The representation variable of an extension type can be named `_`, and no
+// formal parameter name is introduced into any scopes.
+
+// SharedOptions=--enable-experiment=wildcard-variables
+
+import 'package:expect/expect.dart';
+
+extension type Id(int _) {
+  operator <(Id other) => _ < other._;
+}
+
+void main() {
+  var id = Id(1);
+  Expect.isTrue(id < Id(2));
+}
diff --git a/tests/language/wildcard_variables/declarations/local_function_error_test.dart b/tests/language/wildcard_variables/declarations/local_function_error_test.dart
new file mode 100644
index 0000000..d78a2fc
--- /dev/null
+++ b/tests/language/wildcard_variables/declarations/local_function_error_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2024, 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.
+
+// A local function declaration named `_` is non-binding and cannot be accessed.
+
+// SharedOptions=--enable-experiment=wildcard-variables
+
+void main() {
+  void _() {}
+  //   ^
+  // [analyzer] unspecified
+
+  /*indent*/ _();
+  //         ^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+}
diff --git a/tests/language/wildcard_variables/declarations/record_type_test.dart b/tests/language/wildcard_variables/declarations/record_type_test.dart
new file mode 100644
index 0000000..3780643
--- /dev/null
+++ b/tests/language/wildcard_variables/declarations/record_type_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2024, 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.
+
+// Allow positional record fields named `_` in record types.
+
+// SharedOptions=--enable-experiment=wildcard-variables
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+typedef R = (String _, String _);
+
+void main() {
+  (int _, int _) record;
+  record = (1, 2);
+  Expect.equals(1, record.$1);
+  Expect.equals(2, record.$2);
+
+  R rType = ('1', '2');
+  Expect.equals('1', rType.$1);
+  Expect.equals('2', rType.$2);
+
+  // Has a named field (which cannot be `_`).
+  (int _, int _, {int x}) recordX;
+  recordX = (1, 2, x: 3);
+  Expect.equals(1, recordX.$1);
+  Expect.equals(2, recordX.$2);
+
+  // In composite types.
+  (int _, int _) functionReturn() => (1, 2);
+  (int _, int _) Function() functionTypeReturn() => functionReturn;
+  (int _, int _) functionArgument((int _, int _) _) => (1, 2);
+  (int _, int _)? nullableType;
+  FutureOr<(int _, int _)> futureOrType = record;
+  List<(int _, int _)> listOfType = [(1, 2)];
+
+  // In type tests, where it promotes.
+
+  // True value that promotion cannot recognize.
+  // Used to prevent promotion from affecting later tests.
+  bool truth() => DateTime.now().millisecondsSinceEpoch > 0; //
+
+  Object? maybeRecord = truth() ? record : "not a record";
+
+  if (truth() && maybeRecord is (int _, int _)) {
+    Expect.equals(1, maybeRecord.$1);
+    Expect.equals(2, maybeRecord.$2);
+  } else {
+    Expect.fail("is check failed");
+  }
+
+  if (truth()) {
+    maybeRecord as (int _, int _);
+    Expect.equals(1, maybeRecord.$1);
+    Expect.equals(2, maybeRecord.$2);
+  }
+
+  if (truth()) {
+    (int _, int _) implicitDowncast = (maybeRecord as dynamic);
+    Expect.equals(1, implicitDowncast.$1);
+    Expect.equals(2, implicitDowncast.$2);
+  }
+
+  try {
+    throw record;
+  } on (int _, int _) catch (onClauseTest) {
+    Expect.equals(1, onClauseTest.$1);
+    Expect.equals(2, onClauseTest.$2);
+  }
+
+  // Type tests in patterns.
+  switch (record as dynamic) {
+    case R(:var $1, :var $2):
+      Expect.equals(1, $1);
+      Expect.equals(2, $2);
+    default:
+      Expect.fail("Not here!");
+  }
+  switch (record as dynamic) {
+    case (int _, int _) pair:
+      {
+        // Occurs as type here, not pattern.
+        Expect.equals(1, pair.$1);
+        Expect.equals(2, pair.$2);
+      }
+    default:
+      Expect.fail("Not here!");
+  }
+}