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

/// Data produced by dart2js when run with the `--dump-info` flag.
library dart2js_info.info;

import 'dart:collection';
import 'dart:convert';

import 'package:collection/collection.dart';

import 'src/measurements.dart';
import 'src/util.dart';

export 'src/measurements.dart';

part 'json_info_codec.dart';

/// Common interface to many pieces of information generated by the dart2js
/// compiler that are directly associated with an element (compilation unit,
/// library, class, function, or field).
abstract class Info {
  /// An identifier for the kind of information.
  InfoKind get kind;

  /// Name of the element associated with this info.
  String name;

  /// An id to uniquely identify this info among infos of the same [kind].
  // TODO(kevmoo) Consider removing `id` entirely. Make it an impl detail of
  //              the JSON encoder
  int get id;

  /// A globally unique id combining [kind] and [id] together.
  String get serializedId;

  /// Id used by the compiler when instrumenting code for code coverage.
  // TODO(sigmund): It would be nice if we could use the same id for
  // serialization and for coverage. Could we unify them?
  String coverageId;

  /// Bytes used in the generated code for the corresponding element.
  int size;

  /// Info of the enclosing element.
  Info parent;

  dynamic accept(InfoVisitor visitor);
}

/// Common information used for most kind of elements.
// TODO(sigmund): add more:
//  - inputSize: bytes used in the Dart source program
abstract class BasicInfo implements Info {
  static final Set<int> _ids = new Set<int>();
  final InfoKind kind;

  int _id;
  // TODO(kevmoo) Make computation of id explicit and not on-demand.
  int get id {
    if (_id == null) {
      assert(this is LibraryInfo ||
          this is ConstantInfo ||
          this is OutputUnitInfo ||
          this.parent != null);

      if (this is ConstantInfo) {
        // No name and no parent, so `longName` isn't helpful
        assert(this.name == null);
        assert(this.parent == null);
        assert((this as ConstantInfo).code != null);
        // Instead, use the content of the code.
        _id = (this as ConstantInfo).code.hashCode;
      } else {
        _id = longName(this, useLibraryUri: true).hashCode;
      }
      while (!_ids.add(_id)) {
        _id++;
      }
    }

    return _id;
  }

  String coverageId;
  int size;
  Info parent;

  String get serializedId => '${kindToString(kind)}/$id';

  String name;

  /// If using deferred libraries, where the element associated with this info
  /// is generated.
  OutputUnitInfo outputUnit;

  BasicInfo(this.kind, this.name, this.outputUnit, this.size, this.coverageId);

  BasicInfo._fromId(String serializedId)
      : kind = _kindFromSerializedId(serializedId),
        _id = _idFromSerializedId(serializedId);

  String toString() => '$serializedId $name [$size]';
}

/// Info associated with elements containing executable code (like fields and
/// methods)
abstract class CodeInfo implements Info {
  /// How does this function or field depend on others.
  final List<DependencyInfo> uses = <DependencyInfo>[];
}

/// The entire information produced while compiling a program.
class AllInfo {
  /// Summary information about the program.
  ProgramInfo program;

  /// Information about each library processed by the compiler.
  List<LibraryInfo> libraries = <LibraryInfo>[];

  /// Information about each function (includes methods and getters in any
  /// library)
  List<FunctionInfo> functions = <FunctionInfo>[];

  /// Information about type defs in the program.
  List<TypedefInfo> typedefs = <TypedefInfo>[];

  /// Information about each class (in any library).
  List<ClassInfo> classes = <ClassInfo>[];

  /// Information about fields (in any class).
  List<FieldInfo> fields = <FieldInfo>[];

  /// Information about constants anywhere in the program.
  // TODO(sigmund): expand docs about canonicalization. We don't put these
  // inside library because a single constant can be used in more than one lib,
  // and we'll include it only once in the output.
  List<ConstantInfo> constants = <ConstantInfo>[];

  /// Information about closures anywhere in the program.
  List<ClosureInfo> closures = <ClosureInfo>[];

  /// Information about output units (should be just one entry if not using
  /// deferred loading).
  List<OutputUnitInfo> outputUnits = <OutputUnitInfo>[];

  /// Details about all deferred imports and what files would be loaded when the
  /// import is resolved.
  // TODO(sigmund): use a different format for dump-info. This currently emits
  // the same map that is created for the `--deferred-map` flag.
  Map<String, Map<String, dynamic>> deferredFiles;

  /// A new representation of dependencies from one info to another. An entry in
  /// this map indicates that an [Info] depends on another (e.g. a function
  /// invokes another). Please note that the data in this field might not be
  /// accurate yet (this is work in progress).
  Map<Info, List<Info>> dependencies = {};

  /// Major version indicating breaking changes in the format. A new version
  /// means that an old deserialization algorithm will not work with the new
  /// format.
  final int version = 5;

  /// Minor version indicating non-breaking changes in the format. A change in
  /// this version number means that the json parsing in this library from a
  /// previous will continue to work after the change. This is typically
  /// increased when adding new entries to the file format.
  // Note: the dump-info.viewer app was written using a json parser version 3.2.
  final int minorVersion = 0;

  AllInfo();

  dynamic accept(InfoVisitor visitor) => visitor.visitAll(this);
}

class ProgramInfo {
  FunctionInfo entrypoint;
  int size;
  String dart2jsVersion;
  DateTime compilationMoment;
  Duration compilationDuration;
  Duration toJsonDuration;
  Duration dumpInfoDuration;
  bool noSuchMethodEnabled;
  bool minified;

  ProgramInfo(
      {this.entrypoint,
      this.size,
      this.dart2jsVersion,
      this.compilationMoment,
      this.compilationDuration,
      this.toJsonDuration,
      this.dumpInfoDuration,
      this.noSuchMethodEnabled,
      this.minified});

  dynamic accept(InfoVisitor visitor) => visitor.visitProgram(this);
}

/// Info associated with a library element.
class LibraryInfo extends BasicInfo {
  /// Canonical uri that identifies the library.
  Uri uri;

  /// Top level functions defined within the library.
  final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[];

  /// Top level fields defined within the library.
  final List<FieldInfo> topLevelVariables = <FieldInfo>[];

  /// Classes defined within the library.
  final List<ClassInfo> classes = <ClassInfo>[];

  /// Typedefs defined within the library.
  final List<TypedefInfo> typedefs = <TypedefInfo>[];

  // TODO(sigmund): add here a list of parts. That can help us improve how we
  // encode source-span information in metrics (rather than include the uri on
  // each function, include an index into this list).

  /// Whether there is any information recorded for this library.
  bool get isEmpty =>
      topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty;

  LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size)
      : super(InfoKind.library, name, outputUnit, size, null);

  LibraryInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitLibrary(this);
}

/// Information about an output unit. Normally there is just one for the entire
/// program unless the application uses deferred imports, in which case there
/// would be an additional output unit per deferred chunk.
class OutputUnitInfo extends BasicInfo {
  /// The deferred imports that will load this output unit.
  List<String> imports = <String>[];

  OutputUnitInfo(String name, int size)
      : super(InfoKind.outputUnit, name, null, size, null);

  OutputUnitInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitOutput(this);
}

/// Information about a class element.
class ClassInfo extends BasicInfo {
  /// Whether the class is abstract.
  bool isAbstract;

  // TODO(sigmund): split static vs instance vs closures
  /// Functions (static or instance) defined in the class.
  final List<FunctionInfo> functions = <FunctionInfo>[];

  /// Fields defined in the class.
  // TODO(sigmund): currently appears to only be populated with instance fields,
  // but this should be fixed.
  final List<FieldInfo> fields = <FieldInfo>[];

  ClassInfo(
      {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
      : super(InfoKind.clazz, name, outputUnit, size, null);

  ClassInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitClass(this);
}

/// Information about a constant value.
// TODO(sigmund): add dependency data for ConstantInfo
class ConstantInfo extends BasicInfo {
  /// The actual generated code for the constant.
  String code;

  // TODO(sigmund): Add coverage support to constants?
  ConstantInfo({int size: 0, this.code, OutputUnitInfo outputUnit})
      : super(InfoKind.constant, null, outputUnit, size, null);

  ConstantInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitConstant(this);
}

/// Information about a field element.
class FieldInfo extends BasicInfo with CodeInfo {
  /// The type of the field.
  String type;

  /// The type inferred by dart2js's whole program analysis
  String inferredType;

  /// Nested closures seen in the field initializer.
  List<ClosureInfo> closures;

  /// The actual generated code for the field.
  String code;

  /// Whether this corresponds to a const field declaration.
  bool isConst;

  /// When [isConst] is true, the constant initializer expression.
  ConstantInfo initializer;

  FieldInfo(
      {String name,
      String coverageId,
      int size: 0,
      this.type,
      this.inferredType,
      this.closures,
      this.code,
      OutputUnitInfo outputUnit,
      this.isConst})
      : super(InfoKind.field, name, outputUnit, size, coverageId);

  FieldInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitField(this);
}

/// Information about a typedef declaration.
class TypedefInfo extends BasicInfo {
  /// The declared type.
  String type;

  TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
      : super(InfoKind.typedef, name, outputUnit, 0, null);

  TypedefInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitTypedef(this);
}

/// Information about a function or method.
class FunctionInfo extends BasicInfo with CodeInfo {
  static const int TOP_LEVEL_FUNCTION_KIND = 0;
  static const int CLOSURE_FUNCTION_KIND = 1;
  static const int METHOD_FUNCTION_KIND = 2;
  static const int CONSTRUCTOR_FUNCTION_KIND = 3;

  /// Kind of function (top-level function, closure, method, or constructor).
  int functionKind;

  /// Modifiers applied to this function.
  FunctionModifiers modifiers;

  /// Nested closures that appear within the body of this function.
  List<ClosureInfo> closures;

  /// The type of this function.
  String type;

  /// The declared return type.
  String returnType;

  /// The inferred return type.
  String inferredReturnType;

  /// Name and type information for each parameter.
  List<ParameterInfo> parameters;

  /// Side-effects.
  // TODO(sigmund): serialize more precisely, not just a string representation.
  String sideEffects;

  /// How many function calls were inlined into this function.
  int inlinedCount;

  /// The actual generated code.
  String code;

  /// Measurements collected for this function.
  Measurements measurements;

  FunctionInfo(
      {String name,
      String coverageId,
      OutputUnitInfo outputUnit,
      int size: 0,
      this.functionKind,
      this.modifiers,
      this.closures,
      this.type,
      this.returnType,
      this.inferredReturnType,
      this.parameters,
      this.sideEffects,
      this.inlinedCount,
      this.code,
      this.measurements})
      : super(InfoKind.function, name, outputUnit, size, coverageId);

  FunctionInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitFunction(this);
}

/// Information about a closure, also known as a local function.
class ClosureInfo extends BasicInfo {
  /// The function that is wrapped by this closure.
  FunctionInfo function;

  ClosureInfo(
      {String name, OutputUnitInfo outputUnit, int size: 0, this.function})
      : super(InfoKind.closure, name, outputUnit, size, null);

  ClosureInfo._(String serializedId) : super._fromId(serializedId);

  dynamic accept(InfoVisitor visitor) => visitor.visitClosure(this);
}

/// Information about how a dependency is used.
class DependencyInfo {
  /// The dependency, either a FunctionInfo or FieldInfo.
  final Info target;

  /// Either a selector mask indicating how this is used, or 'inlined'.
  // TODO(sigmund): split mask into an enum or something more precise to really
  // describe the dependencies in detail.
  final String mask;

  DependencyInfo(this.target, this.mask);
}

/// Name and type information about a function parameter.
class ParameterInfo {
  final String name;
  final String type;
  final String declaredType;

  ParameterInfo(this.name, this.type, this.declaredType);
}

/// Modifiers that may apply to methods.
class FunctionModifiers {
  final bool isStatic;
  final bool isConst;
  final bool isFactory;
  final bool isExternal;

  FunctionModifiers(
      {this.isStatic: false,
      this.isConst: false,
      this.isFactory: false,
      this.isExternal: false});
}

/// Possible values of the `kind` field in the serialized infos.
enum InfoKind {
  library,
  clazz,
  function,
  field,
  constant,
  outputUnit,
  typedef,
  closure,
}

String kindToString(InfoKind kind) {
  switch (kind) {
    case InfoKind.library:
      return 'library';
    case InfoKind.clazz:
      return 'class';
    case InfoKind.function:
      return 'function';
    case InfoKind.field:
      return 'field';
    case InfoKind.constant:
      return 'constant';
    case InfoKind.outputUnit:
      return 'outputUnit';
    case InfoKind.typedef:
      return 'typedef';
    case InfoKind.closure:
      return 'closure';
    default:
      return null;
  }
}

int _idFromSerializedId(String serializedId) =>
    int.parse(serializedId.substring(serializedId.indexOf('/') + 1));

InfoKind _kindFromSerializedId(String serializedId) =>
    kindFromString(serializedId.substring(0, serializedId.indexOf('/')));

InfoKind kindFromString(String kind) {
  switch (kind) {
    case 'library':
      return InfoKind.library;
    case 'class':
      return InfoKind.clazz;
    case 'function':
      return InfoKind.function;
    case 'field':
      return InfoKind.field;
    case 'constant':
      return InfoKind.constant;
    case 'outputUnit':
      return InfoKind.outputUnit;
    case 'typedef':
      return InfoKind.typedef;
    case 'closure':
      return InfoKind.closure;
    default:
      return null;
  }
}

/// A simple visitor for information produced by the dart2js compiler.
abstract class InfoVisitor<T> {
  T visitAll(AllInfo info);
  T visitProgram(ProgramInfo info);
  T visitLibrary(LibraryInfo info);
  T visitClass(ClassInfo info);
  T visitField(FieldInfo info);
  T visitConstant(ConstantInfo info);
  T visitFunction(FunctionInfo info);
  T visitTypedef(TypedefInfo info);
  T visitClosure(ClosureInfo info);
  T visitOutput(OutputUnitInfo info);
}

/// A visitor that recursively walks each portion of the program. Because the
/// info representation is redundant, this visitor only walks the structure of
/// the program and skips some redundant links. For example, even though
/// visitAll contains references to functions, this visitor only recurses to
/// visit libraries, then from each library we visit functions and classes, and
/// so on.
class RecursiveInfoVisitor extends InfoVisitor<Null> {
  visitAll(AllInfo info) {
    // Note: we don't visit functions, fields, classes, and typedefs because
    // they are reachable from the library info.
    info.libraries.forEach(visitLibrary);
    info.constants.forEach(visitConstant);
  }

  visitProgram(ProgramInfo info) {}

  visitLibrary(LibraryInfo info) {
    info.topLevelFunctions.forEach(visitFunction);
    info.topLevelVariables.forEach(visitField);
    info.classes.forEach(visitClass);
    info.typedefs.forEach(visitTypedef);
  }

  visitClass(ClassInfo info) {
    info.functions.forEach(visitFunction);
    info.fields.forEach(visitField);
  }

  visitField(FieldInfo info) {
    info.closures.forEach(visitClosure);
  }

  visitConstant(ConstantInfo info) {}

  visitFunction(FunctionInfo info) {
    info.closures.forEach(visitClosure);
  }

  visitTypedef(TypedefInfo info) {}
  visitOutput(OutputUnitInfo info) {}
  visitClosure(ClosureInfo info) {
    visitFunction(info.function);
  }
}
