[CFE] Make incremental tests output expect files for expression compilations

Also add reproduction for issue #41976.

Change-Id: I65c55ce0b7ef65e28903b924945e148a1a2285d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149844
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
index 015e3d5..902cdd4 100644
--- a/pkg/front_end/test/incremental_load_from_dill_suite.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart
@@ -62,12 +62,13 @@
         Member,
         Name,
         Procedure,
-        Supertype;
+        Supertype,
+        TreeNode;
 
 import 'package:kernel/target/targets.dart'
     show NoneTarget, Target, TargetFlags;
 
-import 'package:kernel/text/ast_to_text.dart' show componentToString;
+import 'package:kernel/text/ast_to_text.dart' show Printer, componentToString;
 
 import "package:testing/testing.dart"
     show Chain, ChainContext, Result, Step, TestDescription, runMe;
@@ -643,7 +644,7 @@
         }
       }
 
-      checkExpectFile(data, worldNum, context, actualSerialized);
+      checkExpectFile(data, worldNum, "", context, actualSerialized);
       checkClassHierarchy(compiler, component, data, worldNum, context);
 
       int nonSyntheticLibraries = countNonSyntheticLibraries(component);
@@ -777,13 +778,15 @@
         } else {
           compilations = [world["expressionCompilation"]];
         }
+        int expressionCompilationNum = 0;
         for (Map compilation in compilations) {
+          expressionCompilationNum++;
           clearPrevErrorsEtc();
           bool expectErrors = compilation["errors"] ?? false;
           bool expectWarnings = compilation["warnings"] ?? false;
           Uri uri = base.resolve(compilation["uri"]);
           String expression = compilation["expression"];
-          await compiler.compileExpression(
+          Procedure procedure = await compiler.compileExpression(
               expression, {}, [], "debugExpr", uri);
           if (gotError && !expectErrors) {
             throw "Got error(s) on expression compilation: ${formattedErrors}.";
@@ -796,6 +799,12 @@
           } else if (!gotWarning && expectWarnings) {
             throw "Didn't get any warnings.";
           }
+          checkExpectFile(
+              data,
+              worldNum,
+              ".expression.$expressionCompilationNum",
+              context,
+              nodeToString(procedure));
         }
       }
 
@@ -876,10 +885,10 @@
   }
 }
 
-void checkExpectFile(
-    TestData data, int worldNum, Context context, String actualSerialized) {
-  Uri uri = data.loadedFrom
-      .resolve(data.loadedFrom.pathSegments.last + ".world.$worldNum.expect");
+void checkExpectFile(TestData data, int worldNum, String extraUriString,
+    Context context, String actualSerialized) {
+  Uri uri = data.loadedFrom.resolve(data.loadedFrom.pathSegments.last +
+      ".world.$worldNum${extraUriString}.expect");
   String expected;
   File file = new File.fromUri(uri);
   if (file.existsSync()) {
@@ -1274,6 +1283,12 @@
   }
 }
 
+String nodeToString(TreeNode node) {
+  StringBuffer buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: new NameSystem()).writeNode(node);
+  return '$buffer';
+}
+
 String componentToStringSdkFiltered(Component node) {
   Component c = new Component();
   List<Uri> dartUris = new List<Uri>();
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.1.expression.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.1.expression.1.expect
new file mode 100644
index 0000000..9772cff
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/expression_calculation_with_error.yaml.world.1.expression.1.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:1: Error: Method not found: 'foo'.\nfoo()\n^^^";
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_expression_compilation_usage.yaml.world.1.expression.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_expression_compilation_usage.yaml.world.1.expression.1.expect
new file mode 100644
index 0000000..8b090f5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_expression_compilation_usage.yaml.world.1.expression.1.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::NumberParsing|parseInt("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.1.expect
new file mode 100644
index 0000000..8b090f5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.1.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::NumberParsing|parseInt("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.2.expect
new file mode 100644
index 0000000..a4440be
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.2.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:14: Error: The method 'parseInt' isn't defined for the class 'String'.\nTry correcting the name to the name of an existing method, or defining a method named 'parseInt'.\nprint(\"1234\".parseInt())\n             ^^^^^^^^");
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.3.expect
new file mode 100644
index 0000000..a4440be
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.3.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:14: Error: The method 'parseInt' isn't defined for the class 'String'.\nTry correcting the name to the name of an existing method, or defining a method named 'parseInt'.\nprint(\"1234\".parseInt())\n             ^^^^^^^^");
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.4.expect
new file mode 100644
index 0000000..8b090f5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.4.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::NumberParsing|parseInt("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.5.expect
new file mode 100644
index 0000000..aae336e4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.1.expression.5.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::DuplicateName|fooMe1("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.1.expect
new file mode 100644
index 0000000..8b090f5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.1.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::NumberParsing|parseInt("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.2.expect
new file mode 100644
index 0000000..a4440be
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.2.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:14: Error: The method 'parseInt' isn't defined for the class 'String'.\nTry correcting the name to the name of an existing method, or defining a method named 'parseInt'.\nprint(\"1234\".parseInt())\n             ^^^^^^^^");
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.3.expect
new file mode 100644
index 0000000..a4440be
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.3.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:14: Error: The method 'parseInt' isn't defined for the class 'String'.\nTry correcting the name to the name of an existing method, or defining a method named 'parseInt'.\nprint(\"1234\".parseInt())\n             ^^^^^^^^");
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.4.expect
new file mode 100644
index 0000000..8b090f5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.4.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::NumberParsing|parseInt("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.5.expect
new file mode 100644
index 0000000..aae336e4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/extension_usage_from_dill.yaml.world.2.expression.5.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::DuplicateName|fooMe1("1234"));
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expression.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expression.1.expect
new file mode 100644
index 0000000..35a37c6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expression.1.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return dart.core::print(#lib1::coordinate.{#lib2::Coordinate::x});
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml
new file mode 100644
index 0000000..1a35d29
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml
@@ -0,0 +1,35 @@
+# Copyright (c) 2020, 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.md file.
+
+# https://github.com/dart-lang/sdk/issues/41976
+
+type: newworld
+worlds:
+  - entry: foo.dart
+    sources:
+      foo.dart: |
+        abstract class Key {
+          const factory Key(String value) = ValueKey;
+          const Key.empty();
+        }
+
+        abstract class LocalKey extends Key {
+          const LocalKey() : super.empty();
+        }
+
+        class ValueKey implements LocalKey {
+          const ValueKey(this.value);
+          final String value;
+        }
+
+        void main() {
+          var k = Key('t');
+          /* breakpoint here */
+          print('$k');
+        }
+    expectedLibraryCount: 1
+    expressionCompilation:
+      uri: foo.dart
+      expression: Key('t')
+      errors: false
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect
new file mode 100644
index 0000000..086c622
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect
@@ -0,0 +1,47 @@
+main = <No Member>;
+library from "org-dartlang-test:///foo.dart" as foo {
+
+  abstract class Key extends dart.core::Object /*hasConstConstructor*/  {
+    static field dynamic _redirecting# = <dynamic>[foo::Key::•];
+    const constructor empty() → foo::Key*
+      : super dart.core::Object::•()
+      ;
+    static factory •(dart.core::String* value) → foo::Key*
+      let dynamic #redirecting_factory = foo::ValueKey::• in invalid-expression;
+    abstract member-signature get _identityHashCode() → dart.core::int*;
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*;
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*;
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*;
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*;
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*;
+    abstract member-signature get hashCode() → dart.core::int*;
+    abstract member-signature method toString() → dart.core::String*;
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic;
+    abstract member-signature get runtimeType() → dart.core::Type*;
+  }
+  abstract class LocalKey extends foo::Key /*hasConstConstructor*/  {
+    const constructor •() → foo::LocalKey*
+      : super foo::Key::empty()
+      ;
+  }
+  class ValueKey extends dart.core::Object implements foo::LocalKey /*hasConstConstructor*/  {
+    final field dart.core::String* value;
+    const constructor •(dart.core::String* value) → foo::ValueKey*
+      : foo::ValueKey::value = value, super dart.core::Object::•()
+      ;
+    abstract member-signature get _identityHashCode() → dart.core::int*;
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*;
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*;
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*;
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*;
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*;
+    abstract member-signature get hashCode() → dart.core::int*;
+    abstract member-signature method toString() → dart.core::String*;
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic;
+    abstract member-signature get runtimeType() → dart.core::Type*;
+  }
+  static method main() → void {
+    foo::Key* k = new foo::ValueKey::•("t");
+    dart.core::print("${k}");
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expression.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expression.1.expect
new file mode 100644
index 0000000..6dea614
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expression.1.expect
@@ -0,0 +1,2 @@
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return #lib1::Key::•("t");