diff --git a/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart b/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart index 9d4bcbed360b..eea5e1d1f757 100644 --- a/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart +++ b/pkg/dart2js_info/bin/src/runtime_coverage_analysis.dart @@ -35,6 +35,7 @@ import 'package:collection/collection.dart'; import 'package:dart2js_info/info.dart'; import 'package:dart2js_info/src/io.dart'; import 'package:dart2js_info/src/util.dart'; +import 'package:dart2js_info/src/runtime_coverage_utils.dart'; import 'usage_exception.dart'; @@ -274,12 +275,9 @@ Future _reportWithClassFilter( // The value associated with each coverage item isn't used for now. Set coverage = coverageRaw.keys.toSet(); - final classFilterData = {}; - for (final runtimeClassInfo in File(filterFile) - .readAsLinesSync() - .map((l) => RuntimeClassInfo.fromAngularInfo(l))) { - classFilterData[runtimeClassInfo.key] = runtimeClassInfo; - } + final classFilterData = { + for (final info in runtimeInfoFromAngularInfo(filterFile)) info.key: info + }; // Ensure that a used class's super, mixed in, and implemented classes are // correctly marked as used. @@ -445,88 +443,3 @@ void _show(String msg, int size, int total) { void _leftPadded(String msg1, String msg2) { print(' ${pad(msg1, 50, right: true)} $msg2'); } - -class RuntimePackageInfo { - final elements = PriorityQueue((a, b) => b.size.compareTo(a.size)); - - num mainUnitSize = 0; - num totalSize = 0; - num unusedMainUnitSize = 0; - num unusedSize = 0; - num usedRatio = 0; - num usedSize = 0; - - RuntimePackageInfo(); - - void add(BasicInfo i, {bool used = true}) { - totalSize += i.size; - if (used) { - usedSize += i.size; - } else { - unusedSize += i.size; - } - if (i.outputUnit!.name == 'main') { - mainUnitSize += i.size; - if (!used) { - unusedMainUnitSize += i.size; - } - } - elements.add(i); - usedRatio = usedSize / totalSize; - } -} - -class RuntimeClassInfo { - late String scheme; - late String package; - late String? path; - late String name; - - late num size; - late bool used; - late bool inMainUnit; - late ClassInfo info; - - bool annotated = false; - - RuntimeClassInfo(); - - /// Ingests the output from Angular's info generator. - /// - /// Example: 'fully:qualified/path/to/file.dart - ClassName' - RuntimeClassInfo.fromAngularInfo(String input) { - final colonIndex = input.indexOf(':'); - if (colonIndex < 0) { - throw ArgumentError('AngularInfo format cannot accept undefined schemes.' - ' No scheme found for: $input'); - } - final slashIndex = input.indexOf('/'); - final spaceIndex = input.indexOf(' '); - final separatorSize = ' - '.length; - scheme = input.substring(0, colonIndex); - if (slashIndex < 0) { - path = null; - package = input.substring(colonIndex + 1, spaceIndex); - } else { - package = input.substring(colonIndex + 1, slashIndex); - path = input.substring(slashIndex + 1, spaceIndex); - } - name = input.substring(spaceIndex + separatorSize, input.length); - } - - String get key => - '$package${path == null ? '' : '/$path'}:$name'.replaceAll('/lib/', '/'); - - void annotateWithClassInfo(ClassInfo i, {bool used = true}) { - size = i.size; - this.used = used; - inMainUnit = i.outputUnit!.name == 'main'; - info = i; - annotated = true; - } - - @override - String toString() { - return '$package/$path - $name'; - } -} diff --git a/pkg/dart2js_info/lib/src/runtime_coverage_utils.dart b/pkg/dart2js_info/lib/src/runtime_coverage_utils.dart new file mode 100644 index 000000000000..04a13562312d --- /dev/null +++ b/pkg/dart2js_info/lib/src/runtime_coverage_utils.dart @@ -0,0 +1,117 @@ +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:dart2js_info/info.dart'; + +List runtimeInfoFromAngularInfo(String angularInfoFilePath) { + final angularInfoFile = File(angularInfoFilePath); + final runtimeInfo = []; + final separator = ' - '; + for (final line in angularInfoFile.readAsLinesSync()) { + // Ignore lines without two ' - ' separators. + if (separator.allMatches(line).length != 2) continue; + runtimeInfo.add(RuntimeClassInfo.fromAngularInfo(line)); + } + return runtimeInfo; +} + +class RuntimePackageInfo { + final elements = PriorityQueue((a, b) => b.size.compareTo(a.size)); + + num mainUnitSize = 0; + num totalSize = 0; + num unusedMainUnitSize = 0; + num unusedSize = 0; + num usedRatio = 0; + num usedSize = 0; + + RuntimePackageInfo(); + + void add(BasicInfo i, {bool used = true}) { + totalSize += i.size; + if (used) { + usedSize += i.size; + } else { + unusedSize += i.size; + } + if (i.outputUnit!.name == 'main') { + mainUnitSize += i.size; + if (!used) { + unusedMainUnitSize += i.size; + } + } + elements.add(i); + usedRatio = usedSize / totalSize; + } +} + +class RuntimeClassInfo { + late String scheme; + late String package; + late String? path; + late String name; + + late num size; + late bool used; + late bool inMainUnit; + late ClassInfo info; + + bool annotated = false; + + RuntimeClassInfo(); + + RuntimeClassInfo.fromQualifiedName(String qualifiedName) { + final colonIndex = qualifiedName.indexOf(':'); + final slashIndex = qualifiedName.indexOf('/'); + final colonIndex2 = qualifiedName.lastIndexOf(':'); + scheme = qualifiedName.substring(0, colonIndex); + package = qualifiedName.substring(colonIndex + 1, slashIndex); + path = qualifiedName.substring(slashIndex + 1, colonIndex2); + name = qualifiedName.substring(colonIndex2 + 1, qualifiedName.length); + } + + /// Ingests the output from Angular's info generator. + /// + /// Example: 'fully:qualified/path/to/file.dart - ClassName - 123 (bytes)' + RuntimeClassInfo.fromAngularInfo(String rawInput) { + final separator = ' - '; + final separatorSize = separator.length; + // Remove the size specification. + var input = rawInput; + if (separator.allMatches(rawInput).length > 1) { + input = rawInput.substring(0, rawInput.lastIndexOf(separator)); + } + final colonIndex = input.indexOf(':'); + if (colonIndex < 0) { + throw ArgumentError('AngularInfo format cannot accept undefined schemes.' + ' No scheme found for: $input'); + } + final slashIndex = input.indexOf('/'); + final spaceIndex = input.indexOf(' '); + scheme = input.substring(0, colonIndex); + if (slashIndex < 0) { + path = null; + package = input.substring(colonIndex + 1, spaceIndex); + } else { + package = input.substring(colonIndex + 1, slashIndex); + path = input.substring(slashIndex + 1, spaceIndex); + } + name = input.substring(spaceIndex + separatorSize, input.length); + } + + String get key => + '$package${path == null ? '' : '/$path'}:$name'.replaceAll('/lib/', '/'); + + void annotateWithClassInfo(ClassInfo i, {bool used = true}) { + size = i.size; + this.used = used; + inMainUnit = i.outputUnit!.name == 'main'; + info = i; + annotated = true; + } + + @override + String toString() { + return '$package/$path - $name'; + } +} diff --git a/pkg/dart2js_info/test/classes/class_filter.txt b/pkg/dart2js_info/test/classes/class_filter.txt index aa011aa3d607..e1aec5bad8c8 100644 --- a/pkg/dart2js_info/test/classes/class_filter.txt +++ b/pkg/dart2js_info/test/classes/class_filter.txt @@ -1,5 +1,5 @@ -dart:_rti - _Universe -dart:core - Error -testroot:classes.dart - Subsub1 -testroot:classes.dart - Super -package:expect/expect.dart - Expect +dart:_rti - _Universe - 300 (bytes) +dart:core - Error - 300 (bytes) +testroot:classes.dart - Subsub1 - 300 (bytes) +testroot:classes.dart - Super - 300 (bytes) +package:expect/expect.dart - Expect - 300 (bytes) diff --git a/pkg/dart2js_info/test/runtime_coverage_test.dart b/pkg/dart2js_info/test/runtime_coverage_test.dart index 9d5d0484bce4..d73b8366437c 100644 --- a/pkg/dart2js_info/test/runtime_coverage_test.dart +++ b/pkg/dart2js_info/test/runtime_coverage_test.dart @@ -14,10 +14,10 @@ import 'dart:io'; import 'package:dart2js_info/binary_serialization.dart'; +import 'package:dart2js_info/src/runtime_coverage_utils.dart'; import 'package:dart2js_info/src/util.dart'; -import 'package:test/test.dart'; -import '../bin/src/runtime_coverage_analysis.dart'; +import 'package:test/test.dart'; void main() { group('runtime coverage', () {