// 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 {
  DEBUG_MODE = 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;
}
