Version 2.16.0-160.0.dev

Merge commit '0a8298d14c96cfd82cd391dc68a10ad77e5ff352' into 'dev'
diff --git a/tests/language/enum/enhanced_enums_basic_test.dart b/tests/language/enum/enhanced_enums_basic_test.dart
new file mode 100644
index 0000000..ee3a0e0
--- /dev/null
+++ b/tests/language/enum/enhanced_enums_basic_test.dart
@@ -0,0 +1,370 @@
+// Copyright (c) 2021, 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.
+
+// SharedOptions=--enable-experiment=enhanced-enums
+
+// Test new enhanced enum syntax.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  Expect.equals(3, EnumPlain.values.length);
+  Expect.identical(EnumPlain.v1, EnumPlain.values[0]);
+  Expect.identical(EnumPlain.v2, EnumPlain.values[1]);
+  Expect.identical(EnumPlain.v3, EnumPlain.values[2]);
+
+  Expect.equals(3, EnumPlainTrailingComma.values.length);
+  Expect.identical(EnumPlainTrailingComma.v1, EnumPlainTrailingComma.values[0]);
+  Expect.identical(EnumPlainTrailingComma.v2, EnumPlainTrailingComma.values[1]);
+  Expect.identical(EnumPlainTrailingComma.v3, EnumPlainTrailingComma.values[2]);
+
+  Expect.equals(3, EnumPlainNoSemicolon.values.length);
+  Expect.identical(EnumPlainNoSemicolon.v1, EnumPlainNoSemicolon.values[0]);
+  Expect.identical(EnumPlainNoSemicolon.v2, EnumPlainNoSemicolon.values[1]);
+  Expect.identical(EnumPlainNoSemicolon.v3, EnumPlainNoSemicolon.values[2]);
+  Expect.type<EnumNoSemicolon<num>>(EnumNoSemicolon.v1);
+
+  Expect.equals(3, EnumPlainSemicolon.values.length);
+  Expect.identical(EnumPlainSemicolon.v1, EnumPlainSemicolon.values[0]);
+  Expect.identical(EnumPlainSemicolon.v2, EnumPlainSemicolon.values[1]);
+  Expect.identical(EnumPlainSemicolon.v3, EnumPlainSemicolon.values[2]);
+
+  Expect.equals(3, EnumPlainTrailingCommaSemicolon.values.length);
+  Expect.identical(EnumPlainTrailingCommaSemicolon.v1,
+      EnumPlainTrailingCommaSemicolon.values[0]);
+  Expect.identical(EnumPlainTrailingCommaSemicolon.v2,
+      EnumPlainTrailingCommaSemicolon.values[1]);
+  Expect.identical(EnumPlainTrailingCommaSemicolon.v3,
+      EnumPlainTrailingCommaSemicolon.values[2]);
+
+  Expect.equals(6, EnumAll.values.length);
+  Expect.identical(EnumAll.v1, EnumAll.values[0]);
+  Expect.identical(EnumAll.v2, EnumAll.values[1]);
+  Expect.identical(EnumAll.v3, EnumAll.values[2]);
+  Expect.identical(EnumAll.v4, EnumAll.values[3]);
+  Expect.identical(EnumAll.v5, EnumAll.values[4]);
+  Expect.identical(EnumAll.v6, EnumAll.values[5]);
+
+  Expect.equals("unnamed", EnumAll.v1.constructor);
+  Expect.equals("unnamed", EnumAll.v2.constructor);
+  Expect.equals("unnamed", EnumAll.v3.constructor);
+  Expect.equals("named", EnumAll.v4.constructor);
+  Expect.equals("renamed", EnumAll.v5.constructor);
+  Expect.equals("unnamed", EnumAll.v6.constructor);
+
+  Expect.type<EnumAll<num, num>>(EnumAll.v1);
+  Expect.type<EnumAll<num, int>>(EnumAll.v2);
+  Expect.type<EnumAll<int, int>>(EnumAll.v3);
+  Expect.type<EnumAll<int, int>>(EnumAll.v4);
+  Expect.type<EnumAll<int, int>>(EnumAll.v5);
+  Expect.type<EnumAll<num, num>>(EnumAll.v6);
+
+  // Access static members.
+  Expect.identical(EnumAll.v3, EnumAll.sConst);
+  Expect.identical(EnumAll.v3, EnumAll.sFinal);
+
+  Expect.throws(() => EnumAll.sLateFinal);
+  EnumAll.sLateFinal = EnumAll.v1;
+  Expect.identical(EnumAll.v1, EnumAll.sLateFinal);
+  Expect.throws(() => EnumAll.sLateFinal = EnumAll.v1);
+
+  Expect.identical(EnumAll.v3, EnumAll.sFinalInit);
+
+  Expect.throws(() => EnumAll.sLate);
+  EnumAll.sLate = EnumAll.v1;
+  Expect.identical(EnumAll.v1, EnumAll.sLate);
+  EnumAll.sLate = EnumAll.v3;
+  Expect.identical(EnumAll.v3, EnumAll.sLate);
+  Expect.identical(EnumAll.v3, EnumAll.sLateVarInit);
+  Expect.isNull(EnumAll.sVar);
+  Expect.identical(EnumAll.v3, EnumAll.sVarInit);
+
+  Expect.identical(EnumAll.v3, EnumAll.staticGetSet);
+  EnumAll.staticGetSet = EnumAll.v5;
+  Expect.equals(42, EnumAll.staticMethod());
+
+  Expect.identical(EnumAll.v2, EnumAll<num, num>.factory(2));
+  Expect.identical(EnumAll.v2, EnumAll<num, num>.refactory(2));
+
+  // Access static members through typedef.
+  Expect.identical(EnumAll.v3, TypeDefAll.sConst);
+  Expect.identical(EnumAll.v3, TypeDefAll.sFinal);
+  Expect.identical(EnumAll.v1, TypedefAll.sLateFinal);
+  Expect.identical(EnumAll.v3, TypedefAll.sFinalInit);
+
+  Expect.identical(EnumAll.v3, TypeDefAll.staticGetSet);
+  TypeDefAll.staticGetSet = EnumAll.v5;
+  Expect.equals(42, TypeDefAll.staticMethod());
+
+  Expect.identical(EnumAll.v2, TypeDefAll.factory(2));
+  Expect.identical(EnumAll.v2, TypeDefAll.refactory(2));
+
+  // Access instance members.
+  Expect.equals(0, EnumAll.v1.instanceGetSet);
+  EnumAll.v1.instanceGetSet = 0.5;
+  Expect.equals(0, EnumAll.v1.instanceMethod());
+  Expect.identical(EnumAll.v1, EnumAll.v3 ^ EnumAll.v2);
+
+  Expect.equals("EnumAll.v1:EnumMixin<num>:ObjectMixin:this",
+      EnumAll.v1.thisAndSuper());
+
+  // Which can reference type parameters.
+  Expect.isTrue(EnumAll.v2.test(2)); // does `is T` with `T` being `int`.
+  Expect.isFalse(EnumAll.v2.test(2.5));
+
+  // Including `call`.
+  Expect.equals(42, EnumAll.v1<int>(42));
+  Expect.equals(42, EnumAll.v1(42));
+  // Also as tear-off.
+  Function eaf1 = EnumAll.v1;
+  Expect.type<T Function<T>(T)>(eaf1);
+  Function eaf2 = EnumAll.v1<String>;
+  Expect.type<String Function(String)>(eaf2);
+
+  // Instance members shadow extensions.
+  Expect.equals("not extension", EnumAll.v1.notExtension);
+  // But you can call extension members if there is no conflict.
+  Expect.equals("extension", EnumAll.v1.extension);
+
+  // The `index` and `toString` implementations are inherited from
+  // the `Enum` implementing superclass.
+  Expect.equals(3.5, StringIndexEnum.v1.index);
+  Expect.equals(3.5, StringIndexEnum.v2.index);
+  Expect.equals(0, StringIndexEnum.v1.realIndex);
+  Expect.equals(1, StringIndexEnum.v2.realIndex);
+  Expect.equals("FakeString", StringIndexEnum.v1.toString());
+  Expect.equals("FakeString", StringIndexEnum.v2.toString());
+  Expect.equals("StringIndexEnum.v1", StringIndexEnum.v1.realToString());
+  Expect.equals("StringIndexEnum.v2", StringIndexEnum.v2.realToString());
+
+  // Enum elements are always distinct, even if their state doesn't differ.
+  Expect.distinct(Canonical.v1, Canonical.v2, "Canonical - type only");
+  Expect.distinct(Canonical.v2, Canonical.v3, "Canonical - no difference");
+
+  // A `values` static constant is added only if *not* causing a conflict.
+  Expect.equals("StaticDeclaration", DeclaresValuesStatic.values);
+  Expect.equals("Declaration", DeclaresValues.v1.values);
+  Expect.equals("Mixin", InheritsValues.v1.values);
+  Expect.equals("NSM", ImplementsValues.v1.values);
+}
+
+// Original syntax still works, without semicolon after values.
+enum EnumPlain { v1, v2, v3 }
+
+// Also with trailing comma.
+enum EnumPlainTrailingComma {
+  v1,
+  v2,
+  v3,
+}
+
+// Also if using type parameters, mixins or interfaces.
+// It only matters whether there is something after the values.
+enum EnumNoSemicolon<T extends num> with ObjectMixin implements Interface {
+  v1, v2, v3
+}
+
+
+// Allows semicolon after values, even when not needed.
+// Without trailing comma.
+enum EnumPlainSemicolon { v1, v2, v3; }
+
+// With trailing comma.
+enum EnumPlainTrailingCommaSemicolon {
+  v1,
+  v2,
+  v3,
+  ;
+}
+
+// Full syntax, with every possible option.
+@EnumAll.v1
+@EnumAll.sConst
+enum EnumAll<S extends num, T extends num>
+    with GenericEnumMixin<T>, ObjectMixin
+    implements Interface, GenericInterface<S> {
+  @v1
+  @v2
+  v1,
+  @EnumAll.v2
+  v2(y: 2),
+  @sConst
+  v3<int, int>(y: 2),
+  v4.named(1, y: 2),
+  v5<int, int>.renamed(1, y: 2),
+  v6.new(),
+  ;
+
+  /// Static members.
+  ///
+  /// Any kind of static variable.
+  static const sConst = v3;
+  static final sFinal = v3;
+  static late final EnumAll sLateFinal;
+  static late final sLateFinalInit = v3;
+  static late EnumAll sLateVar;
+  static late var sLateVarInit = v3;
+  static EnumAll? sVar;
+  static EnumAll sVarInit = v3;
+  /// Static getters, setters and methods
+  static EnumAll<int, int> get staticGetSet => v3;
+  static set staticGetSet(EnumAll<int, int> _) {}
+  static int staticMethod() => 42;
+
+  // Constructors.
+  // Generative, non-redirecting, unnamed.
+  const EnumAll({T? y})
+      : constructor = "unnamed", this.x = 0 as S, y = y ?? (0 as T);
+  // Generative, non-redirecting, named.
+  const EnumAll.named(this.x, {T? y, String? constructor})
+      : constructor = constructor ?? "named", y = y ?? (0 as T);
+  // Generative, redirecting.
+  const EnumAll.renamed(S x, {T? y})
+      : this.named(x, y: y, constructor: "renamed");
+  // Factory, non-redirecting.
+  factory EnumAll.factory(int index) => values[index] as EnumAll<S, T>;
+  // Factory, redirecting (only to other factory constructor).
+  factory EnumAll.refactory(int index) = EnumAll<S, T>.factory;
+
+  // Cannot have factory constructors redirecting to generative constructors.
+  // (Nothing can refer to generative constructors except redirecting generative
+  // constructors and the implicit element creation expressions.)
+  // Cannot have const factory constructor, because they *must* redirect to
+  // generative constructors.
+  // Cannot have `super`-constuctor invocations in initializer lists.
+
+  // Instance members.
+
+  // Instance variables must be final and non-late because of const constructor.
+  final String constructor;
+  final S x;
+  final num y;
+
+  // Getters, setters, methods and operators.
+  S get instanceGetSet => x;
+  set instanceGetSet(S _) {}
+  S instanceMethod() => x;
+  EnumAll<num, num> operator ^(EnumAll<num, num> other) {
+    var newIndex = index ^ other.index;
+    if (newIndex > 4) newIndex = 4;
+    return values[newIndex]; // Can refer to `values`.
+  }
+
+  // Can have non-primitive equality and hashCode.
+  int get hashCode => index;
+  bool operator==(covariant EnumAll other) => index == other.index;
+
+  // Can access `this` and `super` in an instance method.
+  String thisAndSuper() => "${super.toString()}:${this.toString()}";
+
+  // Can be callable.
+  T call<T>(T value) => value;
+
+  // Instance members shadow extensions.
+  String get notExtension => "not extension";
+
+  String toString() => "this";
+}
+
+extension EnumAllExtension on EnumAll {
+  String get notExtension => Expect.fail("Unreachable");
+  String get extension => "extension":
+}
+
+typedef TypeDefAll = EnumAll<num, num>;
+
+// Can have no unnamed constructor.
+enum EnumNoUnnamedConstructor {
+  v1.named(1),
+  v2.named(2);
+
+  final int x;
+  EnumNoUnnamedConstructor.named(this.x);
+}
+
+// Can have an unnamed factory constructor.
+enum EnumFactoryUnnamedConstructor {
+  v1.named(1),
+  v2.named(2);
+
+  final int x;
+  factory EnumFactoryUnnamedConstructor() => v1;
+  EnumFactoryUnnamedConstructor.named(this.x);
+}
+
+// Elements which do not differ in public state are still different.
+// Ditto if only differing in type arguments.
+enum Canonical<T> {
+  v1<int>(1),
+  v2<num>(1),
+  v3<num>(1);
+  final T value;
+  Canonical(this.value);
+}
+
+// Both `toString` and `index` are inherited from superclass.
+enum StringIndexEnum {
+  v1, v2;
+  num get index => 3.5;
+  int get realIndex => super.index;
+  String toString() => "FakeString";
+  String realToString() => super.toString();
+}
+
+enum DeclaresValuesStatic {
+  v1;
+  static String get values => "StaticDeclaration";
+}
+
+enum DeclaresValues {
+  v1;
+  String get values => "Declaration";
+}
+
+enum InheritsValues with ValuesMixin {
+  v1;
+}
+
+enum ImplementsValues implements ValuesInterface {
+  v1;
+  dynamic noSuchMethod(i) => "NSM";
+}
+
+// --------------------------------------------------------------------
+// Helper declarations
+
+mixin ObjectMixin on Object {
+  String toString() => "${super.toString()}:ObjectMixin";
+}
+
+mixin EnumMixin on Enum {
+  String toString() => "${super.toString()}:EnumMixin";
+}
+
+mixin GenericObjectMixin<T> on Object {
+  bool test(Object o) => o is T;
+  String toString() => "${super.toString()}:ObjectMixin<$T>";
+}
+
+mixin GenericEnumMixin<T> on Enum {
+  bool test(Object o) => o is T;
+  String toString() => "${super.toString()}:EnumMixin<$T>";
+}
+
+abstract class Interface {
+
+}
+
+abstract class GenericInterface<T> {
+  // Implemented by mixins.
+  bool test(Object o);
+}
+
+abstract class ValuesInterface {
+  String get values;
+}
+
+mixin ValuesMixin {
+  String get values => "Mixin";
+}
diff --git a/tools/VERSION b/tools/VERSION
index 6c960b2..65a1042 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 159
+PRERELEASE 160
 PRERELEASE_PATCH 0
\ No newline at end of file