Add Forest support for assert statements and initializers

Change-Id: I7a1f51144e69890d9858e60948cf59800ed81e53
Reviewed-on: https://dart-review.googlesource.com/56005
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index 5a4c1c6..1f3035f 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -58,9 +58,31 @@
   Expression asExpression(Expression expression, type, Token location) =>
       astFactory.asExpression(expression, location, type);
 
+  @override
   Expression asLiteralString(Expression value) => value;
 
   @override
+  ConstructorInitializer assertInitializer(
+          Token assertKeyword,
+          Token leftParenthesis,
+          Expression condition,
+          Token comma,
+          Expression message) =>
+      astFactory.assertInitializer(assertKeyword, leftParenthesis, condition,
+          comma, message, leftParenthesis.endGroup);
+
+  @override
+  Statement assertStatement(
+          Token assertKeyword,
+          Token leftParenthesis,
+          Expression condition,
+          Token comma,
+          Expression message,
+          Token semicolon) =>
+      astFactory.assertStatement(assertKeyword, leftParenthesis, condition,
+          comma, message, leftParenthesis.endGroup, semicolon);
+
+  @override
   Expression awaitExpression(Expression operand, Token awaitKeyword) =>
       astFactory.awaitExpression(awaitKeyword, operand);
 
@@ -114,6 +136,7 @@
   Statement emptyStatement(Token semicolon) =>
       astFactory.emptyStatement(semicolon);
 
+  @override
   Statement expressionStatement(Expression expression, Token semicolon) =>
       astFactory.expressionStatement(expression, semicolon);
 
diff --git a/pkg/analyzer/test/generated/parser_forest_test.dart b/pkg/analyzer/test/generated/parser_forest_test.dart
index d6fd4e0..1ec29cc 100644
--- a/pkg/analyzer/test/generated/parser_forest_test.dart
+++ b/pkg/analyzer/test/generated/parser_forest_test.dart
@@ -3181,6 +3181,8 @@
   @failingTest
   void test_parsePrimaryExpression_const() {
     super.test_parsePrimaryExpression_const();
+    fail(
+        'This passes under Dart 1, but fails under Dart 2 because of a cast exception');
   }
 
   @failingTest
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 68e1074..abbbb39 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3345,48 +3345,10 @@
     Expression message = popForValueIfNotNull(commaToken);
     Expression condition = popForValue();
 
-    // Compute start and end offsets for the condition expression.
-    // This code is a temporary workaround because expressions don't carry
-    // their start and end offsets currently.
-    //
-    // The token that follows leftParenthesis is considered to be the
-    // first token of the condition.
-    // TODO(ahe): this really should be condition.fileOffset.
-    int startOffset = leftParenthesis.next.offset;
-    int endOffset;
-    {
-      // Search forward from leftParenthesis to find the last token of
-      // the condition - which is a token immediately followed by a commaToken,
-      // right parenthesis or a trailing comma.
-      Token conditionBoundary = commaToken ?? leftParenthesis.endGroup;
-      Token conditionLastToken = leftParenthesis;
-      while (!conditionLastToken.isEof) {
-        Token nextToken = conditionLastToken.next;
-        if (nextToken == conditionBoundary) {
-          break;
-        } else if (optional(',', nextToken) &&
-            nextToken.next == conditionBoundary) {
-          // The next token is trailing comma, which means current token is
-          // the last token of the condition.
-          break;
-        }
-        conditionLastToken = nextToken;
-      }
-      if (conditionLastToken.isEof) {
-        endOffset = startOffset = -1;
-      } else {
-        endOffset = conditionLastToken.offset + conditionLastToken.length;
-      }
-    }
-
-    AssertStatement statement = new ShadowAssertStatement(
-        toKernelExpression(condition),
-        conditionStartOffset: startOffset,
-        conditionEndOffset: endOffset,
-        message: toKernelExpression(message));
     switch (kind) {
       case Assert.Statement:
-        push(statement);
+        push(forest.assertStatement(assertKeyword, leftParenthesis, condition,
+            commaToken, message, semicolonToken));
         break;
 
       case Assert.Expression:
@@ -3397,7 +3359,8 @@
         break;
 
       case Assert.Initializer:
-        push(new ShadowAssertInitializer(statement));
+        push(forest.assertInitializer(
+            assertKeyword, leftParenthesis, condition, commaToken, message));
         break;
     }
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 2315281..49330c6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -9,6 +9,7 @@
 import 'package:kernel/ast.dart'
     show
         Arguments,
+        AssertInitializer,
         BreakStatement,
         Block,
         Catch,
@@ -30,7 +31,7 @@
         VariableDeclaration,
         setParents;
 
-import '../parser.dart' show offsetForToken;
+import '../parser.dart' show offsetForToken, optional;
 
 import '../problems.dart' show unsupported;
 
@@ -40,6 +41,8 @@
     show
         ShadowArguments,
         ShadowAsExpression,
+        ShadowAssertInitializer,
+        ShadowAssertStatement,
         ShadowAwaitExpression,
         ShadowBlock,
         ShadowBoolLiteral,
@@ -223,6 +226,59 @@
   }
 
   @override
+  AssertInitializer assertInitializer(
+      Token assertKeyword,
+      Token leftParenthesis,
+      Expression condition,
+      Token comma,
+      Expression message) {
+    return new ShadowAssertInitializer(assertStatement(
+        assertKeyword, leftParenthesis, condition, comma, message, null));
+  }
+
+  @override
+  Statement assertStatement(Token assertKeyword, Token leftParenthesis,
+      Expression condition, Token comma, Expression message, Token semicolon) {
+    // Compute start and end offsets for the condition expression.
+    // This code is a temporary workaround because expressions don't carry
+    // their start and end offsets currently.
+    //
+    // The token that follows leftParenthesis is considered to be the
+    // first token of the condition.
+    // TODO(ahe): this really should be condition.fileOffset.
+    int startOffset = leftParenthesis.next.offset;
+    int endOffset;
+    {
+      // Search forward from leftParenthesis to find the last token of
+      // the condition - which is a token immediately followed by a commaToken,
+      // right parenthesis or a trailing comma.
+      Token conditionBoundary = comma ?? leftParenthesis.endGroup;
+      Token conditionLastToken = leftParenthesis;
+      while (!conditionLastToken.isEof) {
+        Token nextToken = conditionLastToken.next;
+        if (nextToken == conditionBoundary) {
+          break;
+        } else if (optional(',', nextToken) &&
+            nextToken.next == conditionBoundary) {
+          // The next token is trailing comma, which means current token is
+          // the last token of the condition.
+          break;
+        }
+        conditionLastToken = nextToken;
+      }
+      if (conditionLastToken.isEof) {
+        endOffset = startOffset = -1;
+      } else {
+        endOffset = conditionLastToken.offset + conditionLastToken.length;
+      }
+    }
+    return new ShadowAssertStatement(condition,
+        conditionStartOffset: startOffset,
+        conditionEndOffset: endOffset,
+        message: message);
+  }
+
+  @override
   Expression awaitExpression(Expression operand, Token token) {
     return new ShadowAwaitExpression(operand)
       ..fileOffset = offsetForToken(token);
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index b6e35d7..f7a8b61 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -135,6 +135,20 @@
   Expression asExpression(
       Expression expression, covariant type, Location location);
 
+  /// Return a representation of an assert that appears in a constructor's
+  /// initializer list.
+  Object assertInitializer(Location assertKeyword, Location leftParenthesis,
+      Expression condition, Location comma, Expression message);
+
+  /// Return a representation of an assert that appears as a statement.
+  Statement assertStatement(
+      Location assertKeyword,
+      Location leftParenthesis,
+      Expression condition,
+      Location comma,
+      Expression message,
+      Location semicolon);
+
   Expression awaitExpression(Expression operand, Location location);
 
   /// Return a representation of a block of [statements] enclosed between the