[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!");
+ }
+}