2c13c7ea80
Change-Id: I496ed3abbb29ebef14542636aaf1b878f3420740 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192288 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
88 lines
2.5 KiB
Dart
88 lines
2.5 KiB
Dart
// Copyright (c) 2016, 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 file.
|
|
|
|
/// This file contains code for collecting statistics about the use of fields in
|
|
/// a summary file.
|
|
import 'dart:io';
|
|
import 'dart:mirrors';
|
|
|
|
import 'package:analyzer/src/summary/base.dart';
|
|
import 'package:analyzer/src/summary/idl.dart';
|
|
|
|
main(List<String> args) {
|
|
if (args.length != 1) {
|
|
_printUsage();
|
|
exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
String inputFilePath = args[0];
|
|
|
|
// Read the input.
|
|
PackageBundle bundle =
|
|
PackageBundle.fromBuffer(File(inputFilePath).readAsBytesSync());
|
|
|
|
// Compute and output stats.
|
|
Stats stats = Stats();
|
|
stats.record(bundle);
|
|
stats.dump();
|
|
}
|
|
|
|
/// The name of the stats tool.
|
|
const String BINARY_NAME = "stats";
|
|
|
|
/// Print information about how to use the stats tool.
|
|
void _printUsage() {
|
|
print('Usage: $BINARY_NAME input_file_path');
|
|
}
|
|
|
|
/// An instance of [Stats] keeps track of statistics about the use of fields in
|
|
/// summary objects.
|
|
class Stats {
|
|
/// Map from type to field name to a count of how often the field is used.
|
|
Map<Type, Map<String, int>> counts = <Type, Map<String, int>>{};
|
|
|
|
/// Print out statistics gathered so far.
|
|
void dump() {
|
|
counts.forEach((Type type, Map<String, int> typeCounts) {
|
|
print(type);
|
|
List<String> keys = typeCounts.keys.toList();
|
|
keys.sort((a, b) => typeCounts[b]!.compareTo(typeCounts[a]!));
|
|
for (String key in keys) {
|
|
print(' $key: ${typeCounts[key]}');
|
|
}
|
|
print('');
|
|
});
|
|
}
|
|
|
|
/// Record statistics for [obj] and all objects it refers to.
|
|
void record(SummaryClass obj) {
|
|
Map<String, int> typeCounts =
|
|
counts.putIfAbsent(obj.runtimeType, () => <String, int>{});
|
|
obj.toMap().forEach((key, value) {
|
|
if (value == null ||
|
|
value == 0 ||
|
|
value == false ||
|
|
value == '' ||
|
|
value is List && value.isEmpty ||
|
|
// TODO(srawlins): Remove this and enumerate each enum which may
|
|
// be encountered.
|
|
// ignore: avoid_dynamic_calls
|
|
reflect(value).type.isEnum && (value as dynamic).index == 0) {
|
|
return;
|
|
}
|
|
typeCounts.update(key, (value) => value + 1, ifAbsent: () => 0);
|
|
if (value is SummaryClass) {
|
|
record(value);
|
|
} else if (value is List) {
|
|
value.forEach((element) {
|
|
if (element is SummaryClass) {
|
|
record(element);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|