Add Forest support for do statements

Change-Id: Iefa5f5bda3f7b47cc230f4ae8da93fbe3897961f
Reviewed-on: https://dart-review.googlesource.com/55912
Reviewed-by: Dan Rubel <danrubel@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@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 17c95f8..e141f1d 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -63,14 +63,12 @@
   Expression asLiteralString(Expression value) => value;
 
   @override
-  Expression awaitExpression(Expression operand, Token awaitKeyword) {
-    return astFactory.awaitExpression(awaitKeyword, operand);
-  }
+  Expression awaitExpression(Expression operand, Token awaitKeyword) =>
+      astFactory.awaitExpression(awaitKeyword, operand);
 
   @override
-  Block block(Token openBrace, List<Statement> statements, Token closeBrace) {
-    return astFactory.block(openBrace, statements, closeBrace);
-  }
+  Block block(Token openBrace, List<Statement> statements, Token closeBrace) =>
+      astFactory.block(openBrace, statements, closeBrace);
 
   @override
   kernel.Arguments castArguments(_Arguments arguments) {
@@ -91,6 +89,18 @@
           condition, question, thenExpression, colon, elseExpression);
 
   @override
+  Statement doStatement(Token doKeyword, Statement body, Token whileKeyword,
+          ParenthesizedExpression condition, Token semicolon) =>
+      astFactory.doStatement(
+          doKeyword,
+          body,
+          whileKeyword,
+          condition.leftParenthesis,
+          condition.expression,
+          condition.rightParenthesis,
+          semicolon);
+
+  @override
   Statement emptyStatement(Token semicolon) =>
       astFactory.emptyStatement(semicolon);
 
@@ -107,17 +117,20 @@
       typeArguments.arguments.length;
 
   @override
-  Statement ifStatement(Token ifKeyword, ParenthesizedExpression condition,
-      Statement thenStatement, Token elseKeyword, Statement elseStatement) {
-    return astFactory.ifStatement(
-        ifKeyword,
-        condition.leftParenthesis,
-        condition.expression,
-        condition.rightParenthesis,
-        thenStatement,
-        elseKeyword,
-        elseStatement);
-  }
+  Statement ifStatement(
+          Token ifKeyword,
+          ParenthesizedExpression condition,
+          Statement thenStatement,
+          Token elseKeyword,
+          Statement elseStatement) =>
+      astFactory.ifStatement(
+          ifKeyword,
+          condition.leftParenthesis,
+          condition.expression,
+          condition.rightParenthesis,
+          thenStatement,
+          elseKeyword,
+          elseStatement);
 
   @override
   bool isBlock(Object node) => node is Block;
@@ -134,9 +147,8 @@
   bool isThisExpression(Object node) => node is ThisExpression;
 
   @override
-  bool isVariablesDeclaration(Object node) {
-    return node is VariableDeclarationStatement && node.variables != 1;
-  }
+  bool isVariablesDeclaration(Object node) =>
+      node is VariableDeclarationStatement && node.variables != 1;
 
   @override
   Expression literalBool(bool value, Token location) =>
@@ -189,11 +201,10 @@
 
   @override
   Expression literalSymbolMultiple(
-      String value, Token hash, List<Identifier> components) {
-    return astFactory.symbolLiteral(
-        hash, components.map((identifier) => identifier.token).toList())
-      ..staticType = _typeProvider?.symbolType;
-  }
+          String value, Token hash, List<Identifier> components) =>
+      astFactory.symbolLiteral(
+          hash, components.map((identifier) => identifier.token).toList())
+        ..staticType = _typeProvider?.symbolType;
 
   @override
   Expression literalSymbolSingluar(String value, Token hash, Object component) {
@@ -299,9 +310,8 @@
 
   @override
   NodeList<VariableDeclaration> variablesDeclarationExtractDeclarations(
-      VariableDeclarationStatement variablesDeclaration) {
-    return variablesDeclaration.variables.variables;
-  }
+          VariableDeclarationStatement variablesDeclaration) =>
+      variablesDeclaration.variables.variables;
 
   @override
   Statement whileStatement(Token whileKeyword,
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 9e0027f..6be79bc 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3151,19 +3151,17 @@
     Statement body = popStatement();
     JumpTarget continueTarget = exitContinueTarget();
     JumpTarget breakTarget = exitBreakTarget();
-    kernel.Statement kernelBody = toKernelStatement(body);
     if (continueTarget.hasUsers) {
-      kernelBody = new ShadowLabeledStatement(kernelBody);
-      continueTarget.resolveContinues(forest, kernelBody);
+      body = forest.syntheticLabeledStatement(body);
+      continueTarget.resolveContinues(forest, body);
     }
-    kernel.Statement result =
-        new ShadowDoStatement(kernelBody, toKernelExpression(condition))
-          ..fileOffset = doKeyword.charOffset;
+    Statement result =
+        forest.doStatement(doKeyword, body, whileKeyword, condition, endToken);
     if (breakTarget.hasUsers) {
-      result = new ShadowLabeledStatement(result);
+      result = forest.syntheticLabeledStatement(result);
       breakTarget.resolveBreaks(forest, result);
     }
-    exitLoopOrSwitch(toStatement(result));
+    exitLoopOrSwitch(result);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 5b8667c..ea8bc98 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -45,6 +45,7 @@
         ShadowBoolLiteral,
         ShadowCheckLibraryIsLoaded,
         ShadowConditionalExpression,
+        ShadowDoStatement,
         ShadowDoubleLiteral,
         ShadowExpressionStatement,
         ShadowIfStatement,
@@ -250,6 +251,13 @@
       ..fileOffset = offsetForToken(question);
   }
 
+  @override
+  Statement doStatement(Token doKeyword, Statement body, Token whileKeyword,
+      Expression condition, Token semicolon) {
+    return new ShadowDoStatement(body, condition)
+      ..fileOffset = doKeyword.charOffset;
+  }
+
   Statement expressionStatement(Expression expression, Token semicolon) {
     return new ShadowExpressionStatement(expression);
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index d686f1f..f85e1e2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -148,6 +148,14 @@
   Expression conditionalExpression(Expression condition, Location question,
       Expression thenExpression, Location colon, Expression elseExpression);
 
+  /// Return a representation of a do statement.
+  Statement doStatement(
+      Location doKeyword,
+      Statement body,
+      Location whileKeyword,
+      covariant Expression condition,
+      Location semicolon);
+
   /// Return a representation of an expression statement composed from the
   /// [expression] and [semicolon].
   Statement expressionStatement(Expression expression, Location semicolon);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index a6d0c8c..6817deb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -72,7 +72,6 @@
         ShadowConstructorInvocation,
         ShadowContinueSwitchStatement,
         ShadowDeferredCheck,
-        ShadowDoStatement,
         ShadowExpressionStatement,
         ShadowFactoryConstructorInvocation,
         ShadowFieldInitializer,