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

/// 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 get name;

  /// 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? get coverageId;

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

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

  /// At which stage of the compiler this component was treeshaken.
  TreeShakenStatus get treeShakenStatus;

  T accept<T>(InfoVisitor<T> visitor);
}

/// Indicates at what stage of compilation the [Info] element was treeshaken.
enum TreeShakenStatus { Dead, Live }

/// 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 {
  @override
  final InfoKind kind;

  @override
  String? coverageId;
  @override
  late int size;
  @override
  Info? parent;
  @override
  TreeShakenStatus treeShakenStatus = TreeShakenStatus.Dead;

  @override
  late 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.internal(this.kind);

  @override
  String toString() => '$kind $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.
  List<DependencyInfo> uses = [];
}

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

  /// Information about each package in the program.
  List<PackageInfo> packages = <PackageInfo>[];

  /// 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 each class type (in any library).
  List<ClassTypeInfo> classTypes = <ClassTypeInfo>[];

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

  /// 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 = 1;

  AllInfo();

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

class ProgramInfo {
  final FunctionInfo entrypoint;
  final String ramUsage;
  final int size;
  final String? dart2jsVersion;
  final DateTime compilationMoment;
  final Duration compilationDuration;
  final Duration toJsonDuration;
  final Duration dumpInfoDuration;

  /// `true` if `noSuchMethod` is used.
  final bool noSuchMethodEnabled;

  /// `true` if `Object.runtimeType` is used.
  final bool isRuntimeTypeUsed;

  /// `true` if the `dart:isolate` library is in use.
  final bool isIsolateInUse;

  /// `true` if `Function.apply` is used.
  final bool isFunctionApplyUsed;

  /// `true` if `dart:mirrors` features are used.
  final bool isMirrorsUsed;

  final bool minified;

  ProgramInfo(
      {required this.entrypoint,
      required this.ramUsage,
      required this.size,
      required this.dart2jsVersion,
      required this.compilationMoment,
      required this.compilationDuration,
      required this.toJsonDuration,
      required this.dumpInfoDuration,
      required this.noSuchMethodEnabled,
      required this.isRuntimeTypeUsed,
      required this.isIsolateInUse,
      required this.isFunctionApplyUsed,
      required this.isMirrorsUsed,
      required this.minified});

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

/// Info associated with a package element.
///
/// Note that PackageInfo is only used for converting dart2js info to
/// vm_snapshot_analysis ProgramInfo and is not expected for --dump-info output.
class PackageInfo extends BasicInfo {
  /// All libraries defined within the package
  List<LibraryInfo> libraries = <LibraryInfo>[];

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

  @override
  T accept<T>(InfoVisitor<T> visitor) =>
      throw Exception("PackageInfo is not supported by InfoVisitor.");
}

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

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

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

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

  /// Class types defined within the library.
  List<ClassTypeInfo> classTypes = <ClassTypeInfo>[];

  /// Typedefs defined within the library.
  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 &&
      classTypes.isEmpty;

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

  LibraryInfo.internal() : super.internal(InfoKind.library);

  @override
  T accept<T>(InfoVisitor<T> 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 {
  late final String filename;

  /// The deferred imports that will load this output unit.
  final List<String> imports = <String>[];

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

  OutputUnitInfo.internal() : super.internal(InfoKind.outputUnit);

  @override
  T accept<T>(InfoVisitor<T> visitor) => visitor.visitOutput(this);
}

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

  // TODO(sigmund): split static vs instance vs closures
  /// Functions (static or instance) defined in the class.
  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.
  List<FieldInfo> fields = <FieldInfo>[];

  /// Classes in the supertype hierarchy for this class.
  List<ClassInfo> supers = <ClassInfo>[];

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

  ClassInfo.fromKernel(
      {required String name, required this.isAbstract, required this.supers})
      : super(InfoKind.clazz, name, null, 0, null);

  ClassInfo.internal() : super.internal(InfoKind.clazz);

  @override
  T accept<T>(InfoVisitor<T> visitor) => visitor.visitClass(this);
}

/// Information about a class type element. [ClassTypeInfo] is distinct from
/// [ClassInfo] because a class and its type may end up in different output
/// units.
class ClassTypeInfo extends BasicInfo {
  ClassTypeInfo(
      {required String name, OutputUnitInfo? outputUnit, int size = 0})
      : super(InfoKind.classType, name, outputUnit, size, null);

  ClassTypeInfo.internal() : super.internal(InfoKind.classType);

  @override
  T accept<T>(InfoVisitor<T> visitor) => visitor.visitClassType(this);
}

/// A code span of generated code. A [CodeSpan] object is associated with a
/// single [BasicInfo]. The offsets in the span corresponds to offsets on the
/// file of [BasicInfo.outputUnit].
class CodeSpan {
  /// Start offset in the generated file.
  int? start;

  /// end offset in the generated file.
  int? end;

  /// The actual code (optional, blank when using a compact representation of
  /// the encoding).
  String? text;

  CodeSpan({required this.start, required this.end, this.text});
  CodeSpan.empty();
}

/// Information about a constant value.
// TODO(sigmund): add dependency data for ConstantInfo
class ConstantInfo extends BasicInfo {
  /// The actual generated code for the constant.
  late final List<CodeSpan> code;

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

  ConstantInfo.internal() : super.internal(InfoKind.constant);

  @override
  T accept<T>(InfoVisitor<T> visitor) => visitor.visitConstant(this);
}

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

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

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

  /// The actual generated code for the field.
  late final List<CodeSpan> code;

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

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

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

  FieldInfo.fromKernel(
      {required String name,
      String? coverageId,
      required this.type,
      required this.isConst})
      : super(InfoKind.field, name, null, 0, coverageId);

  FieldInfo.internal() : super.internal(InfoKind.field);

  @override
  T accept<T>(InfoVisitor<T> visitor) => visitor.visitField(this);
}

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

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

  TypedefInfo.internal() : super.internal(InfoKind.typedef);

  @override
  T accept<T>(InfoVisitor<T> 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).
  late final int functionKind;

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

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

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

  /// The declared return type.
  late final String returnType;

  /// The inferred return type.
  late final String inferredReturnType;

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

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

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

  /// The actual generated code.
  late final List<CodeSpan> code;

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

  FunctionInfo.fromKernel(
      {required String name,
      String? coverageId,
      required this.functionKind,
      required this.modifiers,
      required this.type,
      required this.returnType})
      : super(InfoKind.function, name, null, 0, coverageId);

  FunctionInfo.internal() : super.internal(InfoKind.function);

  @override
  T accept<T>(InfoVisitor<T> 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.
  late final FunctionInfo function;

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

  ClosureInfo.fromKernel({required String name})
      : super(InfoKind.closure, name, null, 0, null);

  ClosureInfo.internal() : super.internal(InfoKind.closure);

  @override
  T accept<T>(InfoVisitor<T> 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;
  final bool isGetter;
  final bool isSetter;

  FunctionModifiers({
    this.isStatic = false,
    this.isConst = false,
    this.isFactory = false,
    this.isExternal = false,
    this.isGetter = false,
    this.isSetter = false,
  });
}

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

String? kindToString(InfoKind kind) {
  switch (kind) {
    case InfoKind.library:
      return 'library';
    case InfoKind.clazz:
      return 'class';
    case InfoKind.classType:
      return 'classType';
    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;
  }
}

InfoKind? kindFromString(String kind) {
  switch (kind) {
    case 'library':
      return InfoKind.library;
    case 'class':
      return InfoKind.clazz;
    case 'classType':
      return InfoKind.classType;
    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 visitClassType(ClassTypeInfo 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 adds implementation for PackageInfo specifically for building
/// the VM ProgramInfo Tree from a Dart2js info tree.
abstract class VMProgramInfoVisitor<T> {
  T visitAll(AllInfo info, String outputUnit);
  T visitProgram(ProgramInfo info);
  T visitPackage(PackageInfo info, String outputUnit);
  T visitLibrary(LibraryInfo info, String outputUnit);
  T visitClass(ClassInfo info);
  T visitClassType(ClassTypeInfo 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<void> {
  @override
  void 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);
  }

  @override
  void visitProgram(ProgramInfo info) {}

  void visitPackage(PackageInfo info) {
    throw Exception(
        "PackageInfo objects are only defined for the VM Devtools format.");
  }

  @override
  void visitLibrary(LibraryInfo info) {
    info.topLevelFunctions.forEach(visitFunction);
    info.topLevelVariables.forEach(visitField);
    info.classes.forEach(visitClass);
    info.classTypes.forEach(visitClassType);
    info.typedefs.forEach(visitTypedef);
  }

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

  @override
  void visitClassType(ClassTypeInfo info) {}

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

  @override
  void visitConstant(ConstantInfo info) {}

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

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