// 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 dart2js.source_information.position;

import '../common.dart';
import '../elements/elements.dart'
    show MemberElement, ResolvedAst, ResolvedAstKind;
import '../js/js.dart' as js;
import '../js/js_debug.dart';
import '../js/js_source_mapping.dart';
import '../tree/tree.dart' show Node, Send;
import 'code_output.dart' show BufferedCodeOutput;
import 'source_file.dart';
import 'source_information.dart';

/// [SourceInformation] that consists of an offset position into the source
/// code.
class PositionSourceInformation extends SourceInformation {
  @override
  final SourceLocation startPosition;

  @override
  final SourceLocation innerPosition;

  PositionSourceInformation(this.startPosition, [this.innerPosition]);

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

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

  int get hashCode {
    return 0x7FFFFFFF &
        (startPosition.hashCode * 17 + innerPosition.hashCode * 19);
  }

  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! PositionSourceInformation) return false;
    return startPosition == other.startPosition &&
        innerPosition == other.innerPosition;
  }

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

  String get shortText {
    if (startPosition != null) {
      return _computeText(startPosition.sourceUri.pathSegments.last);
    } else {
      return _computeText(innerPosition.sourceUri.pathSegments.last);
    }
  }

  String toString() {
    if (startPosition != null) {
      return _computeText('${startPosition.sourceUri}');
    } else {
      return _computeText('${innerPosition.sourceUri}');
    }
  }
}

abstract class AbstractPositionSourceInformationStrategy<T>
    implements JavaScriptSourceInformationStrategy<T> {
  const AbstractPositionSourceInformationStrategy();

  @override
  SourceInformationProcessor createProcessor(
      SourceMapperProvider provider, SourceInformationReader reader) {
    return new PositionSourceInformationProcessor(provider, reader);
  }

  @override
  void onComplete() {}

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

class PositionSourceInformationStrategy
    extends AbstractPositionSourceInformationStrategy<Node> {
  const PositionSourceInformationStrategy();

  @override
  SourceInformationBuilder<Node> createBuilderForContext(MemberElement member) {
    return new PositionSourceInformationBuilder(member);
  }
}

/// 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 premable) 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 <SourceLocation>[];

  @override
  SourceSpan get sourceSpan => new SourceSpan(null, null, null);
}

/// [SourceInformationBuilder] that generates [PositionSourceInformation] from
/// AST nodes.
class PositionSourceInformationBuilder
    implements SourceInformationBuilder<Node> {
  final SourceFile sourceFile;
  final String name;
  final ResolvedAst resolvedAst;

  PositionSourceInformationBuilder(MemberElement member)
      : this.resolvedAst = member.resolvedAst,
        sourceFile = computeSourceFile(member.resolvedAst),
        name = computeElementNameForSourceMaps(member.resolvedAst.element);

  SourceInformation buildDeclaration(MemberElement member) {
    ResolvedAst resolvedAst = member.resolvedAst;
    SourceFile sourceFile = computeSourceFile(member.resolvedAst);
    if (resolvedAst.kind != ResolvedAstKind.PARSED) {
      SourceSpan span = resolvedAst.element.sourcePosition;
      return new PositionSourceInformation(
          new OffsetSourceLocation(sourceFile, span.begin, name));
    } else {
      return new PositionSourceInformation(
          new OffsetSourceLocation(
              sourceFile, resolvedAst.node.getBeginToken().charOffset, name),
          new OffsetSourceLocation(
              sourceFile, resolvedAst.node.getEndToken().charOffset, name));
    }
  }

  /// Builds a source information object pointing the start position of [node].
  SourceInformation buildBegin(Node node) {
    return new PositionSourceInformation(new OffsetSourceLocation(
        sourceFile, node.getBeginToken().charOffset, name));
  }

  /// Builds a source information object pointing the end position of [node].
  SourceInformation buildEnd(Node node) {
    return new PositionSourceInformation(new OffsetSourceLocation(
        sourceFile, node.getEndToken().charOffset, name));
  }

  @override
  SourceInformation buildGeneric(Node node) => buildBegin(node);

  @override
  SourceInformation buildCreate(Node node) => buildBegin(node);

  @override
  SourceInformation buildListLiteral(Node node) => buildBegin(node);

  @override
  SourceInformation buildReturn(Node node) {
    SourceFile sourceFile = computeSourceFile(resolvedAst);
    SourceLocation startPosition = new OffsetSourceLocation(
        sourceFile, node.getBeginToken().charOffset, name);
    SourceLocation endPosition;
    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
      endPosition = new OffsetSourceLocation(
          sourceFile, resolvedAst.node.getEndToken().charOffset, name);
    }
    return new PositionSourceInformation(startPosition, endPosition);
  }

  @override
  SourceInformation buildImplicitReturn(MemberElement element) {
    if (element.isSynthesized) {
      return new PositionSourceInformation(new OffsetSourceLocation(
          sourceFile, element.position.charOffset, name));
    } else {
      return new PositionSourceInformation(new OffsetSourceLocation(
          sourceFile, element.resolvedAst.node.getEndToken().charOffset, name));
    }
  }

  @override
  SourceInformation buildLoop(Node node) => buildBegin(node);

  @override
  SourceInformation buildGet(Node node) {
    Node left = node;
    Node right = node;
    Send send = node.asSend();
    if (send != null) {
      right = send.selector;
    }
    // For a read access like `a.b` the first source locations points to the
    // left-most part of the access, `a` in the example, and the second source
    // location points to the 'name' of accessed property, `b` in the
    // example. The latter is needed when both `a` and `b` are compiled into
    // JavaScript invocations.
    return new PositionSourceInformation(
        new OffsetSourceLocation(
            sourceFile, left.getBeginToken().charOffset, name),
        new OffsetSourceLocation(
            sourceFile, right.getBeginToken().charOffset, name));
  }

  // TODO(johnniwinther): Clean up the use of this and [buildBinary],
  // [buildIndex], etc.
  @override
  SourceInformation buildCall(Node receiver, Node call) {
    return new PositionSourceInformation(
        new OffsetSourceLocation(
            sourceFile, receiver.getBeginToken().charOffset, name),
        new OffsetSourceLocation(
            sourceFile, call.getBeginToken().charOffset, name));
  }

  @override
  SourceInformation buildNew(Node node) {
    return buildBegin(node);
  }

  @override
  SourceInformation buildIf(Node node) => buildBegin(node);

  @override
  SourceInformation buildThrow(Node node) => buildBegin(node);

  @override
  SourceInformation buildAssignment(Node node) => buildBegin(node);

  SourceInformation _buildMemberBody() {
    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
      Node body = resolvedAst.body;
      if (body != null) {
        return buildBegin(body);
      }
      // TODO(johnniwinther): Are there other cases?
    }
    return null;
  }

  SourceInformation _buildMemberExit() {
    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
      Node body = resolvedAst.body;
      if (body != null) {
        return buildEnd(body);
      }
      // TODO(johnniwinther): Are there other cases?
    }
    return null;
  }

  @override
  SourceInformation buildVariableDeclaration() {
    return _buildMemberBody();
  }

  @override
  SourceInformation buildAwait(Node node) => buildBegin(node);

  @override
  SourceInformation buildYield(Node node) => buildBegin(node);

  @override
  SourceInformation buildAsyncBody() {
    return _buildMemberBody();
  }

  @override
  SourceInformation buildAsyncExit() {
    return _buildMemberExit();
  }

  @override
  SourceInformationBuilder forContext(MemberElement member) {
    return new PositionSourceInformationBuilder(member);
  }

  @override
  SourceInformation buildForeignCode(Node node) => buildBegin(node);

  @override
  SourceInformation buildStringInterpolation(Node node) => buildBegin(node);

  @override
  SourceInformation buildForInIterator(Node node) => buildBegin(node);

  @override
  SourceInformation buildForInMoveNext(Node node) => buildBegin(node);

  @override
  SourceInformation buildForInCurrent(Node node) => buildBegin(node);

  @override
  SourceInformation buildForInSet(Node node) => buildBegin(node);

  @override
  SourceInformation buildIndex(Node node) => buildBegin(node);

  @override
  SourceInformation buildIndexSet(Node node) => buildBegin(node);

  @override
  SourceInformation buildBinary(Node node) => buildBegin(node);

  @override
  SourceInformation buildUnary(Node node) => buildBegin(node);

  @override
  SourceInformation buildTry(Node node) => buildBegin(node);

  @override
  SourceInformation buildCatch(Node node) => buildBegin(node);

  @override
  SourceInformation buildIs(Node node) => buildBegin(node);

  @override
  SourceInformation buildAs(Node node) => buildBegin(node);

  @override
  SourceInformation buildSwitch(Node node) => buildBegin(node);

  @override
  SourceInformation buildSwitchCase(Node node) => buildBegin(node);

  @override
  SourceInformation buildGoto(Node node) => buildBegin(node);
}

/// 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);

  // ignore: MISSING_RETURN
  int getPosition(CodePositionKind kind) {
    switch (kind) {
      case CodePositionKind.START:
        return startPosition;
      case CodePositionKind.END:
        return endPosition;
      case CodePositionKind.CLOSING:
        return closingPosition;
    }
  }

  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 {
  Map<js.Node, CodePosition> _codePositionMap =
      new Map<js.Node, CodePosition>.identity();

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

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

  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,
}

// ignore: MISSING_RETURN
SourceLocation getSourceLocation(SourceInformation sourceInformation,
    [SourcePositionKind sourcePositionKind = SourcePositionKind.START]) {
  if (sourceInformation == null) return null;
  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
  START,

  /// 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
  ///
  CLOSING,

  /// 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
  ///
  END,
}

/// Processor that associates [SourceLocation]s from [SourceInformation] on
/// [js.Node]s with the target offsets in a [SourceMapper].
class PositionSourceInformationProcessor 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';

  final CodePositionRecorder codePositionRecorder = new CodePositionRecorder();
  final SourceInformationReader reader;
  CodePositionMap codePositionMap;
  List<TraceListener> traceListeners;

  PositionSourceInformationProcessor(SourceMapperProvider provider, this.reader,
      [Coverage coverage]) {
    codePositionMap = coverage != null
        ? new CodePositionCoverage(codePositionRecorder, coverage)
        : codePositionRecorder;
    traceListeners = [
      new PositionTraceListener(provider.createSourceMapper(id), reader)
    ];
    if (coverage != null) {
      traceListeners.add(new CoverageListener(coverage, reader));
    }
  }

  void process(js.Node node, BufferedCodeOutput code) {
    new JavaScriptTracer(codePositionMap, reader, traceListeners).apply(node);
  }

  @override
  void onPositions(
      js.Node node, int startPosition, int endPosition, int closingPosition) {
    codePositionRecorder.registerPositions(
        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 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].
abstract class NodeToSourceInformationMixin {
  SourceInformationReader get reader;

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

/// [TraceListener] that register [SourceLocation]s with a [SourceMapper].
class PositionTraceListener extends TraceListener
    with NodeToSourceInformationMixin {
  final SourceMapper sourceMapper;
  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 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.FUN_EXIT] 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.NO_INFO) {
      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.FUN_ENTRY:
        // 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.FUN_EXIT:
        registerPosition(SourcePositionKind.INNER);
        break;
      case StepKind.CALL:
        CallPosition callPosition =
            CallPosition.getSemanticPositionForCall(node);
        registerPosition(callPosition.sourcePositionKind);
        break;
      case StepKind.NEW:
      case StepKind.RETURN:
      case StepKind.BREAK:
      case StepKind.CONTINUE:
      case StepKind.THROW:
      case StepKind.EXPRESSION_STATEMENT:
      case StepKind.IF_CONDITION:
      case StepKind.FOR_INITIALIZER:
      case StepKind.FOR_CONDITION:
      case StepKind.FOR_UPDATE:
      case StepKind.WHILE_CONDITION:
      case StepKind.DO_CONDITION:
      case StepKind.SWITCH_EXPRESSION:
        registerPosition(SourcePositionKind.START);
        break;
      case StepKind.NO_INFO:
        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) {
    if (node.target is js.PropertyAccess) {
      js.PropertyAccess access = node.target;
      js.Node target = access;
      bool pureAccess = false;
      while (target is js.PropertyAccess) {
        js.PropertyAccess targetAccess = target;
        if (targetAccess.receiver is js.VariableUse ||
            targetAccess.receiver is js.This) {
          pureAccess = true;
          break;
        } else {
          target = targetAccess.receiver;
        }
      }
      if (pureAccess) {
        // a.m()   this.m()  a.b.c.d.m()
        // ^       ^         ^
        return new CallPosition(
            node, CodePositionKind.START, SourcePositionKind.START);
      } else {
        // *.m()  *.a.b.c.d.m()
        //   ^              ^
        return new CallPosition(
            access.selector, CodePositionKind.START, SourcePositionKind.INNER);
      }
    } else if (node.target is js.VariableUse || node.target is js.This) {
      // m()   this()
      // ^     ^
      return new CallPosition(
          node, CodePositionKind.START, SourcePositionKind.START);
    } else if (node.target is js.Fun ||
        node.target is js.New ||
        node.target is js.NamedFunction) {
      // function(){}()  new Function("...")()   function foo(){}()
      //             ^                      ^                    ^
      return new CallPosition(
          node.target, CodePositionKind.END, SourcePositionKind.INNER);
    } else if (node.target is js.Binary || node.target is js.Call) {
      // (0,a)()   m()()
      //      ^       ^
      return new CallPosition(
          node.target, CodePositionKind.END, SourcePositionKind.INNER);
    } else {
      // TODO(johnniwinther): Maybe remove this assertion.
      assert(
          false,
          failedAt(
              NO_LOCATION_SPANNABLE,
              "Unexpected property access ${nodeToString(node)}:\n"
              "${DebugPrinter.prettyPrint(node)}"));
      // Don't know....
      return new CallPosition(
          node, CodePositionKind.START, 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.
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.
  ///
  final int leftToRightOffset;

  Offset(
      this.statementOffset, this.leftToRightOffset, this.subexpressionOffset);

  int get value => subexpressionOffset;

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

enum BranchKind {
  CONDITION,
  LOOP,
  CATCH,
  FINALLY,
  CASE,
}

enum StepKind {
  FUN_ENTRY,
  FUN_EXIT,
  CALL,
  NEW,
  RETURN,
  BREAK,
  CONTINUE,
  THROW,
  EXPRESSION_STATEMENT,
  IF_CONDITION,
  FOR_INITIALIZER,
  FOR_CONDITION,
  FOR_UPDATE,
  WHILE_CONDITION,
  DO_CONDITION,
  SWITCH_EXPRESSION,
  NO_INFO,
}

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

  /// Called after [root] node has been procesed 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, [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) {}
}

/// Visitor that computes the [js.Node]s the are part of the JavaScript
/// steppable execution and thus needs source mapping locations.
class JavaScriptTracer extends js.BaseVisitor {
  final CodePositionMap codePositions;
  final SourceInformationReader reader;
  final List<TraceListener> listeners;

  /// The steps added by subexpressions.
  List steps = [];

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

  /// The current offset in left-to-right progression.
  int leftToRightOffset;

  /// The offset of the surrounding statement, used for the first subexpression.
  int offsetPosition;

  bool active;

  JavaScriptTracer(this.codePositions, this.reader, this.listeners,
      {this.active: false});

  void notifyStart(js.Node node) {
    listeners.forEach((listener) => listener.onStart(node));
  }

  void notifyEnd(js.Node node) {
    listeners.forEach((listener) => listener.onEnd(node));
  }

  void notifyPushBranch(BranchKind kind, [value]) {
    if (active) {
      listeners.forEach((listener) => listener.pushBranch(kind, value));
    }
  }

  void notifyPopBranch() {
    if (active) {
      listeners.forEach((listener) => listener.popBranch());
    }
  }

  void notifyStep(js.Node node, Offset offset, StepKind kind,
      {bool force: false}) {
    if (active || force) {
      listeners.forEach((listener) => listener.onStep(node, offset, kind));
    }
  }

  void apply(js.Node node) {
    notifyStart(node);

    int startPosition = getSyntaxOffset(node, kind: CodePositionKind.START);
    Offset startOffset = getOffsetForNode(node, startPosition);
    notifyStep(node, startOffset, StepKind.NO_INFO, force: true);

    node.accept(this);
    notifyEnd(node);
  }

  @override
  visitNode(js.Node node) {
    node.visitChildren(this);
  }

  visit(js.Node node, [BranchKind branch, value]) {
    if (node != null) {
      if (branch != null) {
        notifyPushBranch(branch, value);
        node.accept(this);
        notifyPopBranch();
      } else {
        node.accept(this);
      }
    }
  }

  visitList(List<js.Node> nodeList) {
    if (nodeList != null) {
      for (js.Node node in nodeList) {
        visit(node);
      }
    }
  }

  void _handleFunction(js.Node node, js.Node body) {
    bool activeBefore = active;
    if (!active) {
      active = reader.getSourceInformation(node) != null;
    }
    leftToRightOffset =
        statementOffset = getSyntaxOffset(node, kind: CodePositionKind.START);
    Offset entryOffset = getOffsetForNode(node, statementOffset);
    notifyStep(node, entryOffset, StepKind.FUN_ENTRY);

    visit(body);

    leftToRightOffset =
        statementOffset = getSyntaxOffset(node, kind: CodePositionKind.CLOSING);
    Offset exitOffset = getOffsetForNode(node, statementOffset);
    notifyStep(node, exitOffset, StepKind.FUN_EXIT);
    if (active && !activeBefore) {
      int endPosition = getSyntaxOffset(node, kind: CodePositionKind.END);
      Offset endOffset = getOffsetForNode(node, endPosition);
      notifyStep(node, endOffset, StepKind.NO_INFO);
    }
    active = activeBefore;
  }

  @override
  visitFun(js.Fun node) {
    _handleFunction(node, node.body);
  }

  @override
  visitNamedFunction(js.NamedFunction node) {
    _handleFunction(node, node.function.body);
  }

  @override
  visitBlock(js.Block node) {
    for (js.Statement statement in node.statements) {
      visit(statement);
    }
  }

  int getSyntaxOffset(js.Node node,
      {CodePositionKind kind: CodePositionKind.START}) {
    CodePosition codePosition = codePositions[node];
    if (codePosition != null) {
      return codePosition.getPosition(kind);
    }
    return null;
  }

  visitSubexpression(
      js.Node parent, js.Expression child, int codeOffset, StepKind kind) {
    var oldSteps = steps;
    steps = [];
    offsetPosition = codeOffset;
    visit(child);
    if (steps.isEmpty) {
      notifyStep(parent, getOffsetForNode(parent, offsetPosition), kind);
      // The [offsetPosition] should only be used by the first subexpression.
      offsetPosition = null;
    }
    steps = oldSteps;
  }

  @override
  visitExpressionStatement(js.ExpressionStatement node) {
    statementOffset = getSyntaxOffset(node);
    visitSubexpression(
        node, node.expression, statementOffset, StepKind.EXPRESSION_STATEMENT);
    statementOffset = null;
    leftToRightOffset = null;
  }

  @override
  visitEmptyStatement(js.EmptyStatement node) {}

  @override
  visitCall(js.Call node) {
    visit(node.target);
    int oldPosition = offsetPosition;
    offsetPosition = null;
    visitList(node.arguments);
    offsetPosition = oldPosition;
    CallPosition callPosition = CallPosition.getSemanticPositionForCall(node);
    js.Node positionNode = callPosition.node;
    int callOffset =
        getSyntaxOffset(positionNode, kind: callPosition.codePositionKind);
    if (offsetPosition == null) {
      // Use the call offset if this is not the first subexpression.
      offsetPosition = callOffset;
    }
    Offset offset = getOffsetForNode(positionNode, offsetPosition);
    notifyStep(node, offset, StepKind.CALL);
    steps.add(node);
    offsetPosition = null;
  }

  @override
  visitNew(js.New node) {
    visit(node.target);
    visitList(node.arguments);
    if (offsetPosition == null) {
      // Use the syntax offset if this is not the first subexpression.
      offsetPosition = getSyntaxOffset(node);
    }
    notifyStep(node, getOffsetForNode(node, offsetPosition), StepKind.NEW);
    steps.add(node);
    offsetPosition = null;
  }

  @override
  visitAccess(js.PropertyAccess node) {
    visit(node.receiver);
    visit(node.selector);
  }

  @override
  visitVariableUse(js.VariableUse node) {}

  @override
  visitLiteralBool(js.LiteralBool node) {}

  @override
  visitLiteralString(js.LiteralString node) {}

  @override
  visitLiteralNumber(js.LiteralNumber node) {}

  @override
  visitLiteralNull(js.LiteralNull node) {}

  @override
  visitName(js.Name node) {}

  @override
  visitVariableDeclarationList(js.VariableDeclarationList node) {
    visitList(node.declarations);
  }

  @override
  visitVariableDeclaration(js.VariableDeclaration node) {}

  @override
  visitVariableInitialization(js.VariableInitialization node) {
    visit(node.leftHandSide);
    visit(node.value);
  }

  @override
  visitAssignment(js.Assignment node) {
    visit(node.leftHandSide);
    visit(node.value);
  }

  @override
  visitIf(js.If node) {
    statementOffset = getSyntaxOffset(node);
    visitSubexpression(
        node, node.condition, statementOffset, StepKind.IF_CONDITION);
    statementOffset = null;
    visit(node.then, BranchKind.CONDITION, true);
    visit(node.otherwise, BranchKind.CONDITION, false);
  }

  @override
  visitFor(js.For node) {
    int offset = statementOffset = getSyntaxOffset(node);
    statementOffset = offset;
    leftToRightOffset = null;
    if (node.init != null) {
      visitSubexpression(
          node, node.init, getSyntaxOffset(node), StepKind.FOR_INITIALIZER);
    }

    if (node.condition != null) {
      visitSubexpression(node, node.condition, getSyntaxOffset(node.condition),
          StepKind.FOR_CONDITION);
    }

    notifyPushBranch(BranchKind.LOOP);
    visit(node.body);

    statementOffset = offset;
    if (node.update != null) {
      visitSubexpression(
          node, node.update, getSyntaxOffset(node.update), StepKind.FOR_UPDATE);
    }

    notifyPopBranch();
  }

  @override
  visitWhile(js.While node) {
    statementOffset = getSyntaxOffset(node);
    if (node.condition != null) {
      visitSubexpression(node, node.condition, getSyntaxOffset(node),
          StepKind.WHILE_CONDITION);
    }
    statementOffset = null;
    leftToRightOffset = null;

    visit(node.body, BranchKind.LOOP);
  }

  @override
  visitDo(js.Do node) {
    statementOffset = getSyntaxOffset(node);
    visit(node.body);
    if (node.condition != null) {
      visitSubexpression(node, node.condition, getSyntaxOffset(node.condition),
          StepKind.DO_CONDITION);
    }
    statementOffset = null;
    leftToRightOffset = null;
  }

  @override
  visitBinary(js.Binary node) {
    visit(node.left);
    visit(node.right);
  }

  @override
  visitThis(js.This node) {}

  @override
  visitReturn(js.Return node) {
    statementOffset = getSyntaxOffset(node);
    visit(node.value);
    notifyStep(
        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.RETURN);
    Offset exitOffset = getOffsetForNode(
        node, getSyntaxOffset(node, kind: CodePositionKind.CLOSING));
    notifyStep(node, exitOffset, StepKind.FUN_EXIT);
    statementOffset = null;
    leftToRightOffset = null;
  }

  @override
  visitThrow(js.Throw node) {
    statementOffset = getSyntaxOffset(node);
    // Do not use [offsetPosition] for the subexpression.
    offsetPosition = null;
    visit(node.expression);
    notifyStep(
        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.THROW);
    statementOffset = null;
    leftToRightOffset = null;
  }

  @override
  visitContinue(js.Continue node) {
    statementOffset = getSyntaxOffset(node);
    notifyStep(
        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.CONTINUE);
    statementOffset = null;
    leftToRightOffset = null;
  }

  @override
  visitBreak(js.Break node) {
    statementOffset = getSyntaxOffset(node);
    notifyStep(
        node, getOffsetForNode(node, getSyntaxOffset(node)), StepKind.BREAK);
    statementOffset = null;
    leftToRightOffset = null;
  }

  @override
  visitTry(js.Try node) {
    visit(node.body);
    visit(node.catchPart, BranchKind.CATCH);
    visit(node.finallyPart, BranchKind.FINALLY);
  }

  @override
  visitCatch(js.Catch node) {
    visit(node.body);
  }

  @override
  visitConditional(js.Conditional node) {
    visit(node.condition);
    visit(node.then, BranchKind.CONDITION, true);
    visit(node.otherwise, BranchKind.CONDITION, false);
  }

  @override
  visitPrefix(js.Prefix node) {
    visit(node.argument);
  }

  @override
  visitPostfix(js.Postfix node) {
    visit(node.argument);
  }

  @override
  visitObjectInitializer(js.ObjectInitializer node) {
    visitList(node.properties);
  }

  @override
  visitProperty(js.Property node) {
    visit(node.name);
    visit(node.value);
  }

  @override
  visitRegExpLiteral(js.RegExpLiteral node) {}

  @override
  visitSwitch(js.Switch node) {
    statementOffset = getSyntaxOffset(node);
    visitSubexpression(
        node, node.key, getSyntaxOffset(node), StepKind.SWITCH_EXPRESSION);
    statementOffset = null;
    leftToRightOffset = null;
    for (int i = 0; i < node.cases.length; i++) {
      visit(node.cases[i], BranchKind.CASE, i);
    }
  }

  @override
  visitCase(js.Case node) {
    visit(node.expression);
    visit(node.body);
  }

  @override
  visitDefault(js.Default node) {
    visit(node.body);
  }

  @override
  visitArrayInitializer(js.ArrayInitializer node) {
    visitList(node.elements);
  }

  @override
  visitArrayHole(js.ArrayHole node) {}

  @override
  visitLabeledStatement(js.LabeledStatement node) {
    statementOffset = getSyntaxOffset(node);
    visit(node.body);
    statementOffset = null;
  }

  Offset getOffsetForNode(js.Node node, int codeOffset) {
    if (codeOffset == null) {
      CodePosition codePosition = codePositions[node];
      if (codePosition != null) {
        codeOffset = codePosition.startPosition;
      }
    }
    if (leftToRightOffset != null &&
        codeOffset != null &&
        leftToRightOffset < codeOffset) {
      leftToRightOffset = codeOffset;
    }
    if (leftToRightOffset == null) {
      leftToRightOffset = statementOffset;
    }
    return new Offset(statementOffset, leftToRightOffset, codeOffset);
  }
}

class Coverage {
  Set<js.Node> _nodesWithInfo = new Set<js.Node>();
  int _nodesWithInfoCount = 0;
  Set<js.Node> _nodesWithoutInfo = new Set<js.Node>();
  int _nodesWithoutInfoCount = 0;
  Map<Type, int> _nodesWithoutInfoCountByType = <Type, int>{};
  Set<js.Node> _nodesWithoutOffset = new Set<js.Node>();
  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) {
      if (node is js.ExpressionStatement) {
        _nodesWithoutInfoCountByType.putIfAbsent(
            node.expression.runtimeType, () => 0);
        _nodesWithoutInfoCountByType[node.expression.runtimeType]++;
      } else {
        _nodesWithoutInfoCountByType.putIfAbsent(node.runtimeType, () => 0);
        _nodesWithoutInfoCountByType[node.runtimeType]++;
      }
    }
    _nodesWithoutInfo.clear();
  }

  String getCoverageReport() {
    collapse();
    StringBuffer sb = new 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]);
      });

      types.forEach((Type type) {
        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();
  }

  String toString() => getCoverageReport();
}

/// [TraceListener] that registers [onStep] callbacks with [coverage].
class CoverageListener extends TraceListener with NodeToSourceInformationMixin {
  final Coverage coverage;
  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 node) {
    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;
  }
}
