anchor.diff:      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';
  +  }
  +}
  
positive.code:   String infoFile,
    String coverageFile,
  ) async {
    var info = await infoFromFile(infoFile);
    var coverageRaw = jsonDecode(File(coverageFile).readAsStringSync());
    // The value associated with each coverage item isn't used for now.
    var coverage = coverageRaw.keys.toSet();
  
    int totalProgramSize = info.program!.size;
    int totalLibSize = info.libraries.fold(0, (n, lib) => n + lib.size);
  
negative.code:   RuntimeCoverageAnalysisCommand() {
      argParser.addFlag('show-packages',
          defaultsTo: false, help: "Show coverage details at the package level.");
      argParser.addOption('class-filter',
          defaultsTo: '', help: "Show coverage details filtered by class.");
    }
  
    @override
    void run() async {
      var args = argResults!.rest;
      if (args.length < 2) {
        usageException('Missing arguments, expected: info.data coverage.json');
      }
      var showPackages = argResults!['show-packages'] as bool;
      var filterFile = argResults!['class-filter'] as String;
      if (showPackages && filterFile.isNotEmpty) {
        throw StateError('Cannot specify both packages view and filtered view.');
      }
      if (showPackages) {
        await _reportWithPackages(args[0], args[1]);
      } else if (filterFile.isNotEmpty) {
        _reportWithClassFilter(args[0], args[1], filterFile);
      } else {
        await _report(args[0], args[1]);
      }
  