anchor.diff:  library front_end.tool.perf;
   
   import 'dart:async';
  -import 'dart:io' show exit, stderr;
  +import 'dart:io' show exit;
   
   import 'package:analyzer/dart/ast/ast.dart';
   import 'package:analyzer/error/listener.dart';
  
positive.code: import 'package:analyzer/src/summary/idl.dart';
  import 'package:analyzer/src/summary/link.dart';
  import 'package:analyzer/src/summary/summarize_ast.dart';
  import 'package:kernel/analyzer/loader.dart';
  import 'package:kernel/kernel.dart';
  import 'package:package_config/discovery.dart';
  
  import 'package:front_end/compiler_options.dart';
  import 'package:front_end/kernel_generator.dart';
  import 'package:front_end/src/scanner/reader.dart';
  import 'package:front_end/src/scanner/scanner.dart';
  import 'package:front_end/src/scanner/token.dart';
  
  /// Cumulative total number of chars scanned.
  int scanTotalChars = 0;
  
  /// Cumulative time spent scanning.
  Stopwatch scanTimer = new Stopwatch();
  
  /// Cumulative time spent parsing.
  Stopwatch parseTimer = new Stopwatch();
  
  /// Cumulative time spent building unlinked summaries.
  Stopwatch unlinkedSummarizeTimer = new Stopwatch();
  
  /// Cumulative time spent prelinking summaries.
  Stopwatch prelinkSummaryTimer = new Stopwatch();
  
  /// Factory to load and resolve app, packages, and sdk sources.
  SourceFactory sources;
  
  main(List<String> args) async {
    // TODO(sigmund): provide sdk folder as well.
  
negative.code:   return token;
  }
  
  UnlinkedUnitBuilder unlinkedSummarize(Source source) {
    var unit = parseFull(source);
    unlinkedSummarizeTimer.start();
    var unlinkedUnit = serializeAstUnlinked(unit);
    unlinkedSummarizeTimer.stop();
    return unlinkedUnit;
  }
  
  /// Produces unlinked summaries for every file in [files] and reports the time
  /// spent doing so.
  void unlinkedSummarizeFiles(Set<Source> files) {
    // The code below will record again how many chars are scanned and how long it
    // takes to scan them, even though we already did so in [scanReachableFiles].
    // Recording and reporting this twice is unnecessary, but we do so for now to
    // validate that the results are consistent.
    scanTimer = new Stopwatch();
    var old = scanTotalChars;
    scanTotalChars = 0;
    parseTimer = new Stopwatch();
    unlinkedSummarizeTimer = new Stopwatch();
    generateUnlinkedSummaries(files);
  
    if (old != scanTotalChars) print('input size changed? ${old} chars');
    report("scan", scanTimer.elapsedMicroseconds);
    report("parse", parseTimer.elapsedMicroseconds);
    report('unlinked summarize', unlinkedSummarizeTimer.elapsedMicroseconds);
    report(
        'unlinked summarize + parse',
        unlinkedSummarizeTimer.elapsedMicroseconds +
            parseTimer.elapsedMicroseconds);
  }
  
  /// Simple container for a mapping from URI string to an unlinked summary.
  class UnlinkedSummaries {
    final summariesByUri = <String, UnlinkedUnit>{};
  
    /// Get the unlinked summary for the given URI, and report a warning if it
    /// can't be found.
    UnlinkedUnit getUnit(String uri) {
      var result = summariesByUri[uri];
      if (result == null) {
        print('Warning: no summary found for: $uri');
      }
      return result;
    }
  }
  
  class _Scanner extends Scanner {
    _Scanner(String contents) : super(new CharSequenceReader(contents)) {
      preserveComments = false;
  