// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library frame;


import 'package:path/path.dart' as path;

import 'trace.dart';

// #1      Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)
final _vmFrame = new RegExp(
    r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$');

//     at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28)
//     at http://pub.dartlang.org/stuff.dart.js:560:28
final _v8Frame = new RegExp(
    r'^\s*at (?:([^\s].*) \((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$');

// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560
// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
final _firefoxFrame = new RegExp(
    r'^([^@(/]*)(?:\(.*\))?(/[^<]*<?)?(?:\(.*\))?@(.*):(\d+)$');

// foo/bar.dart 10:11 in Foo._bar
// http://dartlang.org/foo/bar.dart in Foo._bar
final _friendlyFrame = new RegExp(
    r'^([^\s]+)(?: (\d+):(\d+))?\s+([^\d][^\s]*)$');

final _initialDot = new RegExp(r"^\.");

/// A single stack frame. Each frame points to a precise location in Dart code.
class Frame {
  /// The URI of the file in which the code is located.
  ///
  /// This URI will usually have the scheme `dart`, `file`, `http`, or `https`.
  final Uri uri;

  /// The line number on which the code location is located.
  ///
  /// This can be null, indicating that the line number is unknown or
  /// unimportant.
  final int line;

  /// The column number of the code location.
  ///
  /// This can be null, indicating that the column number is unknown or
  /// unimportant.
  final int column;

  /// The name of the member in which the code location occurs.
  ///
  /// Anonymous closures are represented as `<fn>` in this member string.
  final String member;

  /// Whether this stack frame comes from the Dart core libraries.
  bool get isCore => uri.scheme == 'dart';

  /// Returns a human-friendly description of the library that this stack frame
  /// comes from.
  ///
  /// This will usually be the string form of [uri], but a relative URI will be
  /// used if possible.
  String get library {
    if (uri.scheme != 'file') return uri.toString();
    return path.relative(path.fromUri(uri));
  }

  /// Returns the name of the package this stack frame comes from, or `null` if
  /// this stack frame doesn't come from a `package:` URL.
  String get package {
    if (uri.scheme != 'package') return null;
    return uri.path.split('/').first;
  }

  /// A human-friendly description of the code location.
  String get location {
    if (line == null || column == null) return library;
    return '$library $line:$column';
  }

  /// Returns a single frame of the current stack.
  ///
  /// By default, this will return the frame above the current method. If
  /// [level] is `0`, it will return the current method's frame; if [level] is
  /// higher than `1`, it will return higher frames.
  factory Frame.caller([int level=1]) {
    if (level < 0) {
      throw new ArgumentError("Argument [level] must be greater than or equal "
          "to 0.");
    }

    return new Trace.current(level + 1).frames.first;
  }

  /// Parses a string representation of a Dart VM stack frame.
  factory Frame.parseVM(String frame) {
    // The VM sometimes folds multiple stack frames together and replaces them
    // with "...".
    if (frame == '...') {
      return new Frame(new Uri(), null, null, '...');
    }

    var match = _vmFrame.firstMatch(frame);
    if (match == null) {
      throw new FormatException("Couldn't parse VM stack trace line '$frame'.");
    }

    var uri = Uri.parse(match[2]);
    var member = match[1].replaceAll("<anonymous closure>", "<fn>");
    return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member);
  }

  /// Parses a string representation of a Chrome/V8 stack frame.
  factory Frame.parseV8(String frame) {
    var match = _v8Frame.firstMatch(frame);
    if (match == null) {
      throw new FormatException("Couldn't parse V8 stack trace line '$frame'.");
    }

    // V8 stack frames can be in two forms.
    if (match[2] != null) {
      // The first form looks like "  at FUNCTION (URI:LINE:COL)"
      var uri = Uri.parse(match[2]);
      var member = match[1].replaceAll("<anonymous>", "<fn>");
      return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member);
    } else {
      // The second form looks like " at URI:LINE:COL", and is used for
      // anonymous functions.
      var uri = Uri.parse(match[5]);
      return new Frame(uri, int.parse(match[6]), int.parse(match[7]), "<fn>");
    }
  }

  /// Parses a string representation of a Firefox stack frame.
  factory Frame.parseFirefox(String frame) {
    var match = _firefoxFrame.firstMatch(frame);
    if (match == null) {
      throw new FormatException(
          "Couldn't parse Firefox stack trace line '$frame'.");
    }

    var uri = Uri.parse(match[3]);
    var member = match[1];
    if (member == "") {
      member = "<fn>";
    } else if (match[2] != null) {
      member = "$member.<fn>";
    }
    // Some Firefox members have initial dots. We remove them for consistency
    // with other platforms.
    member = member.replaceFirst(_initialDot, '');
    return new Frame(uri, int.parse(match[4]), null, member);
  }

  /// Parses this package's string representation of a stack frame.
  factory Frame.parseFriendly(String frame) {
    var match = _friendlyFrame.firstMatch(frame);
    if (match == null) {
      throw new FormatException(
          "Couldn't parse package:stack_trace stack trace line '$frame'.");
    }

    var uri = Uri.parse(match[1]);
    // If there's no scheme, this is a relative URI. We should interpret it as
    // relative to the current working directory.
    if (uri.scheme == '') {
      uri = path.toUri(path.absolute(path.fromUri(uri)));
    }

    var line = match[2] == null ? null : int.parse(match[2]);
    var column = match[3] == null ? null : int.parse(match[3]);
    return new Frame(uri, line, column, match[4]);
  }

  Frame(this.uri, this.line, this.column, this.member);

  String toString() => '$location in $member';
}
