Skip dart: sources by default (dart-lang/coverage#257)

Skips collecting coverage for VM scripts with URIs with scheme 'dart'.
There's a lot of this source, most users aren't interested in collecting
coverage for it, and those who do, can still get at it by passing the
`--include-dart` flag if they want it.
diff --git a/pkgs/coverage/CHANGELOG.md b/pkgs/coverage/CHANGELOG.md
index fc834fb..31b10eb 100644
--- a/pkgs/coverage/CHANGELOG.md
+++ b/pkgs/coverage/CHANGELOG.md
@@ -1,5 +1,9 @@
 ## dev
 
+ * BREAKING CHANGE: Skips collecting coverage for `dart:` libaries by default,
+   which provides a significant performance boost. To restore the previous
+   behaviour and collect coverage for these libraries, use the `--include-dart`
+   flag.
  * Disables WebSocket compression for coverage collection. Since almost all
    coverage collection runs happen over the loopback interface to localhost,
    this improves performance and reduces CPU usage.
diff --git a/pkgs/coverage/bin/collect_coverage.dart b/pkgs/coverage/bin/collect_coverage.dart
index 60b354b..dccb996 100644
--- a/pkgs/coverage/bin/collect_coverage.dart
+++ b/pkgs/coverage/bin/collect_coverage.dart
@@ -19,8 +19,8 @@
 
   final options = _parseArgs(arguments);
   await Chain.capture(() async {
-    final coverage = await collect(
-        options.serviceUri, options.resume, options.waitPaused,
+    final coverage = await collect(options.serviceUri, options.resume,
+        options.waitPaused, options.includeDart,
         timeout: options.timeout);
     options.out.write(json.encode(coverage));
     await options.out.close();
@@ -34,14 +34,15 @@
 }
 
 class Options {
-  Options(
-      this.serviceUri, this.out, this.timeout, this.waitPaused, this.resume);
+  Options(this.serviceUri, this.out, this.timeout, this.waitPaused, this.resume,
+      this.includeDart);
 
   final Uri serviceUri;
   final IOSink out;
   final Duration timeout;
   final bool waitPaused;
   final bool resume;
+  final bool includeDart;
 }
 
 Options _parseArgs(List<String> arguments) {
@@ -65,6 +66,8 @@
         help: 'wait for all isolates to be paused before collecting coverage')
     ..addFlag('resume-isolates',
         abbr: 'r', defaultsTo: false, help: 'resume all isolates on exit')
+    ..addFlag('include-dart',
+        abbr: 'd', defaultsTo: false, help: 'include "dart:" libraries')
     ..addFlag('help', abbr: 'h', negatable: false, help: 'show this help');
 
   final args = parser.parse(arguments);
@@ -108,6 +111,6 @@
   final timeout = (args['connect-timeout'] == null)
       ? null
       : Duration(seconds: int.parse(args['connect-timeout']));
-  return Options(
-      serviceUri, out, timeout, args['wait-paused'], args['resume-isolates']);
+  return Options(serviceUri, out, timeout, args['wait-paused'],
+      args['resume-isolates'], args['include-dart']);
 }
diff --git a/pkgs/coverage/lib/src/collect.dart b/pkgs/coverage/lib/src/collect.dart
index aef1c7f..cc8ec42 100644
--- a/pkgs/coverage/lib/src/collect.dart
+++ b/pkgs/coverage/lib/src/collect.dart
@@ -25,7 +25,7 @@
 /// If [waitPaused] is true, collection will not begin until all isolates are
 /// in the paused state.
 Future<Map<String, dynamic>> collect(
-    Uri serviceUri, bool resume, bool waitPaused,
+    Uri serviceUri, bool resume, bool waitPaused, bool includeDart,
     {Duration timeout}) async {
   if (serviceUri == null) throw ArgumentError('serviceUri must not be null');
 
@@ -55,7 +55,7 @@
       await _waitIsolatesPaused(service, timeout: timeout);
     }
 
-    return await _getAllCoverage(service);
+    return await _getAllCoverage(service, includeDart);
   } finally {
     if (resume) {
       await _resumeIsolates(service);
@@ -64,7 +64,8 @@
   }
 }
 
-Future<Map<String, dynamic>> _getAllCoverage(VmService service) async {
+Future<Map<String, dynamic>> _getAllCoverage(
+    VmService service, bool includeDart) async {
   final vm = await service.getVM();
   final allCoverage = <Map<String, dynamic>>[];
 
@@ -74,7 +75,8 @@
       <String>[SourceReportKind.kCoverage],
       forceCompile: true,
     );
-    final coverage = await _getCoverageJson(service, isolateRef, report);
+    final coverage =
+        await _getCoverageJson(service, isolateRef, report, includeDart);
     allCoverage.addAll(coverage);
   }
   return <String, dynamic>{'type': 'CodeCoverage', 'coverage': allCoverage};
@@ -137,8 +139,8 @@
 }
 
 /// Returns a JSON coverage list backward-compatible with pre-1.16.0 SDKs.
-Future<List<Map<String, dynamic>>> _getCoverageJson(
-    VmService service, IsolateRef isolateRef, SourceReport report) async {
+Future<List<Map<String, dynamic>>> _getCoverageJson(VmService service,
+    IsolateRef isolateRef, SourceReport report, bool includeDart) async {
   // script uri -> { line -> hit count }
   final hitMaps = <Uri, Map<int, int>>{};
   final scripts = <ScriptRef, Script>{};
@@ -149,6 +151,9 @@
     // Not returned in scripts section of source report.
     if (scriptUri.scheme == 'evaluate') continue;
 
+    // Skip scripts from dart:.
+    if (!includeDart && scriptUri.scheme == 'dart') continue;
+
     if (!scripts.containsKey(scriptRef)) {
       scripts[scriptRef] = await service.getObject(isolateRef.id, scriptRef.id);
     }
diff --git a/pkgs/coverage/lib/src/run_and_collect.dart b/pkgs/coverage/lib/src/run_and_collect.dart
index 9142b43..448009b 100644
--- a/pkgs/coverage/lib/src/run_and_collect.dart
+++ b/pkgs/coverage/lib/src/run_and_collect.dart
@@ -13,6 +13,7 @@
     {List<String> scriptArgs,
     bool checked = false,
     String packageRoot,
+    bool includeDart = false,
     Duration timeout}) async {
   final dartArgs = [
     '--enable-vm-service',
@@ -48,7 +49,8 @@
   final serviceUri = await serviceUriCompleter.future;
   Map<String, dynamic> coverage;
   try {
-    coverage = await collect(serviceUri, true, true, timeout: timeout);
+    coverage =
+        await collect(serviceUri, true, true, includeDart, timeout: timeout);
   } finally {
     await process.stderr.drain<List<int>>();
   }
diff --git a/pkgs/coverage/test/collect_coverage_api_test.dart b/pkgs/coverage/test/collect_coverage_api_test.dart
index 1747762..ca5ba11 100644
--- a/pkgs/coverage/test/collect_coverage_api_test.dart
+++ b/pkgs/coverage/test/collect_coverage_api_test.dart
@@ -19,7 +19,7 @@
 
 void main() {
   test('collect throws when serviceUri is null', () {
-    expect(() => collect(null, true, false), throwsArgumentError);
+    expect(() => collect(null, true, false, false), throwsArgumentError);
   });
 
   test('collect_coverage_api', () async {
@@ -77,5 +77,5 @@
   });
   final Uri serviceUri = await serviceUriCompleter.future;
 
-  return collect(serviceUri, true, true, timeout: timeout);
+  return collect(serviceUri, true, true, false, timeout: timeout);
 }
diff --git a/pkgs/coverage/test/lcov_test.dart b/pkgs/coverage/test/lcov_test.dart
index 8ac0e80..9eabad3 100644
--- a/pkgs/coverage/test/lcov_test.dart
+++ b/pkgs/coverage/test/lcov_test.dart
@@ -176,7 +176,7 @@
 
   // collect hit map.
   final List<Map> coverageJson =
-      (await collect(serviceUri, true, true))['coverage'];
+      (await collect(serviceUri, true, true, false))['coverage'];
   final hitMap = createHitmap(coverageJson);
 
   // wait for sample app to terminate.