Fix analyzer/FE integration of postfix-of-postfix and prefix-of-prefix increments.

These cases don't appear to be exercised by language_2 tests, so no
language_2 tests are fixed by this CL.  I've added test cases to the
analyzer's driver_resolution_test to validate the fix.

Change-Id: I4a364e78f95981e94b51cf94d6f3236b022d42b8
Reviewed-on: https://dart-review.googlesource.com/71229
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 232a626..d872324 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -7177,6 +7177,19 @@
     assertElement(gRef, findElement.parameter('g'));
   }
 
+  test_postfix_increment_of_postfix_increment() async {
+    addTestFile('''
+void f(int x) {
+  x ++ ++;
+}
+''');
+    await resolveTestFile();
+
+    var xRef = findNode.simple('x ++');
+    assertType(xRef, 'int');
+    assertElement(xRef, findElement.parameter('x'));
+  }
+
   test_postfixExpression_local() async {
     String content = r'''
 main() {
@@ -7264,6 +7277,19 @@
     assertElement(xRef, findElement.parameter('x'));
   }
 
+  test_prefix_increment_of_prefix_increment() async {
+    addTestFile('''
+void f(int x) {
+  ++ ++ x;
+}
+''');
+    await resolveTestFile();
+
+    var xRef = findNode.simple('x;');
+    assertType(xRef, 'int');
+    assertElement(xRef, findElement.parameter('x'));
+  }
+
   test_prefixedIdentifier_classInstance_instanceField() async {
     String content = r'''
 main() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 8e02719..0dfb764 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -68,6 +68,7 @@
         DartType,
         DynamicType,
         Expression,
+        IllegalAssignmentJudgment,
         Initializer,
         InvalidConstructorInvocationJudgment,
         InvalidType,
@@ -967,7 +968,18 @@
   @override
   Expression buildPostfixIncrement(Name binaryOperator,
       {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
-    return makeInvalidWrite(null);
+    var innerExpression = buildSimpleRead();
+    // The inner expression needs to have a parent so that type inference can be
+    // applied to it, but it doesn't matter what the parent is because the
+    // inner expression won't appear in the tree.  So just give it a quick and
+    // dirty parent.
+    new VariableDeclaration.forValue(innerExpression);
+
+    return new IllegalAssignmentJudgment(
+        forest.literalInt(1, null, isSynthetic: true),
+        assignmentOffset: offset,
+        desugared: makeInvalidWrite(null))
+      ..write = innerExpression;
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 3d1637b..a6fb377 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -559,7 +559,8 @@
   /// pre-decrement.
   bool isPreIncDec = false;
 
-  ComplexAssignmentJudgment(this.rhs) : super(null);
+  ComplexAssignmentJudgment(this.rhs, {Expression desugared})
+      : super(desugared);
 
   String toString() {
     var parts = _getToStringParts();
@@ -1492,8 +1493,9 @@
   /// If `-1`, then there is no separate location for invalid assignment.
   final int assignmentOffset;
 
-  IllegalAssignmentJudgment(ExpressionJudgment rhs, {this.assignmentOffset: -1})
-      : super(rhs) {
+  IllegalAssignmentJudgment(ExpressionJudgment rhs,
+      {this.assignmentOffset: -1, Expression desugared})
+      : super(rhs, desugared: desugared) {
     rhs.parent = this;
   }