Add AstBuilder spread-collections and control-flow-collections flags

Change-Id: I280b09970851d0d5bc0ad630be94ccd11f4385b1
Reviewed-on: https://dart-review.googlesource.com/c/90081
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index 4a016fa..e99ffb5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -113,11 +113,18 @@
   /// Initializes a newly created set of experiments based on optional
   /// arguments.
   ExperimentStatus(
-      {bool constant_update_2018, bool set_literals, bool non_nullable})
+      {bool constant_update_2018,
+      bool control_flow_collections,
+      bool non_nullable,
+      bool set_literals,
+      bool spread_collections})
       : _enableFlags = <bool>[
           constant_update_2018 ?? IsEnabledByDefault.constant_update_2018,
           set_literals ?? IsEnabledByDefault.set_literals,
           non_nullable ?? IsEnabledByDefault.non_nullable,
+          spread_collections ?? IsEnabledByDefault.spread_collections,
+          control_flow_collections ??
+              IsEnabledByDefault.control_flow_collections,
         ];
 
   /// Decodes the strings given in [flags] into a representation of the set of
@@ -145,6 +152,12 @@
   /// Current state for the flag "set-literals"
   bool get set_literals => _enableFlags[1];
 
+  /// Current state for the flag "spread_collections"
+  bool get spread_collections => _enableFlags[3];
+
+  /// Current state for the flag "control_flow_collections"
+  bool get control_flow_collections => _enableFlags[4];
+
   /// Queries whether the given [feature] is enabled or disabled.
   bool isEnabled(ExperimentalFeature feature) => feature.isExpired
       ? feature.isEnabledByDefault
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index eb87535..c0c16fe 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -702,6 +702,9 @@
     parser.enableOptionalNewAndConst = true;
     parser.enableSetLiterals = experimentStatus.set_literals;
     parser.enableNonNullable = experimentStatus.non_nullable;
+    parser.enableSpreadCollections = experimentStatus.spread_collections;
+    parser.enableControlFlowCollections =
+        experimentStatus.control_flow_collections;
     CompilationUnit unit = parser.parseCompilationUnit(token);
     unit.lineInfo = lineInfo;
 
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 2d799a8..477b9c1 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -100,6 +100,12 @@
   /// `true` if non-nullable behavior is enabled
   bool enableNonNullable = false;
 
+  /// `true` if spread-collections behavior is enabled
+  bool enableSpreadCollections = false;
+
+  /// `true` if control-flow-collections behavior is enabled
+  bool enableControlFlowCollections = false;
+
   /// Is `true` if [enableNonNullable] is enabled, and the library directive
   /// is annotated with `@pragma('analyzer:non-nullable')`.
   bool hasPragmaAnalyzerNonNullable = false;
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index b75defe..9ea56c4 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -251,6 +251,22 @@
     }
   }
 
+  /// Enables or disables parsing of spread collections.
+  void set enableSpreadCollections(bool value) {
+    if (value) {
+      throw new UnimplementedError(
+          'spread_collections experiment not supported by analyzer parser');
+    }
+  }
+
+  /// Enables or disables parsing of control flow collections.
+  void set enableControlFlowCollections(bool value) {
+    if (value) {
+      throw new UnimplementedError('control_flow_collections experiment'
+          ' not supported by analyzer parser');
+    }
+  }
+
   /// Return `true` if the parser is to allow URI's in part-of directives.
   @deprecated
   bool get enableUriInPartOf => true;
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart
index 389c230..62e616e 100644
--- a/pkg/analyzer/lib/src/generated/parser_fasta.dart
+++ b/pkg/analyzer/lib/src/generated/parser_fasta.dart
@@ -63,6 +63,26 @@
   }
 
   @override
+  void set enableSpreadCollections(bool value) {
+    if (IsExpired.spread_collections &&
+        value != IsEnabledByDefault.spread_collections) {
+      throw new StateError('spread_collections may only be set'
+          ' to ${IsEnabledByDefault.spread_collections}');
+    }
+    astBuilder.enableSpreadCollections = value;
+  }
+
+  @override
+  void set enableControlFlowCollections(bool value) {
+    if (IsExpired.control_flow_collections &&
+        value != IsEnabledByDefault.control_flow_collections) {
+      throw new StateError('control_flow_collections may only be set'
+          ' to ${IsEnabledByDefault.control_flow_collections}');
+    }
+    astBuilder.enableControlFlowCollections = value;
+  }
+
+  @override
   void set parseFunctionBodies(bool parseFunctionBodies) {
     astBuilder.parseFunctionBodies = parseFunctionBodies;
   }