Incremental compiler should respect omitPlatform setting

Change-Id: Id842db646ba95945c8fadce0626cb8cbee2812ad
Reviewed-on: https://dart-review.googlesource.com/c/93433
Reviewed-by: Peter von der Ahé <ahe@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index baec375..67c131f 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -272,10 +272,16 @@
 
       List<Library> outputLibraries;
       Set<Library> allLibraries;
-      if (data.includeUserLoadedLibraries || fullComponent) {
+      if (data.component != null || fullComponent) {
         outputLibraries = computeTransitiveClosure(compiledLibraries,
             entryPoint, reusedLibraries, hierarchy, uriTranslator);
         allLibraries = outputLibraries.toSet();
+        if (!c.options.omitPlatform) {
+          for (int i = 0; i < platformBuilders.length; i++) {
+            Library lib = platformBuilders[i].target;
+            outputLibraries.add(lib);
+          }
+        }
       } else {
         outputLibraries = new List<Library>();
         allLibraries = computeTransitiveClosure(compiledLibraries, entryPoint,
@@ -494,7 +500,6 @@
         initializedFromDill = true;
         bytesLength += initializationBytes.length;
         data.userLoadedUriMain = data.component.mainMethod;
-        data.includeUserLoadedLibraries = true;
         saveComponentProblems(data);
       }
     }
@@ -545,7 +550,6 @@
         new Component(libraries: combinedLibs, uriToSource: combinedMaps)
           ..mainMethod = componentToInitializeFrom.mainMethod;
     data.userLoadedUriMain = data.component.mainMethod;
-    data.includeUserLoadedLibraries = true;
     saveComponentProblems(data);
   }
 
@@ -795,7 +799,6 @@
 }
 
 class IncrementalCompilerData {
-  bool includeUserLoadedLibraries = false;
   Procedure userLoadedUriMain = null;
   Component component = null;
   List<int> initializationBytes = null;
diff --git a/pkg/front_end/test/fasta/expression_test.dart b/pkg/front_end/test/fasta/expression_test.dart
index e7161c0..252a5a1 100644
--- a/pkg/front_end/test/fasta/expression_test.dart
+++ b/pkg/front_end/test/fasta/expression_test.dart
@@ -405,6 +405,7 @@
   final CompilerOptions optionBuilder = new CompilerOptions()
     ..target = new VmTarget(new TargetFlags())
     ..verbose = true
+    ..omitPlatform = true
     ..fileSystem = fs
     ..sdkSummary = sdkSummary
     ..onDiagnostic = (DiagnosticMessage message) {
diff --git a/pkg/front_end/test/fasta/incremental_hello_test.dart b/pkg/front_end/test/fasta/incremental_hello_test.dart
index 1ac768d..dbf48e6 100644
--- a/pkg/front_end/test/fasta/incremental_hello_test.dart
+++ b/pkg/front_end/test/fasta/incremental_hello_test.dart
@@ -37,6 +37,7 @@
     ..packagesFileUri = Uri.base.resolve(".packages")
     ..target = new VmTarget(new TargetFlags(legacyMode: true))
     ..legacyMode = true
+    ..omitPlatform = true
     ..onDiagnostic = diagnosticMessageHandler;
 
   if (sdkFromSource) {
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
index a52ac90..1e98000 100644
--- a/pkg/front_end/test/incremental_bulk_compiler_full.dart
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.dart
@@ -56,6 +56,7 @@
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
     ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
+    ..omitPlatform = true
     ..onDiagnostic = (DiagnosticMessage message) {
       // Ignored.
     }
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index 682f362..8d5ed31 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -111,6 +111,7 @@
         await newWorldTest(
           map["strong"],
           map["worlds"],
+          map["omitPlatform"],
         );
         break;
       default:
@@ -179,7 +180,7 @@
   checkIsEqual(normalDillData, initializedDillData);
 }
 
-Future<Null> newWorldTest(bool strong, List worlds) async {
+Future<Null> newWorldTest(bool strong, List worlds, bool omitPlatform) async {
   final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
   final Uri base = Uri.parse("org-dartlang-test:///");
   final Uri sdkSummary = base.resolve("vm_platform.dill");
@@ -204,6 +205,10 @@
     if (world["worldType"] == "updated") {
       brandNewWorld = false;
     }
+    bool noFullComponent = false;
+    if (world["noFullComponent"] == true) {
+      noFullComponent = true;
+    }
 
     if (brandNewWorld) {
       fs = new MemoryFileSystem(base);
@@ -241,6 +246,7 @@
       options.fileSystem = fs;
       options.sdkRoot = null;
       options.sdkSummary = sdkSummary;
+      options.omitPlatform = omitPlatform != false;
       if (packagesUri != null) {
         options.packagesFileUri = packagesUri;
       }
@@ -291,20 +297,39 @@
 
     Stopwatch stopwatch = new Stopwatch()..start();
     Component component = await compiler.computeDelta(
-        fullComponent: brandNewWorld ? false : true);
+        fullComponent:
+            brandNewWorld ? false : (noFullComponent ? false : true));
     performErrorAndWarningCheck(
         world, gotError, formattedErrors, gotWarning, formattedWarnings);
     util.throwOnEmptyMixinBodies(component);
     print("Compile took ${stopwatch.elapsedMilliseconds} ms");
     newestWholeComponentData = util.postProcess(component);
     newestWholeComponent = component;
-    print("*****\n\ncomponent:\n${componentToString(component)}\n\n\n");
+    print("*****\n\ncomponent:\n"
+        "${componentToStringSdkFiltered(component)}\n\n\n");
 
     int nonSyntheticLibraries = countNonSyntheticLibraries(component);
+    int nonSyntheticPlatformLibraries =
+        countNonSyntheticPlatformLibraries(component);
     int syntheticLibraries = countSyntheticLibraries(component);
-    if (nonSyntheticLibraries != world["expectedLibraryCount"]) {
-      throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
-          "libraries, got ${nonSyntheticLibraries}";
+    if (world["expectsPlatform"] == true) {
+      if (nonSyntheticPlatformLibraries < 5)
+        throw "Expected to have at least 5 platform libraries "
+            "(actually, the entire sdk), "
+            "but got $nonSyntheticPlatformLibraries.";
+    } else {
+      if (nonSyntheticPlatformLibraries != 0)
+        throw "Expected to have 0 platform libraries "
+            "but got $nonSyntheticPlatformLibraries.";
+    }
+    if (world["expectedLibraryCount"] != null) {
+      if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
+          world["expectedLibraryCount"]) {
+        throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
+            "libraries, got "
+            "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
+            "(not counting platform libraries)";
+      }
     }
     if (world["expectedSyntheticLibraryCount"] != null) {
       if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
@@ -312,12 +337,15 @@
             "libraries, got ${syntheticLibraries}";
       }
     }
-    List<Library> entryLib = component.libraries
-        .where((Library lib) => lib.importUri == entry || lib.fileUri == entry)
-        .toList();
-    if (entryLib.length != 1) {
-      throw "Expected the entry to become a library. Got ${entryLib.length} "
-          "libraries for it.";
+    if (!noFullComponent) {
+      List<Library> entryLib = component.libraries
+          .where(
+              (Library lib) => lib.importUri == entry || lib.fileUri == entry)
+          .toList();
+      if (entryLib.length != 1) {
+        throw "Expected the entry to become a library. Got ${entryLib.length} "
+            "libraries for it.";
+      }
     }
     if (compiler.initializedFromDill != expectInitializeFromDill) {
       throw "Expected that initializedFromDill would be "
@@ -340,7 +368,7 @@
       }
     }
 
-    {
+    if (!noFullComponent) {
       Set<String> prevFormattedErrors = formattedErrors.toSet();
       Set<String> prevFormattedWarnings = formattedWarnings.toSet();
       gotError = false;
@@ -351,7 +379,8 @@
       performErrorAndWarningCheck(
           world, gotError, formattedErrors, gotWarning, formattedWarnings);
       List<int> thisWholeComponent = util.postProcess(component2);
-      print("*****\n\ncomponent2:\n${componentToString(component2)}\n\n\n");
+      print("*****\n\ncomponent2:\n"
+          "${componentToStringSdkFiltered(component2)}\n\n\n");
       checkIsEqual(newestWholeComponentData, thisWholeComponent);
       if (prevFormattedErrors.length != formattedErrors.length) {
         Expect.fail("Previously had ${prevFormattedErrors.length} errors, "
@@ -380,6 +409,31 @@
   }
 }
 
+String componentToStringSdkFiltered(Component node) {
+  Component c = new Component();
+  List<Uri> dartUris = new List<Uri>();
+  for (Library lib in node.libraries) {
+    if (lib.importUri.scheme == "dart") {
+      dartUris.add(lib.importUri);
+    } else {
+      c.libraries.add(lib);
+    }
+  }
+
+  StringBuffer s = new StringBuffer();
+  s.write(componentToString(c));
+
+  if (dartUris.isNotEmpty) {
+    s.writeln("");
+    s.writeln("And ${dartUris.length} platform libraries:");
+    for (Uri uri in dartUris) {
+      s.writeln(" - $uri");
+    }
+  }
+
+  return s.toString();
+}
+
 int countNonSyntheticLibraries(Component c) {
   int result = 0;
   for (Library lib in c.libraries) {
@@ -388,6 +442,14 @@
   return result;
 }
 
+int countNonSyntheticPlatformLibraries(Component c) {
+  int result = 0;
+  for (Library lib in c.libraries) {
+    if (!lib.isSynthetic && lib.importUri.scheme == "dart") result++;
+  }
+  return result;
+}
+
 int countSyntheticLibraries(Component c) {
   int result = 0;
   for (Library lib in c.libraries) {
@@ -433,6 +495,7 @@
     ..sdkRoot = sdkRoot
     ..target = new VmTarget(new TargetFlags(legacyMode: !strong))
     ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
+    ..omitPlatform = true
     ..onDiagnostic = (DiagnosticMessage message) {
       if (message.severity == Severity.error ||
           message.severity == Severity.warning) {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml
new file mode 100644
index 0000000..e306e5a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_1.yaml
@@ -0,0 +1,27 @@
+# Copyright (c) 2019, 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.
+
+# Compile a hello world program, check that omit platform works as expected.
+
+type: newworld
+strong: true
+omitPlatform: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("Hello world");
+        }
+    expectedLibraryCount: 1
+  - entry: main.dart
+    noFullComponent: true
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("Hello world!");
+        }
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml
new file mode 100644
index 0000000..e1a42a8a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_2.yaml
@@ -0,0 +1,27 @@
+# Copyright (c) 2019, 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.
+
+# Compile a hello world program, check that omit platform works as expected.
+# Omit platform is true by default in tests.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("Hello world");
+        }
+    expectedLibraryCount: 1
+  - entry: main.dart
+    noFullComponent: true
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("Hello world!");
+        }
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml
new file mode 100644
index 0000000..b649bbd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml
@@ -0,0 +1,80 @@
+# Copyright (c) 2019, 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.
+
+# Compile a hello world program, check that omit platform works as expected.
+# Check that we can compile again, that changes work, than we can ask for a full
+# component again etc.
+
+type: newworld
+strong: true
+omitPlatform: false
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        main() {
+          print("Hello world");
+        }
+    expectedLibraryCount: 1
+    expectsPlatform: true
+    expectInitializeFromDill: false
+  - entry: main.dart
+    noFullComponent: true
+    worldType: updated
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import "lib.dart";
+        main() {
+          print(lib());
+        }
+      lib.dart: |
+        lib() {
+          return "hello";
+        }
+    expectedLibraryCount: 2
+    expectsPlatform: false
+    expectInitializeFromDill: false
+  - entry: main.dart
+    noFullComponent: true
+    worldType: updated
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import "lib.dart";
+        main() {
+          print(lib() + "!");
+        }
+    expectedLibraryCount: 1
+    expectsPlatform: false
+    expectInitializeFromDill: false
+  - entry: main.dart
+    noFullComponent: false
+    worldType: updated
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import "lib.dart";
+        main() {
+          print(lib());
+        }
+    expectedLibraryCount: 2
+    expectsPlatform: true
+    expectInitializeFromDill: false
+  - entry: main.dart
+    noFullComponent: false
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import "lib.dart";
+        main() {
+          print(lib() + "!!");
+        }
+    expectedLibraryCount: 2
+    expectsPlatform: true
+    expectInitializeFromDill: true
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 141fb61..619c943 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -110,6 +110,7 @@
       ..packagesFileUri = packagesUri
       ..sdkSummary = platformKernelPath
       ..verbose = verbose
+      ..omitPlatform = true
       ..bytecode = bytecode
       ..experimentalFlags =
           parseExperimentalFlags(expFlags, (msg) => errors.add(msg))
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 8b15aa5..3263706 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -333,6 +333,7 @@
     Component component;
     if (options['incremental']) {
       _compilerOptions = compilerOptions;
+      _compilerOptions.omitPlatform = true;
       _generator =
           generator ?? _createGenerator(new Uri.file(_initializeFromDill));
       await invalidateIfInitializingFromDill();