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

library fasta.class_hierarchy_builder;

import 'package:kernel/ast.dart' hide MapEntry;

import 'package:kernel/class_hierarchy.dart' show ClassHierarchyBase;

import 'package:kernel/core_types.dart' show CoreTypes;

import 'package:kernel/type_algebra.dart' show Substitution;
import 'package:kernel/type_environment.dart';

import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/src/nnbd_top_merge.dart';
import 'package:kernel/src/norm.dart';
import 'package:kernel/src/types.dart' show Types;

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

import '../source/source_class_builder.dart';

import 'class_hierarchy_builder.dart';

/// Class used for computing and inspecting the combined member signature for
/// a set of overridden/inherited members.
abstract class CombinedMemberSignatureBase<T> {
  ClassHierarchyBase get hierarchy;

  /// The target class for the combined member signature.
  ///
  /// The [_memberTypes] are computed in terms of each member is inherited into
  /// [classBuilder].
  ///
  /// [classBuilder] is also used for determining whether the combined member
  /// signature should be computed using nnbd or legacy semantics.
  final SourceClassBuilder classBuilder;

  /// The list of members from which the combined member signature is computed.
  List<T> get members;

  /// If `true` the combined member signature is for the setter aspect of the
  /// members. Otherwise it is for the getter/method aspect of the members.
  final bool forSetter;

  /// The index within [members] for the member whose type is the most specific
  /// among [members]. If `null`, the combined member signature is not defined
  /// for [members] in [classBuilder].
  ///
  /// For the legacy computation, the type of this member defines the combined
  /// member signature.
  ///
  /// For the nnbd computation, this is one of the members whose type define
  /// the combined member signature, and the indices of the remaining members
  /// are stored in [_mutualSubtypes].
  int _canonicalMemberIndex;

  /// For the nnbd computation, this maps each distinct but most specific member
  /// type to the index of one of the [members] with that type.
  ///
  /// If there is only one most specific member type, this is `null`.
  Map<DartType, int> _mutualSubtypes;

  /// Cache for the types of [members] as inherited into [classBuilder].
  List<DartType> _memberTypes;

  /// Cache for the this type of [classBuilder].
  DartType _thisType;

  /// If `true` the combined member signature type has been computed.
  ///
  /// Note that the combined member signature type might be undefined in which
  /// case [_combinedMemberSignatureType] is `null`.
  bool _isCombinedMemberSignatureTypeComputed = false;

  /// Cache the computed combined member signature type.
  ///
  /// If the combined member signature type is undefined this is set to `null`.
  DartType _combinedMemberSignatureType;

  /// Accumulated result for [neededLegacyErasure]. This is fully computed when
  /// [combinedMemberSignatureType] has been computed.
  bool _neededLegacyErasure = false;

  /// Creates a [CombinedClassMemberSignature] whose canonical member is already
  /// defined.
  CombinedMemberSignatureBase.internal(
      this.classBuilder, this._canonicalMemberIndex, this.forSetter)
      : assert(forSetter != null);

  /// Creates a [CombinedClassMemberSignature] for [members] inherited into
  /// [classBuilder].
  ///
  /// If [forSetter] is `true`, contravariance of the setter types is used to
  /// compute the most specific member type. Otherwise covariance of the getter
  /// types or function types is used.
  CombinedMemberSignatureBase(this.classBuilder, {this.forSetter}) {
    assert(forSetter != null);
    int bestSoFarIndex;
    if (members.length == 1) {
      bestSoFarIndex = 0;
    } else {
      bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;

      DartType bestTypeSoFar;
      for (int candidateIndex = members.length - 1;
          candidateIndex >= 0;
          candidateIndex--) {
        DartType candidateType = getMemberType(candidateIndex);
        if (bestSoFarIndex == null) {
          bestTypeSoFar = candidateType;
          bestSoFarIndex = candidateIndex;
        } else {
          if (_isMoreSpecific(candidateType, bestTypeSoFar, forSetter)) {
            if (isNonNullableByDefault &&
                _isMoreSpecific(bestTypeSoFar, candidateType, forSetter)) {
              if (_mutualSubtypes == null) {
                _mutualSubtypes = {
                  bestTypeSoFar: bestSoFarIndex,
                  candidateType: candidateIndex
                };
              } else {
                _mutualSubtypes[candidateType] = candidateIndex;
              }
            } else {
              _mutualSubtypes = null;
            }
            bestSoFarIndex = candidateIndex;
            bestTypeSoFar = candidateType;
          }
        }
      }
      if (bestSoFarIndex != null) {
        for (int candidateIndex = 0;
            candidateIndex < members.length;
            candidateIndex++) {
          DartType candidateType = getMemberType(candidateIndex);
          if (!_isMoreSpecific(bestTypeSoFar, candidateType, forSetter)) {
            if (!shouldOverrideProblemBeOverlooked(classBuilder)) {
              bestSoFarIndex = null;
              bestTypeSoFar = null;
              _mutualSubtypes = null;
            }
            break;
          }
        }
      }
    }

    _canonicalMemberIndex = bestSoFarIndex;
  }

  /// The member within [members] type is the most specific among [members].
  /// If `null`, the combined member signature is not defined for [members] in
  /// [classBuilder].
  ///
  /// For the legacy computation, the type of this member defines the combined
  /// member signature.
  ///
  /// For the nnbd computation, this is one of the members whose type define
  /// the combined member signature, and the indices of the all members whose
  /// type define the combined member signature are in [mutualSubtypeIndices].
  T get canonicalMember =>
      _canonicalMemberIndex != null ? members[_canonicalMemberIndex] : null;

  /// The index within [members] for the member whose type is the most specific
  /// among [members]. If `null`, the combined member signature is not defined
  /// for [members] in [classBuilder].
  ///
  /// For the legacy computation, the type of this member defines the combined
  /// member signature.
  ///
  /// For the nnbd computation, this is one of the members whose type define
  /// the combined member signature, and the indices of the all members whose
  /// type define the combined member signature are in [mutualSubtypeIndices].
  int get canonicalMemberIndex => _canonicalMemberIndex;

  /// For the nnbd computation, the indices of the [members] with most specific
  /// member type.
  ///
  /// If there is only one most specific member type, this is `null`.
  Set<int> get mutualSubtypeIndices => _mutualSubtypes?.values?.toSet();

  Member _getMember(int index);

  CoreTypes get _coreTypes => hierarchy.coreTypes;

  Types get _types;

  /// Returns `true` if legacy erasure was needed to compute the combined
  /// member signature type.
  ///
  /// Legacy erasure is considered need of if the used of it resulted in a
  /// different type.
  bool get neededLegacyErasure {
    _ensureCombinedMemberSignatureType();
    return _neededLegacyErasure;
  }

  /// The this type of [classBuilder].
  DartType get thisType {
    return _thisType ??= _coreTypes.thisInterfaceType(
        classBuilder.cls, classBuilder.library.nonNullable);
  }

  /// Returns type of the [index]th member in [members] as inherited in
  /// [classBuilder].
  DartType getMemberType(int index) {
    _memberTypes ??= new List<DartType>(members.length);
    DartType candidateType = _memberTypes[index];
    if (candidateType == null) {
      Member target = _getMember(index);
      assert(target != null,
          "No member computed for index ${index} in ${members}");
      candidateType = _computeMemberType(thisType, target);
      if (!classBuilder.library.isNonNullableByDefault) {
        DartType legacyErasure = rawLegacyErasure(_coreTypes, candidateType);
        if (legacyErasure != null) {
          _neededLegacyErasure = true;
          candidateType = legacyErasure;
        }
      }
      _memberTypes[index] = candidateType;
    }
    return candidateType;
  }

  void _ensureCombinedMemberSignatureType() {
    if (!_isCombinedMemberSignatureTypeComputed) {
      _isCombinedMemberSignatureTypeComputed = true;
      if (_canonicalMemberIndex == null) {
        return null;
      }
      if (classBuilder.library.isNonNullableByDefault) {
        _combinedMemberSignatureType = getMemberType(_canonicalMemberIndex);
        if (_mutualSubtypes != null) {
          _combinedMemberSignatureType =
              norm(_coreTypes, _combinedMemberSignatureType);
          for (int index in _mutualSubtypes.values) {
            if (_canonicalMemberIndex != index) {
              _combinedMemberSignatureType = nnbdTopMerge(
                  _coreTypes,
                  _combinedMemberSignatureType,
                  norm(_coreTypes, getMemberType(index)));
            }
          }
        }
      } else {
        _combinedMemberSignatureType = getMemberType(_canonicalMemberIndex);
      }
    }
  }

  /// Returns the type of the combined member signature, if defined.
  DartType get combinedMemberSignatureType {
    _ensureCombinedMemberSignatureType();
    return _combinedMemberSignatureType;
  }

  /// Returns the type of the combined member signature, if defined, with
  /// all method type parameters substituted with [typeParameters].
  ///
  /// This is used for inferring types on a declared member from the type of the
  /// combined member signature.
  DartType getCombinedSignatureTypeInContext(
      List<TypeParameter> typeParameters) {
    DartType type = combinedMemberSignatureType;
    if (type == null) {
      return null;
    }
    int typeParameterCount = typeParameters.length;
    if (type is FunctionType) {
      List<TypeParameter> signatureTypeParameters = type.typeParameters;
      if (typeParameterCount != signatureTypeParameters.length) {
        return null;
      }
      if (typeParameterCount == 0) {
        return type;
      }
      List<DartType> types = new List<DartType>(typeParameterCount);
      for (int i = 0; i < typeParameterCount; i++) {
        types[i] = new TypeParameterType.forAlphaRenaming(
            signatureTypeParameters[i], typeParameters[i]);
      }
      Substitution substitution =
          Substitution.fromPairs(signatureTypeParameters, types);
      for (int i = 0; i < typeParameterCount; i++) {
        DartType typeParameterBound = typeParameters[i].bound;
        DartType signatureTypeParameterBound =
            substitution.substituteType(signatureTypeParameters[i].bound);
        if (!_types
            .performNullabilityAwareMutualSubtypesCheck(
                typeParameterBound, signatureTypeParameterBound)
            .isSubtypeWhenUsingNullabilities()) {
          return null;
        }
      }
      return substitution.substituteType(type.withoutTypeParameters);
    } else if (typeParameterCount != 0) {
      return null;
    }
    return type;
  }

  /// Create a member signature with the [combinedMemberSignatureType] using the
  /// [canonicalMember] as member signature origin.
  Procedure createMemberFromSignature() {
    if (canonicalMemberIndex == null) {
      return null;
    }
    Member member = _getMember(canonicalMemberIndex);
    if (member is Procedure) {
      switch (member.kind) {
        case ProcedureKind.Getter:
          return _createGetterMemberSignature(
              member, combinedMemberSignatureType);
        case ProcedureKind.Setter:
          VariableDeclaration parameter =
              member.function.positionalParameters.first;
          return _createSetterMemberSignature(
              member, combinedMemberSignatureType,
              isGenericCovariantImpl: parameter.isGenericCovariantImpl,
              isCovariant: parameter.isCovariant,
              parameterName: parameter.name);
        case ProcedureKind.Method:
        case ProcedureKind.Operator:
          return _createMethodSignature(member, combinedMemberSignatureType);
        case ProcedureKind.Factory:
        default:
          throw new UnsupportedError(
              'Unexpected canonical member kind ${member.kind} for $member');
      }
    } else if (member is Field) {
      if (forSetter) {
        return _createSetterMemberSignature(member, combinedMemberSignatureType,
            isGenericCovariantImpl: member.isGenericCovariantImpl,
            isCovariant: member.isCovariant);
      } else {
        return _createGetterMemberSignature(
            member, combinedMemberSignatureType);
      }
    } else {
      throw new UnsupportedError(
          'Unexpected canonical member $member (${member.runtimeType})');
    }
  }

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

  /// Creates a setter member signature for [member] 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 member, DartType type,
      {bool isCovariant, bool isGenericCovariantImpl, String parameterName}) {
    assert(isCovariant != null);
    assert(isGenericCovariantImpl != null);
    Class enclosingClass = classBuilder.cls;
    Procedure referenceFrom;
    if (classBuilder.referencesFromIndexed != null) {
      referenceFrom = classBuilder.referencesFromIndexed
          .lookupProcedureSetter(member.name.text);
    }
    Uri fileUri = member.fileUri;
    int startFileOffset =
        member is Procedure ? member.startFileOffset : member.fileOffset;
    int fileOffset = member.fileOffset;
    return new Procedure(
        member.name,
        ProcedureKind.Setter,
        new FunctionNode(null,
            returnType: const VoidType(),
            positionalParameters: [
              new VariableDeclaration(parameterName ?? 'value',
                  type: type, isCovariant: isCovariant)
                ..isGenericCovariantImpl = isGenericCovariantImpl
            ]),
        isAbstract: true,
        isMemberSignature: true,
        fileUri: fileUri,
        memberSignatureOrigin: member.memberSignatureOrigin ?? member,
        reference: referenceFrom?.reference)
      ..startFileOffset = startFileOffset
      ..fileOffset = fileOffset
      ..parent = enclosingClass;
  }

  Member _createMethodSignature(
      Procedure procedure, FunctionType functionType) {
    Class enclosingClass = classBuilder.cls;
    Procedure referenceFrom;
    if (classBuilder.referencesFromIndexed != null) {
      referenceFrom = classBuilder.referencesFromIndexed
          .lookupProcedureNotSetter(procedure.name.text);
    }
    Uri fileUri = procedure.fileUri;
    int startFileOffset = procedure.startFileOffset;
    int fileOffset = procedure.fileOffset;
    FunctionNode function = procedure.function;
    List<VariableDeclaration> positionalParameters = [];
    for (int i = 0; i < function.positionalParameters.length; i++) {
      VariableDeclaration parameter = function.positionalParameters[i];
      DartType parameterType = functionType.positionalParameters[i];
      if (i == 0 && procedure == 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 = functionType.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 functionType.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(
        procedure.name,
        procedure.kind,
        new FunctionNode(null,
            typeParameters: functionType.typeParameters,
            returnType: functionType.returnType,
            positionalParameters: positionalParameters,
            namedParameters: namedParameters,
            requiredParameterCount: function.requiredParameterCount),
        isAbstract: true,
        isMemberSignature: true,
        fileUri: fileUri,
        memberSignatureOrigin: procedure.memberSignatureOrigin ?? procedure,
        reference: referenceFrom?.reference)
      ..startFileOffset = startFileOffset
      ..fileOffset = fileOffset
      ..parent = enclosingClass;
  }

  DartType _computeMemberType(DartType thisType, Member member) {
    DartType type;
    if (member is Procedure) {
      if (member.isGetter) {
        type = member.getterType;
      } else if (member.isSetter) {
        type = member.setterType;
      } else {
        type = member.function
            .computeFunctionType(classBuilder.cls.enclosingLibrary.nonNullable);
      }
    } else if (member is Field) {
      type = member.type;
    } else {
      unhandled("${member.runtimeType}", "$member", classBuilder.charOffset,
          classBuilder.fileUri);
    }
    if (member.enclosingClass.typeParameters.isEmpty) {
      return type;
    }
    InterfaceType instance = hierarchy.getTypeAsInstanceOf(
        thisType,
        member.enclosingClass,
        classBuilder.library.library,
        hierarchy.coreTypes);
    assert(
        instance != null,
        "No instance of $thisType as ${member.enclosingClass} found for "
        "$member.");
    return Substitution.fromInterfaceType(instance).substituteType(type);
  }

  bool _isMoreSpecific(DartType a, DartType b, bool forSetter) {
    if (forSetter) {
      return _types.isSubtypeOf(b, a, SubtypeCheckMode.withNullabilities);
    } else {
      return _types.isSubtypeOf(a, b, SubtypeCheckMode.withNullabilities);
    }
  }
}

/// Class used for computing and inspecting the combined member signature for
/// a set of overridden/inherited [ClassMember]s.
class CombinedClassMemberSignature
    extends CombinedMemberSignatureBase<ClassMember> {
  /// The class hierarchy builder used for building this class.
  final ClassHierarchyBuilder hierarchy;

  /// The list of the members inherited into or overridden in [classBuilder].
  final List<ClassMember> members;

  /// Creates a [CombinedClassMemberSignature] whose canonical member is already
  /// defined.
  CombinedClassMemberSignature.internal(this.hierarchy,
      SourceClassBuilder classBuilder, int canonicalMemberIndex, this.members,
      {bool forSetter})
      : super.internal(classBuilder, canonicalMemberIndex, forSetter);

  /// Creates a [CombinedClassMemberSignature] for [members] inherited into
  /// [classBuilder].
  ///
  /// If [forSetter] is `true`, contravariance of the setter types is used to
  /// compute the most specific member type. Otherwise covariance of the getter
  /// types or function types is used.
  CombinedClassMemberSignature(
      this.hierarchy, SourceClassBuilder classBuilder, this.members,
      {bool forSetter})
      : super(classBuilder, forSetter: forSetter);

  Types get _types => hierarchy.types;

  Member _getMember(int index) {
    ClassMember candidate = members[index];
    Member target = candidate.getMember(hierarchy);
    assert(target != null,
        "No member computed for ${candidate} (${candidate.runtimeType})");
    return target;
  }
}

/// Class used for computing and inspecting the combined member signature for
/// a set of overridden/inherited [Member]s.
class CombinedMemberSignatureBuilder
    extends CombinedMemberSignatureBase<Member> {
  @override
  final ClassHierarchyBase hierarchy;

  @override
  final Types _types;

  @override
  final List<Member> members;

  CombinedMemberSignatureBuilder(
      this.hierarchy, SourceClassBuilder classBuilder, this.members,
      {bool forSetter})
      : _types = new Types(hierarchy),
        super(classBuilder, forSetter: forSetter);

  @override
  Member _getMember(int index) => members[index];
}
