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

/// 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,
      this.isMirrorsUsed = false,
      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({this.start, this.end, this.text});
}

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