// Copyright (c) 2015, 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.

/// Source information system mapping that attempts a semantic mapping between
/// offsets of JavaScript code points to offsets of Dart code points.

library;

import '../common.dart';
import '../js/js.dart' as js;
import '../js/js_debug.dart';
import '../js/js_source_mapping.dart';
import '../serialization/serialization.dart';
import '../util/util.dart';
import 'source_information.dart';

/// [SourceInformation] that consists of an offset position into the source
/// code.
class PositionSourceInformation extends SourceInformation {
  static const String tag = 'source-information';

  @override
  final SourceLocation startPosition;

  @override
  final SourceLocation? innerPosition;

  @override
  final List<FrameContext>? inliningContext;

  PositionSourceInformation(
    this.startPosition,
    this.innerPosition,
    this.inliningContext,
  );

  factory PositionSourceInformation.readFromDataSource(
    DataSourceReader source,
  ) {
    source.begin(tag);
    SourceLocation startPosition = source.readIndexedNoCache<SourceLocation>(
      () => SourceLocation.readFromDataSource(source),
    );
    SourceLocation? innerPosition = source
        .readIndexedOrNullNoCache<SourceLocation>(
          () => SourceLocation.readFromDataSource(source),
        );
    List<FrameContext>?
    inliningContext = source.readIndexedOrNullNoCache<List<FrameContext>>(
      () =>
      // FrameContext must be cached since PositionSourceInformation.==
      // requires identity comparison on the objects in inliningContext.
      source.readList(
        () => source.readIndexed(() => FrameContext.readFromDataSource(source)),
      ),
    );
    source.end(tag);
    return PositionSourceInformation(
      startPosition,
      innerPosition,
      inliningContext,
    );
  }

  void writeToDataSinkInternal(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeIndexed(
      startPosition,
      (SourceLocation sourceLocation) =>
          SourceLocation.writeToDataSink(sink, sourceLocation),
    );
    sink.writeIndexed(
      innerPosition,
      (SourceLocation sourceLocation) =>
          SourceLocation.writeToDataSink(sink, sourceLocation),
    );
    sink.writeIndexed(
      inliningContext,
      (_) => sink.writeListOrNull(
        inliningContext,
        (FrameContext context) =>
            sink.writeIndexed(context, (_) => context.writeToDataSink(sink)),
      ),
    );
    sink.end(tag);
  }

  @override
  List<SourceLocation> get sourceLocations {
    List<SourceLocation> list = [];
    list.add(startPosition);
    if (innerPosition != null) {
      list.add(innerPosition!);
    }
    return list;
  }

  @override
  SourceSpan get sourceSpan {
    SourceLocation location = startPosition;
    Uri uri = location.sourceUri!;
    int offset = location.offset;
    return SourceSpan(uri, offset, offset);
  }

  @override
  int get hashCode {
    return Hashing.listHash(
      inliningContext,
      Hashing.objectsHash(startPosition, innerPosition),
    );
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    return other is PositionSourceInformation &&
        startPosition == other.startPosition &&
        innerPosition == other.innerPosition &&
        equalElements(inliningContext, other.inliningContext);
  }

  /// Create a textual representation of the source information using [uriText]
  /// as the Uri representation.
  String _computeText(String uriText) {
    StringBuffer sb = StringBuffer();
    sb.write('$uriText:');
    // Use 1-based line/column info to match usual dart tool output.
    sb.write(
      '[${startPosition.line},'
      '${startPosition.column}]',
    );
    if (innerPosition != null) {
      sb.write(
        '-[${innerPosition!.line},'
        '${innerPosition!.column}]',
      );
    }
    return sb.toString();
  }

  @override
  String get shortText {
    return _computeText(startPosition.sourceUri!.pathSegments.last);
  }

  @override
  String toString() {
    return _computeText('${startPosition.sourceUri}');
  }
}

abstract class OnlinePositionSourceInformationStrategy
    implements JavaScriptSourceInformationStrategy {
  const OnlinePositionSourceInformationStrategy();

  @override
  SourceInformationProcessor createProcessor(
    SourceMapperProvider provider,
    SourceInformationReader reader,
  ) {
    var sourceMapper = provider.createSourceMapper(
      OnlineSourceInformationProcessor.id,
    );
    final inliningListener = InliningTraceListener(sourceMapper, reader);
    final List<TraceListener> traceListeners = [
      PositionTraceListener(sourceMapper, reader),
      inliningListener,
    ];
    return OnlineSourceInformationProcessor(
      provider,
      reader,
      traceListeners,
      onComplete: inliningListener.finish,
    );
  }

  @override
  void onComplete() {}

  @override
  SourceInformation buildSourceMappedMarker() {
    return const SourceMappedMarker();
  }
}

/// Marker used to tag the root nodes of source-mapped code.
///
/// This is needed to be able to distinguish JavaScript nodes that shouldn't
/// have source locations (like the preamble) from the nodes that should
/// (like functions compiled from Dart code).
class SourceMappedMarker extends SourceInformation {
  const SourceMappedMarker();

  @override
  String get shortText => '';

  @override
  List<SourceLocation> get sourceLocations => const [];

  @override
  SourceSpan get sourceSpan => SourceSpan.unknown();
}

/// The start, end and closing offsets for a [js.Node].
class CodePosition {
  final int startPosition;
  final int endPosition;
  final int? closingPosition;

  CodePosition(this.startPosition, this.endPosition, this.closingPosition);

  int? getPosition(CodePositionKind kind) {
    switch (kind) {
      case CodePositionKind.startPosition:
        return startPosition;
      case CodePositionKind.endPosition:
        return endPosition;
      case CodePositionKind.closingPosition:
        return closingPosition;
    }
  }

  @override
  String toString() {
    return 'CodePosition(start=$startPosition,'
        'end=$endPosition,closing=$closingPosition)';
  }
}

/// A map from a [js.Node] to its [CodePosition].
abstract class CodePositionMap {
  CodePosition? operator [](js.Node node);
}

/// Registry for mapping [js.Node]s to their [CodePosition].
class CodePositionRecorder implements CodePositionMap {
  final Map<js.Node, CodePosition> _codePositionMap =
      Map<js.Node, CodePosition>.identity();

  void registerPositions(
    js.Node node,
    int startPosition,
    int endPosition,
    int? closingPosition,
  ) {
    registerCodePosition(
      node,
      CodePosition(startPosition, endPosition, closingPosition),
    );
  }

  void registerCodePosition(js.Node node, CodePosition codePosition) {
    _codePositionMap[node] = codePosition;
  }

  @override
  CodePosition? operator [](js.Node node) => _codePositionMap[node];
}

/// Enum values for the part of a Dart node used for the source location offset.
enum SourcePositionKind {
  /// The source mapping should point to the start of the Dart node.
  ///
  /// For instance the first '(' for the `(*)()` call and 'f' of both the
  /// `foo()` and the `*.bar()` call:
  ///
  ///     (foo().bar())()
  ///     ^                       // the start of the `(*)()` node
  ///      ^                      // the start of the `foo()` node
  ///      ^                      // the start of the `*.bar()` node
  ///
  start,

  /// The source mapping should point an inner position of the Dart node.
  ///
  /// For instance the second '(' of the `(*)()` call, the 'f' of the `foo()`
  /// call and the 'b' of the `*.bar()` call:
  ///
  ///     (foo().bar())()
  ///                  ^          // the inner position of the `(*)()` node
  ///      ^                      // the inner position of the `foo()` node
  ///            ^                // the inner position of the `*.bar()` node
  ///
  /// For function expressions the inner position is the closing brace or the
  /// arrow:
  ///
  ///     foo() => () {}
  ///           ^                 // the inner position of the 'foo' function
  ///                  ^          // the inner position of the closure
  ///
  inner,
}

SourceLocation? getSourceLocation(
  SourceInformation sourceInformation, [
  SourcePositionKind sourcePositionKind = SourcePositionKind.start,
]) {
  switch (sourcePositionKind) {
    case SourcePositionKind.start:
      return sourceInformation.startPosition;
    case SourcePositionKind.inner:
      return sourceInformation.innerPosition ?? sourceInformation.startPosition;
  }
}

/// Enum values for the part of the JavaScript node used for the JavaScript
/// code offset of a source mapping.
enum CodePositionKind {
  /// The source mapping is put on left-most offset of the node.
  ///
  /// For instance on the 'f' of a function or 'r' of a return statement:
  ///
  ///     foo: function() { return 0; }
  ///          ^                              // the function start position
  ///                       ^                 // the return start position
  startPosition,

  /// The source mapping is put on the closing token.
  ///
  /// For instance on the '}' of a function or the ';' of a return statement:
  ///
  ///     foo: function() { return 0; }
  ///                                 ^       // the function closing position
  ///                               ^         // the return closing position
  ///
  closingPosition,

  /// The source mapping is put at the end of the code for the node.
  ///
  /// For instance after '}' of a function or after the ';' of a return
  /// statement:
  ///
  ///     foo: function() { return 0; }
  ///                                  ^       // the function end position
  ///                                ^         // the return end position
  ///
  endPosition;

  int? select({required int start, required int end, required int? closing}) =>
      switch (this) {
        startPosition => start,
        endPosition => end,
        closingPosition => closing,
      };
}

/// Processor that associates [SourceLocation]s from [SourceInformation] on
/// [js.Node]s with the target offsets in a [SourceMapper].
class OnlineSourceInformationProcessor extends SourceInformationProcessor {
  /// The id for this source information engine.
  ///
  /// The id is added to the source map file in an extra "engine" property and
  /// serves as a version number for the engine.
  ///
  /// The version history of this engine is:
  ///
  ///   v2: The initial version with an id.
  static const String id = 'v2';

  late final OnlineJavaScriptTracer tracer = OnlineJavaScriptTracer(
    reader,
    traceListeners,
    onComplete: onComplete,
  );
  final SourceInformationReader reader;
  late final List<TraceListener> traceListeners;
  late final InliningTraceListener inliningListener;
  final void Function()? onComplete;

  OnlineSourceInformationProcessor(
    SourceMapperProvider provider,
    this.reader,
    this.traceListeners, {
    this.onComplete,
  });

  @override
  void onStartPosition(js.Node node, int startPosition) {
    tracer.onStartPosition(node, startPosition);
  }

  @override
  void onPositions(
    js.Node node,
    int startPosition,
    int endPosition,
    int? closingPosition,
  ) {
    tracer.onPositions(node, startPosition, endPosition, closingPosition);
  }
}

/// Visitor that computes [SourceInformation] for a [js.Node] using information
/// attached to the node itself or alternatively from child nodes.
class NodeSourceInformation extends js.BaseVisitor<SourceInformation?> {
  final SourceInformationReader reader;

  const NodeSourceInformation(this.reader);

  SourceInformation? visit(js.Node? node) => node?.accept(this);

  @override
  SourceInformation? visitNode(js.Node node) =>
      reader.getSourceInformation(node);

  @override
  SourceInformation? visitComment(js.Comment node) => null;

  @override
  SourceInformation? visitExpressionStatement(js.ExpressionStatement node) {
    SourceInformation? sourceInformation = reader.getSourceInformation(node);
    if (sourceInformation != null) {
      return sourceInformation;
    }
    return visit(node.expression);
  }

  @override
  SourceInformation? visitVariableDeclarationList(
    js.VariableDeclarationList node,
  ) {
    SourceInformation? sourceInformation = reader.getSourceInformation(node);
    if (sourceInformation != null) {
      return sourceInformation;
    }
    for (js.Node declaration in node.declarations) {
      SourceInformation? sourceInformation = visit(declaration);
      if (sourceInformation != null) {
        return sourceInformation;
      }
    }
    return null;
  }

  @override
  SourceInformation? visitVariableInitialization(
    js.VariableInitialization node,
  ) {
    SourceInformation? sourceInformation = reader.getSourceInformation(node);
    if (sourceInformation != null) {
      return sourceInformation;
    }
    return visit(node.value);
  }

  @override
  SourceInformation? visitAssignment(js.Assignment node) {
    SourceInformation? sourceInformation = reader.getSourceInformation(node);
    if (sourceInformation != null) {
      return sourceInformation;
    }
    return visit(node.value);
  }
}

/// Mixin that add support for computing [SourceInformation] for a [js.Node].
mixin NodeToSourceInformationMixin {
  SourceInformationReader get reader;

  SourceInformation? computeSourceInformation(js.Node node) {
    return NodeSourceInformation(reader).visit(node);
  }
}

/// [TraceListener] that register inlining context-data with a [SourceMapper].
class InliningTraceListener extends TraceListener
    with NodeToSourceInformationMixin {
  final SourceMapper sourceMapper;
  @override
  final SourceInformationReader reader;
  final Map<int, List<FrameContext>?> _frames = {};

  InliningTraceListener(this.sourceMapper, this.reader);

  @override
  void onStep(js.Node node, Offset offset, StepKind kind) {
    SourceInformation? sourceInformation = computeSourceInformation(node);
    if (sourceInformation == null) return;
    // TODO(sigmund): enable this assertion.
    // assert(offset.value != null, "Expected a valid offset: $node $offset");
    final offsetValue = offset.value;
    if (offsetValue == null) return;

    // TODO(sigmund): enable this assertion
    //assert(_frames[offset.value] == null,
    //     "Expect a single entry per offset: $offset $node");
    if (_frames[offsetValue] != null) return;

    // During tracing we only collect information per offset because the tracer
    // visits nodes in tree order. We'll later sort the data by offset before
    // registering the frame data with [SourceMapper].
    if (kind == StepKind.funExit) {
      _frames[offsetValue] = null;
    } else {
      _frames[offsetValue] = sourceInformation.inliningContext;
    }
  }

  /// Converts the inlining context data collected during tracing into push/pop
  /// stack operations that will be emitted with the source-map files.
  void finish() {
    List<FrameContext>? lastInliningContext;
    for (var offset in _frames.keys.toList()..sort()) {
      var newInliningContext = _frames[offset];

      // Note: this relies on the invariant that, when we built the inlining
      // context lists during SSA, we kept lists identical whenever there were
      // no inlining changes.
      if (lastInliningContext == newInliningContext) continue;

      bool isEmpty = false;
      int popCount = 0;
      List<FrameContext> pushes = const [];
      if (newInliningContext == null) {
        popCount = lastInliningContext!.length;
        isEmpty = true;
      } else if (lastInliningContext == null) {
        pushes = newInliningContext;
      } else {
        int min = newInliningContext.length;
        if (min > lastInliningContext.length) min = lastInliningContext.length;
        // Determine the total number of common frames, to produce the minimal
        // set of pop and push operations.
        int i = 0;
        for (i = 0; i < min; i++) {
          if (!identical(newInliningContext[i], lastInliningContext[i])) break;
        }
        isEmpty = i == 0;
        popCount = lastInliningContext.length - i;
        if (i < newInliningContext.length) {
          pushes = newInliningContext.sublist(i);
        }
      }
      lastInliningContext = newInliningContext;

      while (popCount-- > 0) {
        sourceMapper.registerPop(offset, isEmpty: popCount == 0 && isEmpty);
      }
      for (FrameContext push in pushes) {
        sourceMapper.registerPush(
          offset,
          getSourceLocation(push.callInformation),
          push.inlinedMethodName,
        );
      }
    }
  }
}

/// [TraceListener] that register [SourceLocation]s with a [SourceMapper].
class PositionTraceListener extends TraceListener
    with NodeToSourceInformationMixin {
  final SourceMapper sourceMapper;
  @override
  final SourceInformationReader reader;

  PositionTraceListener(this.sourceMapper, this.reader);

  /// Registers source information for [node] on the [offset] in the JavaScript
  /// code using [kind] to determine what information to use.
  ///
  /// For most nodes the start position of the source information is used.
  /// For instance a return expression points to the start position of the
  /// source information, typically the start of the return statement that
  /// created the JavaScript return node:
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     @return "foo";                 return "foo";
  ///                                    ^
  /// (@ marks the current JavaScript position and ^ point to the mapped Dart
  /// code position.)
  ///
  ///
  /// For [StepKind.call] the `CallPosition.getSemanticPositionForCall` method
  /// is called to determine whether the start or the inner position should be
  /// used. For instance if the receiver of the JavaScript call is a "simple"
  /// expression then the start position of the source information is used:
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     t1.@foo$0()                    local.foo()
  ///                                    ^
  ///
  /// If the receiver of the JavaScript call is "complex" then the inner
  /// position of the source information is used:
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     get$bar().@foo()               bar.foo()
  ///                                        ^
  ///
  /// For [StepKind.funExit] the inner position of the source information
  /// is used. For a JavaScript function without a return statement this maps
  /// the end brace to the end brace of the corresponding Dart function. For a
  /// JavaScript function exited through a return statement this maps the end of
  /// the return statement to the end brace of the Dart function:
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     foo: function() {              foo() {
  ///     @}                             }
  ///                                    ^
  ///     foo: function() {              foo() {
  ///       return 0;@                     return 0;
  ///     }                              }
  ///                                    ^
  @override
  void onStep(js.Node node, Offset offset, StepKind kind) {
    int? codeLocation = offset.value;
    if (codeLocation == null) return;

    if (kind == StepKind.noInfo) {
      sourceMapper.register(node, codeLocation, const NoSourceLocationMarker());
      return;
    }

    SourceInformation? sourceInformation = computeSourceInformation(node);
    if (sourceInformation == null) return;

    void registerPosition(SourcePositionKind sourcePositionKind) {
      SourceLocation? sourceLocation = getSourceLocation(
        sourceInformation,
        sourcePositionKind,
      );
      if (sourceLocation != null) {
        sourceMapper.register(node, codeLocation, sourceLocation);
      }
    }

    switch (kind) {
      case StepKind.funEntry:
        // TODO(johnniwinther): Remove this when fully transitioned to the
        // new source info system. Verify that tools no longer expect JS
        // function signatures to map to the origin. The main method may still
        // need mapping to enable breakpoints before calling main.
        registerPosition(SourcePositionKind.start);
        break;
      case StepKind.funExit:
        registerPosition(SourcePositionKind.inner);
        break;
      case StepKind.call:
        CallPosition callPosition = CallPosition.getSemanticPositionForCall(
          node as js.Call,
        );
        registerPosition(callPosition.sourcePositionKind);
        break;
      case StepKind.access:
      case StepKind.new_:
      case StepKind.return_:
      case StepKind.break_:
      case StepKind.continue_:
      case StepKind.throw_:
      case StepKind.expressionStatement:
      case StepKind.ifCondition:
      case StepKind.forInitializer:
      case StepKind.forCondition:
      case StepKind.forUpdate:
      case StepKind.whileCondition:
      case StepKind.doCondition:
      case StepKind.switchExpression:
        registerPosition(SourcePositionKind.start);
        break;
      case StepKind.noInfo:
        break;
    }
  }
}

/// The position of a [js.Call] node.
class CallPosition {
  /// The call node for which the positions have been computed.
  final js.Node node;

  /// The position for [node] used as the offset in the JavaScript code.
  ///
  /// This is either `CodePositionKind.START` for code like
  ///
  ///     t1.foo$0()
  ///     ^
  /// where the left-most offset of the receiver should be used, or
  /// `CodePositionKind.CLOSING` for code like
  ///
  ///     get$bar().foo$0()
  ///               ^
  ///
  /// where the name of the called method should be used (here the method
  /// 'foo$0').
  final CodePositionKind codePositionKind;

  /// The position from the [SourceInformation] used in the mapped Dart code.
  ///
  /// This is either `SourcePositionKind.START` for code like
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     t1.@foo$0()                    local.foo()
  ///                                    ^
  ///
  /// where the JavaScript receiver is a "simple" expression, or
  /// `SourcePositionKind.CLOSING` for code like
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     get$bar().@foo()               bar.foo()
  ///                                        ^
  ///
  /// where the JavaScript receiver is a "complex" expression.
  ///
  /// (@ marks the current JavaScript position and ^ point to the mapped Dart
  /// code position.)
  final SourcePositionKind sourcePositionKind;

  CallPosition(this.node, this.codePositionKind, this.sourcePositionKind);

  /// Computes the [CallPosition] for the call [node].
  ///
  /// For instance if the receiver of the JavaScript call is a "simple"
  /// expression then the start position of the source information is used:
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     t1.@foo$0()                    local.foo()
  ///                                    ^
  ///
  /// If the receiver of the JavaScript call is "complex" then the inner
  /// position of the source information is used:
  ///
  ///     JavaScript:                    Dart:
  ///
  ///     get$bar().@foo()               bar.foo()
  ///                                        ^
  /// (@ marks the current JavaScript position and ^ point to the mapped Dart
  /// code position.)
  static CallPosition getSemanticPositionForCall(js.Call node) {
    js.Expression access = js.undefer(node.target) as js.Expression;
    if (access is js.PropertyAccess) {
      js.Node target = access;
      bool pureAccess = false;
      while (target is js.PropertyAccess) {
        js.PropertyAccess targetAccess = target;
        js.Node receiver = js.undefer(targetAccess.receiver);
        if (receiver is js.VariableUse || receiver is js.This) {
          pureAccess = true;
          break;
        } else {
          target = receiver;
        }
      }
      if (pureAccess) {
        // a.m()   this.m()  a.b.c.d.m()
        // ^       ^         ^
        return CallPosition(
          node,
          CodePositionKind.startPosition,
          SourcePositionKind.start,
        );
      } else {
        // *.m()  *.a.b.c.d.m()
        //   ^              ^
        return CallPosition(
          access.selector,
          CodePositionKind.startPosition,
          SourcePositionKind.inner,
        );
      }
    } else if (access is js.VariableUse || access is js.This) {
      // m()   this()
      // ^     ^
      return CallPosition(
        node,
        CodePositionKind.startPosition,
        SourcePositionKind.start,
      );
    } else if (access is js.FunctionExpression ||
        access is js.New ||
        access is js.NamedFunction ||
        (access is js.Parentheses &&
            (access.enclosed is js.FunctionExpression ||
                access.enclosed is js.New ||
                access.enclosed is js.NamedFunction))) {
      // function(){}()     new Function("...")()     function foo(){}()
      //             ^                         ^                      ^
      // (function(){})()   (new Function("..."))()   (function foo(){})()
      //               ^                         ^                      ^
      // (()=>{})()
      //         ^
      return CallPosition(
        node.target,
        CodePositionKind.endPosition,
        SourcePositionKind.inner,
      );
    } else if (access is js.Binary || access is js.Call) {
      // (0,a)()   m()()
      //      ^       ^
      return CallPosition(
        node.target,
        CodePositionKind.endPosition,
        SourcePositionKind.inner,
      );
    } else {
      // TODO(johnniwinther): Maybe remove this assertion.
      assert(
        false,
        failedAt(
          noLocationSpannable,
          "Unexpected property access ${nodeToString(node)}:\n"
          "${DebugPrinter.prettyPrint(node)}",
        ),
      );
      // Don't know....
      return CallPosition(
        node,
        CodePositionKind.startPosition,
        SourcePositionKind.start,
      );
    }
  }
}

/// An offset of a JavaScript node within the output code.
///
/// This object holds three different values for the offset corresponding to
/// three different ways browsers can compute the offset of a JavaScript node.
///
/// Currently [subexpressionOffset] is used since it corresponds the most to the
/// offset used by most browsers.
///
// TODO(sra): Any or all of the values can be `null`. Investigate why this
// happens. Since we are writing a JavaScript AST to an output, we should be
// able to have non-null values.
class Offset {
  /// The offset of the enclosing statement relative to the beginning of the
  /// file.
  ///
  /// For instance:
  ///
  ///     foo().bar(baz());
  ///     ^                  // the statement offset of the `foo()` call
  ///     ^                  // the statement offset of the `*.bar()` call
  ///     ^                  // the statement offset of the `baz()` call
  ///
  final int? statementOffset;

  /// The `subexpression` offset of the step. This is the (mostly) unique
  /// offset relative to the beginning of the file, that identifies the
  /// current of execution.
  ///
  /// For instance:
  ///
  ///     foo().bar(baz());
  ///     ^                   // the subexpression offset of the `foo()` call
  ///           ^             // the subexpression offset of the `*.bar()` call
  ///               ^         // the subexpression offset of the `baz()` call
  ///
  /// Here, even though the JavaScript node for the `*.bar()` call contains
  /// the `foo()` its execution is identified by the `bar` identifier more than
  /// the foo identifier.
  ///
  final int? subexpressionOffset;

  /// The `left-to-right` offset of the step. This is like [subexpressionOffset]
  /// but restricted so that the offset of each subexpression in execution
  /// order is monotonically increasing.
  ///
  /// For instance:
  ///
  ///     foo().bar(baz());
  ///     ^                   // the left-to-right offset of the `foo()` call
  ///           ^             // the left-to-right offset of the `*.bar()` call
  ///     ^                   // the left-to-right offset of the `baz()` call
  ///
  /// Here, `baz()` is executed before `foo()` so we need to use 'f' as its best
  /// position under the restriction.
  ///
  // TODO: This isn't being used, determine if it has any future value.
  // final int? leftToRightOffset;

  Offset(this.statementOffset, this.subexpressionOffset);

  int? get value => subexpressionOffset;

  @override
  String toString() {
    return 'Offset[statementOffset=$statementOffset,'
        'subexpressionOffset=$subexpressionOffset]';
  }
}

enum BranchKind { condition, loop, catch_, finally_, case_ }

enum StepKind {
  funEntry,
  funExit,
  call,
  new_,
  access,
  return_,
  break_,
  continue_,
  throw_,
  expressionStatement,
  ifCondition,
  forInitializer,
  forCondition,
  forUpdate,
  whileCondition,
  doCondition,
  switchExpression,
  noInfo,
}

/// Listener for the [JavaScriptTracer].
abstract class TraceListener {
  /// Called before [root] node is processed by the [JavaScriptTracer].
  void onStart(js.Node root) {}

  /// Called after [root] node has been processed by the [JavaScriptTracer].
  void onEnd(js.Node root) {}

  /// Called when a branch of the given [kind] is started. [value] is provided
  /// to distinguish true/false branches of [BranchKind.condition] and cases of
  /// [Branch.CASE].
  void pushBranch(BranchKind kind, [int? value]) {}

  /// Called when the current branch ends.
  void popBranch() {}

  /// Called when [node] defines a step of the given [kind] at the given
  /// [offset] when the generated JavaScript code.
  void onStep(js.Node node, Offset offset, StepKind kind) {}
}

/// Flags indicating how [_PositionInfoNode.offsetPosition] should evolve as the
/// associated node starts and ends.
enum OffsetPositionMode {
  // Pass the offset along normally no special action required. By default the
  // offset gets passed to the next sibling when a node ends or the parent if
  // there is no next sibling.
  none,
  // Reset the offset during own start event.
  resetBefore,
  // Reset the offset during own end event.
  resetAfter,
  // Set offset to parent's start offset during start event. Clear offset if no
  // steps taken during end event.
  subexpressionParentOffset,
  // Set offset to own start offset during start event. Clear offset if no
  // steps taken during end event.
  subexpressionSelfOffset,
  // Update [_PositionInfoNode.offsetPositionForInvocation] during end event.
  // Only set on `target` subexpression of [js.New] and [js.Call].
  invocationTarget,
}

enum _BranchNotificationMode {
  // Emit a push notification when the node is started and a pop when the node
  // ends.
  both,
  // Only emit a pop notification when the node ends and nothing when the node
  // is started.
  skipPush,
  // Only emit a push notification when the node is started and nothing when the
  // node ends.
  skipPop,
}

class _BranchData {
  /// The type of branch this node represents in its parent.
  final BranchKind branchKind;

  /// The token that identifies this branch in its parent (e.g. the index of a
  /// switch case).
  final int? branchToken;

  /// Controls when the associated node will emit a branch notification.
  final _BranchNotificationMode branchNotificationMode;

  _BranchData(this.branchKind, this.branchNotificationMode, this.branchToken);
}

class _PositionInfoNode {
  /// The JS node this info is for.
  final js.Node astNode;

  /// The parent of the node in the traversal. Since the AST is a DAG the JS
  /// node itself might have multiple parents.
  _PositionInfoNode? parent;

  /// Start pointer of the children linked list.
  _PositionInfoNode? first;

  /// End pointer of the children linked list.
  _PositionInfoNode? last;

  /// Next pointer of the children linked list (i.e. this node's sibling).
  _PositionInfoNode? next;

  /// The start position for [astNode].
  late int startPosition;

  /// The offset of the current statement.
  final int? statementOffset;

  /// List of steps emitted for a statements subexpression. Used to determine
  /// if any subexpressions have already been emitted. The same List is shared
  /// between nodes until we enter a new statement subexpression scope.
  final List<js.Node> steps;

  /// Whether or not [astNode] is in user code (i.e. it has a source location).
  bool active;

  /// Used only for [js.Call] and [js.New], tracks the offset position as
  /// determined by the target subexpression.
  int? offsetPositionForInvocation;

  /// The offset of the surrounding statement, used for the first subexpression.
  /// This is the only state that moves laterally through the tree.
  /// [offsetPositionMode] determines how the value evolves.
  int? offsetPosition;

  /// Flag to determine how this node's offset position should evolve on start
  /// and end events.
  final OffsetPositionMode offsetPositionMode;

  /// Steps associated with this node. Each might lead to an emitted step
  /// notification when this node's end event is triggered.
  List<StepKind>? notifySteps;

  /// A node with a non-null [branchData] will trigger push and/or pop
  /// notifications based on [_BranchData.branchNotificationMode].
  final _BranchData? branchData;

  _PositionInfoNode(
    this.astNode,
    this.parent, {
    required this.active,
    required this.steps,
    this.offsetPositionMode = OffsetPositionMode.none,
    this.branchData,
    this.statementOffset,
  }) {
    final localParent = parent;
    // Add this node to the parent's children linked list.
    if (localParent != null) {
      if (localParent.last == null) {
        localParent.first = this;
        localParent.last = this;
      } else {
        localParent.last!.next = this;
        localParent.last = this;
      }
    }
  }

  void clearPointers() {
    // Clear all pointers held by this node to allow other nodes to be GCed.
    parent = null;
    first = null;
    last = null;
    next = null;
  }

  void addNotifyStep(StepKind kind) {
    (notifySteps ??= []).add(kind);
  }
}

/// Tracer that uses hooks provided by the JS AST [js.Printer] to generate
/// source map info while the AST is being printed.
///
/// Maintains a shadow tree of [_PositionInfoNode] that get created at the
/// printer triggers start events for nodes in the JS AST. For relevant nodes
/// we will prepopulate metadata about their children that will help us trigger
/// step and branch notifications with the proper offsets.
///
/// The shadow tree is created lazily so its size is tightly coupled to the
/// depth of the tree. Since we prepopulate a single extra layer sometimes, we
/// do have siblings of the nodes that constitute the current spine of the tree.
/// But none of those siblings' children will be populated.
class OnlineJavaScriptTracer extends js.BaseVisitor1Void<int>
    implements CodePositionListener {
  final SourceInformationReader reader;
  final List<TraceListener> listeners;

  /// The root of the position info shadow tree.
  _PositionInfoNode? _rootNode;

  /// The current node being worked on in the position info shadow tree.
  late _PositionInfoNode _currentNode;

  /// Contains nodes whose positions are needed by an active Call node. This
  /// will have at most one entry per Call currently on the stack.
  /// Only calls that don't use their own position are included here but most
  /// calls use their own position.
  /// A node may be needed multiple times to we track the number of uses
  /// so we can clear it from the map when they have all been processed.
  final Map<js.Node, ({CodePositionKind kind, int counter, int? position})>
  _needsCallPosition = {};

  void Function()? onComplete;

  OnlineJavaScriptTracer(this.reader, this.listeners, {this.onComplete});

  void notifyStart(js.Node node) {
    for (var listener in listeners) {
      listener.onStart(node);
    }
  }

  void notifyEnd(js.Node node) {
    for (var listener in listeners) {
      listener.onEnd(node);
    }
  }

  void notifyPushBranch(BranchKind kind, [int? value]) {
    if (_currentNode.active) {
      for (var listener in listeners) {
        listener.pushBranch(kind, value);
      }
    }
  }

  void notifyPopBranch() {
    if (_currentNode.active) {
      for (var listener in listeners) {
        listener.popBranch();
      }
    }
  }

  void notifyStep(
    js.Node node,
    Offset offset,
    StepKind kind, {
    bool force = false,
  }) {
    if (_currentNode.active || force) {
      for (var listener in listeners) {
        listener.onStep(node, offset, kind);
      }
    }
  }

  _PositionInfoNode? _visit(
    js.Node? node, {
    BranchKind? branchKind,
    int? branchToken,
    _BranchNotificationMode branchNotificationMode =
        _BranchNotificationMode.both,
    int? statementOffset,
    OffsetPositionMode offsetPositionMode = OffsetPositionMode.none,
    bool resetSteps = false,
  }) {
    if (node == null) return null;

    final newNode = _PositionInfoNode(
      node,
      _currentNode,
      active: _currentNode.active,
      branchData:
          branchKind == null
              ? null
              : _BranchData(branchKind, branchNotificationMode, branchToken),
      statementOffset: statementOffset ?? _currentNode.statementOffset,
      offsetPositionMode: offsetPositionMode,
      steps: resetSteps ? [] : _currentNode.steps,
    );
    return newNode;
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitNode(js.Node node, _) {}

  void _handleFunction(_PositionInfoNode node, js.Node body, int start) {
    _currentNode.active =
        _currentNode.active ||
        reader.getSourceInformation(node.astNode) != null;
    Offset entryOffset = getOffsetForNode(node.statementOffset, start);
    notifyStep(node.astNode, entryOffset, StepKind.funEntry);

    _visit(body, statementOffset: start);

    node.addNotifyStep(StepKind.funExit);
  }

  void _handleFunctionExpression(js.FunctionExpression node, int start) {
    final parentNode = _currentNode.parent;
    final parentAstNode = _currentNode.parent?.astNode;
    _PositionInfoNode functionNode = _currentNode;
    js.Expression? declaration;
    if (parentAstNode is js.NamedFunction) {
      functionNode = parentNode!;
      declaration = parentAstNode.name;
    } else if (parentAstNode is js.FunctionDeclaration) {
      declaration = parentAstNode.name;
    }

    _visit(declaration);
    for (final param in node.params) {
      _visit(param);
    }
    // For named functions we treat the named parent as the main node.
    _handleFunction(functionNode, node.body, start);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitFunctionDeclaration(js.FunctionDeclaration node, int start) {
    _visit(node.function);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitNamedFunction(js.NamedFunction node, int start) {
    _visit(node.function);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitFun(js.Fun node, int start) {
    _handleFunctionExpression(node, start);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitArrowFunction(js.ArrowFunction node, int start) {
    _handleFunctionExpression(node, start);
  }

  void _visitSubexpression(
    js.Node parent,
    js.Expression child,
    StepKind kind, {
    required int statementOffset,
    required OffsetPositionMode offsetPositionMode,
    BranchKind? branchKind,
    _BranchNotificationMode branchNotificationMode =
        _BranchNotificationMode.both,
  }) {
    final childNode = _visit(
      child,
      statementOffset: statementOffset,
      resetSteps: true,
      branchKind: branchKind,
      branchNotificationMode: branchNotificationMode,
      // The [offsetPosition] should only be used by the first subexpression.
      offsetPositionMode: offsetPositionMode,
    );
    childNode!.addNotifyStep(kind);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitExpressionStatement(js.ExpressionStatement node, int start) {
    _visitSubexpression(
      node,
      node.expression,
      StepKind.expressionStatement,
      statementOffset: start,
      offsetPositionMode: OffsetPositionMode.subexpressionParentOffset,
    );
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitCall(js.Call node, _) {
    _visit(
      node.target,
      offsetPositionMode: OffsetPositionMode.invocationTarget,
    );
    for (js.Node argument in node.arguments) {
      _visit(argument, offsetPositionMode: OffsetPositionMode.resetBefore);
    }
    CallPosition callPosition = CallPosition.getSemanticPositionForCall(node);
    js.Node positionNode = callPosition.node;
    if (positionNode != node) {
      _needsCallPosition.update(
        positionNode,
        (value) => (
          kind: value.kind,
          counter: value.counter + 1,
          position: value.position,
        ),
        ifAbsent:
            () => (
              kind: callPosition.codePositionKind,
              counter: 1,
              position: null,
            ),
      );
    }
    _currentNode.addNotifyStep(StepKind.call);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitNew(js.New node, _) {
    _visit(
      node.target,
      offsetPositionMode: OffsetPositionMode.invocationTarget,
    );
    for (js.Node node in node.arguments) {
      _visit(node, offsetPositionMode: OffsetPositionMode.resetBefore);
    }

    _currentNode.addNotifyStep(StepKind.new_);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitAccess(js.PropertyAccess node, _) {
    final receiverNode = _visit(node.receiver);
    // Technically we'd like to use the offset of the `.` in the property
    // access, but the js_ast doesn't expose it. Since this is only used to
    // search backwards for inlined frames, we use the receiver's END offset
    // instead as an approximation. Note that the END offset points one
    // character after the end of the node, so it is likely always the
    // offset we want.
    receiverNode!.addNotifyStep(StepKind.access);
    _visit(node.selector);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitIf(js.If node, int start) {
    _visitSubexpression(
      node,
      node.condition,
      StepKind.ifCondition,
      statementOffset: start,
      offsetPositionMode: OffsetPositionMode.subexpressionParentOffset,
    );
    _visit(
      node.then,
      statementOffset: null,
      branchKind: BranchKind.condition,
      branchToken: 1,
    );
    if (node.hasElse) {
      _visit(
        node.otherwise,
        statementOffset: null,
        branchKind: BranchKind.condition,
        branchToken: 0,
      );
    }
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitFor(js.For node, int start) {
    final init = node.init;
    if (init != null) {
      _visitSubexpression(
        node,
        init,
        StepKind.forInitializer,
        statementOffset: start,
        offsetPositionMode: OffsetPositionMode.subexpressionParentOffset,
      );
    }

    final condition = node.condition;
    if (condition != null) {
      _visitSubexpression(
        node,
        condition,
        StepKind.forCondition,
        statementOffset: start,
        offsetPositionMode: OffsetPositionMode.subexpressionSelfOffset,
      );
    }

    final update = node.update;

    if (update != null) {
      _visitSubexpression(
        node,
        update,
        StepKind.forUpdate,
        offsetPositionMode: OffsetPositionMode.subexpressionSelfOffset,
        branchKind: BranchKind.loop,
        statementOffset: start,
        branchNotificationMode: _BranchNotificationMode.skipPop,
      );
    }

    _visit(
      node.body,
      statementOffset: start,
      branchKind: update == null ? BranchKind.loop : null,
      branchNotificationMode: _BranchNotificationMode.skipPush,
    );
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitWhile(js.While node, int start) {
    _visitSubexpression(
      node,
      node.condition,
      StepKind.whileCondition,
      statementOffset: start,
      offsetPositionMode: OffsetPositionMode.subexpressionParentOffset,
    );

    _visit(node.body, branchKind: BranchKind.loop);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitDo(js.Do node, int start) {
    _visit(node.body, statementOffset: start);
    final condition = node.condition;
    _visitSubexpression(
      node,
      condition,
      StepKind.doCondition,
      offsetPositionMode: OffsetPositionMode.subexpressionSelfOffset,
      statementOffset: start,
    );
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitReturn(js.Return node, int start) {
    _visit(node.value, statementOffset: start);
    _currentNode.addNotifyStep(StepKind.return_);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitThrow(js.Throw node, int start) {
    // Do not use [offsetPosition] for the subexpression.
    _visit(
      node.expression,
      statementOffset: start,
      offsetPositionMode: OffsetPositionMode.resetBefore,
    );
    _currentNode.addNotifyStep(StepKind.throw_);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitContinue(js.Continue node, _) {
    _currentNode.addNotifyStep(StepKind.continue_);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitBreak(js.Break node, _) {
    _currentNode.addNotifyStep(StepKind.break_);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitTry(js.Try node, _) {
    _visit(node.body);
    _visit(node.catchPart, branchKind: BranchKind.catch_);
    _visit(node.finallyPart, branchKind: BranchKind.finally_);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitConditional(js.Conditional node, _) {
    _visit(node.condition);
    _visit(node.then, branchKind: BranchKind.condition, branchToken: 1);
    _visit(node.otherwise, branchKind: BranchKind.condition, branchToken: 0);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitSwitch(js.Switch node, int start) {
    _visitSubexpression(
      node,
      node.key,
      StepKind.switchExpression,
      statementOffset: start,
      offsetPositionMode: OffsetPositionMode.subexpressionParentOffset,
    );
    for (int i = 0; i < node.cases.length; i++) {
      _visit(node.cases[i], branchKind: BranchKind.case_, branchToken: i);
    }
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitLabeledStatement(js.LabeledStatement node, int start) {
    _visit(node.body, statementOffset: start);
  }

  @override
  // ignore: avoid_renaming_method_parameters
  void visitDeferredExpression(js.DeferredExpression node, _) {
    _visit(node.value);
  }

  void _beginTracing(js.Node node, int startPosition) {
    notifyStart(node);

    // Create empty node as root of tree.
    _rootNode =
        _currentNode = _PositionInfoNode(node, null, active: false, steps: []);

    Offset startOffset = getOffsetForNode(null, startPosition);
    notifyStep(node, startOffset, StepKind.noInfo, force: true);
  }

  void _endTracing(js.Node node) {
    notifyEnd(node);
    if (onComplete != null) {
      onComplete!();
    }
  }

  @override
  void onStartPosition(js.Node node, int start) {
    if (node is js.Comment) return;
    if (_rootNode == null) {
      _beginTracing(node, start);
    } else if (_currentNode.first != null) {
      // If the last node that ended was a sibling it should have updated
      // [_currentNode] back to the parent in its end event.
      _currentNode = _currentNode.first!;
    } else {
      // If the old current node doesn't have children then we didn't explicitly
      // visit it and so there's no relevant info for this node. We make a
      // placeholder node here instead since the new node may be visited.
      _currentNode = _PositionInfoNode(
        node,
        _currentNode,
        active: _currentNode.active,
        steps: _currentNode.steps,
        statementOffset: _currentNode.statementOffset,
      );
    }

    _updateStartState(start);
    _handleBranchPush();

    node.accept1(this, start);
  }

  @override
  void onPositions(js.Node node, int start, int end, int? closing) {
    if (node is js.Comment) return;
    if (node == _rootNode!.astNode) {
      _endTracing(node);
      return;
    }

    _handleNotifySteps(
      node,
      _currentNode.notifySteps,
      start: start,
      end: end,
      closing: closing,
    );
    _handleBranchPop();

    _updateEndState(node, start: start, end: end, closing: closing);

    // Move the [_currentNode] pointer to the parent and remove self from
    // parent's children list. Parent will either end next or the sibling will
    // start and move the pointer to themselves.
    final parentNode = _currentNode.parent!;
    parentNode.offsetPosition = _currentNode.offsetPosition;
    parentNode.first = _currentNode.next;
    _currentNode.clearPointers();
    _currentNode = parentNode;
  }

  void _updateStartState(int start) {
    _currentNode.startPosition = start;

    if (_currentNode.offsetPositionMode ==
        OffsetPositionMode.subexpressionSelfOffset) {
      _currentNode.offsetPosition = _currentNode.startPosition;
    } else if (_currentNode.offsetPositionMode ==
        OffsetPositionMode.subexpressionParentOffset) {
      _currentNode.offsetPosition = _currentNode.parent!.startPosition;
    } else if (_currentNode.offsetPositionMode ==
        OffsetPositionMode.resetBefore) {
      _currentNode.offsetPosition = null;
    } else {
      _currentNode.offsetPosition = _currentNode.parent?.offsetPosition;
    }
  }

  void _updateEndState(
    js.Node node, {
    required int start,
    required int end,
    required int? closing,
  }) {
    final callPosition = _needsCallPosition[node];
    if (callPosition != null) {
      int? offset = callPosition.kind.select(
        start: start,
        end: end,
        closing: closing,
      );
      _needsCallPosition[node] = (
        kind: callPosition.kind,
        counter: callPosition.counter,
        position: offset,
      );
    }

    switch (_currentNode.offsetPositionMode) {
      case OffsetPositionMode.resetAfter:
        _currentNode.offsetPosition = null;
        break;
      case OffsetPositionMode.invocationTarget:
        _currentNode.parent!.offsetPositionForInvocation =
            _currentNode.offsetPosition;
        _currentNode.offsetPosition = null;
        break;
      case OffsetPositionMode.subexpressionParentOffset:
      case OffsetPositionMode.subexpressionSelfOffset:
        if (_currentNode.steps.isEmpty) {
          _currentNode.offsetPosition = null;
        }
        break;
      case OffsetPositionMode.none:
      case OffsetPositionMode.resetBefore:
        break;
    }
  }

  void _handleBranchPush() {
    final branchData = _currentNode.branchData;
    if (branchData != null &&
        branchData.branchNotificationMode != _BranchNotificationMode.skipPush) {
      notifyPushBranch(branchData.branchKind, branchData.branchToken);
    }
  }

  void _handleBranchPop() {
    final branchData = _currentNode.branchData;
    if (branchData != null &&
        branchData.branchNotificationMode != _BranchNotificationMode.skipPop) {
      notifyPopBranch();
    }
  }

  void _handleNotifySteps(
    js.Node node,
    List<StepKind>? stepKinds, {
    required int start,
    required int end,
    required int? closing,
  }) {
    if (stepKinds == null) return;

    for (final stepKind in stepKinds) {
      _PositionInfoNode target;
      int? offset;
      bool addStep = false;
      StepKind? secondaryKind;
      int? secondaryOffset;

      switch (stepKind) {
        case StepKind.call:
          target = _currentNode;
          final callPosition = CallPosition.getSemanticPositionForCall(
            node as js.Call,
          );
          if (callPosition.node == node) {
            // Use the syntax offset if this is not the first subexpression.
            offset =
                _currentNode.offsetPositionForInvocation ??
                callPosition.codePositionKind.select(
                  start: start,
                  end: end,
                  closing: closing,
                );
          } else {
            final positionInfo = _needsCallPosition.remove(callPosition.node)!;
            if (positionInfo.counter > 1) {
              _needsCallPosition[callPosition.node] = (
                kind: positionInfo.kind,
                counter: positionInfo.counter - 1,
                position: positionInfo.position,
              );
            }
            offset = positionInfo.position;
          }
          addStep = true;
          break;
        case StepKind.new_:
          target = _currentNode;
          // Use the syntax offset if this is not the first subexpression.
          offset = _currentNode.offsetPositionForInvocation ?? start;
          addStep = true;
          break;
        case StepKind.access:
          target = _currentNode.parent!;
          offset = end;
          addStep = true;
          break;
        case StepKind.noInfo:
          target = _currentNode;
          offset = end;
          break;
        case StepKind.funExit:
          target = _currentNode;
          offset = closing ?? start;
          // We also emit a step for the closing brace.
          if (_currentNode.active && !_currentNode.parent!.active) {
            secondaryKind = StepKind.noInfo;
            secondaryOffset = end;
          }
          break;
        case StepKind.return_:
          target = _currentNode;
          offset = start;
          // We also emit a step for the enclosing function exiting.
          secondaryKind = StepKind.funExit;
          secondaryOffset = closing;
          break;
        case StepKind.funEntry:
        case StepKind.throw_:
        case StepKind.continue_:
        case StepKind.break_:
          target = _currentNode;
          offset = start;
          break;
        // The remaining kinds are all subexpressions of statements.
        case StepKind.expressionStatement:
        case StepKind.ifCondition:
        case StepKind.forInitializer:
        case StepKind.whileCondition:
        case StepKind.switchExpression:
          if (_currentNode.steps.isNotEmpty) continue;
          target = _currentNode.parent!;
          offset = _currentNode.parent!.startPosition;
          break;
        case StepKind.forCondition:
        case StepKind.forUpdate:
        case StepKind.doCondition:
          if (_currentNode.steps.isNotEmpty) continue;
          target = _currentNode.parent!;
          offset = _currentNode.startPosition;
          break;
      }

      notifyStep(
        target.astNode,
        getOffsetForNode(target.statementOffset, offset),
        stepKind,
      );
      if (secondaryKind != null) {
        notifyStep(
          target.astNode,
          getOffsetForNode(target.statementOffset, secondaryOffset),
          secondaryKind,
        );
      }
      if (addStep) {
        _currentNode.steps.add(node);
      }
    }
  }

  Offset getOffsetForNode(int? statementOffset, int? codeOffset) {
    return Offset(statementOffset, codeOffset);
  }
}

class Coverage {
  final Set<js.Node> _nodesWithInfo = {};
  int _nodesWithInfoCount = 0;
  final Set<js.Node> _nodesWithoutInfo = {};
  int _nodesWithoutInfoCount = 0;
  final Map<Type, int> _nodesWithoutInfoCountByType = {};
  final Set<js.Node> _nodesWithoutOffset = {};
  int _nodesWithoutOffsetCount = 0;

  void registerNodeWithInfo(js.Node node) {
    _nodesWithInfo.add(node);
  }

  void registerNodeWithoutInfo(js.Node node) {
    _nodesWithoutInfo.add(node);
  }

  void registerNodesWithoutOffset(js.Node node) {
    _nodesWithoutOffset.add(node);
  }

  void collapse() {
    _nodesWithInfoCount += _nodesWithInfo.length;
    _nodesWithInfo.clear();
    _nodesWithoutOffsetCount += _nodesWithoutOffset.length;
    _nodesWithoutOffset.clear();

    _nodesWithoutInfoCount += _nodesWithoutInfo.length;

    for (js.Node node in _nodesWithoutInfo) {
      Type type;
      if (node is js.ExpressionStatement) {
        type = node.expression.runtimeType;
      } else {
        type = node.runtimeType;
      }
      _nodesWithoutInfoCountByType.update(
        type,
        (count) => count + 1,
        ifAbsent: () => 1,
      );
    }
    _nodesWithoutInfo.clear();
  }

  String getCoverageReport() {
    collapse();
    StringBuffer sb = StringBuffer();
    int total = _nodesWithInfoCount + _nodesWithoutInfoCount;
    if (total > 0) {
      sb.write(_nodesWithInfoCount);
      sb.write('/');
      sb.write(total);
      sb.write(' (');
      sb.write((100.0 * _nodesWithInfoCount / total).toStringAsFixed(2));
      sb.write('%) nodes with info.');
    } else {
      sb.write('No nodes.');
    }
    if (_nodesWithoutOffsetCount > 0) {
      sb.write(' ');
      sb.write(_nodesWithoutOffsetCount);
      sb.write(' node');
      if (_nodesWithoutOffsetCount > 1) {
        sb.write('s');
      }
      sb.write(' without offset.');
    }
    if (_nodesWithoutInfoCount > 0) {
      sb.write('\nNodes without info (');
      sb.write(_nodesWithoutInfoCount);
      sb.write(') by runtime type:');
      List<Type> types = _nodesWithoutInfoCountByType.keys.toList();
      types.sort((a, b) {
        return -_nodesWithoutInfoCountByType[a]!.compareTo(
          _nodesWithoutInfoCountByType[b]!,
        );
      });

      for (var type in types) {
        int count = _nodesWithoutInfoCountByType[type]!;
        sb.write('\n ');
        sb.write(count);
        sb.write(' ');
        sb.write(type);
        sb.write(' node');
        if (count > 1) {
          sb.write('s');
        }
      }
      sb.write('\n');
    }
    return sb.toString();
  }

  @override
  String toString() => getCoverageReport();
}

/// [TraceListener] that registers [onStep] callbacks with [coverage].
class CoverageListener extends TraceListener with NodeToSourceInformationMixin {
  final Coverage coverage;
  @override
  final SourceInformationReader reader;

  CoverageListener(this.coverage, this.reader);

  @override
  void onStep(js.Node node, Offset offset, StepKind kind) {
    SourceInformation? sourceInformation = computeSourceInformation(node);
    if (sourceInformation != null) {
      coverage.registerNodeWithInfo(node);
    } else {
      coverage.registerNodeWithoutInfo(node);
    }
  }

  @override
  void onEnd(js.Node root) {
    coverage.collapse();
  }
}

/// [CodePositionMap] that registers calls with [Coverage].
class CodePositionCoverage implements CodePositionMap {
  final CodePositionMap codePositions;
  final Coverage coverage;

  CodePositionCoverage(this.codePositions, this.coverage);

  @override
  CodePosition? operator [](js.Node node) {
    CodePosition? codePosition = codePositions[node];
    if (codePosition == null) {
      coverage.registerNodesWithoutOffset(node);
    }
    return codePosition;
  }
}
