// 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 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> counts = >{}; /// Print out statistics gathered so far. void dump() { counts.forEach((Type type, Map typeCounts) { print(type); List 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 typeCounts = counts.putIfAbsent(obj.runtimeType, () => {}); 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); } }); } }); } }