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

part of '../fragment.dart';

/// Strategy pattern for creating different encodings of a declared field.
///
/// This is used to provide lowerings for late fields using synthesized getters
/// and setters.
sealed class FieldEncoding {
  /// Creates the members necessary for this field encoding.
  ///
  /// This method is called for both outline and full compilation so the created
  /// members should be without body. The member bodies are created through
  /// [createBodies].
  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
      NameScheme nameScheme, PropertyReferences references,
      {required bool isAbstractOrExternal,
      required List<TypeParameter>? classTypeParameters});

  /// Calls [f] for each member needed for this field encoding.
  void registerMembers(BuildNodesCallback f);

  /// Creates the bodies needed for the field encoding using [initializer] as
  /// the declared initializer expression.
  ///
  /// This method is not called for fields in outlines unless their are constant
  /// or part of a const constructor.
  void createBodies(CoreTypes coreTypes, Expression? initializer);

  /// The type of the declared field.
  abstract DartType type;

  /// Builds the [Initializer]s for each field used to encode this field
  /// using the [fileOffset] for the created nodes and [value] as the initial
  /// field value.
  ///
  /// This is only used for instance fields.
  List<Initializer> createInitializer(int fileOffset, Expression value,
      {required bool isSynthetic});

  /// Creates the AST node for this field as the default initializer.
  ///
  /// This is only used for instance fields.
  void buildImplicitDefaultValue();

  /// Creates the [Initializer] for the implicit initialization of this field
  /// in a constructor.
  ///
  /// This is only used for instance fields.
  Initializer buildImplicitInitializer();

  /// Creates the [Initializer] for the invalid initialization of this field.
  ///
  /// This is only used for instance fields.
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset});

  /// Registers that the (implicit) setter associated with this field needs to
  /// contain a runtime type check to deal with generic covariance.
  void setCovariantByClass();

  /// Returns the field that holds the field value at runtime.
  Field get field;

  /// The [Member] built during [FieldDeclaration.buildFieldOutlineExpressions].
  Member get builtMember;

  /// Returns the members that holds the field annotations.
  Iterable<Annotatable> get annotatables;

  /// Returns the member used to read the field value.
  Member get readTarget;

  /// Returns the reference used to read the field value.
  Reference get readTargetReference;

  /// Returns the member used to write to the field.
  Member? get writeTarget;

  /// Returns the reference used to write to the field.
  Reference? get writeTargetReference;

  /// Returns the references to the generated members that are visible through
  /// exports.
  ///
  /// This is the getter reference, and, if available, the setter reference.
  Iterable<Reference> get exportedReferenceMembers;

  /// Returns a list of the field, getters and methods created by this field
  /// encoding.
  List<ClassMember> get localMembers;

  /// Returns a list of the setters created by this field encoding.
  List<ClassMember> get localSetters;

  /// Registers that a `super` call has occurred in the initializer of this
  /// field.
  void registerSuperCall();
}

class RegularFieldEncoding implements FieldEncoding {
  final FieldFragment _fragment;
  final bool isEnumElement;
  Field? _field;
  DartType _type = const DynamicType();

  RegularFieldEncoding(this._fragment, {required this.isEnumElement}) {}

  @override
  DartType get type => _type;

  @override
  void set type(DartType value) {
    _type = value;
    _field?.type = value;
  }

  @override
  void createBodies(CoreTypes coreTypes, Expression? initializer) {
    if (initializer != null) {
      _field!.initializer = initializer..parent = _field;
    }
  }

  @override
  List<Initializer> createInitializer(int fileOffset, Expression value,
      {required bool isSynthetic}) {
    return <Initializer>[
      new FieldInitializer(_field!, value)
        ..fileOffset = fileOffset
        ..isSynthetic = isSynthetic
    ];
  }

  @override
  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
      NameScheme nameScheme, PropertyReferences references,
      {required bool isAbstractOrExternal,
      required List<TypeParameter>? classTypeParameters}) {
    bool isImmutable = _fragment.modifiers.isLate
        ? (_fragment.modifiers.isFinal && _fragment.modifiers.hasInitializer)
        : (_fragment.modifiers.isFinal || _fragment.modifiers.isConst);
    _field = isImmutable
        ? new Field.immutable(dummyName,
            type: _type,
            isFinal: _fragment.modifiers.isFinal,
            isConst: _fragment.modifiers.isConst,
            isLate: _fragment.modifiers.isLate,
            fileUri: _fragment.fileUri,
            fieldReference: references.fieldReference,
            getterReference: references.getterReference,
            isEnumElement: isEnumElement)
        : new Field.mutable(dummyName,
            type: _type,
            isFinal: _fragment.modifiers.isFinal,
            isLate: _fragment.modifiers.isLate,
            fileUri: _fragment.fileUri,
            fieldReference: references.fieldReference,
            getterReference: references.getterReference,
            setterReference: references.setterReference);
    nameScheme
        .getFieldMemberName(FieldNameType.Field, _fragment.name,
            isSynthesized: false)
        .attachMember(_field!);
    _field!
      ..fileOffset = _fragment.nameOffset
      ..fileEndOffset = _fragment.endOffset;
    _field!..isCovariantByDeclaration = _fragment.modifiers.isCovariant;
    if (_fragment.builder.isExtensionMember) {
      _field!
        ..isStatic = true
        ..isExtensionMember = true;
    } else if (_fragment.builder.isExtensionTypeMember) {
      _field!
        ..isStatic = _fragment.builder.isStatic
        ..isExtensionTypeMember = true;
    } else {
      bool isInstanceMember =
          !_fragment.builder.isStatic && !_fragment.builder.isTopLevel;
      _field!
        ..isStatic = !isInstanceMember
        ..isExtensionMember = false;
    }
    _field!.isLate = _fragment.modifiers.isLate;
  }

  @override
  void registerMembers(BuildNodesCallback f) {
    f(
        member: _field!,
        kind: _fragment.builder.isExtensionMember ||
                _fragment.builder.isExtensionTypeMember
            ? BuiltMemberKind.ExtensionField
            : BuiltMemberKind.Field);
  }

  @override
  void setCovariantByClass() {
    if (_field!.hasSetter) {
      _field!.isCovariantByClass = true;
    }
  }

  @override
  // Coverage-ignore(suite): Not run.
  Field get field => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  Member get builtMember => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Annotatable> get annotatables => [_field!];

  @override
  Member get readTarget => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  Reference get readTargetReference => _field!.getterReference;

  @override
  Member get writeTarget => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  Reference? get writeTargetReference => _field!.setterReference;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Reference> get exportedReferenceMembers => [
        _field!.getterReference,
        if (_field!.hasSetter) _field!.setterReference!
      ];

  @override
  List<ClassMember> get localMembers => <ClassMember>[
        new _FieldClassMember(_fragment.builder, _fragment, forSetter: false)
      ];

  @override
  List<ClassMember> get localSetters => _fragment.hasSetter
      ? [new _FieldClassMember(_fragment.builder, _fragment, forSetter: true)]
      : const [];

  @override
  void buildImplicitDefaultValue() {
    _field!.initializer = new NullLiteral()..parent = _field;
  }

  @override
  Initializer buildImplicitInitializer() {
    return new FieldInitializer(_field!, new NullLiteral())..isSynthetic = true;
  }

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    return new ShadowInvalidFieldInitializer(type, value, effect)
      ..fileOffset = fileOffset;
  }

  @override
  void registerSuperCall() {
    _field!.transformerFlags |= TransformerFlag.superCalls;
  }
}

abstract class AbstractLateFieldEncoding implements FieldEncoding {
  final FieldFragment _fragment;
  DartType? _type;
  Field? _field;
  Field? _lateIsSetField;
  Procedure? _lateGetter;
  Procedure? _lateSetter;

  // If `true`, an isSet field is used even when the type of the field is
  // not potentially nullable.
  //
  // This is used to force use isSet fields in mixed mode encoding since
  // we cannot trust non-nullable fields to be initialized with non-null values.
  final late_lowering.IsSetStrategy _isSetStrategy;
  late_lowering.IsSetEncoding? _isSetEncoding;

  // If `true`, the is-set field was register before the type was known to be
  // nullable or non-nullable. In this case we do not try to remove it from
  // the generated AST to avoid inconsistency between the class hierarchy used
  // during and after inference.
  //
  // This is also used to force use isSet fields in mixed mode encoding since
  // we cannot trust non-nullable fields to be initialized with non-null values.
  bool _forceIncludeIsSetField;

  AbstractLateFieldEncoding(this._fragment,
      {required late_lowering.IsSetStrategy isSetStrategy})
      : _isSetStrategy = isSetStrategy,
        _forceIncludeIsSetField =
            isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {}

  late_lowering.IsSetEncoding get isSetEncoding {
    assert(_type != null,
        "Type has not been computed for field ${_fragment.name}.");
    return _isSetEncoding ??=
        late_lowering.computeIsSetEncoding(_type!, _isSetStrategy);
  }

  @override
  void createBodies(CoreTypes coreTypes, Expression? initializer) {
    assert(_type != null,
        "Type has not been computed for field ${_fragment.name}.");
    if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
      _field!.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
          new Arguments([], types: [_type!])..fileOffset = _fragment.nameOffset)
        ..fileOffset = _fragment.nameOffset
        ..parent = _field;
    } else {
      _field!.initializer = new NullLiteral()
        ..fileOffset = _fragment.nameOffset
        ..parent = _field;
    }
    if (_lateIsSetField != null) {
      _lateIsSetField!.initializer = new BoolLiteral(false)
        ..fileOffset = _fragment.nameOffset
        ..parent = _lateIsSetField;
    }
    _lateGetter!.function.body =
        _createGetterBody(coreTypes, _fragment.name, initializer)
          ..parent = _lateGetter!.function;
    // The initializer is copied from [_field] to [_lateGetter] so we copy the
    // transformer flags to reflect whether the getter contains super calls.
    _lateGetter!.transformerFlags = _field!.transformerFlags;

    if (_lateSetter != null) {
      _lateSetter!.function.body = _createSetterBody(coreTypes, _fragment.name,
          _lateSetter!.function.positionalParameters.first)
        ..parent = _lateSetter!.function;
    }
  }

  @override
  List<Initializer> createInitializer(int fileOffset, Expression value,
      {required bool isSynthetic}) {
    List<Initializer> initializers = <Initializer>[];
    if (_lateIsSetField != null) {
      initializers.add(new FieldInitializer(
          _lateIsSetField!, new BoolLiteral(true)..fileOffset = fileOffset)
        ..fileOffset = fileOffset
        ..isSynthetic = isSynthetic);
    }
    initializers.add(new FieldInitializer(_field!, value)
      ..fileOffset = fileOffset
      ..isSynthetic = isSynthetic);
    return initializers;
  }

  /// Creates an [Expression] that reads [_field].
  ///
  /// If [needsPromotion] is `true`, the field will be read through a `let`
  /// expression that promotes the expression to [_type]. This is needed for a
  /// sound encoding of fields with type parameter type of undetermined
  /// nullability.
  Expression _createFieldRead({bool needsPromotion = false}) {
    assert(_type != null,
        "Type has not been computed for field ${_fragment.name}.");
    if (needsPromotion) {
      VariableDeclaration variable = new VariableDeclaration.forValue(
          _createFieldGet(_field!),
          type: _type!.withDeclaredNullability(Nullability.nullable))
        ..fileOffset = _fragment.nameOffset;
      return new Let(variable,
          new VariableGet(variable, _type)..fileOffset = _fragment.nameOffset);
    } else {
      return _createFieldGet(_field!);
    }
  }

  /// Creates an [Expression] that reads [field].
  Expression _createFieldGet(Field field) {
    if (field.isStatic) {
      return new StaticGet(field)..fileOffset = _fragment.nameOffset;
    } else {
      // No substitution needed for the result type, since any type parameters
      // in there are also in scope at the access site.
      return new InstanceGet(InstanceAccessKind.Instance,
          new ThisExpression()..fileOffset = _fragment.nameOffset, field.name,
          interfaceTarget: field, resultType: field.type)
        ..fileOffset = _fragment.nameOffset;
    }
  }

  /// Creates an [Expression] that writes [value] to [field].
  Expression _createFieldSet(Field field, Expression value) {
    if (field.isStatic) {
      return new StaticSet(field, value)..fileOffset = _fragment.nameOffset;
    } else {
      return new InstanceSet(
          InstanceAccessKind.Instance,
          new ThisExpression()..fileOffset = _fragment.nameOffset,
          field.name,
          value,
          interfaceTarget: field)
        ..fileOffset = _fragment.nameOffset;
    }
  }

  Statement _createGetterBody(
      CoreTypes coreTypes, String name, Expression? initializer);

  Procedure? _createSetter(Uri fileUri, int charOffset, Reference? reference,
      {required bool isCovariantByDeclaration}) {
    VariableDeclaration parameter =
        new VariableDeclaration("${_fragment.name}#param")
          ..isCovariantByDeclaration = isCovariantByDeclaration
          ..fileOffset = _fragment.nameOffset;
    return new Procedure(
        dummyName,
        ProcedureKind.Setter,
        new FunctionNode(null,
            positionalParameters: [parameter], returnType: const VoidType())
          ..fileOffset = charOffset
          ..fileEndOffset = _fragment.endOffset,
        fileUri: fileUri,
        reference: reference)
      ..fileOffset = charOffset
      ..fileEndOffset = _fragment.endOffset;
  }

  Statement _createSetterBody(
      CoreTypes coreTypes, String name, VariableDeclaration parameter);

  @override
  DartType get type {
    assert(_type != null,
        "Type has not been computed for field ${_fragment.name}.");
    return _type!;
  }

  /// Updates the field/getter/setter types of [_field], [_lateGetter] and
  /// [_lateSetter] to match the value of [_type].
  ///
  /// This allows for creating the members and computing the type in arbitrary
  /// order.
  void _updateMemberTypes() {
    DartType? type = _type;
    Field? field = _field;
    if (type != null && type is! InferredType && field != null) {
      field.type = type.withDeclaredNullability(Nullability.nullable);
      _lateGetter!.function.returnType = type;
      _lateSetter?.function.positionalParameters.single.type = type;
      if (!type.isPotentiallyNullable && !_forceIncludeIsSetField) {
        // We only need the is-set field if the field is potentially nullable.
        //  Otherwise we use `null` to signal that the field is uninitialized.
        _lateIsSetField = null;
      }
    }
  }

  @override
  void set type(DartType value) {
    assert(_type == null || _type is InferredType,
        "Type has already been computed for field ${_fragment.name}.");
    _type = value;
    _updateMemberTypes();
  }

  @override
  void setCovariantByClass() {
    if (_field!.hasSetter) {
      _field!.isCovariantByClass = true;
    }
    _lateSetter?.function.positionalParameters.single.isCovariantByClass = true;
  }

  @override
  // Coverage-ignore(suite): Not run.
  Field get field => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  Member get builtMember => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Annotatable> get annotatables {
    List<Annotatable> list = [_lateGetter!];
    if (_lateSetter != null) {
      list.add(_lateSetter!);
    }
    return list;
  }

  @override
  Member get readTarget => _lateGetter!;

  @override
  // Coverage-ignore(suite): Not run.
  Reference get readTargetReference => _lateGetter!.reference;

  @override
  Member? get writeTarget => _lateSetter;

  @override
  // Coverage-ignore(suite): Not run.
  Reference? get writeTargetReference => _lateSetter?.reference;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Reference> get exportedReferenceMembers {
    if (_lateSetter != null) {
      return [_lateGetter!.reference, _lateSetter!.reference];
    }
    return [_lateGetter!.reference];
  }

  @override
  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
      NameScheme nameScheme, PropertyReferences references,
      {required bool isAbstractOrExternal,
      required List<TypeParameter>? classTypeParameters}) {
    _field = new Field.mutable(dummyName,
        fileUri: _fragment.fileUri, fieldReference: references.fieldReference)
      ..fileOffset = _fragment.nameOffset
      ..fileEndOffset = _fragment.endOffset
      ..isInternalImplementation = true;
    nameScheme
        .getFieldMemberName(FieldNameType.Field, _fragment.name,
            isSynthesized: true)
        .attachMember(_field!);
    switch (_isSetStrategy) {
      case late_lowering.IsSetStrategy.useSentinelOrNull:
      case late_lowering.IsSetStrategy.forceUseSentinel:
        // [_lateIsSetField] is never needed.
        break;
      case late_lowering.IsSetStrategy.forceUseIsSetField:
      case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
        _lateIsSetField =
            new Field.mutable(dummyName, fileUri: _fragment.fileUri)
              ..fileOffset = _fragment.nameOffset
              ..fileEndOffset = _fragment.endOffset
              ..isInternalImplementation = true;
        nameScheme
            .getFieldMemberName(FieldNameType.IsSetField, _fragment.name,
                isSynthesized: true)
            .attachMember(_lateIsSetField!);
        break;
    }
    _lateGetter = new Procedure(
        dummyName,
        ProcedureKind.Getter,
        new FunctionNode(null)
          ..fileOffset = _fragment.nameOffset
          ..fileEndOffset = _fragment.endOffset,
        fileUri: _fragment.fileUri,
        reference: references.getterReference)
      ..fileOffset = _fragment.nameOffset
      ..fileEndOffset = _fragment.endOffset;
    nameScheme
        .getFieldMemberName(FieldNameType.Getter, _fragment.name,
            isSynthesized: true)
        .attachMember(_lateGetter!);
    _lateSetter = _createSetter(
        _fragment.fileUri, _fragment.nameOffset, references.setterReference,
        isCovariantByDeclaration: _fragment.modifiers.isCovariant);
    if (_lateSetter != null) {
      nameScheme
          .getFieldMemberName(FieldNameType.Setter, _fragment.name,
              isSynthesized: true)
          .attachMember(_lateSetter!);
    }

    bool isInstanceMember =
        !_fragment.builder.isStatic && !_fragment.builder.isTopLevel;
    bool isExtensionMember = _fragment.builder.isExtensionMember;
    bool isExtensionTypeMember = _fragment.builder.isExtensionTypeMember;
    if (isExtensionMember) {
      _field!
        ..isStatic = true
        ..isExtensionMember = isExtensionMember;
      isInstanceMember = false;
    } else if (isExtensionTypeMember) {
      _field!
        ..isStatic = _fragment.builder.isStatic
        ..isExtensionTypeMember = true;
    } else {
      _field!
        ..isStatic = !isInstanceMember
        ..isExtensionMember = false;
    }
    if (_lateIsSetField != null) {
      _lateIsSetField!
        ..isStatic = !isInstanceMember
        ..isExtensionMember = isExtensionMember
        ..isExtensionTypeMember = isExtensionTypeMember
        ..type = libraryBuilder.loader
            .createCoreType('bool', Nullability.nonNullable);
    }
    _lateGetter!
      ..isStatic = !isInstanceMember
      ..isExtensionMember = isExtensionMember
      ..isExtensionTypeMember = isExtensionTypeMember;
    if (_lateSetter != null) {
      _lateSetter!
        ..isStatic = !isInstanceMember
        ..isExtensionMember = isExtensionMember
        ..isExtensionTypeMember = isExtensionTypeMember;
    }
    _updateMemberTypes();
  }

  @override
  void registerMembers(BuildNodesCallback f) {
    f(member: _field!, kind: BuiltMemberKind.LateBackingField);
    if (_lateIsSetField != null) {
      _forceIncludeIsSetField = true;
      f(member: _lateIsSetField!, kind: BuiltMemberKind.LateIsSetField);
    }
    f(member: _lateGetter!, kind: BuiltMemberKind.LateGetter);
    if (_lateSetter != null) {
      f(member: _lateSetter!, kind: BuiltMemberKind.LateSetter);
    }
  }

  @override
  List<ClassMember> get localMembers => [
        new _SynthesizedFieldClassMember(
            _fragment.builder,
            _lateGetter!,
            _fragment.builder.memberName,
            _SynthesizedFieldMemberKind.LateGetterSetter,
            ClassMemberKind.Getter,
            _fragment.uriOffset)
      ];

  @override
  List<ClassMember> get localSetters => _lateSetter != null
      ? [
          new _SynthesizedFieldClassMember(
              _fragment.builder,
              _lateSetter!,
              _fragment.builder.memberName,
              _SynthesizedFieldMemberKind.LateGetterSetter,
              ClassMemberKind.Setter,
              _fragment.uriOffset)
        ]
      : const [];

  @override
  void registerSuperCall() {
    _field!.transformerFlags |= TransformerFlag.superCalls;
  }
}

mixin NonFinalLate on AbstractLateFieldEncoding {
  @override
  Statement _createSetterBody(
      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
    assert(_type != null, "Type has not been computed for field $name.");
    return late_lowering.createSetterBody(
        coreTypes, _fragment.nameOffset, name, parameter, _type!,
        shouldReturnValue: false,
        createVariableWrite: (Expression value) =>
            _createFieldSet(_field!, value),
        createIsSetWrite: (Expression value) =>
            _createFieldSet(_lateIsSetField!, value),
        isSetEncoding: isSetEncoding);
  }
}

mixin LateWithoutInitializer on AbstractLateFieldEncoding {
  @override
  Statement _createGetterBody(
      CoreTypes coreTypes, String name, Expression? initializer) {
    assert(_type != null, "Type has not been computed for field $name.");
    return late_lowering.createGetterBodyWithoutInitializer(
        coreTypes, _fragment.nameOffset, name, type,
        createVariableRead: _createFieldRead,
        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
        isSetEncoding: isSetEncoding,
        forField: true);
  }

  @override
  void buildImplicitDefaultValue() {
    throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
  }

  @override
  Initializer buildImplicitInitializer() {
    throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
  }

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    throw new UnsupportedError("$runtimeType.buildDuplicatedInitializer");
  }
}

class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
    with NonFinalLate, LateWithoutInitializer {
  LateFieldWithoutInitializerEncoding(super._fragment,
      {required super.isSetStrategy});
}

class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
    with NonFinalLate {
  LateFieldWithInitializerEncoding(super._fragment,
      {required super.isSetStrategy});

  @override
  Statement _createGetterBody(
      CoreTypes coreTypes, String name, Expression? initializer) {
    assert(_type != null, "Type has not been computed for field $name.");
    return late_lowering.createGetterWithInitializer(
        coreTypes, _fragment.nameOffset, name, _type!, initializer!,
        createVariableRead: _createFieldRead,
        createVariableWrite: (Expression value) =>
            _createFieldSet(_field!, value),
        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
        createIsSetWrite: (Expression value) =>
            _createFieldSet(_lateIsSetField!, value),
        isSetEncoding: isSetEncoding);
  }

  @override
  void buildImplicitDefaultValue() {
    throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
  }

  @override
  Initializer buildImplicitInitializer() {
    throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
  }

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    throw new UnsupportedError("$runtimeType.buildDuplicatedInitializer");
  }
}

class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
    with LateWithoutInitializer {
  LateFinalFieldWithoutInitializerEncoding(super._fragment,
      {required super.isSetStrategy});

  @override
  Statement _createSetterBody(
      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
    assert(_type != null, "Type has not been computed for field $name.");
    return late_lowering.createSetterBodyFinal(
        coreTypes, _fragment.nameOffset, name, parameter, type,
        shouldReturnValue: false,
        createVariableRead: () => _createFieldGet(_field!),
        createVariableWrite: (Expression value) =>
            _createFieldSet(_field!, value),
        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
        createIsSetWrite: (Expression value) =>
            _createFieldSet(_lateIsSetField!, value),
        isSetEncoding: isSetEncoding,
        forField: true);
  }
}

class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding {
  LateFinalFieldWithInitializerEncoding(super._fragment,
      {required super.isSetStrategy});

  @override
  Statement _createGetterBody(
      CoreTypes coreTypes, String name, Expression? initializer) {
    assert(_type != null, "Type has not been computed for field $name.");
    return late_lowering.createGetterWithInitializerWithRecheck(
        coreTypes, _fragment.nameOffset, name, _type!, initializer!,
        createVariableRead: _createFieldRead,
        createVariableWrite: (Expression value) =>
            _createFieldSet(_field!, value),
        createIsSetRead: () => _createFieldGet(_lateIsSetField!),
        createIsSetWrite: (Expression value) =>
            _createFieldSet(_lateIsSetField!, value),
        isSetEncoding: isSetEncoding,
        forField: true);
  }

  @override
  Procedure? _createSetter(Uri fileUri, int charOffset, Reference? reference,
          {required bool isCovariantByDeclaration}) =>
      null;

  @override
  // Coverage-ignore(suite): Not run.
  Statement _createSetterBody(
          CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
      throw new UnsupportedError(
          '$runtimeType._createSetterBody is not supported.');

  @override
  void buildImplicitDefaultValue() {
    throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
  }

  @override
  Initializer buildImplicitInitializer() {
    throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
  }

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    throw new UnsupportedError("$runtimeType.buildDuplicatedInitializer");
  }
}

class AbstractOrExternalFieldEncoding implements FieldEncoding {
  final FieldFragment _fragment;
  final bool isAbstract;
  final bool isExternal;
  final bool _isExtensionInstanceMember;
  final bool _isExtensionTypeInstanceMember;

  Procedure? _getter;
  Procedure? _setter;
  DartType? _type;

  AbstractOrExternalFieldEncoding(this._fragment,
      {required bool isExtensionInstanceMember,
      required bool isExtensionTypeInstanceMember,
      required this.isAbstract,
      required this.isExternal,
      bool isForcedExtension = false})
      : _isExtensionInstanceMember =
            (isExternal || isForcedExtension) && isExtensionInstanceMember,
        _isExtensionTypeInstanceMember =
            (isExternal || isForcedExtension) && isExtensionTypeInstanceMember;

  @override
  DartType get type {
    assert(_type != null,
        "Type has not been computed for field ${_fragment.name}.");
    return _type!;
  }

  /// Updates the getter/setter types of [_getter] and [_setter] to match the
  /// value of [_type].
  ///
  /// This allows for creating the members and computing the type in arbitrary
  /// order.
  void _updateMemberTypes() {
    Procedure? getter = _getter;
    Procedure? setter = _setter;
    DartType? type = _type;
    if (type != null && type is! InferredType && getter != null) {
      if (_isExtensionInstanceMember || _isExtensionTypeInstanceMember) {
        DartType thisParameterType;
        List<TypeParameter> typeParameters;
        if (_isExtensionInstanceMember) {
          SourceExtensionBuilder extensionBuilder =
              _fragment.builder.parent as SourceExtensionBuilder;
          thisParameterType = extensionBuilder.extension.onType;
          typeParameters = extensionBuilder.extension.typeParameters;
        } else {
          SourceExtensionTypeDeclarationBuilder
              extensionTypeDeclarationBuilder =
              _fragment.builder.parent as SourceExtensionTypeDeclarationBuilder;
          thisParameterType = extensionTypeDeclarationBuilder
              .extensionTypeDeclaration.declaredRepresentationType;
          typeParameters = extensionTypeDeclarationBuilder
              .extensionTypeDeclaration.typeParameters;
        }
        if (typeParameters.isNotEmpty) {
          FreshTypeParameters getterTypeParameters =
              getFreshTypeParameters(typeParameters);
          getter.function.positionalParameters.first.type =
              getterTypeParameters.substitute(thisParameterType);
          getter.function.returnType = getterTypeParameters.substitute(type);
          getter.function.typeParameters =
              getterTypeParameters.freshTypeParameters;
          setParents(getterTypeParameters.freshTypeParameters, getter.function);

          if (setter != null) {
            FreshTypeParameters setterTypeParameters =
                getFreshTypeParameters(typeParameters);
            setter.function.positionalParameters.first.type =
                setterTypeParameters.substitute(thisParameterType);
            setter.function.positionalParameters[1].type =
                setterTypeParameters.substitute(type);
            setter.function.typeParameters =
                setterTypeParameters.freshTypeParameters;
            setParents(
                setterTypeParameters.freshTypeParameters, setter.function);
          }
        } else {
          getter.function.returnType = type;
          setter?.function.positionalParameters[1].type = type;
          getter.function.positionalParameters.first.type = thisParameterType;
          setter?.function.positionalParameters.first.type = thisParameterType;
        }
      } else {
        getter.function.returnType = type;
        if (setter != null) {
          if (setter.kind == ProcedureKind.Method) {
            // Coverage-ignore-block(suite): Not run.
            setter.function.positionalParameters[1].type = type;
          } else {
            setter.function.positionalParameters.first.type = type;
          }
        }
      }
    }
  }

  @override
  void set type(DartType value) {
    assert(_type == null || _type is InferredType,
        "Type has already been computed for field ${_fragment.name}.");
    _type = value;
    _updateMemberTypes();
  }

  @override
  void createBodies(CoreTypes coreTypes, Expression? initializer) {
    // TODO(johnniwinther): Enable this assert.
    //assert(initializer != null);
  }

  @override
  List<Initializer> createInitializer(int fileOffset, Expression value,
      {required bool isSynthetic}) {
    throw new UnsupportedError('ExternalFieldEncoding.createInitializer');
  }

  @override
  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
      NameScheme nameScheme, PropertyReferences references,
      {required bool isAbstractOrExternal,
      required List<TypeParameter>? classTypeParameters}) {
    if (_isExtensionInstanceMember || _isExtensionTypeInstanceMember) {
      _getter = new Procedure(
          dummyName,
          ProcedureKind.Method,
          new FunctionNode(null, positionalParameters: [
            new VariableDeclaration(syntheticThisName)
              ..fileOffset = _fragment.nameOffset
              ..isLowered = true
          ]),
          fileUri: _fragment.fileUri,
          reference: references.getterReference)
        ..fileOffset = _fragment.nameOffset
        ..fileEndOffset = _fragment.endOffset;
      nameScheme
          .getProcedureMemberName(ProcedureKind.Getter, _fragment.name)
          .attachMember(_getter!);
      if (_fragment.hasSetter) {
        VariableDeclaration parameter =
            new VariableDeclaration("#externalFieldValue", isSynthesized: true)
              ..isCovariantByDeclaration = _fragment.modifiers.isCovariant
              ..fileOffset = _fragment.nameOffset;
        _setter = new Procedure(
            dummyName,
            ProcedureKind.Method,
            new FunctionNode(null,
                positionalParameters: [
                  new VariableDeclaration(syntheticThisName)
                    ..fileOffset = _fragment.nameOffset
                    ..isLowered = true,
                  parameter
                ],
                returnType: const VoidType())
              ..fileOffset = _fragment.nameOffset
              ..fileEndOffset = _fragment.endOffset,
            fileUri: _fragment.fileUri,
            reference: references.setterReference)
          ..fileOffset = _fragment.nameOffset
          ..fileEndOffset = _fragment.endOffset;
        nameScheme
            .getProcedureMemberName(ProcedureKind.Setter, _fragment.name)
            .attachMember(_setter!);
      }
    } else {
      _getter = new Procedure(
          dummyName, ProcedureKind.Getter, new FunctionNode(null),
          fileUri: _fragment.fileUri, reference: references.getterReference)
        ..fileOffset = _fragment.nameOffset
        ..fileEndOffset = _fragment.endOffset;
      nameScheme
          .getFieldMemberName(FieldNameType.Getter, _fragment.name,
              isSynthesized: true)
          .attachMember(_getter!);
      if (!_fragment.modifiers.isFinal) {
        VariableDeclaration parameter =
            new VariableDeclaration("#externalFieldValue", isSynthesized: true)
              ..isCovariantByDeclaration = _fragment.modifiers.isCovariant
              ..fileOffset = _fragment.nameOffset;
        _setter = new Procedure(
            dummyName,
            ProcedureKind.Setter,
            new FunctionNode(null,
                positionalParameters: [parameter], returnType: const VoidType())
              ..fileOffset = _fragment.nameOffset
              ..fileEndOffset = _fragment.endOffset,
            fileUri: _fragment.fileUri,
            reference: references.setterReference)
          ..fileOffset = _fragment.nameOffset
          ..fileEndOffset = _fragment.endOffset;
        nameScheme
            .getFieldMemberName(FieldNameType.Setter, _fragment.name,
                isSynthesized: true)
            .attachMember(_setter!);
      }
    }

    bool isExtensionMember = _fragment.builder.isExtensionMember;
    bool isExtensionTypeMember = _fragment.builder.isExtensionTypeMember;
    bool isInstanceMember = !isExtensionMember &&
        !isExtensionTypeMember &&
        !_fragment.builder.isStatic &&
        !_fragment.builder.isTopLevel;
    _getter!
      ..isConst = _fragment.modifiers.isConst
      ..isStatic = !isInstanceMember
      ..isExtensionMember = isExtensionMember
      ..isExtensionTypeMember = isExtensionTypeMember
      ..isAbstract = isAbstract && !isExternal
      ..isExternal = isExternal;

    _setter
      ?..isStatic = !isInstanceMember
      ..isExtensionMember = isExtensionMember
      ..isExtensionTypeMember = isExtensionTypeMember
      ..isAbstract = isAbstract && !isExternal
      ..isExternal = isExternal;

    _updateMemberTypes();
  }

  @override
  void registerMembers(BuildNodesCallback f) {
    BuiltMemberKind getterMemberKind;
    if (_fragment.builder.isExtensionMember) {
      getterMemberKind = BuiltMemberKind.ExtensionGetter;
    } else if (_fragment.builder.isExtensionTypeMember) {
      getterMemberKind = BuiltMemberKind.ExtensionTypeGetter;
    } else {
      getterMemberKind = BuiltMemberKind.Method;
    }
    f(member: _getter!, kind: getterMemberKind);
    if (_setter != null) {
      BuiltMemberKind setterMemberKind;
      if (_fragment.builder.isExtensionMember) {
        setterMemberKind = BuiltMemberKind.ExtensionSetter;
      } else if (_fragment.builder.isExtensionTypeMember) {
        setterMemberKind = BuiltMemberKind.ExtensionTypeSetter;
      } else {
        setterMemberKind = BuiltMemberKind.Method;
      }
      f(member: _setter!, kind: setterMemberKind);
    }
  }

  @override
  // Coverage-ignore(suite): Not run.
  void setCovariantByClass() {
    _setter!.function.positionalParameters.first.isCovariantByClass = true;
  }

  @override
  Field get field {
    throw new UnsupportedError("ExternalFieldEncoding.field");
  }

  @override
  // Coverage-ignore(suite): Not run.
  Member get builtMember => _getter!;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Annotatable> get annotatables {
    List<Annotatable> list = [_getter!];
    if (_setter != null) {
      list.add(_setter!);
    }
    return list;
  }

  @override
  Member get readTarget => _getter!;

  @override
  // Coverage-ignore(suite): Not run.
  Reference get readTargetReference => _getter!.reference;

  @override
  Member? get writeTarget => _setter;

  @override
  // Coverage-ignore(suite): Not run.
  Reference? get writeTargetReference => _setter?.reference;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Reference> get exportedReferenceMembers {
    if (_setter != null) {
      return [_getter!.reference, _setter!.reference];
    }
    return [_getter!.reference];
  }

  @override
  List<ClassMember> get localMembers => <ClassMember>[
        new _SynthesizedFieldClassMember(
            _fragment.builder,
            _getter!,
            _fragment.builder.memberName,
            _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
            ClassMemberKind.Getter,
            _fragment.uriOffset)
      ];

  @override
  List<ClassMember> get localSetters => _setter != null
      ? <ClassMember>[
          new _SynthesizedFieldClassMember(
              _fragment.builder,
              _setter!,
              _fragment.builder.memberName,
              _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
              ClassMemberKind.Setter,
              _fragment.uriOffset)
        ]
      : const <ClassMember>[];

  @override
  void buildImplicitDefaultValue() {
    throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
  }

  @override
  Initializer buildImplicitInitializer() {
    throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
  }

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    return new ShadowInvalidFieldInitializer(type, value, effect)
      ..fileOffset = fileOffset;
  }

  @override
  void registerSuperCall() {
    throw new UnsupportedError(
        "Unexpected call to ${runtimeType}.registerSuperCall().");
  }
}

/// The encoding of an extension type declaration representation field.
class RepresentationFieldEncoding implements FieldEncoding {
  final PrimaryConstructorFieldFragment _fragment;

  late Procedure _getter;
  DartType? _type;

  RepresentationFieldEncoding(this._fragment);
  @override
  DartType get type {
    assert(_type != null,
        "Type has not been computed for field ${_fragment.name}.");
    return _type!;
  }

  @override
  void set type(DartType value) {
    assert(
        _type == null ||
            // Coverage-ignore(suite): Not run.
            _type is InferredType,
        "Type has already been computed for field ${_fragment.name}.");
    _type = value;
    if (value is! InferredType) {
      _getter.function.returnType = value;
    }
  }

  @override
  // Coverage-ignore(suite): Not run.
  void createBodies(CoreTypes coreTypes, Expression? initializer) {
    // TODO(johnniwinther): Enable this assert.
    //assert(initializer != null);
  }

  @override
  List<Initializer> createInitializer(int fileOffset, Expression value,
      {required bool isSynthetic}) {
    return <Initializer>[
      new ExtensionTypeRepresentationFieldInitializer(_getter, value)
        ..fileOffset = fileOffset
    ];
  }

  @override
  void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
      NameScheme nameScheme, PropertyReferences references,
      {required bool isAbstractOrExternal,
      required List<TypeParameter>? classTypeParameters}) {
    _getter = new Procedure(
        dummyName, ProcedureKind.Getter, new FunctionNode(null),
        fileUri: _fragment.fileUri, reference: references.getterReference)
      ..stubKind = ProcedureStubKind.RepresentationField
      ..fileOffset = _fragment.nameOffset
      ..fileEndOffset = _fragment.nameOffset;
    nameScheme
        .getFieldMemberName(FieldNameType.RepresentationField, _fragment.name,
            isSynthesized: true)
        .attachMember(_getter);
    _getter..isConst = false;
    _getter
      ..isStatic = false
      ..isExtensionMember = false
      ..isExtensionTypeMember = true
      ..isAbstract = true
      ..isExternal = false;
  }

  @override
  void registerMembers(BuildNodesCallback f) {
    f(member: _getter, kind: BuiltMemberKind.ExtensionTypeRepresentationField);
  }

  @override
  void setCovariantByClass() {
    throw new UnsupportedError("$runtimeType.setGenericCovariantImpl");
  }

  @override
  Field get field {
    throw new UnsupportedError("$runtimeType.field");
  }

  @override
  // Coverage-ignore(suite): Not run.
  Member get builtMember => _getter;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Annotatable> get annotatables => [_getter];

  @override
  Member get readTarget => _getter;

  @override
  // Coverage-ignore(suite): Not run.
  Reference get readTargetReference => _getter.reference;

  @override
  // Coverage-ignore(suite): Not run.
  Member? get writeTarget => null;

  @override
  // Coverage-ignore(suite): Not run.
  Reference? get writeTargetReference => null;

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Reference> get exportedReferenceMembers => [_getter.reference];

  @override
  List<ClassMember> get localMembers => [
        new _SynthesizedFieldClassMember(
            _fragment.builder,
            _getter,
            _fragment.builder.memberName,
            _SynthesizedFieldMemberKind.RepresentationField,
            ClassMemberKind.Getter,
            _fragment.uriOffset)
      ];

  @override
  // Coverage-ignore(suite): Not run.
  List<ClassMember> get localSetters => const [];

  @override
  // Coverage-ignore(suite): Not run.
  void buildImplicitDefaultValue() {
    // Not needed.
  }

  @override
  Initializer buildImplicitInitializer() {
    return new ExtensionTypeRepresentationFieldInitializer(
        _getter, new NullLiteral());
  }

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    return new ShadowInvalidFieldInitializer(type, value, effect)
      ..fileOffset = fileOffset;
  }

  @override
  void registerSuperCall() {
    throw new UnsupportedError(
        "Unexpected call to ${runtimeType}.registerSuperCall().");
  }
}
