generate kernel experimental flags
Change-Id: I9430d95c012b752bc4ca0530d79252b8b032a26b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104841
Reviewed-by: Kevin Millikin <kmillikin@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
Auto-Submit: Dan Rubel <danrubel@google.com>
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index f91b17d..6428f9b 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -2,7 +2,10 @@
// 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.
-// TODO(askesc): Generate this file from a flag specification.
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'tools/experimental_features.yaml' and run
+// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
enum ExperimentalFlag {
constantUpdate2018,
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
new file mode 100644
index 0000000..355836a
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2019, 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 'dart:async';
+
+import 'dart:io';
+
+import 'dart:isolate';
+
+import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
+
+import 'package:dart_style/dart_style.dart' show DartFormatter;
+
+import '../../lib/src/fasta/scanner/characters.dart' show $A, $MINUS, $a, $z;
+
+main(List<String> arguments) async {
+ var port = new ReceivePort();
+ await new File.fromUri(await computeGeneratedFile())
+ .writeAsString(await generateMessagesFile(), flush: true);
+ port.close();
+}
+
+Future<Uri> computeGeneratedFile() {
+ return Isolate.resolvePackageUri(
+ Uri.parse('package:front_end/src/api_prototype/experimental_flags.dart'));
+}
+
+Future<String> generateMessagesFile() async {
+ Uri messagesFile =
+ Platform.script.resolve("../../../../tools/experimental_features.yaml");
+ Map<dynamic, dynamic> yaml =
+ loadYaml(await new File.fromUri(messagesFile).readAsStringSync());
+ StringBuffer sb = new StringBuffer();
+
+ sb.write('''
+// Copyright (c) 2018, 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'tools/experimental_features.yaml' and run
+// 'pkg/front_end/tool/fasta generate-experimental-flags' to update.
+''');
+
+ List<String> keys = yaml.keys.cast<String>().toList()..sort();
+
+ sb.write('''
+
+enum ExperimentalFlag {
+''');
+ for (var key in keys) {
+ sb.writeln(' ${keyToIdentifier(key)},');
+ }
+ sb.writeln('}');
+
+ sb.write('''
+
+ExperimentalFlag parseExperimentalFlag(String flag) {
+ switch (flag) {
+''');
+ for (var key in keys) {
+ sb.writeln(' case "$key":');
+ sb.writeln(' return ExperimentalFlag.${keyToIdentifier(key)};');
+ }
+ sb.write(''' }
+ return null;
+}
+''');
+
+ sb.write('''
+
+const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
+''');
+ for (var key in keys) {
+ bool shipped = (yaml[key] as YamlMap)['enabledIn'] != null;
+ sb.writeln(' ExperimentalFlag.${keyToIdentifier(key)}: ${shipped},');
+ if (shipped) {
+ var expired = (yaml[key] as YamlMap)['expired'];
+ if (expired == false) {
+ throw 'Cannot mark shipped feature as "expired: false"';
+ }
+ }
+ }
+ sb.writeln('};');
+
+ return new DartFormatter().format("$sb");
+}
+
+keyToIdentifier(String key) {
+ var identifier = StringBuffer();
+ for (int index = 0; index < key.length; ++index) {
+ var code = key.codeUnitAt(index);
+ if (code == $MINUS) {
+ ++index;
+ code = key.codeUnitAt(index);
+ if ($a <= code && code <= $z) {
+ code = code - $a + $A;
+ }
+ }
+ identifier.writeCharCode(code);
+ }
+ return identifier.toString();
+}
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart
new file mode 100644
index 0000000..81fdca0
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2018, 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 "dart:io" show File;
+
+import "package:async_helper/async_helper.dart" show asyncTest;
+
+import "package:expect/expect.dart" show Expect;
+
+import "generate_experimental_flags.dart"
+ show computeGeneratedFile, generateMessagesFile;
+
+main() {
+ asyncTest(() async {
+ Uri generatedFile = await computeGeneratedFile();
+ String generated = await generateMessagesFile();
+ String actual = (await new File.fromUri(generatedFile).readAsString())
+ .replaceAll('\r\n', '\n');
+ Expect.stringEquals(
+ generated, actual, "${generatedFile.path} is out of date");
+ });
+}
diff --git a/pkg/front_end/tool/fasta b/pkg/front_end/tool/fasta
index 65b9ec4..aa970c3 100755
--- a/pkg/front_end/tool/fasta
+++ b/pkg/front_end/tool/fasta
@@ -55,6 +55,7 @@
set -- "$@" "--config=${REPO_DIR}/pkg/front_end/testing.json"
;;
generate-messages) SCRIPT="${TOOL_DIR}/generate_messages.dart";;
+ generate-experimental-flags) SCRIPT="${TOOL_DIR}/generate_experimental_flags.dart";;
*)
stop "'$1' isn't a valid subcommand."
;;