// Copyright (c) 2017, 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 dart2js.js_model.env;

import 'package:js_shared/variance.dart';
import 'package:kernel/ast.dart' as ir;

import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../ir/element_map.dart';
import '../ir/util.dart';
import '../js_model/class_type_variable_access.dart';
import '../ordered_typeset.dart';
import '../serialization/deferrable.dart';
import '../serialization/serialization.dart';
import 'closure.dart'
    show
        ClosureClassData,
        ContextClassData,
        ClosureFunctionData,
        ClosureFieldData;
import 'element_map.dart'
    show
        ClassDefinition,
        JsToElementMap,
        MemberDefinition,
        forEachOrderedParameterByFunctionNode;
import 'element_map_impl.dart';
import 'elements.dart';
import 'records.dart' show RecordClassData, RecordGetterData;

/// Environment for fast lookup of component libraries.
class JProgramEnv {
  final Iterable<ir.Component> _components;
  final Map<Uri, JLibraryEnv> _libraryMap = {};

  JProgramEnv(this._components);

  /// TODO(johnniwinther): Handle arbitrary load order if needed.
  ir.Member? get mainMethod => _components.first.mainMethod;

  ir.Component get mainComponent => _components.first;

  void registerLibrary(JLibraryEnv env) {
    _libraryMap[env.library.importUri] = env;
  }

  /// Return the [JLibraryEnv] for the library with the canonical [uri].
  JLibraryEnv? lookupLibrary(Uri uri) {
    return _libraryMap[uri];
  }

  /// Calls [f] for each library in this environment.
  void forEachLibrary(void f(JLibraryEnv library)) {
    _libraryMap.values.forEach(f);
  }

  /// Returns the number of libraries in this environment.
  int get length {
    return _libraryMap.length;
  }
}

/// Environment for fast lookup of library classes and members.
class JLibraryEnv {
  /// Tag used for identifying serialized [JLibraryEnv] objects in a
  /// debugging data stream.
  static const String tag = 'library-env';

  final ir.Library library;
  final Map<String, JClassEnv> _classMap = {};
  final Map<String, ir.Member> _memberMap;
  final Map<String, ir.Member> _setterMap;

  JLibraryEnv(this.library, this._memberMap, this._setterMap);

  /// Deserializes a [JLibraryEnv] object from [source].
  factory JLibraryEnv.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Library library = source.readLibraryNode();
    Map<String, ir.Member> memberMap =
        source.readStringMap(source.readMemberNode);
    Map<String, ir.Member> setterMap =
        source.readStringMap(source.readMemberNode);
    source.end(tag);
    return JLibraryEnv(library, memberMap, setterMap);
  }

  /// Serializes this [JLibraryEnv] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeLibraryNode(library);
    sink.writeStringMap(_memberMap, sink.writeMemberNode);
    sink.writeStringMap(_setterMap, sink.writeMemberNode);
    sink.end(tag);
  }

  void registerClass(String name, JClassEnv classEnv) {
    _classMap[name] = classEnv;
  }

  /// Return the [JClassEnv] for the class [name] in [library].
  JClassEnv? lookupClass(String name) {
    return _classMap[name];
  }

  /// Calls [f] for each class in this library.
  void forEachClass(void f(JClassEnv cls)) {
    _classMap.values.forEach(f);
  }

  /// Return the [ir.Member] for the member [name] in [library].
  ir.Member? lookupMember(String name, {bool setter = false}) {
    return setter ? _setterMap[name] : _memberMap[name];
  }

  void forEachMember(void f(ir.Member member)) {
    _memberMap.values.forEach(f);
    for (ir.Member member in _setterMap.values) {
      if (member is ir.Procedure) {
        f(member);
      } else {
        // Skip fields; these are also in _memberMap.
      }
    }
  }
}

class JLibraryData {
  /// Tag used for identifying serialized [JLibraryData] objects in a
  /// debugging data stream.
  static const String tag = 'library-data';

  final ir.Library library;
  // TODO(johnniwinther): Avoid direct access to [imports]. It might be null if
  // it hasn't been computed for the corresponding [KLibraryData].
  final Map<ir.LibraryDependency, ImportEntity> imports;

  JLibraryData(this.library, this.imports);

  factory JLibraryData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Library library = source.readLibraryNode();
    int importCount = source.readInt();
    Map<ir.LibraryDependency, ImportEntity> imports;
    if (importCount > 0) {
      imports = {};
      for (int i = 0; i < importCount; i++) {
        int index = source.readInt();
        ImportEntity import = source.readImport();
        imports[library.dependencies[index]] = import;
      }
    } else {
      imports = const {};
    }
    source.end(tag);
    return JLibraryData(library, imports);
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeLibraryNode(library);
    sink.writeInt(imports.length);
    int index = 0;
    for (ir.LibraryDependency node in library.dependencies) {
      ImportEntity? import = imports[node];
      if (import != null) {
        sink.writeInt(index);
        sink.writeImport(import);
      }
      index++;
    }
    sink.end(tag);
  }
}

/// Enum used for identifying [JClassEnv] subclasses in serialization.
enum JClassEnvKind { node, closure, context, record }

/// Member data for a class.
abstract class JClassEnv {
  /// Deserializes a [JClassEnv] object from [source].
  factory JClassEnv.readFromDataSource(DataSourceReader source) {
    JClassEnvKind kind = source.readEnum(JClassEnvKind.values);
    switch (kind) {
      case JClassEnvKind.node:
        return JClassEnvImpl.readFromDataSource(source);
      case JClassEnvKind.closure:
        return ClosureClassEnv.readFromDataSource(source);
      case JClassEnvKind.context:
        return ContextEnv.readFromDataSource(source);
      case JClassEnvKind.record:
        return RecordClassEnv.readFromDataSource(source);
    }
  }

  /// Serializes this [JClassEnv] to [sink].
  void writeToDataSink(DataSinkWriter sink);

  /// The [ir.Class] that defined the class, if any.
  ir.Class? get cls;

  /// Whether the class is an unnamed mixin application.
  bool get isUnnamedMixinApplication;

  /// Whether the class is a mixin application with its own members.
  ///
  /// This occurs when a mixin contains methods with super calls or when
  /// the mixin application contains concrete forwarding stubs.
  bool get isMixinApplicationWithMembers;

  /// Return the [MemberEntity] for the member [name] in the class. If [setter]
  /// is `true`, the setter or assignable field corresponding to [name] is
  /// returned.
  MemberEntity? lookupMember(IrToElementMap elementMap, Name name);

  /// Calls [f] for each member of [cls].
  void forEachMember(IrToElementMap elementMap, void f(MemberEntity member));

  /// Return the [ConstructorEntity] for the constructor [name] in [cls].
  ConstructorEntity? lookupConstructor(IrToElementMap elementMap, String name);

  /// Calls [f] for each constructor of [cls].
  void forEachConstructor(
      IrToElementMap elementMap, void f(ConstructorEntity constructor));

  /// Calls [f] for each constructor body for the live constructors in the
  /// class.
  void forEachConstructorBody(void f(ConstructorBodyEntity constructor));
}

/// Environment for fast lookup of class members.
class JClassEnvImpl implements JClassEnv {
  /// Tag used for identifying serialized [JClassEnv] objects in a
  /// debugging data stream.
  static const String tag = 'class-env';

  @override
  final ir.Class cls;
  final Map<String, ir.Member> _constructorMap;
  final Map<Name, ir.Member> _memberMap;
  final List<ir.Member> _members; // in declaration order.
  @override
  final bool isMixinApplicationWithMembers;

  /// Constructor bodies created for this class.
  List<ConstructorBodyEntity>? _constructorBodyList;

  JClassEnvImpl(this.cls, this._constructorMap, this._memberMap, this._members,
      this.isMixinApplicationWithMembers);

  factory JClassEnvImpl.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Class cls = source.readClassNode();
    Map<String, ir.Member> constructorMap =
        source.readStringMap(source.readMemberNode);
    Map<Name, ir.Member> memberMap = source.readNameMap(source.readMemberNode);
    List<ir.Member> members = source.readMemberNodes();
    bool isSuperMixinApplication = source.readBool();
    source.end(tag);
    return JClassEnvImpl(
        cls, constructorMap, memberMap, members, isSuperMixinApplication);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassEnvKind.node);
    sink.begin(tag);
    sink.writeClassNode(cls);
    sink.writeStringMap(_constructorMap, sink.writeMemberNode);
    sink.writeNameMap(_memberMap, sink.writeMemberNode);
    sink.writeMemberNodes(_members);
    sink.writeBool(isMixinApplicationWithMembers);
    sink.end(tag);
  }

  @override
  bool get isUnnamedMixinApplication => cls.isAnonymousMixin;

  @override
  MemberEntity? lookupMember(IrToElementMap elementMap, Name name) {
    ir.Member? member = _memberMap[name];
    return member != null ? elementMap.getMember(member) : null;
  }

  @override
  void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
    _members.forEach((ir.Member member) {
      f(elementMap.getMember(member));
    });
  }

  @override
  ConstructorEntity? lookupConstructor(IrToElementMap elementMap, String name) {
    ir.Member? constructor = _constructorMap[name];
    return constructor != null ? elementMap.getConstructor(constructor) : null;
  }

  @override
  void forEachConstructor(
      IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
    _constructorMap.values.forEach((ir.Member constructor) {
      f(elementMap.getConstructor(constructor));
    });
  }

  void addConstructorBody(ConstructorBodyEntity constructorBody) {
    (_constructorBodyList ??= <ConstructorBodyEntity>[]).add(constructorBody);
  }

  @override
  void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
    _constructorBodyList?.forEach(f);
  }
}

class ContextEnv implements JClassEnv {
  /// Tag used for identifying serialized [ContextEnv] objects in a debugging
  /// data stream.
  static const String tag = 'context-env';

  final Map<Name, MemberEntity> _memberMap;

  ContextEnv(this._memberMap);

  factory ContextEnv.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Map<Name, MemberEntity> _memberMap =
        source.readNameMap(() => source.readMember());
    source.end(tag);
    return ContextEnv(_memberMap);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassEnvKind.context);
    sink.begin(tag);
    sink.writeNameMap(_memberMap, (member) => sink.writeMember(member));
    sink.end(tag);
  }

  @override
  void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
    // We do not create constructor bodies for containers.
  }

  @override
  void forEachConstructor(
      IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
    // We do not create constructors for containers.
  }

  @override
  ConstructorEntity? lookupConstructor(IrToElementMap elementMap, String name) {
    // We do not create constructors for containers.
    return null;
  }

  @override
  void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
    _memberMap.values.forEach(f);
  }

  @override
  MemberEntity? lookupMember(IrToElementMap elementMap, Name name) {
    return _memberMap[name];
  }

  @override
  bool get isUnnamedMixinApplication => false;

  @override
  bool get isMixinApplicationWithMembers => false;

  @override
  ir.Class? get cls => null;
}

class ClosureClassEnv extends ContextEnv {
  /// Tag used for identifying serialized [ClosureClassEnv] objects in a
  /// debugging data stream.
  static const String tag = 'closure-class-env';

  ClosureClassEnv(super.memberMap);

  factory ClosureClassEnv.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Map<Name, MemberEntity> _memberMap =
        source.readNameMap(() => source.readMember());
    source.end(tag);
    return ClosureClassEnv(_memberMap);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassEnvKind.closure);
    sink.begin(tag);
    sink.writeNameMap(_memberMap, (member) => sink.writeMember(member));
    sink.end(tag);
  }
}

class RecordClassEnv implements JClassEnv {
  /// Tag used for identifying serialized [ContextEnv] objects in a debugging
  /// data stream.
  static const String tag = 'record-env';

  final Map<Name, MemberEntity> _memberMap;

  RecordClassEnv(this._memberMap);

  factory RecordClassEnv.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    Map<Name, MemberEntity> _memberMap =
        source.readNameMap(() => source.readMember());
    source.end(tag);
    return RecordClassEnv(_memberMap);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassEnvKind.record);
    sink.begin(tag);
    sink.writeNameMap(_memberMap, (member) => sink.writeMember(member));
    sink.end(tag);
  }

  @override
  void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) {
    // We do not create constructor bodies for containers.
  }

  @override
  void forEachConstructor(
      IrToElementMap elementMap, void f(ConstructorEntity constructor)) {
    // We do not create constructors for containers.
  }

  @override
  ConstructorEntity? lookupConstructor(IrToElementMap elementMap, String name) {
    // We do not create constructors for containers.
    return null;
  }

  @override
  void forEachMember(IrToElementMap elementMap, void f(MemberEntity member)) {
    _memberMap.values.forEach(f);
  }

  @override
  MemberEntity? lookupMember(IrToElementMap elementMap, Name name) {
    return _memberMap[name];
  }

  @override
  bool get isUnnamedMixinApplication => false;

  @override
  bool get isMixinApplicationWithMembers => false;

  @override
  ir.Class? get cls => null;
}

/// Enum used for identifying [JClassData] subclasses in serialization.
enum JClassDataKind { node, closure, context, record }

abstract class JClassData {
  /// Deserializes a [JClassData] object from [source].
  factory JClassData.readFromDataSource(DataSourceReader source) {
    JClassDataKind kind = source.readEnum(JClassDataKind.values);
    switch (kind) {
      case JClassDataKind.node:
        return JClassDataImpl.readFromDataSource(source);
      case JClassDataKind.closure:
        return ClosureClassData.readFromDataSource(source);
      case JClassDataKind.context:
        return ContextClassData.readFromDataSource(source);
      case JClassDataKind.record:
        return RecordClassData.readFromDataSource(source);
    }
  }

  /// Serializes this [JClassData] to [sink].
  void writeToDataSink(DataSinkWriter sink);

  ClassDefinition get definition;

  InterfaceType? get thisType;
  InterfaceType? get jsInteropType;
  InterfaceType? get rawType;
  InterfaceType? get instantiationToBounds;
  InterfaceType? get supertype;
  InterfaceType? get mixedInType;
  List<InterfaceType> get interfaces;
  OrderedTypeSet? get orderedTypeSet;
  FunctionType? get callType;

  bool get isEnumClass;
  bool? get isMixinApplication;

  List<Variance> getVariances();
}

class JClassDataImpl implements JClassData {
  /// Tag used for identifying serialized [JClassDataImpl] objects in a
  /// debugging data stream.
  static const String tag = 'class-data';

  final ir.Class cls;
  @override
  final ClassDefinition definition;
  @override
  bool? isMixinApplication;

  @override
  InterfaceType? thisType;
  @override
  InterfaceType? jsInteropType;
  @override
  InterfaceType? rawType;
  @override
  InterfaceType? instantiationToBounds;
  @override
  InterfaceType? supertype;
  @override
  InterfaceType? mixedInType;
  @override
  late List<InterfaceType> interfaces;
  @override
  OrderedTypeSet? orderedTypeSet;

  List<Variance>? _variances;

  JClassDataImpl(this.cls, this.definition);

  factory JClassDataImpl.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Class cls = source.readClassNode();
    ClassDefinition definition = ClassDefinition.readFromDataSource(source);
    source.end(tag);
    return JClassDataImpl(cls, definition);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassDataKind.node);
    sink.begin(tag);
    sink.writeClassNode(cls);
    definition.writeToDataSink(sink);
    sink.end(tag);
  }

  @override
  bool get isEnumClass => cls.isEnum;

  @override
  FunctionType? callType;
  bool isCallTypeComputed = false;

  @override
  List<Variance> getVariances() =>
      _variances ??= cls.typeParameters.map(convertVariance).toList();
}

/// Enum used for identifying [JMemberData] subclasses in serialization.
enum JMemberDataKind {
  function,
  field,
  constructor,
  constructorBody,
  signature,
  generatorBody,
  closureFunction,
  closureField,
  recordGetter,
}

abstract class JMemberData {
  MemberDefinition get definition;

  InterfaceType? getMemberThisType(JsToElementMap elementMap);

  ClassTypeVariableAccess get classTypeVariableAccess;

  JMemberData();

  /// Deserializes a [JMemberData] object from [source].
  factory JMemberData.readFromDataSource(DataSourceReader source) {
    JMemberDataKind kind = source.readEnum(JMemberDataKind.values);
    switch (kind) {
      case JMemberDataKind.function:
        return FunctionDataImpl.readFromDataSource(source);
      case JMemberDataKind.field:
        return JFieldDataImpl.readFromDataSource(source);
      case JMemberDataKind.constructor:
        return JConstructorData.readFromDataSource(source);
      case JMemberDataKind.constructorBody:
        return ConstructorBodyDataImpl.readFromDataSource(source);
      case JMemberDataKind.signature:
        return SignatureFunctionData.readFromDataSource(source);
      case JMemberDataKind.generatorBody:
        return GeneratorBodyFunctionData.readFromDataSource(source);
      case JMemberDataKind.closureFunction:
        return ClosureFunctionData.readFromDataSource(source);
      case JMemberDataKind.closureField:
        return ClosureFieldData.readFromDataSource(source);
      case JMemberDataKind.recordGetter:
        return RecordGetterData.readFromDataSource(source);
    }
  }

  /// Serializes this [JMemberData] to [sink].
  void writeToDataSink(DataSinkWriter sink);
}

abstract class JMemberDataImpl implements JMemberData {
  final ir.Member node;

  @override
  final MemberDefinition definition;

  JMemberDataImpl(this.node, this.definition);

  JMemberDataImpl._deserialized(this.node, this.definition);

  @override
  InterfaceType? getMemberThisType(JsToElementMap elementMap) {
    MemberEntity member = elementMap.getMember(node);
    ClassEntity? cls = member.enclosingClass;
    if (cls != null) {
      return elementMap.elementEnvironment.getThisType(cls);
    }
    return null;
  }
}

abstract class FunctionData implements JMemberData {
  FunctionType getFunctionType(IrToElementMap elementMap);

  List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap);

  void forEachParameter(
      JsToElementMap elementMap,
      ParameterStructure parameterStructure,
      void f(DartType type, String? name, ConstantValue? defaultValue),
      {bool isNative = false});
}

mixin FunctionDataTypeVariablesMixin implements FunctionData {
  ir.FunctionNode get functionNode;
  List<TypeVariableType>? _typeVariables;

  @override
  List<TypeVariableType> getFunctionTypeVariables(
      covariant JsKernelToElementMap elementMap) {
    if (_typeVariables == null) {
      if (functionNode.typeParameters.isEmpty) {
        _typeVariables = const <TypeVariableType>[];
      } else {
        ir.TreeNode parent = functionNode.parent!;
        if (parent is ir.Constructor ||
            (parent is ir.Procedure &&
                parent.kind == ir.ProcedureKind.Factory)) {
          _typeVariables = const <TypeVariableType>[];
        } else {
          _typeVariables = functionNode.typeParameters
              .map<TypeVariableType>((ir.TypeParameter typeParameter) {
            return elementMap
                .getDartType(ir.TypeParameterType(
                    typeParameter, ir.Nullability.nonNullable))
                .withoutNullability as TypeVariableType;
          }).toList();
        }
      }
    }
    return _typeVariables!;
  }
}

mixin FunctionDataForEachParameterMixin implements FunctionData {
  ir.FunctionNode get functionNode;

  @override
  void forEachParameter(
      JsToElementMap elementMap,
      ParameterStructure parameterStructure,
      void f(DartType type, String? name, ConstantValue? defaultValue),
      {bool isNative = false}) {
    void handleParameter(ir.VariableDeclaration parameter,
        {bool isOptional = true}) {
      DartType type = elementMap.getDartType(parameter.type);
      String? name = parameter.name;
      ConstantValue? defaultValue;
      if (parameter.isRequired) {
        if (elementMap.types.useLegacySubtyping) {
          defaultValue = NullConstantValue();
        } else {
          defaultValue = elementMap.getRequiredSentinelConstantValue();
        }
      } else if (isOptional) {
        if (parameter.initializer != null) {
          defaultValue = elementMap.getConstantValue(parameter.initializer!);
        } else {
          defaultValue = NullConstantValue();
        }
      }
      f(type, name, defaultValue);
    }

    forEachOrderedParameterByFunctionNode(functionNode, parameterStructure,
        (ir.VariableDeclaration parameter,
            {required bool isOptional, required bool isElided}) {
      if (!isElided) {
        handleParameter(parameter, isOptional: isOptional);
      }
    }, useNativeOrdering: isNative);
  }
}

class FunctionDataImpl extends JMemberDataImpl
    with FunctionDataTypeVariablesMixin, FunctionDataForEachParameterMixin
    implements FunctionData {
  /// Tag used for identifying serialized [FunctionDataImpl] objects in a
  /// debugging data stream.
  static const String tag = 'function-data';

  @override
  final ir.FunctionNode functionNode;
  FunctionType? _type;

  FunctionDataImpl(
      ir.Member node, this.functionNode, MemberDefinition definition)
      : super(node, definition);

  FunctionDataImpl._deserialized(
      ir.Member node, this.functionNode, MemberDefinition definition)
      : super._deserialized(node, definition);

  factory FunctionDataImpl.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Member node = source.readMemberNode();
    ir.FunctionNode functionNode;
    if (node is ir.Procedure) {
      functionNode = node.function;
    } else if (node is ir.Constructor) {
      functionNode = node.function;
    } else {
      throw UnsupportedError(
          "Unexpected member node $node (${node.runtimeType}).");
    }
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    source.end(tag);
    return FunctionDataImpl._deserialized(node, functionNode, definition);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.function);
    sink.begin(tag);
    sink.writeMemberNode(node);
    definition.writeToDataSink(sink);
    sink.end(tag);
  }

  @override
  FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
    return _type ??= elementMap.getFunctionType(functionNode);
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess {
    if (node.isInstanceMember) return ClassTypeVariableAccess.property;
    return ClassTypeVariableAccess.none;
  }
}

class SignatureFunctionData implements FunctionData {
  /// Tag used for identifying serialized [SignatureFunctionData] objects in a
  /// debugging data stream.
  static const String tag = 'signature-function-data';

  @override
  final MemberDefinition definition;
  final InterfaceType? memberThisType;
  @override
  final ClassTypeVariableAccess classTypeVariableAccess;
  List<ir.TypeParameter> get typeParameters => _typeParameters.loaded();
  final Deferrable<List<ir.TypeParameter>> _typeParameters;

  SignatureFunctionData(this.definition, this.memberThisType,
      List<ir.TypeParameter> typeParameters, this.classTypeVariableAccess)
      : _typeParameters = Deferrable.eager(typeParameters);

  SignatureFunctionData._deserialized(this.definition, this.memberThisType,
      this._typeParameters, this.classTypeVariableAccess);

  static List<ir.TypeParameter> _readTypeParameterNodes(
      DataSourceReader source) {
    return source.readTypeParameterNodes();
  }

  factory SignatureFunctionData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    InterfaceType? memberThisType =
        source.readDartTypeOrNull() as InterfaceType?;
    Deferrable<List<ir.TypeParameter>> typeParameters =
        source.readDeferrable(_readTypeParameterNodes);
    ClassTypeVariableAccess classTypeVariableAccess =
        source.readEnum(ClassTypeVariableAccess.values);
    source.end(tag);
    return SignatureFunctionData._deserialized(
        definition, memberThisType, typeParameters, classTypeVariableAccess);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.signature);
    sink.begin(tag);
    definition.writeToDataSink(sink);
    sink.writeDartTypeOrNull(memberThisType);
    sink.writeDeferrable(() => sink.writeTypeParameterNodes(typeParameters));
    sink.writeEnum(classTypeVariableAccess);
    sink.end(tag);
  }

  @override
  FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
    throw UnsupportedError("SignatureFunctionData.getFunctionType");
  }

  @override
  List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
    return typeParameters
        .map<TypeVariableType>((ir.TypeParameter typeParameter) {
      return elementMap
          .getDartType(
              ir.TypeParameterType(typeParameter, ir.Nullability.nonNullable))
          .withoutNullability as TypeVariableType;
    }).toList();
  }

  @override
  void forEachParameter(
      JsToElementMap elementMap,
      ParameterStructure parameterStructure,
      void f(DartType type, String? name, ConstantValue? defaultValue),
      {bool isNative = false}) {
    throw UnimplementedError('SignatureData.forEachParameter');
  }

  @override
  InterfaceType? getMemberThisType(JsToElementMap elementMap) => memberThisType;
}

abstract class DelegatedFunctionData implements FunctionData {
  final FunctionData baseData;

  DelegatedFunctionData(this.baseData);

  @override
  FunctionType getFunctionType(covariant JsKernelToElementMap elementMap) {
    return baseData.getFunctionType(elementMap);
  }

  @override
  List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap) {
    return baseData.getFunctionTypeVariables(elementMap);
  }

  @override
  void forEachParameter(
      JsToElementMap elementMap,
      ParameterStructure parameterStructure,
      void f(DartType type, String? name, ConstantValue? defaultValue),
      {bool isNative = false}) {
    return baseData.forEachParameter(elementMap, parameterStructure, f,
        isNative: isNative);
  }

  @override
  InterfaceType? getMemberThisType(JsToElementMap elementMap) {
    return baseData.getMemberThisType(elementMap);
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess =>
      baseData.classTypeVariableAccess;
}

class ParameterStubFunctionData extends DelegatedFunctionData {
  @override
  final MemberDefinition definition;

  ParameterStubFunctionData(super.baseData, this.definition);

  @override
  void writeToDataSink(DataSinkWriter sink) {
    throw UnimplementedError('Cannot serialize parameter stub data.');
  }
}

class GeneratorBodyFunctionData extends DelegatedFunctionData {
  /// Tag used for identifying serialized [GeneratorBodyFunctionData] objects in
  /// a debugging data stream.
  static const String tag = 'generator-body-data';

  @override
  final MemberDefinition definition;

  GeneratorBodyFunctionData(super.baseData, this.definition);

  factory GeneratorBodyFunctionData.readFromDataSource(
      DataSourceReader source) {
    source.begin(tag);
    // TODO(johnniwinther): Share the original base data on deserialization.
    FunctionData baseData =
        JMemberData.readFromDataSource(source) as FunctionData;
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    source.end(tag);
    return GeneratorBodyFunctionData(baseData, definition);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.generatorBody);
    sink.begin(tag);
    baseData.writeToDataSink(sink);
    definition.writeToDataSink(sink);
    sink.end(tag);
  }
}

class JConstructorData extends FunctionDataImpl {
  /// Tag used for identifying serialized [JConstructorDataImpl] objects in a
  /// debugging data stream.
  static const String tag = 'constructor-data';

  JConstructorBody? constructorBody;

  JConstructorData(super.node, super.functionNode, super.definition);

  JConstructorData._deserialized(
      super.node, super.functionNode, super.definition)
      : super._deserialized();

  factory JConstructorData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Member node = source.readMemberNode();
    ir.FunctionNode functionNode;
    if (node is ir.Procedure) {
      functionNode = node.function;
    } else if (node is ir.Constructor) {
      functionNode = node.function;
    } else {
      throw UnsupportedError(
          "Unexpected member node $node (${node.runtimeType}).");
    }
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    source.end(tag);
    return JConstructorData._deserialized(node, functionNode, definition);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.constructor);
    sink.begin(tag);
    sink.writeMemberNode(node);
    definition.writeToDataSink(sink);
    assert(constructorBody == null);
    sink.end(tag);
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess =>
      ClassTypeVariableAccess.parameter;
}

class ConstructorBodyDataImpl extends FunctionDataImpl {
  /// Tag used for identifying serialized [ConstructorBodyDataImpl] objects in
  /// a debugging data stream.
  static const String tag = 'constructor-body-data';

  ConstructorBodyDataImpl(super.node, super.functionNode, super.definition);

  ConstructorBodyDataImpl._deserialized(
      super.node, super.functionNode, super.definition)
      : super._deserialized();

  factory ConstructorBodyDataImpl.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Member node = source.readMemberNode();
    ir.FunctionNode functionNode;
    if (node is ir.Procedure) {
      functionNode = node.function;
    } else if (node is ir.Constructor) {
      functionNode = node.function;
    } else {
      throw UnsupportedError(
          "Unexpected member node $node (${node.runtimeType}).");
    }
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    source.end(tag);
    return ConstructorBodyDataImpl._deserialized(
        node, functionNode, definition);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.constructorBody);
    sink.begin(tag);
    sink.writeMemberNode(node);
    definition.writeToDataSink(sink);
    sink.end(tag);
  }

  // TODO(johnniwinther,sra): Constructor bodies should access type variables
  // through `this`.
  @override
  ClassTypeVariableAccess get classTypeVariableAccess =>
      ClassTypeVariableAccess.parameter;
}

abstract class JFieldData extends JMemberData {
  DartType getFieldType(IrToElementMap elementMap);
}

class JFieldDataImpl extends JMemberDataImpl implements JFieldData {
  /// Tag used for identifying serialized [JFieldDataImpl] objects in
  /// a debugging data stream.
  static const String tag = 'field-data';

  DartType? _type;

  JFieldDataImpl(super.node, super.definition);

  JFieldDataImpl._deserialized(super.node, super.definition)
      : super._deserialized();

  factory JFieldDataImpl.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Member node = source.readMemberNode();
    MemberDefinition definition = MemberDefinition.readFromDataSource(source);
    source.end(tag);
    return JFieldDataImpl._deserialized(node as ir.Field, definition);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberDataKind.field);
    sink.begin(tag);
    sink.writeMemberNode(node);
    definition.writeToDataSink(sink);
    sink.end(tag);
  }

  @override
  ir.Field get node => super.node as ir.Field;

  @override
  DartType getFieldType(covariant JsKernelToElementMap elementMap) {
    return _type ??= elementMap.getDartType(node.type);
  }

  @override
  ClassTypeVariableAccess get classTypeVariableAccess {
    if (node.isInstanceMember) return ClassTypeVariableAccess.instanceField;
    return ClassTypeVariableAccess.none;
  }
}

class JTypeVariableData {
  /// Tag used for identifying serialized [JTypeVariableData] objects in
  /// a debugging data stream.
  static const String tag = 'type-variable-data';

  final ir.TypeParameter node;
  DartType? _bound;
  DartType? _defaultType;

  JTypeVariableData(this.node);

  factory JTypeVariableData.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.TypeParameter node = source.readTypeParameterNode();
    source.end(tag);
    return JTypeVariableData(node);
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeTypeParameterNode(node);
    sink.end(tag);
  }

  DartType getBound(IrToElementMap elementMap) {
    return _bound ??= elementMap.getDartType(node.bound);
  }

  DartType getDefaultType(IrToElementMap elementMap) {
    return _defaultType ??= elementMap.getDartType(node.defaultType);
  }
}
