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

// @dart = 2.9

library kernel.transformations.mixin_full_resolution;

import '../ast.dart';
import '../class_hierarchy.dart';
import '../clone.dart';
import '../core_types.dart';
import '../reference_from_index.dart';
import '../target/targets.dart' show Target;
import '../type_algebra.dart';

/// Transforms the libraries in [libraries].
/// Note that [referenceFromIndex] can be null, and is generally only needed
/// when (ultimately) called from the incremental compiler.
void transformLibraries(
    Target targetInfo,
    CoreTypes coreTypes,
    ClassHierarchy hierarchy,
    List<Library> libraries,
    ReferenceFromIndex referenceFromIndex) {
  new MixinFullResolution(targetInfo, coreTypes, hierarchy)
      .transform(libraries, referenceFromIndex);
}

/// Replaces all mixin applications with regular classes, cloning all fields
/// and procedures from the mixed-in class, cloning all constructors from the
/// base class.
class MixinFullResolution {
  final Target targetInfo;
  final CoreTypes coreTypes;

  /// The [ClassHierarchy] that should be used after applying this transformer.
  /// If any class was updated, in general we need to create a new
  /// [ClassHierarchy] instance, with new dispatch targets; or at least let
  /// the existing instance know that some of its dispatch tables are not
  /// valid anymore.
  ClassHierarchy hierarchy;

  MixinFullResolution(this.targetInfo, this.coreTypes, this.hierarchy);

  /// Transform the given new [libraries].  It is expected that all other
  /// libraries have already been transformed.
  void transform(
      List<Library> libraries, ReferenceFromIndex referenceFromIndex) {
    if (libraries.isEmpty) return;

    var transformedClasses = new Set<Class>();

    // Desugar all mixin application classes by copying in fields/methods from
    // the mixin and constructors from the base class.
    var processedClasses = new Set<Class>();
    for (var library in libraries) {
      for (var class_ in library.classes) {
        transformClass(libraries, processedClasses, transformedClasses, class_,
            referenceFromIndex);
      }
    }

    // We might need to update the class hierarchy.
    hierarchy =
        hierarchy.applyMemberChanges(transformedClasses, findDescendants: true);
  }

  transformClass(
      List<Library> librariesToBeTransformed,
      Set<Class> processedClasses,
      Set<Class> transformedClasses,
      Class class_,
      ReferenceFromIndex referenceFromIndex) {
    // If this class was already handled then so were all classes up to the
    // [Object] class.
    if (!processedClasses.add(class_)) return;

    Library enclosingLibrary = class_.enclosingLibrary;

    if (!librariesToBeTransformed.contains(enclosingLibrary) &&
        enclosingLibrary.importUri?.scheme == "dart") {
      // If we're not asked to transform the platform libraries then we expect
      // that they will be already transformed.
      return;
    }

    // Ensure super classes have been transformed before this class.
    if (class_.superclass != null) {
      transformClass(librariesToBeTransformed, processedClasses,
          transformedClasses, class_.superclass, referenceFromIndex);
    }

    // If this is not a mixin application we don't need to make forwarding
    // constructors in this class.
    if (!class_.isMixinApplication) return;
    assert(librariesToBeTransformed.contains(enclosingLibrary));

    transformedClasses.add(class_);

    // Clone fields and methods from the mixin class.
    var substitution = getSubstitutionMap(class_.mixedInType);
    var cloner = new CloneVisitorWithMembers(typeSubstitution: substitution);

    IndexedLibrary indexedLibrary =
        referenceFromIndex?.lookupLibrary(enclosingLibrary);
    IndexedClass indexedClass = indexedLibrary?.lookupIndexedClass(class_.name);

    if (class_.mixin.fields.isNotEmpty) {
      // When we copy a field from the mixed in class, we remove any
      // forwarding-stub getters/setters from the superclass, but copy their
      // covariance-bits onto the new field.
      var nonSetters = <Name, Procedure>{};
      var setters = <Name, Procedure>{};
      for (var procedure in class_.procedures) {
        if (procedure.isSetter) {
          setters[procedure.name] = procedure;
        } else {
          nonSetters[procedure.name] = procedure;
        }
      }

      for (var field in class_.mixin.fields) {
        Reference getterReference =
            indexedClass?.lookupGetterReference(field.name);
        Reference setterReference =
            indexedClass?.lookupSetterReference(field.name);
        if (getterReference == null) {
          getterReference = nonSetters[field.name]?.reference;
          getterReference?.canonicalName?.unbind();
        }
        if (setterReference == null) {
          setterReference = setters[field.name]?.reference;
          setterReference?.canonicalName?.unbind();
        }
        Field clone =
            cloner.cloneField(field, getterReference, setterReference);
        Procedure setter = setters[field.name];
        if (setter != null) {
          setters.remove(field.name);
          VariableDeclaration parameter =
              setter.function.positionalParameters.first;
          clone.isCovariant = parameter.isCovariant;
          clone.isGenericCovariantImpl = parameter.isGenericCovariantImpl;
        }
        nonSetters.remove(field.name);
        class_.addField(clone);
      }
      class_.procedures.clear();
      class_.procedures..addAll(nonSetters.values)..addAll(setters.values);
    }

    // Existing procedures in the class should only be forwarding stubs.
    // Replace them with methods from the mixin class if they have the same
    // name, but keep their parameter flags.
    int originalLength = class_.procedures.length;
    outer:
    for (var procedure in class_.mixin.procedures) {
      // Forwarding stubs in the mixin class are used when calling through the
      // mixin class's interface, not when calling through the mixin
      // application.  They should not be copied.
      if (procedure.isForwardingStub) continue;

      // Factory constructors are not cloned.
      if (procedure.isFactory) continue;

      // NoSuchMethod forwarders aren't cloned.
      if (procedure.isNoSuchMethodForwarder) continue;

      Reference reference;
      if (procedure.isSetter) {
        reference = indexedClass?.lookupSetterReference(procedure.name);
      } else {
        reference = indexedClass?.lookupGetterReference(procedure.name);
      }

      // Linear search for a forwarding stub with the same name.
      int originalIndex;
      for (int i = 0; i < originalLength; ++i) {
        var originalProcedure = class_.procedures[i];
        if (originalProcedure.name == procedure.name &&
            originalProcedure.kind == procedure.kind) {
          FunctionNode src = originalProcedure.function;
          FunctionNode dst = procedure.function;

          if (src.positionalParameters.length !=
                  dst.positionalParameters.length ||
              src.namedParameters.length != dst.namedParameters.length) {
            // A compile time error has already occurred, but don't crash below,
            // and don't add several procedures with the same name to the class.
            continue outer;
          }
          originalIndex = i;
          break;
        }
      }
      if (originalIndex != null) {
        reference ??= class_.procedures[originalIndex]?.reference;
      }
      Procedure clone = cloner.cloneProcedure(procedure, reference);
      if (originalIndex != null) {
        Procedure originalProcedure = class_.procedures[originalIndex];
        FunctionNode src = originalProcedure.function;
        FunctionNode dst = clone.function;
        assert(src.typeParameters.length == dst.typeParameters.length);
        for (int j = 0; j < src.typeParameters.length; ++j) {
          dst.typeParameters[j].flags = src.typeParameters[j].flags;
        }
        for (int j = 0; j < src.positionalParameters.length; ++j) {
          dst.positionalParameters[j].flags = src.positionalParameters[j].flags;
        }
        // TODO(kernel team): The named parameters are not sorted,
        // this might not be correct.
        for (int j = 0; j < src.namedParameters.length; ++j) {
          dst.namedParameters[j].isCovariant =
              src.namedParameters[j].isCovariant;
          dst.namedParameters[j].isGenericCovariantImpl =
              src.namedParameters[j].isGenericCovariantImpl;
        }

        class_.procedures[originalIndex] = clone;
        clone.parent = class_;
      } else {
        class_.addProcedure(clone);
      }
    }
    assert(class_.constructors.isNotEmpty);

    // This class implements the mixin type. Also, backends rely on the fact
    // that eliminated mixin is appended into the end of interfaces list.
    class_.implementedTypes.add(class_.mixedInType);

    // This class is now a normal class.
    class_.mixedInType = null;

    // Leave breadcrumbs for backends (e.g. for dart:mirrors implementation).
    class_.isEliminatedMixin = true;
  }
}
