// 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.

library sourcemap.diff_view;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:_fe_analyzer_shared/src/util/filenames.dart';
import 'package:compiler/src/common/elements.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/invariant.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/io/position_information.dart';
import 'package:compiler/src/io/source_information.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/js/js.dart' as js;

import '../helpers/diff.dart';
import '../helpers/html_parts.dart';
import '../helpers/js_tracer.dart';
import '../helpers/output_structure.dart';
import '../helpers/sourcemap_helper.dart';
import '../helpers/sourcemap_html_helper.dart';
import '../helpers/trace_graph.dart';

main(List<String> args) async {
  debugMode = true;
  String out = 'out.js.diff_view.html';
  late String filename;
  List<String> currentOptions = [];
  List<List<String>> optionSegments = [currentOptions];
  Map<int, String> loadFrom = {};
  Map<int, String> saveTo = {};
  int argGroup = 0;
  bool showAnnotations = true;
  for (String arg in args) {
    if (arg == '--') {
      currentOptions = [];
      optionSegments.add(currentOptions);
      argGroup++;
    } else if (arg == '-h') {
      showAnnotations = false;
      print('Hiding annotations');
    } else if (arg == '-l') {
      loadFrom[argGroup] = 'out.js.diff$argGroup.json';
    } else if (arg.startsWith('--load=')) {
      loadFrom[argGroup] = arg.substring('--load='.length);
    } else if (arg == '-s') {
      saveTo[argGroup] = 'out.js.diff$argGroup.json';
    } else if (arg.startsWith('--save=')) {
      saveTo[argGroup] = arg.substring('--save='.length);
    } else if (arg.startsWith('-o')) {
      out = arg.substring('-o'.length);
    } else if (arg.startsWith('--out=')) {
      out = arg.substring('--out='.length);
    } else if (arg.startsWith('-')) {
      currentOptions.add(arg);
    } else {
      filename = arg;
    }
  }
  List<String> commonArguments = optionSegments[0];
  List<List<String>> options = <List<String>>[];
  if (optionSegments.length == 1) {
    // TODO(sigmund, johnniwinther): change default options now that CPS is
    // deleted.
    // Use default options; comparing SSA and CPS output using the new
    // source information strategy.
    options.add(commonArguments);
    options.add([Flags.useNewSourceInfo]..addAll(commonArguments));
  } else if (optionSegments.length == 2) {
    // Use alternative options for the second output column.
    options.add(commonArguments);
    options.add(optionSegments[1]..addAll(commonArguments));
  } else {
    // Use specific options for both output columns.
    options.add(optionSegments[1]..addAll(commonArguments));
    options.add(optionSegments[2]..addAll(commonArguments));
  }

  SourceFileManager sourceFileManager = IOSourceFileManager(Uri.base);
  List<AnnotatedOutput> outputs = <AnnotatedOutput>[];
  for (int i = 0; i < 2; i++) {
    AnnotatedOutput output;
    if (loadFrom.containsKey(i)) {
      output = AnnotatedOutput.loadOutput(loadFrom[i]);
    } else {
      print('Compiling ${options[i].join(' ')} $filename');
      CodeLinesResult result = await computeCodeLines(
        options[i],
        filename,
        Uri.base.resolve(nativeToUriPath(filename)),
      );
      OutputStructure structure = OutputStructure.parse(result.codeLines);
      computeEntityCodeSources(result, structure);
      output = AnnotatedOutput(
        filename,
        options[i],
        structure,
        result.coverage.getCoverageReport(),
      );
    }
    if (saveTo.containsKey(i)) {
      AnnotatedOutput.saveOutput(output, saveTo[i]!);
    }
    outputs.add(output);
  }

  List<DiffBlock> blocks = createDiffBlocks(
    outputs.map((o) => o.structure).toList(),
    sourceFileManager,
  );

  outputDiffView(
    out,
    outputs,
    blocks,
    showMarkers: showAnnotations,
    showSourceMapped: showAnnotations,
  );
}

/// Attaches [CodeSource]s to the entities in [structure] using the
/// element-to-offset in [result].
void computeEntityCodeSources(
  CodeLinesResult result,
  OutputStructure structure,
) {
  result.elementMap.forEach((int line, MemberEntity element) {
    OutputEntity? entity = structure.getEntityForLine(line);
    if (entity != null) {
      entity.codeSource = codeSourceFromElement(element);
    }
  });
}

class CodeLineAnnotationJsonStrategy implements JsonStrategy {
  const CodeLineAnnotationJsonStrategy();

  @override
  Map encodeAnnotation(Annotation annotation) {
    CodeLineAnnotation data = annotation.data;
    return {
      'id': annotation.id,
      'codeOffset': annotation.codeOffset,
      'title': annotation.title,
      'data': data.toJson(this),
    };
  }

  @override
  Annotation decodeAnnotation(Map json) {
    return Annotation(
      json['id'],
      json['codeOffset'],
      json['title'],
      data: CodeLineAnnotation.fromJson(json['data'], this),
    );
  }

  @override
  decodeLineAnnotation(json) {
    if (json != null) {
      return CodeSource.fromJson(json);
    }
    return null;
  }

  @override
  Map? encodeLineAnnotation(covariant CodeSource? lineAnnotation) {
    if (lineAnnotation != null) {
      return lineAnnotation.toJson();
    }
    return null;
  }
}

/// The structured output of a compilation.
class AnnotatedOutput {
  final String filename;
  final List<String> options;
  final OutputStructure structure;
  final String coverage;

  AnnotatedOutput(this.filename, this.options, this.structure, this.coverage);

  List<CodeLine> get codeLines => structure.lines;

  Map toJson() {
    return {
      'filename': filename,
      'options': options,
      'structure': structure.toJson(const CodeLineAnnotationJsonStrategy()),
      'coverage': coverage,
    };
  }

  static AnnotatedOutput fromJson(Map json) {
    String filename = json['filename'];
    List<String> options = json['options'];
    OutputStructure structure = OutputStructure.fromJson(
      json['structure'],
      const CodeLineAnnotationJsonStrategy(),
    );
    String coverage = json['coverage'];
    return AnnotatedOutput(filename, options, structure, coverage);
  }

  static AnnotatedOutput loadOutput(filename) {
    AnnotatedOutput output = AnnotatedOutput.fromJson(
      json.decode(new File(filename).readAsStringSync()),
    );
    print('Output loaded from $filename');
    return output;
  }

  static void saveOutput(AnnotatedOutput output, String? filename) {
    if (filename != null) {
      File(filename).writeAsStringSync(
        const JsonEncoder.withIndent('  ').convert(output.toJson()),
      );
      print('Output saved in $filename');
    }
  }
}

void outputDiffView(
  String out,
  List<AnnotatedOutput> outputs,
  List<DiffBlock> blocks, {
  bool showMarkers = true,
  bool showSourceMapped = true,
}) {
  assert(outputs[0].filename == outputs[1].filename);

  StringBuffer sb = StringBuffer();
  sb.write('''
<html>
<head>
<title>Diff for ${outputs[0].filename}</title>
<style>
.${ClassNames.lineNumber} {
  font-size: smaller;
  color: #888;
}
.${ClassNames.comment} {
  font-size: smaller;
  color: #888;
  font-family: initial;
}
.${ClassNames.header} {
  position: fixed;
  width: 100%;
  background-color: #FFFFFF;
  left: 0px;
  top: 0px;
  height: 42px;
  z-index: 1000;
}
.${ClassNames.headerTable} {
  width: 100%;
  background-color: #400000;
  color: #FFFFFF;
  border-spacing: 0px;
}
.${ClassNames.headerColumn} {
}
.${ClassNames.legend} {
  padding: 2px;
}
.${ClassNames.buttons} {
  position: fixed;
  right: 0px;
  top: 0px;
  width: 220px;
  background-color: #FFFFFF;
  border: 1px solid #C0C0C0;
  z-index: 2000;
}
.${ClassNames.table} {
  position: absolute;
  left: 0px;
  top: 42px;
  width: 100%;
  border-spacing: 0px;
}
.${ClassNames.cell},
.${ClassNames.innerCell},
.${ClassNames.originalDart},
.${ClassNames.inlinedDart} {
  overflow-y: hidden;
  vertical-align: top;
  overflow-x: hidden;
  white-space: pre-wrap;
  font-family: monospace;
  padding: 0px;
}
.${ClassNames.cell} {
  border-top: 1px solid #F0F0F0;
  border-left: 1px solid #C0C0C0;
}
.${ClassNames.innerCell} {
  /*border-top: 1px solid #F8F8F8;*/
  width: 50%;
  max-width: 250px;
}
.${ClassNames.corresponding(false)} {
  background-color: #FFFFE0;
}
.${ClassNames.corresponding(true)} {
  background-color: #EFEFD0;
}
.${ClassNames.identical(false)} {
  background-color: #E0F0E0;
}
.${ClassNames.identical(true)} {
  background-color: #C0E0C0;
}
.${ClassNames.line} {
  padding-left: 7em;
  text-indent: -7em;
  margin: 0px;
}
.${ClassNames.column(column_js0)} {
  max-width: 500px;
  width: 500px;
}
.${ClassNames.column(column_js1)} {
  max-width: 500px;
  width: 500px;
}
.${ClassNames.column(column_dart)} {
  max-width: 300px;
  width: 300px;
}
.${ClassNames.colored(0)} {
  color: #FF0000;
}
.${ClassNames.colored(1)} {
  color: #C0C000;
}
.${ClassNames.colored(2)} {
  color: #008000;
}
.${ClassNames.colored(3)} {
  color: #00C0C0;
}
.${ClassNames.withSourceInfo} {
  border: solid 1px #FF8080;
}
.${ClassNames.withoutSourceInfo} {
  background-color: #8080FF;
}
.${ClassNames.additionalSourceInfo} {
  border: solid 1px #80FF80;
}
.${ClassNames.unusedSourceInfo} {
  border: solid 1px #8080FF;
}
.${ClassNames.originalDart} {
}
.${ClassNames.inlinedDart} {
}
''');
  for (int i = 0; i < HUE_COUNT; i++) {
    sb.write('''
.${ClassNames.sourceMappingIndex(i)} {
  background-color: ${toColorCss(i)};
}
''');
  }
  sb.write('''
.${ClassNames.sourceMapped} {
  ${showSourceMapped ? '' : 'display: none;'}
}
.${ClassNames.sourceMapping} {
  ${showSourceMapped ? '' : 'border: 0px;'}
  ${showSourceMapped ? '' : 'background-color: transparent;'}
}
.${ClassNames.markers} {
  ${showMarkers ? '' : 'display: none;'}
}
.${ClassNames.marker} {
  ${showMarkers ? '' : 'border: 0px;'}
  ${showMarkers ? '' : 'background-color: transparent;'}
}
</style>
<script>
function isChecked(name) {
  var box = document.getElementById('box-' + name);
  return box.checked;
}
function toggleDisplay(name) {
  var checked = isChecked(name);
  var styleSheet = document.styleSheets[0];
  for (var index = 0; index < styleSheet.cssRules.length; index++) {
    var cssRule = styleSheet.cssRules[index];
    if (cssRule.selectorText == '.' + name) {
      if (checked) {
        cssRule.style.removeProperty('display');
      } else {
        cssRule.style.display = 'none';
      }
    }
  }
  return checked;
}
function toggle${ClassNames.sourceMapped}() {
  var checked = toggleDisplay('${ClassNames.sourceMapped}');
  toggleAnnotations(checked, '${ClassNames.sourceMapping}');
}
function toggle${ClassNames.markers}() {
  var checked = toggleDisplay('${ClassNames.markers}');
  toggleAnnotations(checked, '${ClassNames.marker}');
}
function toggleAnnotations(show, name) {
  var styleSheet = document.styleSheets[0];
  for (var index = 0; index < styleSheet.cssRules.length; index++) {
    var cssRule = styleSheet.cssRules[index];
    if (cssRule.selectorText == '.' + name) {
      if (show) {
        cssRule.style.removeProperty('border');
        cssRule.style.removeProperty('background-color');
      } else {
        cssRule.style.border = '0px';
        cssRule.style.backgroundColor = 'transparent';
      }
    }
  }
}
</script>
</head>
<body>''');

  sb.write('''
<div class="${ClassNames.header}">
<div class="${ClassNames.legend}">
  <span class="${ClassNames.identical(false)}">&nbsp;&nbsp;&nbsp;</span>
  <span class="${ClassNames.identical(true)}">&nbsp;&nbsp;&nbsp;</span>
  identical blocks
  <span class="${ClassNames.corresponding(false)}">&nbsp;&nbsp;&nbsp;</span>
  <span class="${ClassNames.corresponding(true)}">&nbsp;&nbsp;&nbsp;</span>
  corresponding blocks
''');

  sb.write('''
  <span class="${ClassNames.markers}">
  <span class="${ClassNames.withSourceInfo}">&nbsp;&nbsp;&nbsp;</span>
  <span title="'offset with source information' means that source information
is available for an offset which is expected to have a source location
attached. This offset has source information as intended.">
  offset with source information</span>
  <span class="${ClassNames.withoutSourceInfo}">&nbsp;&nbsp;&nbsp;</span>
  <span title="'offset without source information' means that _no_ source
information is available for an offset which was expected to have a source
location attached. Source information must be found for this offset.">
  offset without source information</span>
  <span class="${ClassNames.additionalSourceInfo}">&nbsp;&nbsp;&nbsp;</span>
  <span title="'offset with unneeded source information' means that a source
location was attached to an offset which was _not_ expected to have a source
location attached. The source location should be removed from this offset.">
  offset with unneeded source information</span>
  <span class="${ClassNames.unusedSourceInfo}">&nbsp;&nbsp;&nbsp;</span>
  <span title="'offset with unused source information' means that source
information is available for an offset which is _not_ expected to have a source
location attached. This source information _could_ be used by a parent AST node
offset that is an 'offset without source information'.">
  offset with unused source information</span>
  </span>
  <span class="${ClassNames.sourceMapped}">
''');
  for (int i = 0; i < HUE_COUNT; i++) {
    sb.write('''
<span class="${ClassNames.sourceMappingIndex(i)}">&nbsp;&nbsp;</span>''');
  }
  sb.write('''
  <span title="JavaScript offsets and their corresponding Dart Code offset
as mapped through source-maps.">
  mapped source locations</span>
  </span>
''');

  /// Marker to alternate output colors.
  bool alternating = false;

  List<HtmlPrintContext> printContexts = <HtmlPrintContext>[];
  for (int i = 0; i < 2; i++) {
    int? lineNoWidth;
    if (outputs[i].codeLines.isNotEmpty) {
      lineNoWidth = '${outputs[i].codeLines.last.lineNo + 1}'.length;
    }
    printContexts.add(
      new HtmlPrintContext(
        lineNoWidth: lineNoWidth,
        getAnnotationData: getAnnotationData,
        getLineData: getLineData,
      ),
    );
  }

  Set<DiffColumn> allColumns = Set<DiffColumn>();
  for (DiffBlock block in blocks) {
    allColumns.addAll(block.columns);
  }

  List<DiffColumn> columns = [
    column_js0,
    column_js1,
    column_dart,
  ].where((c) => allColumns.contains(c)).toList();

  sb.write('''
</div>
<table class="${ClassNames.headerTable}"><tr>''');
  for (DiffColumn column in columns) {
    sb.write('''
<td class="${ClassNames.headerColumn} ${ClassNames.column(column)}">''');
    if (column.type == 'js') {
      sb.write('''[${outputs[column.index!].options.join(',')}]''');
    } else {
      sb.write('''Dart code''');
    }
    sb.write('''</td>''');
  }

  sb.write('''
</tr></table>
</div>
<table class="${ClassNames.table}">
''');

  for (DiffBlock block in blocks) {
    String className;
    switch (block.kind) {
      case DiffKind.UNMATCHED:
        className = '${ClassNames.cell}';
        break;
      case DiffKind.MATCHING:
        className =
            '${ClassNames.cell} ${ClassNames.corresponding(alternating)}';
        alternating = !alternating;
        break;
      case DiffKind.IDENTICAL:
        className = '${ClassNames.cell} ${ClassNames.identical(alternating)}';
        alternating = !alternating;
        break;
    }
    sb.write('<tr>');
    for (DiffColumn column in columns) {
      sb.write('''<td class="$className ${ClassNames.column(column)}">''');
      HtmlPrintContext context = HtmlPrintContext(
        lineNoWidth: 4,
        includeAnnotation: (Annotation annotation) {
          CodeLineAnnotation data = annotation.data;
          return data.annotationType == AnnotationType.withSourceInfo ||
              data.annotationType == AnnotationType.additionalSourceInfo;
        },
        getAnnotationData: getAnnotationData,
        getLineData: getLineData,
      );
      if (column.type == 'js') {
        context = printContexts[column.index!];
      }
      block.printHtmlOn(column, sb, context);
      sb.write('''</td>''');
    }
    sb.write('</tr>');
  }

  sb.write('''</tr><tr>''');

  for (DiffColumn column in columns) {
    sb.write('''
<td class="${ClassNames.cell} ${ClassNames.column(column)}"><pre>''');
    if (column.type == 'js') {
      sb.write(outputs[column.index!].coverage);
    }
    sb.write('''</td>''');
  }

  sb.write('''
</table>
<div class="${ClassNames.buttons}">
<input type="checkbox" id="box-${ClassNames.column(column_js0)}"
  onclick="javascript:toggleDisplay('${ClassNames.column(column_js0)}')"
  checked>
Left JavaScript code<br/>

<input type="checkbox" id="box-${ClassNames.column(column_js1)}"
  onclick="javascript:toggleDisplay('${ClassNames.column(column_js1)}')"
  checked>
Right JavaScript code<br/>

<input type="checkbox" id="box-${ClassNames.column(column_dart)}"
  onclick="javascript:toggleDisplay('${ClassNames.column(column_dart)}')"
  checked>
<span title="Show column with Dart code corresponding to the block.">
Dart code</span><br/>

<input type="checkbox" id="box-${ClassNames.inlinedDart}"
  onclick="javascript:toggleDisplay('${ClassNames.inlinedDart}')" checked>
<span title="Show Dart code inlined into the block.">
Inlined Dart code</span><br/>

<input type="checkbox" id="box-${ClassNames.markers}"
  onclick="javascript:toggle${ClassNames.markers}()"
  ${showMarkers ? 'checked' : ''}>
<span title="Show markers for JavaScript offsets with source information.">
Source information markers</span><br/>

<input type="checkbox" id="box-${ClassNames.sourceMapped}"
  onclick="javascript:toggle${ClassNames.sourceMapped}()"
  ${showSourceMapped ? 'checked' : ''}>
<span title="Show line-per-line mappings of JavaScript to Dart code.">
Source mapped Dart code</span><br/>
</div>
</body>
</html>
''');

  File file = File(out);
  file.writeAsStringSync(sb.toString());
  print('Diff generated in ${file.absolute.uri}');
}

class CodeLinesResult {
  final List<CodeLine> codeLines;
  final Coverage coverage;
  final Map<int, MemberEntity> elementMap;
  final SourceFileManager sourceFileManager;
  final CodeSources codeSources;

  CodeLinesResult(
    this.codeLines,
    this.coverage,
    this.elementMap,
    this.sourceFileManager,
    this.codeSources,
  );
}

class CodeSources {
  Map<Entity, CodeSource> codeSourceMap = <Entity, CodeSource>{};
  Map<Uri, Map<Interval, CodeSource>> uriCodeSourceMap =
      <Uri, Map<Interval, CodeSource>>{};

  CodeSources(SourceMapProcessor processor, SourceMaps sourceMaps) {
    ElementEnvironment elementEnvironment =
        sourceMaps.compiler.backendClosedWorldForTesting!.elementEnvironment;

    CodeSource computeCodeSource(Entity element) {
      return codeSourceMap.putIfAbsent(element, () {
        CodeSource codeSource = codeSourceFromElement(element);
        if (codeSource.begin != null) {
          Interval interval = Interval(codeSource.begin!, codeSource.end!);
          Map<Interval, CodeSource>? intervals =
              uriCodeSourceMap[codeSource.uri];
          if (intervals == null) {
            intervals = <Interval, CodeSource>{};
            uriCodeSourceMap[codeSource.uri] = intervals;
          } else {
            for (Interval existingInterval in intervals.keys.toList()) {
              if (existingInterval.contains(interval.from)) {
                CodeSource existingCodeSource = intervals[existingInterval]!;
                intervals.remove(existingInterval);
                if (existingInterval.from < interval.from) {
                  Interval preInterval = Interval(
                    existingInterval.from,
                    interval.from,
                  );
                  intervals[preInterval] = existingCodeSource;
                }
                if (interval.to < existingInterval.to) {
                  Interval postInterval = Interval(
                    interval.to,
                    existingInterval.to,
                  );
                  intervals[postInterval] = existingCodeSource;
                }
              }
            }
          }
          intervals[interval] = codeSource;
        }
        if (element is ClassEntity) {
          elementEnvironment.forEachConstructor(element, computeCodeSource);
          elementEnvironment.forEachLocalClassMember(
            element,
            computeCodeSource,
          );
        }
        return codeSource;
      });
    }

    for (LibraryEntity library in elementEnvironment.libraries) {
      elementEnvironment.forEachClass(library, computeCodeSource);
      elementEnvironment.forEachLibraryMember(library, computeCodeSource);
    }

    uriCodeSourceMap.forEach((Uri uri, Map<Interval, CodeSource> intervals) {
      List<Interval> sortedKeys = intervals.keys.toList()
        ..sort((i1, i2) => i1.from.compareTo(i2.from));
      Map<Interval, CodeSource> sortedintervals = <Interval, CodeSource>{};
      sortedKeys.forEach((Interval interval) {
        sortedintervals[interval] = intervals[interval]!;
      });
      uriCodeSourceMap[uri] = sortedintervals;
    });
  }

  CodeSource? sourceLocationToCodeSource(SourceLocation sourceLocation) {
    Map<Interval, CodeSource>? intervals =
        uriCodeSourceMap[sourceLocation.sourceUri];
    if (intervals == null) {
      print('No code source for $sourceLocation(${sourceLocation.offset})');
      print(' -- no intervals for ${sourceLocation.sourceUri}');
      return null;
    }
    for (Interval interval in intervals.keys) {
      if (interval.contains(sourceLocation.offset)) {
        return intervals[interval];
      }
    }
    print('No code source for $sourceLocation(${sourceLocation.offset})');
    intervals.forEach((k, v) => print(' $k: ${v.name}'));
    return null;
  }
}

/// Compute [CodeLine]s and [Coverage] for [filename] using the given [options].
Future<CodeLinesResult> computeCodeLines(
  List<String> options,
  String filename,
  Uri uri,
) async {
  SourceMapProcessor processor = SourceMapProcessor(uri);
  SourceMaps sourceMaps = await processor.process(
    options,
    perElement: true,
    forMain: true,
  );

  CodeSources codeSources = CodeSources(processor, sourceMaps);

  SourceMapInfo info = sourceMaps.mainSourceMapInfo!;

  int nextAnnotationId = 0;
  List<CodeLine> codeLines;
  Coverage coverage = Coverage();
  Map<int, List<CodeLineAnnotation>> codeLineAnnotationMap =
      <int, List<CodeLineAnnotation>>{};

  /// Create a [CodeLineAnnotation] for [codeOffset].
  void addCodeLineAnnotation({
    required AnnotationType annotationType,
    required int codeOffset,
    List<SourceLocation> locations = const <SourceLocation>[],
    String? stepInfo,
  }) {
    if (annotationType == AnnotationType.withoutSourceInfo ||
        annotationType == AnnotationType.unusedSourceInfo) {
      locations = [];
    }
    List<CodeLocation> codeLocations = locations
        .where((l) => l.sourceUri != null)
        .map((l) => CodeLocation(l.sourceUri!, l.sourceName!, l.offset))
        .toList();
    List<CodeSource> codeSourceList = locations
        .where((l) => l.sourceUri != null)
        .map(codeSources.sourceLocationToCodeSource)
        .whereType<CodeSource>()
        .toList();
    CodeLineAnnotation data = CodeLineAnnotation(
      annotationId: nextAnnotationId++,
      annotationType: annotationType,
      codeLocations: codeLocations,
      codeSources: codeSourceList,
      stepInfo: stepInfo,
    );
    codeLineAnnotationMap
        .putIfAbsent(codeOffset, () => <CodeLineAnnotation>[])
        .add(data);
  }

  String code = info.code;
  TraceGraph graph = createTraceGraph(info, coverage);

  Set<js.Node> mappedNodes = Set<js.Node>();

  /// Add an annotation for [codeOffset] pointing to [locations].
  void addSourceLocations({
    required AnnotationType annotationType,
    required int codeOffset,
    required List<SourceLocation?> locations,
    String? stepInfo,
  }) {
    final nonNullLocations = locations.whereType<SourceLocation>().toList();
    addCodeLineAnnotation(
      annotationType: annotationType,
      codeOffset: codeOffset,
      stepInfo: stepInfo,
      locations: nonNullLocations,
    );
  }

  /// Add annotations for all mappings created for [node].
  bool addSourceLocationsForNode({
    required AnnotationType annotationType,
    required js.Node node,
    String? stepInfo,
  }) {
    Map<int, List<SourceLocation>>? locations = info.nodeMap[node];
    if (locations == null || locations.isEmpty) {
      return false;
    }
    locations.forEach((int offset, List<SourceLocation> locations) {
      addSourceLocations(
        annotationType: annotationType,
        codeOffset: offset,
        locations: locations,
        stepInfo: stepInfo,
      );
    });
    mappedNodes.add(node);
    return true;
  }

  // Add annotations based on trace steps.
  for (TraceStep step in graph.steps) {
    String stepInfo = '${step.id}:${step.kind}:${step.offset}';
    bool added = addSourceLocationsForNode(
      annotationType: AnnotationType.withSourceInfo,
      node: step.node,
      stepInfo: stepInfo,
    );
    if (!added) {
      int? offset;
      if (options.contains(Flags.useNewSourceInfo)) {
        offset = step.offset.value;
      } else {
        offset = info.jsCodePositions[step.node]!.startPosition;
      }
      if (offset != null) {
        addCodeLineAnnotation(
          annotationType: AnnotationType.withoutSourceInfo,
          codeOffset: offset,
          stepInfo: stepInfo,
        );
      }
    }
  }

  // Add additional annotations for mappings created for particular nodes.
  for (js.Node node in info.nodeMap.nodes) {
    if (!mappedNodes.contains(node)) {
      addSourceLocationsForNode(
        annotationType: AnnotationType.additionalSourceInfo,
        node: node,
      );
    }
  }

  // Add annotations for unused source information associated with nodes.
  SourceLocationCollector collector = SourceLocationCollector();
  info.node.accept(collector);
  collector.sourceLocations.forEach((
    js.Node node,
    List<SourceLocation> locations,
  ) {
    if (!mappedNodes.contains(node)) {
      int offset = info.jsCodePositions[node]!.startPosition;
      addSourceLocations(
        annotationType: AnnotationType.unusedSourceInfo,
        codeOffset: offset,
        locations: locations,
      );
    }
  });

  // Assign consecutive ids to source mappings.
  int nextSourceMappedLocationIndex = 0;
  List<Annotation> annotations = <Annotation>[];
  for (int codeOffset in codeLineAnnotationMap.keys.toList()..sort()) {
    bool hasSourceMappedLocation = false;
    for (CodeLineAnnotation data in codeLineAnnotationMap[codeOffset]!) {
      if (data.annotationType.isSourceMapped) {
        data.sourceMappingIndex = nextSourceMappedLocationIndex;
        hasSourceMappedLocation = true;
      }
      annotations.add(
        new Annotation(
          data.annotationType.index,
          codeOffset,
          'id=${data.annotationId}',
          data: data,
        ),
      );
    }
    if (hasSourceMappedLocation) {
      nextSourceMappedLocationIndex++;
    }
  }

  // Associate JavaScript offsets with [Element]s.
  StringSourceFile sourceFile = StringSourceFile.fromName(filename, code);
  Map<int, MemberEntity> elementMap = <int, MemberEntity>{};
  sourceMaps.elementSourceMapInfos.forEach((
    MemberEntity element,
    SourceMapInfo info,
  ) {
    CodePosition position = info.jsCodePositions[info.node]!;
    elementMap[sourceFile.getLocation(position.startPosition).line - 1] =
        element;
  });

  codeLines = convertAnnotatedCodeToCodeLines(code, annotations);
  return CodeLinesResult(
    codeLines,
    coverage,
    elementMap,
    sourceMaps.sourceFileManager,
    codeSources,
  );
}

/// Visitor that computes a map from [js.Node]s to all attached source
/// locations.
class SourceLocationCollector extends js.BaseVisitorVoid {
  Map<js.Node, List<SourceLocation>> sourceLocations =
      <js.Node, List<SourceLocation>>{};

  @override
  void visitNode(js.Node node) {
    final sourceInformation = node.sourceInformation as SourceInformation?;
    if (sourceInformation != null) {
      sourceLocations[node] = sourceInformation.sourceLocations;
    }
    node.visitChildren(this);
  }
}

/// Compute a [CodeSource] for source span of [element].
CodeSource codeSourceFromElement(Entity element) {
  // TODO(johnniwinther): Handle kernel based elements.
  late CodeKind kind;
  late Uri uri;
  late String name;
  if (element is LibraryEntity) {
    kind = CodeKind.LIBRARY;
    name = element.name!;
    uri = element.canonicalUri;
  } else if (element is ClassEntity) {
    kind = CodeKind.CLASS;
    name = element.name;
    uri = element.library.canonicalUri;
  } else if (element is MemberEntity) {
    kind = CodeKind.MEMBER;
    uri = element.library.canonicalUri;
    name = computeElementNameForSourceMaps(element)!;
  }
  return CodeSource(kind, uri, name, null, null);
}

/// Create [LineData] that colors line numbers according to the [CodeSource]s
/// origin if available.
LineData getLineData(Object? lineAnnotation) {
  if (lineAnnotation != null) {
    return LineData(
      lineClass: ClassNames.line,
      lineNumberClass:
          '${ClassNames.lineNumber} '
          '${ClassNames.colored(lineAnnotation.hashCode % 4)}',
    );
  }
  return LineData(
    lineClass: ClassNames.line,
    lineNumberClass: ClassNames.lineNumber,
  );
}

AnnotationData? getAnnotationData(
  Iterable<Annotation> annotations, {
  required bool forSpan,
}) {
  for (Annotation annotation in annotations) {
    CodeLineAnnotation data = annotation.data;
    if (data.annotationType.isSourceMapped) {
      if (forSpan) {
        int index = data.sourceMappingIndex!;
        return AnnotationData(
          tag: 'span',
          properties: {
            'class':
                '${ClassNames.sourceMapping} '
                '${ClassNames.sourceMappingIndex(index % HUE_COUNT)}',
            'title': 'index=$index',
          },
        );
      } else {
        return AnnotationData(
          tag: 'span',
          properties: {
            'title': annotation.title,
            'class':
                '${ClassNames.marker} '
                '${data.annotationType.className}',
          },
        );
      }
    }
  }
  if (forSpan) return null;
  for (Annotation annotation in annotations) {
    CodeLineAnnotation data = annotation.data;
    if (data.annotationType == AnnotationType.unusedSourceInfo) {
      return AnnotationData(
        tag: 'span',
        properties: {
          'title': annotation.title,
          'class':
              '${ClassNames.marker} '
              '${data.annotationType.className}',
        },
      );
    }
  }
  for (Annotation annotation in annotations) {
    CodeLineAnnotation data = annotation.data;
    if (data.annotationType == AnnotationType.withoutSourceInfo) {
      return AnnotationData(
        tag: 'span',
        properties: {
          'title': annotation.title,
          'class':
              '${ClassNames.marker} '
              '${data.annotationType.className}',
        },
      );
    }
  }
  return null;
}
