// Copyright (c) 2019, 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"
    show
        Arguments,
        Class,
        DartType,
        DynamicType,
        Expression,
        Field,
        FunctionNode,
        FunctionType,
        Member,
        Name,
        NamedExpression,
        NamedType,
        Nullability,
        Procedure,
        ProcedureKind,
        ReturnStatement,
        SuperMethodInvocation,
        SuperPropertyGet,
        SuperPropertySet,
        TypeParameter,
        TypeParameterType,
        VariableDeclaration,
        VariableGet,
        Variance,
        VoidType;

import 'package:kernel/transformations/flags.dart' show TransformerFlag;

import "package:kernel/type_algebra.dart" show Substitution;

import "package:kernel/src/legacy_erasure.dart";
import "package:kernel/src/nnbd_top_merge.dart";
import "package:kernel/src/norm.dart";

import "../source/source_class_builder.dart";

import "../problems.dart" show unhandled;

import "../type_inference/type_inference_engine.dart"
    show IncludesTypeParametersNonCovariantly;

import "../type_inference/type_inferrer.dart" show getNamedFormal;

import 'class_hierarchy_builder.dart';

class ForwardingNode {
  ClassHierarchyBuilder get hierarchy => _combinedMemberSignature.hierarchy;

  SourceClassBuilder get classBuilder => _combinedMemberSignature.classBuilder;

  // TODO(johnniwinther): Use [_combinedMemberSignature] more directly in
  // the forwarding node computation.
  final CombinedMemberSignature _combinedMemberSignature;

  ClassMember get combinedMemberSignatureResult =>
      _combinedMemberSignature.canonicalClassMember;

  /// The index of [combinedMemberSignatureResult] in [_candidates].
  int get _combinedMemberIndex => _combinedMemberSignature.classMemberIndex;

  final ProcedureKind kind;

  /// A list containing the directly implemented and directly inherited
  /// procedures of the class in question.
  List<ClassMember> get _candidates => _combinedMemberSignature.members;

  /// The indices of the [_candidates] whose types need to be merged to compute
  /// the resulting member type.
  Set<int> get _mergeIndices => _combinedMemberSignature.mutualSubtypeIndices;

  ForwardingNode(this._combinedMemberSignature, this.kind);

  Name get name => combinedMemberSignatureResult.name;

  Class get enclosingClass => classBuilder.cls;

  /// Finishes handling of this node by propagating covariance and creating
  /// forwarding stubs if necessary.
  Member finalize() => _computeCovarianceFixes();

  /// Creates a getter member signature for [interfaceMember] with the given
  /// [type].
  Member _createGetterMemberSignature(Member interfaceMember, DartType type) {
    Procedure referenceFrom;
    if (classBuilder.referencesFromIndexed != null) {
      referenceFrom = classBuilder.referencesFromIndexed
          .lookupProcedureNotSetter(name.text);
    }
    return new Procedure(name, kind, new FunctionNode(null, returnType: type),
        isAbstract: true,
        isMemberSignature: true,
        fileUri: enclosingClass.fileUri,
        memberSignatureOrigin: interfaceMember,
        reference: referenceFrom?.reference)
      ..startFileOffset = enclosingClass.fileOffset
      ..fileOffset = enclosingClass.fileOffset
      ..parent = enclosingClass;
  }

  /// Creates a setter member signature for [interfaceMember] with the given
  /// [type]. The flags of parameter is set according to [isCovariant] and
  /// [isGenericCovariantImpl] and the [parameterName] is used, if provided.
  Member _createSetterMemberSignature(Member interfaceMember, DartType type,
      {bool isCovariant, bool isGenericCovariantImpl, String parameterName}) {
    assert(isCovariant != null);
    assert(isGenericCovariantImpl != null);
    Procedure referenceFrom;
    if (classBuilder.referencesFromIndexed != null) {
      referenceFrom =
          classBuilder.referencesFromIndexed.lookupProcedureSetter(name.text);
    }
    return new Procedure(
        name,
        kind,
        new FunctionNode(null,
            returnType: const VoidType(),
            positionalParameters: [
              new VariableDeclaration(parameterName ?? '_',
                  type: type, isCovariant: isCovariant)
                ..isGenericCovariantImpl = isGenericCovariantImpl
            ]),
        isAbstract: true,
        isMemberSignature: true,
        fileUri: enclosingClass.fileUri,
        memberSignatureOrigin: interfaceMember,
        reference: referenceFrom?.reference)
      ..startFileOffset = enclosingClass.fileOffset
      ..fileOffset = enclosingClass.fileOffset
      ..parent = enclosingClass;
  }

  /// Creates a legacy member signature for the field [interfaceMember] if the
  /// type of [interfaceMember] contains non-legacy nullabilities.
  Member _createLegacyMemberSignatureForField(Field interfaceMember) {
    DartType type = interfaceMember.type;
    if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
      Substitution substitution =
          _substitutionFor(null, interfaceMember, enclosingClass);
      type = substitution.substituteType(type);
    }
    DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
    if (legacyType == null) {
      return interfaceMember;
    } else {
      // We base the decision to add a member signature on whether the legacy
      // erasure of the declared type is different from the declared type, i.e.
      // whether the declared type contained non-legacy nullabilities.
      //
      // This is slightly different from checking whether the legacy erasure of
      // the inherited type is different from the
      if (kind == ProcedureKind.Getter) {
        return _createGetterMemberSignature(interfaceMember, legacyType);
      } else {
        assert(kind == ProcedureKind.Setter);
        return _createSetterMemberSignature(interfaceMember, legacyType,
            isCovariant: interfaceMember.isCovariant,
            isGenericCovariantImpl: interfaceMember.isGenericCovariantImpl);
      }
    }
  }

  /// Creates a legacy member signature for procedure [interfaceMember] if the
  /// type of [interfaceMember] contains non-legacy nullabilities.
  Member _createLegacyMemberSignatureForProcedure(Procedure interfaceMember) {
    if (interfaceMember.kind == ProcedureKind.Getter) {
      DartType type = interfaceMember.getterType;
      if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
        Substitution substitution =
            _substitutionFor(null, interfaceMember, enclosingClass);
        type = substitution.substituteType(type);
      }
      DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
      if (legacyType == null) {
        return interfaceMember;
      } else {
        return _createGetterMemberSignature(interfaceMember, legacyType);
      }
    } else if (interfaceMember.kind == ProcedureKind.Setter) {
      DartType type = interfaceMember.setterType;
      if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
        Substitution substitution =
            _substitutionFor(null, interfaceMember, enclosingClass);
        type = substitution.substituteType(type);
      }
      DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
      if (legacyType == null) {
        return interfaceMember;
      } else {
        VariableDeclaration parameter =
            interfaceMember.function.positionalParameters.first;
        return _createSetterMemberSignature(interfaceMember, legacyType,
            isCovariant: parameter.isCovariant,
            isGenericCovariantImpl: parameter.isGenericCovariantImpl,
            parameterName: parameter.name);
      }
    } else {
      FunctionNode function = interfaceMember.function;
      FunctionType type = function.computeFunctionType(Nullability.legacy);
      if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
        Substitution substitution =
            _substitutionFor(null, interfaceMember, enclosingClass);
        type = substitution.substituteType(type);
      }
      FunctionType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
      if (legacyType == null) {
        return interfaceMember;
      }
      Procedure referenceFrom;
      if (classBuilder.referencesFromIndexed != null) {
        referenceFrom = classBuilder.referencesFromIndexed
            .lookupProcedureNotSetter(name.text);
      }
      List<VariableDeclaration> positionalParameters = [];
      for (int i = 0; i < function.positionalParameters.length; i++) {
        VariableDeclaration parameter = function.positionalParameters[i];
        DartType parameterType = legacyType.positionalParameters[i];
        if (i == 0 && interfaceMember == hierarchy.coreTypes.objectEquals) {
          // In legacy code we special case `Object.==` to infer `dynamic`
          // instead `Object!`.
          parameterType = const DynamicType();
        }
        positionalParameters.add(new VariableDeclaration(parameter.name,
            type: parameterType, isCovariant: parameter.isCovariant)
          ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
      }
      List<VariableDeclaration> namedParameters = [];
      int namedParameterCount = function.namedParameters.length;
      if (namedParameterCount == 1) {
        NamedType namedType = legacyType.namedParameters.first;
        VariableDeclaration parameter = function.namedParameters.first;
        namedParameters.add(new VariableDeclaration(parameter.name,
            type: namedType.type, isCovariant: parameter.isCovariant)
          ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
      } else if (namedParameterCount > 1) {
        Map<String, DartType> namedTypes = {};
        for (NamedType namedType in legacyType.namedParameters) {
          namedTypes[namedType.name] = namedType.type;
        }
        for (int i = 0; i < namedParameterCount; i++) {
          VariableDeclaration parameter = function.namedParameters[i];
          DartType parameterType = namedTypes[parameter.name];
          namedParameters.add(new VariableDeclaration(parameter.name,
              type: parameterType, isCovariant: parameter.isCovariant)
            ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
        }
      }
      return new Procedure(
          name,
          kind,
          new FunctionNode(null,
              typeParameters: legacyType.typeParameters,
              returnType: legacyType.returnType,
              positionalParameters: positionalParameters,
              namedParameters: namedParameters,
              requiredParameterCount: function.requiredParameterCount),
          isAbstract: true,
          isMemberSignature: true,
          fileUri: enclosingClass.fileUri,
          memberSignatureOrigin: interfaceMember,
          reference: referenceFrom?.reference)
        ..startFileOffset = enclosingClass.fileOffset
        ..fileOffset = enclosingClass.fileOffset
        ..parent = enclosingClass;
    }
  }

  /// Creates a legacy member signature for [interfaceMember] if the type of
  /// [interfaceMember] contains non-legacy nullabilities.
  Member _createLegacyMemberSignature(Member interfaceMember) {
    if (interfaceMember is Field) {
      return _createLegacyMemberSignatureForField(interfaceMember);
    } else {
      assert(interfaceMember is Procedure);
      return _createLegacyMemberSignatureForProcedure(interfaceMember);
    }
  }

  /// Tag the parameters of [interfaceMember] that need type checks
  ///
  /// Parameters can need type checks for calls coming from statically typed
  /// call sites, due to covariant generics and overrides with explicit
  /// `covariant` parameters.
  ///
  /// Tag parameters of [interfaceMember] that need such checks when the member
  /// occurs in [enclosingClass]'s interface.  If parameters need checks but
  /// they would not be checked in an inherited implementation, a forwarding
  /// stub is introduced as a place to put the checks.
  Member _computeCovarianceFixes() {
    Member interfaceMember = combinedMemberSignatureResult.getMember(hierarchy);
    if (_candidates.length == 1) {
      // Covariance can only come from [interfaceMember] so we never need a
      // forwarding stub.
      if (interfaceMember.isNonNullableByDefault &&
          !classBuilder.library.isNonNullableByDefault) {
        // Create a member signature with the legacy erasure type.
        return _createLegacyMemberSignature(interfaceMember);
      } else {
        // Nothing to do.
        return interfaceMember;
      }
    }

    List<TypeParameter> interfaceMemberTypeParameters =
        interfaceMember.function?.typeParameters ?? [];

    List<TypeParameter> stubTypeParameters;
    if (interfaceMember.enclosingClass != enclosingClass &&
        interfaceMemberTypeParameters.isNotEmpty) {
      // Create type parameters for the stub up front. These are needed to
      // ensure the [substitutions] are alpha renamed to the same type
      // parameters.
      stubTypeParameters = new List<TypeParameter>.filled(
          interfaceMemberTypeParameters.length, null);
      for (int i = 0; i < interfaceMemberTypeParameters.length; i++) {
        TypeParameter targetTypeParameter = interfaceMemberTypeParameters[i];
        TypeParameter typeParameter = new TypeParameter(
            targetTypeParameter.name, null)
          ..isGenericCovariantImpl = targetTypeParameter.isGenericCovariantImpl;
        stubTypeParameters[i] = typeParameter;
      }
    }

    List<Substitution> substitutions =
        new List<Substitution>(_candidates.length);
    Substitution substitution;
    for (int j = 0; j < _candidates.length; j++) {
      Member otherMember = getCandidateAt(j);
      substitutions[j] =
          _substitutionFor(stubTypeParameters, otherMember, enclosingClass);
      if (otherMember == interfaceMember) {
        substitution = substitutions[j];
      }
    }
    // We always create a forwarding stub when we've inherited a member from an
    // interface other than the first override candidate.  This is to work
    // around a bug in the Kernel type checker where it chooses the first
    // override candidate.
    //
    // TODO(kmillikin): Fix the Kernel type checker and stop creating these
    // extra stubs.
    Member stub = interfaceMember.enclosingClass == enclosingClass ||
            interfaceMember == getCandidateAt(0)
        ? interfaceMember
        : _createForwardingStub(
            stubTypeParameters, substitution, interfaceMember);

    FunctionNode interfaceFunction = interfaceMember.function;
    List<VariableDeclaration> interfacePositionalParameters =
        getPositionalParameters(interfaceMember);
    List<VariableDeclaration> interfaceNamedParameters =
        interfaceFunction?.namedParameters ?? [];
    List<TypeParameter> interfaceTypeParameters =
        interfaceFunction?.typeParameters ?? [];

    void createStubIfNeeded({bool forMemberSignature: false}) {
      if (stub != interfaceMember) {
        Procedure procedure = stub;
        if (forMemberSignature) {
          procedure.isMemberSignature = true;
          procedure.memberSignatureOrigin =
              interfaceMember.memberSignatureOrigin ?? interfaceMember;
        } else {
          procedure.isForwardingStub = true;
        }
        return;
      }
      if (interfaceMember.enclosingClass == enclosingClass) return;
      stub = _createForwardingStub(
          stubTypeParameters, substitution, interfaceMember,
          memberSignatureTarget: forMemberSignature
              ? interfaceMember.memberSignatureOrigin ?? interfaceMember
              : null);
    }

    bool isImplCreated = false;
    void createImplIfNeeded() {
      if (isImplCreated) return;
      createStubIfNeeded();
      _createForwardingImplIfNeeded(stub.function);
      isImplCreated = true;
    }

    IncludesTypeParametersNonCovariantly needsCheckVisitor =
        enclosingClass.typeParameters.isEmpty
            ? null
            // TODO(ahe): It may be necessary to cache this object.
            : new IncludesTypeParametersNonCovariantly(
                enclosingClass.typeParameters,
                // We are checking the parameter types and these are in a
                // contravariant position.
                initialVariance: Variance.contravariant);
    bool needsCheck(DartType type) => needsCheckVisitor == null
        ? false
        : substitution.substituteType(type).accept(needsCheckVisitor);
    bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;

    DartType initialType(int candidateIndex, DartType a) {
      if (isNonNullableByDefault) {
        if (_mergeIndices != null && _mergeIndices.contains(candidateIndex)) {
          return norm(hierarchy.coreTypes, a);
        } else {
          return a;
        }
      } else {
        return legacyErasure(hierarchy.coreTypes, a);
      }
    }

    DartType mergeTypes(int index, DartType a, DartType b) {
      if (a == null) return null;
      if (isNonNullableByDefault &&
          _mergeIndices != null &&
          _mergeIndices.contains(index)) {
        return nnbdTopMerge(
            hierarchy.coreTypes, a, norm(hierarchy.coreTypes, b));
      } else {
        return a;
      }
    }

    for (int parameterIndex = 0;
        parameterIndex < interfacePositionalParameters.length;
        parameterIndex++) {
      VariableDeclaration parameter =
          interfacePositionalParameters[parameterIndex];
      DartType parameterType = substitution.substituteType(parameter.type);
      DartType type = initialType(_combinedMemberIndex, parameterType);
      if (parameterIndex == 0 &&
          hierarchy
              .coreTypes.objectClass.enclosingLibrary.isNonNullableByDefault &&
          !classBuilder.library.isNonNullableByDefault &&
          interfaceMember == hierarchy.coreTypes.objectEquals) {
        // In legacy code we special case `Object.==` to infer `dynamic`
        // instead `Object!`.
        type = const DynamicType();
      }
      bool isGenericCovariantImpl =
          parameter.isGenericCovariantImpl || needsCheck(parameter.type);
      bool isCovariant = parameter.isCovariant;
      VariableDeclaration superParameter = parameter;
      for (int candidateIndex = 0;
          candidateIndex < _candidates.length;
          candidateIndex++) {
        Member otherMember = getCandidateAt(candidateIndex);
        List<VariableDeclaration> otherPositionalParameters =
            getPositionalParameters(otherMember);
        if (otherPositionalParameters.length <= parameterIndex) continue;
        VariableDeclaration otherParameter =
            otherPositionalParameters[parameterIndex];
        if (candidateIndex == 0) superParameter = otherParameter;
        if (identical(otherMember, interfaceMember)) continue;
        if (otherParameter.isGenericCovariantImpl) {
          isGenericCovariantImpl = true;
        }
        if (otherParameter.isCovariant) {
          isCovariant = true;
        }
        DartType candidateType =
            substitutions[candidateIndex].substituteType(otherParameter.type);
        if (parameterIndex == 0 &&
            hierarchy.coreTypes.objectClass.enclosingLibrary
                .isNonNullableByDefault &&
            !classBuilder.library.isNonNullableByDefault &&
            otherMember == hierarchy.coreTypes.objectEquals) {
          // In legacy code we special case `Object.==` to infer `dynamic`
          // instead `Object!`.
          candidateType = const DynamicType();
        }

        type = mergeTypes(candidateIndex, type, candidateType);
      }
      if (isGenericCovariantImpl) {
        if (!superParameter.isGenericCovariantImpl) {
          createImplIfNeeded();
        }
        if (!parameter.isGenericCovariantImpl) {
          createStubIfNeeded();
          stub.function.positionalParameters[parameterIndex]
              .isGenericCovariantImpl = true;
        }
      }
      if (isCovariant) {
        if (!superParameter.isCovariant) {
          createImplIfNeeded();
        }
        if (!parameter.isCovariant) {
          createStubIfNeeded();
          stub.function.positionalParameters[parameterIndex].isCovariant = true;
        }
      }
      if (type != null && type != parameterType) {
        // TODO(johnniwinther): Report an error when [type] is null; this
        // means that nnbd-top-merge was not defined.
        createStubIfNeeded(forMemberSignature: true);
        stub.function.positionalParameters[parameterIndex].type = type;
      }
    }
    for (int parameterIndex = 0;
        parameterIndex < interfaceNamedParameters.length;
        parameterIndex++) {
      VariableDeclaration parameter = interfaceNamedParameters[parameterIndex];
      DartType parameterType = substitution.substituteType(parameter.type);
      DartType type = initialType(_combinedMemberIndex, parameterType);
      bool isGenericCovariantImpl =
          parameter.isGenericCovariantImpl || needsCheck(parameter.type);
      bool isCovariant = parameter.isCovariant;
      VariableDeclaration superParameter = parameter;
      for (int candidateIndex = 0;
          candidateIndex < _candidates.length;
          candidateIndex++) {
        Member otherMember = getCandidateAt(candidateIndex);
        if (otherMember is ForwardingNode) continue;
        VariableDeclaration otherParameter =
            getNamedFormal(otherMember.function, parameter.name);
        if (otherParameter == null) continue;
        if (candidateIndex == 0) superParameter = otherParameter;
        if (identical(otherMember, interfaceMember)) continue;
        if (otherParameter.isGenericCovariantImpl) {
          isGenericCovariantImpl = true;
        }
        if (otherParameter.isCovariant) {
          isCovariant = true;
        }
        type = mergeTypes(candidateIndex, type,
            substitutions[candidateIndex].substituteType(otherParameter.type));
      }
      if (isGenericCovariantImpl) {
        if (!superParameter.isGenericCovariantImpl) {
          createImplIfNeeded();
        }
        if (!parameter.isGenericCovariantImpl) {
          createStubIfNeeded();
          stub.function.namedParameters[parameterIndex].isGenericCovariantImpl =
              true;
        }
      }
      if (isCovariant) {
        if (!superParameter.isCovariant) {
          createImplIfNeeded();
        }
        if (!parameter.isCovariant) {
          createStubIfNeeded();
          stub.function.namedParameters[parameterIndex].isCovariant = true;
        }
      }
      if (type != null && type != parameterType) {
        // TODO(johnniwinther): Report an error when [type] is null; this
        // means that nnbd-top-merge was not defined.
        createStubIfNeeded(forMemberSignature: true);
        stub.function.namedParameters[parameterIndex].type = type;
      }
    }
    for (int parameterIndex = 0;
        parameterIndex < interfaceTypeParameters.length;
        parameterIndex++) {
      TypeParameter typeParameter = interfaceTypeParameters[parameterIndex];
      DartType parameterBound =
          substitution.substituteType(typeParameter.bound);
      DartType bound = initialType(_combinedMemberIndex, parameterBound);
      DartType parameterDefaultType =
          substitution.substituteType(typeParameter.defaultType);
      DartType defaultType =
          initialType(_combinedMemberIndex, parameterDefaultType);
      bool isGenericCovariantImpl =
          typeParameter.isGenericCovariantImpl || needsCheck(parameterBound);
      TypeParameter superTypeParameter = typeParameter;
      for (int candidateIndex = 0;
          candidateIndex < _candidates.length;
          candidateIndex++) {
        Member otherMember = getCandidateAt(candidateIndex);
        if (otherMember is ForwardingNode) continue;
        List<TypeParameter> otherTypeParameters =
            otherMember.function.typeParameters;
        if (otherTypeParameters.length <= parameterIndex) continue;
        TypeParameter otherTypeParameter = otherTypeParameters[parameterIndex];
        if (candidateIndex == 0) superTypeParameter = otherTypeParameter;
        if (identical(otherMember, interfaceMember)) continue;
        if (otherTypeParameter.isGenericCovariantImpl) {
          isGenericCovariantImpl = true;
        }
      }
      if (isGenericCovariantImpl) {
        if (!superTypeParameter.isGenericCovariantImpl) {
          createImplIfNeeded();
        }
        if (!typeParameter.isGenericCovariantImpl) {
          createStubIfNeeded();
          stub.function.typeParameters[parameterIndex].isGenericCovariantImpl =
              true;
        }
      }
      if (bound != null && bound != parameterBound) {
        createStubIfNeeded(forMemberSignature: true);
        stub.function.typeParameters[parameterIndex].bound = bound;
      }
      if (defaultType != null && defaultType != parameterDefaultType) {
        createStubIfNeeded(forMemberSignature: true);
        stub.function.typeParameters[parameterIndex].defaultType = defaultType;
      }
    }
    DartType returnType =
        substitution.substituteType(getReturnType(interfaceMember));
    DartType type = initialType(_combinedMemberIndex, returnType);
    for (int candidateIndex = 0;
        candidateIndex < _candidates.length;
        candidateIndex++) {
      Member otherMember = getCandidateAt(candidateIndex);
      type = mergeTypes(
          candidateIndex,
          type,
          substitutions[candidateIndex]
              .substituteType(getReturnType(otherMember)));
    }
    if (type != null && type != returnType) {
      // TODO(johnniwinther): Report an error when [type] is null; this
      // means that nnbd-top-merge was not defined.
      createStubIfNeeded(forMemberSignature: true);
      stub.function.returnType = type;
    }
    assert(
        !(stub is Procedure &&
            (stub as Procedure).isMemberSignature &&
            stub.memberSignatureOrigin == null),
        "No member signature origin for member signature $stub.");
    if (stub != interfaceMember && stub is Procedure) {
      Procedure procedure = stub;
      if (procedure.isForwardingStub || procedure.isForwardingSemiStub) {
        procedure.isMemberSignature = false;
        procedure.memberSignatureOrigin = null;
      } else {
        procedure.forwardingStubInterfaceTarget = null;
        procedure.forwardingStubSuperTarget = null;
      }
      assert(
          !(procedure.isMemberSignature && procedure.isForwardingStub),
          "Procedure is both member signature and forwarding stub: "
          "$procedure.");
      assert(
          !(procedure.isMemberSignature && procedure.isForwardingSemiStub),
          "Procedure is both member signature and forwarding semi stub: "
          "$procedure.");
      assert(
          !(procedure.forwardingStubInterfaceTarget is Procedure &&
              (procedure.forwardingStubInterfaceTarget as Procedure)
                  .isMemberSignature),
          "Forwarding stub interface target is member signature: $procedure.");
      assert(
          !(procedure.forwardingStubSuperTarget is Procedure &&
              (procedure.forwardingStubSuperTarget as Procedure)
                  .isMemberSignature),
          "Forwarding stub super target is member signature: $procedure.");
    }
    return stub;
  }

  void _createForwardingImplIfNeeded(FunctionNode function) {
    if (function.body != null) {
      // There is already an implementation; nothing further needs to be done.
      return;
    }
    // Find the concrete implementation in the superclass; this is what we need
    // to forward to.  If we can't find one, then the method is fully abstract
    // and we don't need to do anything.
    Class superclass = enclosingClass.superclass;
    if (superclass == null) return;
    Procedure procedure = function.parent;
    Member superTarget = hierarchy.getDispatchTargetKernel(
        superclass, procedure.name, kind == ProcedureKind.Setter);
    if (superTarget == null) return;
    if (superTarget is Procedure && superTarget.isForwardingStub) {
      Procedure superProcedure = superTarget;
      superTarget = superProcedure.forwardingStubSuperTarget;
    } else {
      superTarget = superTarget.memberSignatureOrigin ?? superTarget;
    }
    procedure.isAbstract = false;
    if (!procedure.isForwardingStub) {
      // This procedure exists abstractly in the source code; we need to make it
      // concrete and give it a body that is a forwarding stub.  This situation
      // is called a "forwarding semi-stub".
      procedure.isForwardingStub = true;
      procedure.isForwardingSemiStub = true;
    }
    List<Expression> positionalArguments = function.positionalParameters
        .map<Expression>((parameter) => new VariableGet(parameter))
        .toList();
    List<NamedExpression> namedArguments = function.namedParameters
        .map((parameter) =>
            new NamedExpression(parameter.name, new VariableGet(parameter)))
        .toList();
    List<DartType> typeArguments = function.typeParameters
        .map<DartType>((typeParameter) =>
            new TypeParameterType.withDefaultNullabilityForLibrary(
                typeParameter, enclosingClass.enclosingLibrary))
        .toList();
    Arguments arguments = new Arguments(positionalArguments,
        types: typeArguments, named: namedArguments);
    Expression superCall;
    switch (kind) {
      case ProcedureKind.Method:
      case ProcedureKind.Operator:
        superCall = new SuperMethodInvocation(name, arguments, superTarget);
        break;
      case ProcedureKind.Getter:
        superCall = new SuperPropertyGet(name, superTarget);
        break;
      case ProcedureKind.Setter:
        superCall =
            new SuperPropertySet(name, positionalArguments[0], superTarget);
        break;
      default:
        unhandled('$kind', '_createForwardingImplIfNeeded', -1, null);
        break;
    }
    function.body = new ReturnStatement(superCall)..parent = function;
    procedure.transformerFlags |= TransformerFlag.superCalls;
    procedure.forwardingStubSuperTarget = superTarget;
  }

  /// Creates a forwarding stub based on the given [target].
  Procedure _createForwardingStub(List<TypeParameter> typeParameters,
      Substitution substitution, Member target,
      {Member memberSignatureTarget}) {
    VariableDeclaration copyParameter(VariableDeclaration parameter) {
      return new VariableDeclaration(parameter.name,
          type: substitution.substituteType(parameter.type),
          isCovariant: parameter.isCovariant)
        ..isGenericCovariantImpl = parameter.isGenericCovariantImpl;
    }

    List<TypeParameter> targetTypeParameters =
        target.function?.typeParameters ?? [];
    if (typeParameters != null) {
      Map<TypeParameter, DartType> additionalSubstitution =
          <TypeParameter, DartType>{};
      for (int i = 0; i < targetTypeParameters.length; i++) {
        TypeParameter targetTypeParameter = targetTypeParameters[i];
        additionalSubstitution[targetTypeParameter] =
            new TypeParameterType.forAlphaRenaming(
                targetTypeParameter, typeParameters[i]);
      }
      substitution = Substitution.combine(
          substitution, Substitution.fromMap(additionalSubstitution));
      for (int i = 0; i < typeParameters.length; i++) {
        typeParameters[i].bound =
            substitution.substituteType(targetTypeParameters[i].bound);
        typeParameters[i].defaultType =
            substitution.substituteType(targetTypeParameters[i].defaultType);
      }
    }
    List<VariableDeclaration> positionalParameters =
        getPositionalParameters(target).map(copyParameter).toList();
    List<VariableDeclaration> namedParameters =
        target.function?.namedParameters?.map(copyParameter)?.toList() ?? [];
    FunctionNode function = new FunctionNode(null,
        positionalParameters: positionalParameters,
        namedParameters: namedParameters,
        typeParameters: typeParameters,
        requiredParameterCount: getRequiredParameterCount(target),
        returnType: substitution.substituteType(getReturnType(target)));
    Member finalTarget;
    if (target is Procedure && target.isForwardingStub) {
      finalTarget = target.forwardingStubInterfaceTarget;
    } else {
      finalTarget = target.memberSignatureOrigin ?? target;
    }
    Procedure referenceFrom;
    if (classBuilder.referencesFromIndexed != null) {
      if (kind == ProcedureKind.Setter) {
        referenceFrom =
            classBuilder.referencesFromIndexed.lookupProcedureSetter(name.text);
      } else {
        referenceFrom = classBuilder.referencesFromIndexed
            .lookupProcedureNotSetter(name.text);
      }
    }
    return new Procedure(name, kind, function,
        isAbstract: true,
        isForwardingStub: memberSignatureTarget == null,
        isMemberSignature: memberSignatureTarget != null,
        fileUri: enclosingClass.fileUri,
        forwardingStubInterfaceTarget: finalTarget,
        reference: referenceFrom?.reference,
        memberSignatureOrigin: memberSignatureTarget)
      ..startFileOffset = enclosingClass.fileOffset
      ..fileOffset = enclosingClass.fileOffset
      ..parent = enclosingClass
      ..isNonNullableByDefault =
          enclosingClass.enclosingLibrary.isNonNullableByDefault;
  }

  /// Returns the [i]th element of [_candidates], finalizing it if necessary.
  Member getCandidateAt(int i) {
    ClassMember candidate = _candidates[i];
    return candidate.getMember(hierarchy);
  }

  Substitution _substitutionFor(
      List<TypeParameter> stubTypeParameters, Member candidate, Class class_) {
    Substitution substitution = Substitution.fromInterfaceType(
        hierarchy.getTypeAsInstanceOf(
            hierarchy.coreTypes
                .thisInterfaceType(class_, class_.enclosingLibrary.nonNullable),
            candidate.enclosingClass,
            class_.enclosingLibrary,
            hierarchy.coreTypes));
    if (stubTypeParameters != null) {
      // If the stub is generic ensure that type parameters are alpha renamed
      // to the [stubTypeParameters].
      Map<TypeParameter, TypeParameterType> map = {};
      for (int i = 0; i < stubTypeParameters.length; i++) {
        TypeParameter typeParameter = candidate.function.typeParameters[i];
        map[typeParameter] = new TypeParameterType.forAlphaRenaming(
            typeParameter, stubTypeParameters[i]);
      }
      substitution =
          Substitution.combine(substitution, Substitution.fromMap(map));
    }
    return substitution;
  }

  List<VariableDeclaration> getPositionalParameters(Member member) {
    if (member is Field) {
      if (kind == ProcedureKind.Setter) {
        return <VariableDeclaration>[
          new VariableDeclaration("_",
              type: member.type, isCovariant: member.isCovariant)
            ..isGenericCovariantImpl = member.isGenericCovariantImpl
        ];
      } else {
        return <VariableDeclaration>[];
      }
    } else {
      return member.function.positionalParameters;
    }
  }

  int getRequiredParameterCount(Member member) {
    switch (kind) {
      case ProcedureKind.Getter:
        return 0;
      case ProcedureKind.Setter:
        return 1;
      default:
        return member.function.requiredParameterCount;
    }
  }

  DartType getReturnType(Member member) {
    switch (kind) {
      case ProcedureKind.Getter:
        return member is Field ? member.type : member.function.returnType;
      case ProcedureKind.Setter:
        return const VoidType();
      default:
        return member.function.returnType;
    }
  }
}
