// Copyright (c) 2018, 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.

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

import '../common.dart';
import '../common/elements.dart' show JCommonElements, JElementEnvironment;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/names.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../ir/closure.dart';
import '../ir/util.dart';
import '../native/behavior.dart';
import '../serialization/deferrable.dart';
import '../serialization/serialization.dart';
import '../universe/call_structure.dart';
import '../universe/selector.dart';
import 'class_type_variable_access.dart';
import 'closure.dart';
import 'elements.dart' show JGeneratorBody;
import 'js_world.dart' show JClosedWorld;

/// Interface that translates between Kernel IR nodes and entities used for
/// global type inference and building the SSA graph for members.
abstract class JsToElementMap {
  /// Access to the commonly used elements and types.
  JCommonElements get commonElements;

  /// Access to the [DartTypes] object.
  DartTypes get types;

  /// Returns the [DartType] corresponding to [type].
  DartType getDartType(ir.DartType type);

  /// Returns the [InterfaceType] corresponding to [type].
  InterfaceType getInterfaceType(ir.InterfaceType type);

  Iterable<InterfaceType> getInterfaces(ClassEntity cls);

  /// Returns the [TypeVariableType] corresponding to [type].
  TypeVariableType getTypeVariableType(ir.TypeParameterType type);

  /// Returns the [FunctionType] of the [node].
  FunctionType getFunctionType(ir.FunctionNode node);

  /// Return the [InterfaceType] corresponding to the [cls] with the given
  /// [typeArguments] and [nullability].
  InterfaceType createInterfaceType(
    ir.Class cls,
    List<ir.DartType> typeArguments,
  );

  /// Returns the [CallStructure] corresponding to the [arguments].
  CallStructure getCallStructure(ir.Arguments arguments);

  /// Returns the [Selector] corresponding to the invocation or getter/setter
  /// access of [node].
  Selector getSelector(ir.Expression node);

  /// Returns the [MemberEntity] corresponding to the member [node].
  MemberEntity getMember(ir.Member node);

  /// Returns the [FunctionEntity] corresponding to the procedure [node].
  FunctionEntity getMethod(ir.Procedure node);

  /// Returns `true` if [node] has been included into this map.
  bool containsMethod(ir.Procedure node);

  /// Returns the [ConstructorEntity] corresponding to the generative or factory
  /// constructor [node].
  ConstructorEntity getConstructor(ir.Member node);

  /// Returns the [FieldEntity] corresponding to the field [node].
  FieldEntity getField(ir.Field node);

  /// Returns the [ClassEntity] corresponding to the class [node].
  ClassEntity getClass(ir.Class node);

  /// Returns the [Name] corresponding to [name].
  Name getName(ir.Name name);

  /// Computes the [native.NativeBehavior] for a call to the [JS] function.
  NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node);

  /// Computes the [native.NativeBehavior] for a call to the [JS_BUILTIN]
  /// function.
  NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node);

  /// Computes the [native.NativeBehavior] for a call to the
  /// [JS_EMBEDDED_GLOBAL] function.
  NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
    ir.StaticInvocation node,
  );

  /// Computes the [ConstantValue] for the constant [expression].
  ConstantValue? getConstantValue(
    ir.Expression? expression, {
    bool requireConstant = true,
    bool implicitNull = false,
  });

  /// Returns the [ConstantValue] for the sentinel used to indicate that a
  /// parameter is required.
  ///
  /// These should only appear within the defaultValues object attached to
  /// closures and tearoffs when emitting Function.apply.
  ConstantValue getRequiredSentinelConstantValue();

  /// Return the [ImportEntity] corresponding to [node].
  ImportEntity getImport(ir.LibraryDependency node);

  /// Returns the definition information for [cls].
  ClassDefinition getClassDefinition(covariant ClassEntity cls);

  /// [ElementEnvironment] for library, class and member lookup.
  JElementEnvironment get elementEnvironment;

  /// Returns the list of [DartType]s corresponding to [types].
  List<DartType> getDartTypes(List<ir.DartType> types);

  /// Returns the definition information for [member].
  MemberDefinition getMemberDefinition(MemberEntity member);

  /// Returns the [ir.Member] containing the definition of [member], if any.
  ir.Member? getMemberContextNode(MemberEntity member);

  /// Returns the type of `this` in [member], or `null` if member is defined in
  /// a static context.
  InterfaceType? getMemberThisType(MemberEntity member);

  /// Returns how [member] has access to type variables of the this type
  /// returned by [getMemberThisType].
  ClassTypeVariableAccess getClassTypeVariableAccessForMember(
    MemberEntity member,
  );

  /// Returns the [LibraryEntity] corresponding to the library [node].
  LibraryEntity getLibrary(ir.Library node);

  /// Returns a [Spannable] for a message pointing to the IR [node] in the
  /// context of [member].
  Spannable getSpannable(MemberEntity member, ir.Node node);

  /// Returns the constructor body entity corresponding to [constructor].
  FunctionEntity getConstructorBody(ir.Constructor node);

  /// Returns the constructor body entity corresponding to [function].
  JGeneratorBody getGeneratorBody(FunctionEntity function);

  /// Make a mapping from closed-over variables to the context fields where they
  /// are stored.
  Map<ir.Variable, JContextField> makeContextContainer(
    KernelScopeInfo info,
    MemberEntity member,
  );

  /// Returns the library URI of the symbol if [value] represents a [Symbol].
  Uri? getSymbolLibraryUri(ConstantValue value);
}

/// Interface for type inference results for kernel IR nodes.
abstract class KernelToTypeInferenceMap {
  /// Returns the inferred return type of [function].
  AbstractValue getReturnTypeOf(FunctionEntity function);

  /// Returns the inferred receiver type of the dynamic [invocation].
  // TODO(johnniwinther): Improve the type of the [invocation] once the new
  // method invocation encoding is fully utilized.
  AbstractValue? receiverTypeOfInvocation(
    ir.Expression invocation,
    AbstractValueDomain abstractValueDomain,
  );

  /// Returns the inferred receiver type of the dynamic [read].
  // TODO(johnniwinther): Improve the type of the [invocation] once the new
  // method invocation encoding is fully utilized.
  AbstractValue? receiverTypeOfGet(ir.Expression read);

  /// Returns the inferred receiver type of the dynamic [write].
  // TODO(johnniwinther): Improve the type of the [invocation] once the new
  // method invocation encoding is fully utilized.
  AbstractValue? receiverTypeOfSet(
    ir.Expression write,
    AbstractValueDomain abstractValueDomain,
  );

  /// Returns the inferred type of [listLiteral].
  AbstractValue typeOfListLiteral(
    ir.ListLiteral listLiteral,
    AbstractValueDomain abstractValueDomain,
  );

  /// Returns the inferred type of [recordLiteral].
  AbstractValue? typeOfRecordLiteral(
    ir.RecordLiteral recordLiteral,
    AbstractValueDomain abstractValueDomain,
  );

  /// Returns the inferred type of iterator in [forInStatement].
  AbstractValue? typeOfIterator(ir.ForInStatement forInStatement);

  /// Returns the inferred type of `current` in [forInStatement].
  AbstractValue? typeOfIteratorCurrent(ir.ForInStatement forInStatement);

  /// Returns the inferred type of `moveNext` in [forInStatement].
  AbstractValue? typeOfIteratorMoveNext(ir.ForInStatement forInStatement);

  /// Returns `true` if [forInStatement] is inferred to be a JavaScript
  /// indexable iterator.
  bool isJsIndexableIterator(
    ir.ForInStatement forInStatement,
    AbstractValueDomain abstractValueDomain,
  );

  /// Returns the inferred index type of [forInStatement].
  AbstractValue inferredIndexType(ir.ForInStatement forInStatement);

  /// Returns the inferred type of [member].
  AbstractValue getInferredTypeOf(MemberEntity member);

  /// Returns the inferred type of the [parameter]. [member] is the member that
  /// declares [parameter], if any.
  AbstractValue getInferredTypeOfParameter(
    Local parameter,
    MemberEntity? member,
  );

  /// Returns the inferred result type of a dynamic [selector] access on the
  /// [receiver].
  AbstractValue resultTypeOfSelector(Selector selector, AbstractValue receiver);

  /// Returns the returned type annotation in the [nativeBehavior].
  AbstractValue typeFromNativeBehavior(
    NativeBehavior nativeBehavior,
    JClosedWorld closedWorld,
  );
}

/// Returns the [ir.FunctionNode] that defines [member] or `null` if [member]
/// is not a constructor, method or local function.
ir.FunctionNode? getFunctionNode(
  JsToElementMap elementMap,
  MemberEntity member,
) {
  MemberDefinition definition = elementMap.getMemberDefinition(member);
  switch (definition.kind) {
    case MemberKind.regular:
    case MemberKind.constructor:
    case MemberKind.constructorBody:
      ir.Member node = definition.node as ir.Member;
      return node.function;
    case MemberKind.generatorBody:
      final node = definition.node;
      if (node is ir.LocalFunction) return node.function;
      return (node as ir.Member).function;
    case MemberKind.closureCall:
      ir.LocalFunction node = definition.node as ir.LocalFunction;
      return node.function;
    case MemberKind.closureField:
    case MemberKind.signature:
    case MemberKind.recordGetter:
    case MemberKind.parameterStub:
      return null;
  }
}

/// Returns the initializer for [field].
///
/// If [field] is an instance field with a null literal initializer `null` is
/// returned, otherwise the initializer of the [ir.Field] is returned.
ir.Node? getFieldInitializer(JsToElementMap elementMap, FieldEntity field) {
  MemberDefinition definition = elementMap.getMemberDefinition(field);
  ir.Field node = definition.node as ir.Field;
  ir.Expression? initializer = node.initializer;
  if (initializer != null &&
      node.isInstanceMember &&
      !node.isFinal &&
      isNullLiteral(initializer)) {
    return null;
  }
  return initializer;
}

/// Map from kernel IR nodes to local entities.
abstract class KernelToLocalsMap {
  /// The member currently being built.
  MemberEntity get currentMember;

  /// Returns the [Local] for [node].
  Local getLocalVariable(ir.Variable node);

  /// Returns the [Local] for the [typeVariable].
  Local getLocalTypeVariableEntity(TypeVariableEntity typeVariable);

  /// Returns the [ir.FunctionNode] that declared [parameter].
  ir.FunctionNode getFunctionNodeForParameter(Local parameter);

  /// Returns the [DartType] of [local].
  DartType getLocalType(JsToElementMap elementMap, Local local);

  /// Returns the [JumpTarget] for the break statement [node].
  JumpTarget getJumpTargetForBreak(ir.BreakStatement node);

  /// Returns `true` if [node] should generate a `continue` to its [JumpTarget].
  bool generateContinueForBreak(ir.BreakStatement node);

  /// Returns the [JumpTarget] defined by the labelled statement [node] or
  /// `null` if [node] is not a jump target.
  JumpTarget? getJumpTargetForLabel(ir.LabeledStatement node);

  /// Returns the [JumpTarget] defined by the switch statement [node] or `null`
  /// if [node] is not a jump target.
  JumpTarget? getJumpTargetForSwitch(ir.SwitchStatement node);

  /// Returns the [JumpTarget] for the continue switch statement [node].
  JumpTarget getJumpTargetForContinueSwitch(ir.ContinueSwitchStatement node);

  /// Returns the [JumpTarget] defined by the switch case [node] or `null`
  /// if [node] is not a jump target.
  JumpTarget? getJumpTargetForSwitchCase(ir.SwitchCase node);

  /// Returns the [JumpTarget] defined the do statement [node] or `null`
  /// if [node] is not a jump target.
  JumpTarget? getJumpTargetForDo(ir.DoStatement node);

  /// Returns the [JumpTarget] defined by the for statement [node] or `null`
  /// if [node] is not a jump target.
  JumpTarget? getJumpTargetForFor(ir.ForStatement node);

  /// Returns the [JumpTarget] defined by the for-in statement [node] or `null`
  /// if [node] is not a jump target.
  JumpTarget? getJumpTargetForForIn(ir.ForInStatement node);

  /// Returns the [JumpTarget] defined by the while statement [node] or `null`
  /// if [node] is not a jump target.
  JumpTarget? getJumpTargetForWhile(ir.WhileStatement node);

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

// TODO(johnniwinther,efortuna): Add more when needed.
// TODO(johnniwinther): Should we split regular into method, field, etc.?
enum MemberKind {
  /// A regular member defined by an [ir.Node].
  regular,

  /// A constructor whose initializer is defined by an [ir.Constructor] node.
  constructor,

  /// A constructor whose body is defined by an [ir.Constructor] node.
  constructorBody,

  /// A closure class `call` method whose body is defined by an
  /// [ir.LocalFunction].
  closureCall,

  /// A field corresponding to a captured variable in the closure. It does not
  /// have a corresponding ir.Node.
  closureField,

  /// A method that describes the type of a function (in this case the type of
  /// the closure class. It does not have a corresponding ir.Node or a method
  /// body.
  signature,

  /// A separated body of a generator (sync*/async/async*) function.
  generatorBody,

  /// A dynamic getter for a field of a record.
  recordGetter,

  /// A parameter stub for an invokable member.
  parameterStub,
}

/// Definition information for a [MemberEntity].
abstract class MemberDefinition {
  /// The kind of the defined member. This determines the semantics of [node].
  MemberKind get kind;

  /// The defining [ir.Node] for this member, if supported by its [kind].
  ///
  /// For a regular class this is the [ir.Class] node. For closure classes this
  /// might be an [ir.FunctionExpression] node if needed.
  ir.Node get node;

  /// The canonical location of [member]. This is used for sorting the members
  /// in the emitted code.
  SourceSpan get location;

  /// Deserializes a [MemberDefinition] object from [source].
  factory MemberDefinition.readFromDataSource(DataSourceReader source) {
    MemberKind kind = source.readEnum(MemberKind.values);
    switch (kind) {
      case MemberKind.regular:
        return RegularMemberDefinition.readFromDataSource(source);
      case MemberKind.constructor:
      case MemberKind.constructorBody:
      case MemberKind.signature:
      case MemberKind.generatorBody:
      case MemberKind.parameterStub:
        return SpecialMemberDefinition.readFromDataSource(source, kind);
      case MemberKind.closureCall:
      case MemberKind.closureField:
        return ClosureMemberDefinition.readFromDataSource(source, kind);
      case MemberKind.recordGetter:
        return RecordGetterDefinition.readFromDataSource(source);
    }
  }

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

/// A member directly defined by its [ir.Member] node.
class RegularMemberDefinition implements MemberDefinition {
  /// Tag used for identifying serialized [RegularMemberDefinition] objects in a
  /// debugging data stream.
  static const String tag = 'regular-member-definition';

  @override
  final ir.Member node;

  RegularMemberDefinition(this.node);

  factory RegularMemberDefinition.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Member node = source.readMemberNode();
    source.end(tag);
    return RegularMemberDefinition(node);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(MemberKind.regular);
    sink.begin(tag);
    sink.writeMemberNode(node);
    sink.end(tag);
  }

  @override
  SourceSpan get location => computeSourceSpanFromTreeNode(node);

  @override
  MemberKind get kind => MemberKind.regular;

  @override
  String toString() =>
      'RegularMemberDefinition(kind:$kind,'
      'node:$node,location:$location)';
}

/// The definition of a special kind of member
class SpecialMemberDefinition implements MemberDefinition {
  /// Tag used for identifying serialized [SpecialMemberDefinition] objects in a
  /// debugging data stream.
  static const String tag = 'special-member-definition';

  @override
  ir.TreeNode get node => _node.loaded();
  final Deferrable<ir.TreeNode> _node;
  @override
  final MemberKind kind;

  SpecialMemberDefinition(ir.TreeNode node, this.kind)
    : _node = Deferrable.eager(node);

  SpecialMemberDefinition.from(MemberDefinition baseMember, this.kind)
    : _node = baseMember is ClosureMemberDefinition
          ? baseMember._node
          : Deferrable.eager(baseMember.node as ir.TreeNode);

  SpecialMemberDefinition._deserialized(this._node, this.kind);

  static ir.TreeNode _readNode(DataSourceReader source) =>
      source.readTreeNode();

  factory SpecialMemberDefinition.readFromDataSource(
    DataSourceReader source,
    MemberKind kind,
  ) {
    source.begin(tag);
    Deferrable<ir.TreeNode> node = source.readDeferrable(_readNode);
    source.end(tag);
    return SpecialMemberDefinition._deserialized(node, kind);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(kind);
    sink.begin(tag);
    sink.writeDeferrable(() => sink.writeTreeNode(node));
    sink.end(tag);
  }

  @override
  SourceSpan get location => computeSourceSpanFromTreeNode(node);

  @override
  String toString() =>
      'SpecialMemberDefinition(kind:$kind,'
      'node:$node,location:$location)';
}

class ClosureMemberDefinition implements MemberDefinition {
  /// Tag used for identifying serialized [ClosureMemberDefinition] objects in a
  /// debugging data stream.
  static const String tag = 'closure-member-definition';

  @override
  final SourceSpan location;
  @override
  final MemberKind kind;
  @override
  ir.TreeNode get node => _node.loaded();
  final Deferrable<ir.TreeNode> _node;

  ClosureMemberDefinition(this.location, this.kind, ir.TreeNode node)
    : _node = Deferrable.eager(node),
      assert(kind == MemberKind.closureCall || kind == MemberKind.closureField);

  ClosureMemberDefinition._deserialized(this.location, this.kind, this._node)
    : assert(kind == MemberKind.closureCall || kind == MemberKind.closureField);

  static ir.TreeNode _readNode(DataSourceReader source) =>
      source.readTreeNode();

  factory ClosureMemberDefinition.readFromDataSource(
    DataSourceReader source,
    MemberKind kind,
  ) {
    source.begin(tag);
    SourceSpan location = source.readSourceSpan();
    Deferrable<ir.TreeNode> node = source.readDeferrable(_readNode);
    source.end(tag);
    return ClosureMemberDefinition._deserialized(location, kind, node);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(kind);
    sink.begin(tag);
    sink.writeSourceSpan(location);
    sink.writeDeferrable(() => sink.writeTreeNode(node));
    sink.end(tag);
  }

  @override
  String toString() => 'ClosureMemberDefinition(kind:$kind,location:$location)';
}

/// Definition for a record getter member.
class RecordGetterDefinition implements MemberDefinition {
  /// Tag used for identifying serialized [RecordMemberDefinition] objects in a
  /// debugging data stream.
  static const String tag = 'record-getter-definition';

  @override
  final SourceSpan location;

  final int indexInShape;

  @override
  ir.TreeNode get node => throw UnsupportedError('RecordGetterDefinition.node');

  RecordGetterDefinition(this.location, this.indexInShape);

  factory RecordGetterDefinition.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    SourceSpan location = source.readSourceSpan();
    int indexInShape = source.readInt();
    source.end(tag);
    return RecordGetterDefinition(location, indexInShape);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(kind);
    sink.begin(tag);
    sink.writeSourceSpan(location);
    sink.writeInt(indexInShape);
    sink.end(tag);
  }

  @override
  MemberKind get kind => MemberKind.recordGetter;

  @override
  String toString() =>
      'RecordGetterDefinition(indexInShape:$indexInShape,location:$location)';
}

void forEachOrderedParameterByFunctionNode(
  ir.FunctionNode node,
  ParameterStructure parameterStructure,
  void Function(
    ir.FunctionParameter parameter, {
    required bool isOptional,
    required bool isElided,
  })
  f, {
  bool useNativeOrdering = false,
}) {
  for (
    int position = 0;
    position < node.positionalParameters.length;
    position++
  ) {
    ir.PositionalParameter variable = node.positionalParameters[position];
    f(
      variable,
      isOptional: position >= parameterStructure.requiredPositionalParameters,
      isElided: position >= parameterStructure.positionalParameters,
    );
  }

  if (node.namedParameters.isEmpty) {
    return;
  }

  List<ir.NamedParameter> namedParameters = node.namedParameters.toList();
  if (useNativeOrdering) {
    namedParameters.sort(nativeOrdering);
  } else {
    namedParameters.sort(namedOrdering);
  }
  for (ir.NamedParameter parameter in namedParameters) {
    f(
      parameter,
      isOptional: true,
      isElided: !parameterStructure.namedParameters.contains(
        parameter.parameterName,
      ),
    );
  }
}

void forEachOrderedParameter(
  JsToElementMap elementMap,
  FunctionEntity function,
  void Function(ir.Variable parameter, {required bool isElided}) f,
) {
  ParameterStructure parameterStructure = function.parameterStructure;

  void handleParameter(
    ir.Variable parameter, {
    required bool isOptional,
    required bool isElided,
  }) {
    f(parameter, isElided: isElided);
  }

  MemberDefinition definition = elementMap.getMemberDefinition(function);
  switch (definition.kind) {
    case MemberKind.regular:
      ir.Node node = definition.node;
      if (node is ir.Procedure) {
        forEachOrderedParameterByFunctionNode(
          node.function,
          parameterStructure,
          handleParameter,
        );
        return;
      }
      break;
    case MemberKind.constructor:
    case MemberKind.constructorBody:
      ir.Node node = definition.node;
      if (node is ir.Procedure) {
        forEachOrderedParameterByFunctionNode(
          node.function,
          parameterStructure,
          handleParameter,
        );
        return;
      } else if (node is ir.Constructor) {
        forEachOrderedParameterByFunctionNode(
          node.function,
          parameterStructure,
          handleParameter,
        );
        return;
      }
      break;
    case MemberKind.closureCall:
      final node = definition.node as ir.LocalFunction;
      forEachOrderedParameterByFunctionNode(
        node.function,
        parameterStructure,
        handleParameter,
      );
      return;
    case MemberKind.closureField:
    case MemberKind.generatorBody:
    case MemberKind.recordGetter:
    case MemberKind.signature:
    case MemberKind.parameterStub:
      break;
  }
  failedAt(function, "Unexpected function definition $definition.");
}

enum ClassKind {
  regular,
  closure,
  // TODO(efortuna, johnniwinther): Context is not a class, but is
  // masquerading as one currently for consistency with the old element model.
  context,
  record,
}

/// Definition information for a [ClassEntity].
abstract class ClassDefinition {
  /// The kind of the defined class. This determines the semantics of [node].
  ClassKind get kind;

  /// The defining [ir.Node] for this class, if supported by its [kind].
  ir.Node get node;

  /// The canonical location of [cls]. This is used for sorting the classes
  /// in the emitted code.
  SourceSpan get location;

  /// Deserializes a [ClassDefinition] object from [source].
  factory ClassDefinition.readFromDataSource(DataSourceReader source) {
    ClassKind kind = source.readEnum(ClassKind.values);
    switch (kind) {
      case ClassKind.regular:
        return RegularClassDefinition.readFromDataSource(source);
      case ClassKind.closure:
        return ClosureClassDefinition.readFromDataSource(source);
      case ClassKind.context:
        return ContextContainerDefinition.readFromDataSource(source);
      case ClassKind.record:
        return RecordClassDefinition.readFromDataSource(source);
    }
  }

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

/// A class directly defined by its [ir.Class] node.
class RegularClassDefinition implements ClassDefinition {
  /// Tag used for identifying serialized [RegularClassDefinition] objects in a
  /// debugging data stream.
  static const String tag = 'regular-class-definition';

  @override
  final ir.Class node;

  RegularClassDefinition(this.node);

  factory RegularClassDefinition.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    ir.Class node = source.readClassNode();
    source.end(tag);
    return RegularClassDefinition(node);
  }

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

  @override
  SourceSpan get location => computeSourceSpanFromTreeNode(node);

  @override
  ClassKind get kind => ClassKind.regular;

  @override
  String toString() =>
      'RegularClassDefinition(kind:$kind,'
      'node:$node,location:$location)';
}

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

  @override
  final SourceSpan location;

  ClosureClassDefinition(this.location);

  factory ClosureClassDefinition.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    SourceSpan location = source.readSourceSpan();
    source.end(tag);
    return ClosureClassDefinition(location);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ClassKind.closure);
    sink.begin(tag);
    sink.writeSourceSpan(location);
    sink.end(tag);
  }

  @override
  ClassKind get kind => ClassKind.closure;

  @override
  ir.Node get node =>
      throw UnsupportedError('ClosureClassDefinition.node for $location');

  @override
  String toString() => 'ClosureClassDefinition(kind:$kind,location:$location)';
}

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

  @override
  final SourceSpan location;

  ContextContainerDefinition(this.location);

  factory ContextContainerDefinition.readFromDataSource(
    DataSourceReader source,
  ) {
    source.begin(tag);
    SourceSpan location = source.readSourceSpan();
    source.end(tag);
    return ContextContainerDefinition(location);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ClassKind.context);
    sink.begin(tag);
    sink.writeSourceSpan(location);
    sink.end(tag);
  }

  @override
  ClassKind get kind => ClassKind.context;

  @override
  ir.Node get node =>
      throw UnsupportedError('ContextContainerDefinition.node for $location');

  @override
  String toString() =>
      'ContextContainerDefinition(kind:$kind,location:$location)';
}

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

  @override
  final SourceSpan location;

  RecordClassDefinition(this.location);

  factory RecordClassDefinition.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    SourceSpan location = source.readSourceSpan();
    source.end(tag);
    return RecordClassDefinition(location);
  }

  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(ClassKind.record);
    sink.begin(tag);
    sink.writeSourceSpan(location);
    sink.end(tag);
  }

  @override
  ClassKind get kind => ClassKind.record;

  @override
  ir.Node get node =>
      throw UnsupportedError('RecordClassDefinition.node for $location');

  @override
  String toString() => 'RecordClassDefinition(kind:$kind,location:$location)';
}
