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

import 'package:kernel/ast.dart' as ir show LocalFunction;

import '../common/names.dart' show Names;
import '../elements/entities.dart';
import '../elements/entity_map.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../serialization/serialization.dart';
import '../universe/class_set.dart' show ClassHierarchyNodesMapKey;
import '../universe/selector.dart';
import 'closure.dart';
import 'records.dart' show JRecordClass, JRecordGetter;

const String jsElementPrefix = 'j:';

class JLibrary with EntityMapKey implements LibraryEntity {
  /// Tag used for identifying serialized [JLibrary] objects in a
  /// debugging data stream.
  static const String tag = 'library';

  @override
  final String name;
  @override
  final Uri canonicalUri;

  JLibrary(this.name, this.canonicalUri);

  /// Deserializes a [JLibrary] object from [source].
  factory JLibrary.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    String name = source.readString();
    Uri canonicalUri = source.readUri();
    source.end(tag);
    return JLibrary(name, canonicalUri);
  }

  /// Serializes this [JLibrary] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeString(name);
    sink.writeUri(canonicalUri);
    sink.end(tag);
  }

  @override
  String toString() => '${jsElementPrefix}library($name)';
}

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

class JClass
    with ClassHierarchyNodesMapKey, EntityMapKey
    implements ClassEntity {
  /// Tag used for identifying serialized [JClass] objects in a
  /// debugging data stream.
  static const String tag = 'class';

  @override
  final JLibrary library;

  @override
  final String name;
  @override
  final bool isAbstract;

  JClass(this.library, this.name, {required this.isAbstract});

  /// Deserializes a [JClass] object from [source].
  factory JClass.readFromDataSource(DataSourceReader source) {
    JClassKind kind = source.readEnum(JClassKind.values);
    switch (kind) {
      case JClassKind.node:
        source.begin(tag);
        final library = source.readLibrary() as JLibrary;
        String name = source.readString();
        bool isAbstract = source.readBool();
        source.end(tag);
        return JClass(library, name, isAbstract: isAbstract);
      case JClassKind.closure:
        return JClosureClass.readFromDataSource(source);
      case JClassKind.context:
        return JContext.readFromDataSource(source);
      case JClassKind.record:
        return JRecordClass.readFromDataSource(source);
    }
  }

  /// Serializes this [JClass] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JClassKind.node);
    sink.begin(tag);
    sink.writeLibrary(library);
    sink.writeString(name);
    sink.writeBool(isAbstract);
    sink.end(tag);
  }

  @override
  bool get isClosure => false;

  @override
  String toString() => '${jsElementPrefix}class($name)';
}

/// Enum used for identifying [JMember] subclasses in serialization.
enum JMemberKind {
  generativeConstructor,
  factoryConstructor,
  constructorBody,
  field,
  getter,
  setter,
  method,
  closureField,
  closureCallMethod,
  generatorBody,
  signatureMethod,
  contextField,
  recordGetter,
  parameterStub,
}

@override
String _membertoString(JMember member) => '${jsElementPrefix}${member._kind}'
    '(${member.enclosingClass != null ? '${member.enclosingClass!.name}.' : ''}'
    '${member.name})';

abstract class JMember with EntityMapKey implements MemberEntity {
  @override
  final JLibrary library;
  @override
  final JClass? enclosingClass;
  final Name _name;
  final bool _isStatic;

  JMember(this.library, this.enclosingClass, this._name,
      {bool isStatic = false})
      : _isStatic = isStatic;

  /// Deserializes a [JMember] object from [source].
  factory JMember.readFromDataSource(DataSourceReader source) {
    JMemberKind kind = source.readEnum(JMemberKind.values);
    switch (kind) {
      case JMemberKind.generativeConstructor:
        return JGenerativeConstructor.readFromDataSource(source);
      case JMemberKind.factoryConstructor:
        return JFactoryConstructor.readFromDataSource(source);
      case JMemberKind.constructorBody:
        return JConstructorBody.readFromDataSource(source);
      case JMemberKind.field:
        return JField.readFromDataSource(source);
      case JMemberKind.getter:
        return JGetter.readFromDataSource(source);
      case JMemberKind.setter:
        return JSetter.readFromDataSource(source);
      case JMemberKind.method:
        return JMethod.readFromDataSource(source);
      case JMemberKind.closureField:
        return JClosureField.readFromDataSource(source);
      case JMemberKind.closureCallMethod:
        return JClosureCallMethod.readFromDataSource(source);
      case JMemberKind.generatorBody:
        return JGeneratorBody.readFromDataSource(source);
      case JMemberKind.signatureMethod:
        return JSignatureMethod.readFromDataSource(source);
      case JMemberKind.contextField:
        return JContextField.readFromDataSource(source);
      case JMemberKind.recordGetter:
        return JRecordGetter.readFromDataSource(source);
      case JMemberKind.parameterStub:
        return JParameterStub.readFromDataSource(source);
    }
  }

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

  @override
  String get name => _name.text;

  @override
  Name get memberName => _name;

  @override
  bool get isAssignable => false;

  @override
  bool get isConst => false;

  @override
  bool get isAbstract => false;

  @override
  bool get isSetter => false;

  @override
  bool get isGetter => false;

  @override
  bool get isFunction => false;

  @override
  bool get isInstanceMember => enclosingClass != null && !_isStatic;

  @override
  bool get isStatic => enclosingClass != null && _isStatic;

  @override
  bool get isTopLevel => enclosingClass == null;

  String get _kind;

  @override
  String toString() => _membertoString(this);
}

abstract class JFunction extends JMember implements FunctionEntity {
  @override
  final ParameterStructure parameterStructure;
  @override
  final bool isExternal;
  @override
  final AsyncMarker asyncMarker;

  JFunction(super.library, super.enclosingClass, super.name,
      this.parameterStructure, this.asyncMarker,
      {super.isStatic, this.isExternal = false});
}

abstract class JConstructor extends JFunction implements ConstructorEntity {
  @override
  final bool isConst;
  @override
  final JClass enclosingClass;

  JConstructor(
      this.enclosingClass, Name name, ParameterStructure parameterStructure,
      {required bool isExternal, required this.isConst})
      : super(enclosingClass.library, enclosingClass, name, parameterStructure,
            AsyncMarker.SYNC,
            isExternal: isExternal);

  @override
  bool get isInstanceMember => false;

  @override
  bool get isStatic => false;

  @override
  bool get isTopLevel => false;

  @override
  bool get isFromEnvironmentConstructor => false;

  @override
  String get _kind => 'constructor';
}

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

  JGenerativeConstructor(
      super.enclosingClass, super.name, super.parameterStructure,
      {required super.isExternal, required super.isConst});

  factory JGenerativeConstructor.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final enclosingClass = source.readClass() as JClass;
    String name = source.readString();
    ParameterStructure parameterStructure =
        ParameterStructure.readFromDataSource(source);
    bool isExternal = source.readBool();
    bool isConst = source.readBool();
    source.end(tag);
    return JGenerativeConstructor(enclosingClass,
        Name(name, enclosingClass.library.canonicalUri), parameterStructure,
        isExternal: isExternal, isConst: isConst);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.generativeConstructor);
    sink.begin(tag);
    sink.writeClass(enclosingClass);
    sink.writeString(name);
    parameterStructure.writeToDataSink(sink);
    sink.writeBool(isExternal);
    sink.writeBool(isConst);
    sink.end(tag);
  }

  @override
  bool get isFactoryConstructor => false;

  @override
  bool get isGenerativeConstructor => true;
}

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

  @override
  final bool isFromEnvironmentConstructor;

  JFactoryConstructor(
      super.enclosingClass, super.name, super.parameterStructure,
      {required super.isExternal,
      required super.isConst,
      required this.isFromEnvironmentConstructor});

  factory JFactoryConstructor.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final enclosingClass = source.readClass() as JClass;
    String name = source.readString();
    ParameterStructure parameterStructure =
        ParameterStructure.readFromDataSource(source);
    bool isExternal = source.readBool();
    bool isConst = source.readBool();
    bool isFromEnvironmentConstructor = source.readBool();
    source.end(tag);
    return JFactoryConstructor(enclosingClass,
        Name(name, enclosingClass.library.canonicalUri), parameterStructure,
        isExternal: isExternal,
        isConst: isConst,
        isFromEnvironmentConstructor: isFromEnvironmentConstructor);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.factoryConstructor);
    sink.begin(tag);
    sink.writeClass(enclosingClass);
    sink.writeString(name);
    parameterStructure.writeToDataSink(sink);
    sink.writeBool(isExternal);
    sink.writeBool(isConst);
    sink.writeBool(isFromEnvironmentConstructor);
    sink.end(tag);
  }

  @override
  bool get isFactoryConstructor => true;

  @override
  bool get isGenerativeConstructor => false;
}

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

  @override
  final JConstructor constructor;

  JConstructorBody(this.constructor, ParameterStructure parameterStructure)
      : super(constructor.library, constructor.enclosingClass,
            constructor.memberName, parameterStructure, AsyncMarker.SYNC,
            isStatic: false, isExternal: constructor.isExternal);

  factory JConstructorBody.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final constructor = source.readMember() as JConstructor;
    ParameterStructure parameterStructure =
        ParameterStructure.readFromDataSource(source);
    source.end(tag);
    return JConstructorBody(constructor, parameterStructure);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.constructorBody);
    sink.begin(tag);
    sink.writeMember(constructor);
    parameterStructure.writeToDataSink(sink);
    sink.end(tag);
  }

  @override
  String get _kind => 'constructor_body';

  /// These lazy member bodies implement `==` since different SSA shards can
  /// create different copies of the same constructor body. Upon deserialization
  /// we should consider the different copies equivalent.
  @override
  bool operator ==(Object other) {
    return other is JConstructorBody && constructor == other.constructor;
  }

  @override
  int get hashCode => constructor.hashCode + 7;
}

class JParameterStub with EntityMapKey implements JMethod {
  static const String kind = 'parameter-stub';

  final JFunction target;
  @override
  final ParameterStructure parameterStructure;
  final Selector? callSelector;
  final bool needsSuper;

  JParameterStub(this.target, this.parameterStructure,
      {required this.callSelector, required this.needsSuper});

  @override
  String toString() => _membertoString(this);

  @override
  String get _kind => 'parameter_stub';

  @override
  bool get _isStatic => target._isStatic;

  @override
  Name get _name => target._name;

  @override
  AsyncMarker get asyncMarker => target.asyncMarker;

  @override
  JClass? get enclosingClass => target.enclosingClass;

  @override
  bool get isAbstract => target.isAbstract;

  @override
  bool get isAssignable => target.isAssignable;

  @override
  bool get isConst => target.isConst;

  @override
  bool get isExternal => target.isExternal;

  @override
  bool get isFunction => target.isFunction;

  @override
  bool get isGetter => target.isGetter;

  @override
  bool get isInstanceMember => target.isInstanceMember;

  @override
  bool get isSetter => target.isSetter;

  @override
  bool get isStatic => target.isStatic;

  @override
  bool get isTopLevel => target.isTopLevel;

  @override
  JLibrary get library => target.library;

  @override
  Name get memberName => target.memberName;

  @override
  String get name => target.name;

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.parameterStub);
    sink.begin(kind);
    sink.writeMember(target);
    parameterStructure.writeToDataSink(sink);
    sink.writeValueOrNull(callSelector, (value) => value.writeToDataSink(sink));
    sink.writeBool(needsSuper);
    sink.end(kind);
  }

  factory JParameterStub.readFromDataSource(DataSourceReader source) {
    source.begin(kind);
    final target = source.readMember() as JFunction;
    final parameterStructure = ParameterStructure.readFromDataSource(source);
    final callSelector =
        source.readValueOrNull(() => Selector.readFromDataSource(source));
    final needsSuper = source.readBool();
    source.end(kind);
    return JParameterStub(target, parameterStructure,
        callSelector: callSelector, needsSuper: needsSuper);
  }
}

class JMethod extends JFunction {
  /// Tag used for identifying serialized [JMethod] objects in a
  /// debugging data stream.
  static const String tag = 'method';

  @override
  final bool isAbstract;

  JMethod(super.library, super.enclosingClass, super.name,
      super.parameterStructure, super.asyncMarker,
      {required super.isStatic,
      required super.isExternal,
      required this.isAbstract});

  factory JMethod.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberContextKind kind = source.readEnum(MemberContextKind.values);
    late final JLibrary library;
    JClass? enclosingClass;
    switch (kind) {
      case MemberContextKind.library:
        library = source.readLibrary() as JLibrary;
        break;
      case MemberContextKind.cls:
        enclosingClass = source.readClass() as JClass;
        library = enclosingClass.library;
        break;
    }
    Name memberName = source.readMemberName();
    ParameterStructure parameterStructure =
        ParameterStructure.readFromDataSource(source);
    AsyncMarker asyncMarker = source.readEnum(AsyncMarker.values);
    bool isStatic = source.readBool();
    bool isExternal = source.readBool();
    bool isAbstract = source.readBool();
    source.end(tag);
    return JMethod(
        library, enclosingClass, memberName, parameterStructure, asyncMarker,
        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.method);
    sink.begin(tag);
    if (enclosingClass != null) {
      sink.writeEnum(MemberContextKind.cls);
      sink.writeClass(enclosingClass!);
    } else {
      sink.writeEnum(MemberContextKind.library);
      sink.writeLibrary(library);
    }
    sink.writeMemberName(memberName);
    parameterStructure.writeToDataSink(sink);
    sink.writeEnum(asyncMarker);
    sink.writeBool(isStatic);
    sink.writeBool(isExternal);
    sink.writeBool(isAbstract);
    sink.end(tag);
  }

  @override
  bool get isFunction => true;

  @override
  String get _kind => 'method';
}

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

  final JFunction function;
  final DartType elementType;
  @override
  final int hashCode;

  JGeneratorBody(this.function, this.elementType)
      : hashCode = function.hashCode + 1, // Hack stabilize sort order.
        super(function.library, function.enclosingClass, function.memberName,
            function.parameterStructure, function.asyncMarker,
            isStatic: function.isStatic, isExternal: false);

  factory JGeneratorBody.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final function = source.readMember() as JFunction;
    DartType elementType = source.readDartType();
    source.end(tag);
    return JGeneratorBody(function, elementType);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.generatorBody);
    sink.begin(tag);
    sink.writeMember(function);
    sink.writeDartType(elementType);
    sink.end(tag);
  }

  @override
  String get _kind => 'generator_body';

  /// These lazy member bodies implement `==` since different SSA shards can
  /// create different copies of the same constructor body. Upon deserialization
  /// we should consider the different copies equivalent.
  @override
  bool operator ==(Object other) {
    return other is JGeneratorBody && function == other.function;
  }
}

class JGetter extends JFunction {
  /// Tag used for identifying serialized [JGetter] objects in a
  /// debugging data stream.
  static const String tag = 'getter';

  @override
  final bool isAbstract;

  JGetter(JLibrary library, JClass? enclosingClass, Name name,
      AsyncMarker asyncMarker,
      {required bool isStatic,
      required bool isExternal,
      required this.isAbstract})
      : super(library, enclosingClass, name, ParameterStructure.getter,
            asyncMarker,
            isStatic: isStatic, isExternal: isExternal);

  factory JGetter.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberContextKind kind = source.readEnum(MemberContextKind.values);
    late final JLibrary library;
    JClass? enclosingClass;
    switch (kind) {
      case MemberContextKind.library:
        library = source.readLibrary() as JLibrary;
        break;
      case MemberContextKind.cls:
        enclosingClass = source.readClass() as JClass;
        library = enclosingClass.library;
        break;
    }
    Name memberName = source.readMemberName();
    AsyncMarker asyncMarker = source.readEnum(AsyncMarker.values);
    bool isStatic = source.readBool();
    bool isExternal = source.readBool();
    bool isAbstract = source.readBool();
    source.end(tag);
    return JGetter(library, enclosingClass, memberName, asyncMarker,
        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.getter);
    sink.begin(tag);
    if (enclosingClass != null) {
      sink.writeEnum(MemberContextKind.cls);
      sink.writeClass(enclosingClass!);
    } else {
      sink.writeEnum(MemberContextKind.library);
      sink.writeLibrary(library);
    }
    sink.writeMemberName(memberName);
    sink.writeEnum(asyncMarker);
    sink.writeBool(isStatic);
    sink.writeBool(isExternal);
    sink.writeBool(isAbstract);
    sink.end(tag);
  }

  @override
  bool get isGetter => true;

  @override
  String get _kind => 'getter';
}

class JSetter extends JFunction {
  /// Tag used for identifying serialized [JSetter] objects in a
  /// debugging data stream.
  static const String tag = 'setter';

  @override
  final bool isAbstract;

  JSetter(JLibrary library, JClass? enclosingClass, Name name,
      {required bool isStatic,
      required bool isExternal,
      required this.isAbstract})
      : super(library, enclosingClass, name, ParameterStructure.setter,
            AsyncMarker.SYNC,
            isStatic: isStatic, isExternal: isExternal);

  factory JSetter.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberContextKind kind = source.readEnum(MemberContextKind.values);
    late final JLibrary library;
    JClass? enclosingClass;
    switch (kind) {
      case MemberContextKind.library:
        library = source.readLibrary() as JLibrary;
        break;
      case MemberContextKind.cls:
        enclosingClass = source.readClass() as JClass;
        library = enclosingClass.library;
        break;
    }
    Name memberName = source.readMemberName();
    bool isStatic = source.readBool();
    bool isExternal = source.readBool();
    bool isAbstract = source.readBool();
    source.end(tag);
    return JSetter(library, enclosingClass, memberName,
        isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.setter);
    sink.begin(tag);
    if (enclosingClass != null) {
      sink.writeEnum(MemberContextKind.cls);
      sink.writeClass(enclosingClass!);
    } else {
      sink.writeEnum(MemberContextKind.library);
      sink.writeLibrary(library);
    }
    sink.writeMemberName(memberName);
    sink.writeBool(isStatic);
    sink.writeBool(isExternal);
    sink.writeBool(isAbstract);
    sink.end(tag);
  }

  @override
  bool get isAssignable => true;

  @override
  bool get isSetter => true;

  @override
  String get _kind => 'setter';
}

class JField extends JMember implements FieldEntity {
  /// Tag used for identifying serialized [JField] objects in a
  /// debugging data stream.
  static const String tag = 'field';

  @override
  final bool isAssignable;
  @override
  final bool isConst;

  JField(super.library, super.enclosingClass, super.name,
      {required super.isStatic,
      required this.isAssignable,
      required this.isConst});

  factory JField.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    MemberContextKind kind = source.readEnum(MemberContextKind.values);
    late final JLibrary library;
    JClass? enclosingClass;
    switch (kind) {
      case MemberContextKind.library:
        library = source.readLibrary() as JLibrary;
        break;
      case MemberContextKind.cls:
        enclosingClass = source.readClass() as JClass;
        library = enclosingClass.library;
        break;
    }
    Name memberName = source.readMemberName();
    bool isStatic = source.readBool();
    bool isAssignable = source.readBool();
    bool isConst = source.readBool();
    source.end(tag);
    return JField(library, enclosingClass, memberName,
        isStatic: isStatic, isAssignable: isAssignable, isConst: isConst);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.field);
    sink.begin(tag);
    if (enclosingClass != null) {
      sink.writeEnum(MemberContextKind.cls);
      sink.writeClass(enclosingClass!);
    } else {
      sink.writeEnum(MemberContextKind.library);
      sink.writeLibrary(library);
    }
    sink.writeMemberName(memberName);
    sink.writeBool(isStatic);
    sink.writeBool(isAssignable);
    sink.writeBool(isConst);
    sink.end(tag);
  }

  @override
  String get _kind => 'field';
}

class JClosureCallMethod extends JMethod {
  /// Tag used for identifying serialized [JClosureCallMethod] objects in a
  /// debugging data stream.
  static const String tag = 'closure-call-method';

  JClosureCallMethod(ClassEntity enclosingClass,
      ParameterStructure parameterStructure, AsyncMarker asyncMarker)
      : super(enclosingClass.library as JLibrary, enclosingClass as JClass,
            Names.call, parameterStructure, asyncMarker,
            isStatic: false, isExternal: false, isAbstract: false);

  factory JClosureCallMethod.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final enclosingClass = source.readClass() as JClass;
    ParameterStructure parameterStructure =
        ParameterStructure.readFromDataSource(source);
    AsyncMarker asyncMarker = source.readEnum(AsyncMarker.values);
    source.end(tag);
    return JClosureCallMethod(enclosingClass, parameterStructure, asyncMarker);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.closureCallMethod);
    sink.begin(tag);
    sink.writeClass(enclosingClass!);
    parameterStructure.writeToDataSink(sink);
    sink.writeEnum(asyncMarker);
    sink.end(tag);
  }

  @override
  String get _kind => 'closure_call';
}

/// A method that returns the signature of the Dart closure/tearoff that this
/// method's parent class is representing.
class JSignatureMethod extends JMethod {
  /// Tag used for identifying serialized [JSignatureMethod] objects in a
  /// debugging data stream.
  static const String tag = 'signature-method';

  JSignatureMethod(ClassEntity enclosingClass)
      : super(enclosingClass.library as JLibrary, enclosingClass as JClass,
            Names.signature, ParameterStructure.zeroArguments, AsyncMarker.SYNC,
            isStatic: false, isExternal: false, isAbstract: false);

  factory JSignatureMethod.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    final cls = source.readClass() as JClass;
    source.end(tag);
    return JSignatureMethod(cls);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(JMemberKind.signatureMethod);
    sink.begin(tag);
    sink.writeClass(enclosingClass!);
    sink.end(tag);
  }

  @override
  String get _kind => 'signature';
}

/// Enum used for identifying [JTypeVariable] variants in serialization.
///
/// [JLocalTypeVariable] in the K-world can contain a [Local] as its
/// `typeDeclaration` but those are never serialized. When converted to the
/// J-world they use a [JClosureCallMethod] as [JTypeVariable.typeDeclaration].
enum JTypeVariableKind { cls, member }

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

  @override
  final Entity typeDeclaration;
  @override
  final String name;
  @override
  final int index;

  JTypeVariable(this.typeDeclaration, this.name, this.index) {
    assert(typeDeclaration is ClassEntity || typeDeclaration is MemberEntity);
  }

  /// Deserializes a [JTypeVariable] object from [source].
  factory JTypeVariable.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    JTypeVariableKind kind = source.readEnum(JTypeVariableKind.values);
    Entity typeDeclaration;
    switch (kind) {
      case JTypeVariableKind.cls:
        typeDeclaration = source.readClass();
        break;
      case JTypeVariableKind.member:
        typeDeclaration = source.readMember();
        break;
    }
    String name = source.readString();
    int index = source.readInt();
    source.end(tag);
    return JTypeVariable(typeDeclaration, name, index);
  }

  /// Serializes this [JTypeVariable] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    final declaration = typeDeclaration;
    if (declaration is ClassEntity) {
      sink.writeEnum(JTypeVariableKind.cls);
      sink.writeClass(declaration);
    } else if (declaration is MemberEntity) {
      sink.writeEnum(JTypeVariableKind.member);
      sink.writeMember(declaration);
    } else {
      throw UnsupportedError(
          "Unexpected type variable declarer $typeDeclaration.");
    }
    sink.writeString(name);
    sink.writeInt(index);
    sink.end(tag);
  }

  @override
  String toString() =>
      '${jsElementPrefix}type_variable(${typeDeclaration.name}.$name)';
}

class JLocalFunction implements Local {
  @override
  final String? name;
  final MemberEntity memberContext;
  final Entity executableContext;
  final ir.LocalFunction node;
  late final FunctionType functionType;

  JLocalFunction(
      this.name, this.memberContext, this.executableContext, this.node);

  @override
  String toString() => '${jsElementPrefix}local_function'
      '(${memberContext.name}.${name ?? '<anonymous>'})';
}

class JLocalTypeVariable implements TypeVariableEntity {
  @override
  final JLocalFunction typeDeclaration;
  @override
  final String name;
  @override
  final int index;
  late final DartType bound;
  late final DartType defaultType;

  JLocalTypeVariable(this.typeDeclaration, this.name, this.index);

  @override
  String toString() =>
      '${jsElementPrefix}local_type_variable(${typeDeclaration.name}.$name)';
}
