// 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:convert';

import 'src/measurements.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].
  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 {
  final InfoKind kind;
  final int 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.id, 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 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 = 4;

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

  static int _id = 0;

  /// 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, _id++, 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>[];

  static int _ids = 0;

  OutputUnitInfo(String name, int size)
      : super(InfoKind.outputUnit, _ids++, 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>[];
  static int _ids = 0;

  ClassInfo(
      {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
      : super(InfoKind.clazz, _ids++, 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;

  static int _ids = 0;
  // TODO(sigmund): Add coverage support to constants?
  ConstantInfo({int size: 0, this.code, OutputUnitInfo outputUnit})
      : super(InfoKind.constant, _ids++, 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<FunctionInfo> 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;

  static int _ids = 0;
  FieldInfo(
      {String name,
      String coverageId,
      int size: 0,
      this.type,
      this.inferredType,
      this.closures,
      this.code,
      OutputUnitInfo outputUnit,
      this.isConst})
      : super(InfoKind.field, _ids++, 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;

  static int _ids = 0;
  TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
      : super(InfoKind.typedef, _ids++, 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;
  static int _ids = 0;

  /// 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<FunctionInfo> 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, _ids++, name, outputUnit, size, coverageId);

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

  dynamic accept(InfoVisitor visitor) => visitor.visitFunction(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 serialied infos.
enum InfoKind {
  library,
  clazz,
  function,
  field,
  constant,
  outputUnit,
  typedef,
}

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';
    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;
    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 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(visitFunction);
  }

  visitConstant(ConstantInfo info) {}

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

  visitTypedef(TypedefInfo info) {}
  visitOutput(OutputUnitInfo info) {}
}
