// Copyright (c) 2015, 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 dart2js.resolution.class_hierarchy;

import '../common.dart';
import '../common/resolution.dart' show Resolution;
import '../common_elements.dart' show CommonElements;
import '../elements/resolution_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart'
    show
        BaseClassElementX,
        ErroneousElementX,
        LibraryElementX,
        MixinApplicationElementX,
        SynthesizedConstructorElementX,
        TypeVariableElementX,
        UnnamedMixinApplicationElementX;
import '../elements/names.dart';
import '../ordered_typeset.dart'
    show OrderedTypeSet, ResolutionOrderedTypeSetBuilder;
import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../universe/feature.dart' show Feature;
import '../util/util.dart' show Link, Setlet;
import 'enum_creator.dart';
import 'members.dart' show lookupInScope;
import 'registry.dart' show ResolutionRegistry;
import 'resolution_common.dart' show CommonResolverVisitor, MappingVisitor;
import 'scope.dart' show Scope, TypeDeclarationScope;

/// If `true` compatible mixin applications are shared within a library. This
/// matches the mixins generated by fasta.
bool useOptimizedMixins = false;

class TypeDefinitionVisitor extends MappingVisitor<ResolutionDartType> {
  Scope scope;
  final TypeDeclarationElement enclosingElement;
  TypeDeclarationElement get element => enclosingElement;

  TypeDefinitionVisitor(Resolution resolution, TypeDeclarationElement element,
      ResolutionRegistry registry)
      : this.enclosingElement = element,
        scope = Scope.buildEnclosingScope(element),
        super(resolution, registry);

  CommonElements get commonElements => resolution.commonElements;

  ResolutionInterfaceType get objectType => commonElements.objectType;

  void resolveTypeVariableBounds(NodeList node) {
    if (node == null) return;

    Setlet<String> nameSet = new Setlet<String>();
    // Resolve the bounds of type variables.
    Iterator<ResolutionDartType> types = element.typeVariables.iterator;
    Link<Node> nodeLink = node.nodes;
    while (!nodeLink.isEmpty) {
      types.moveNext();
      ResolutionTypeVariableType typeVariable = types.current;
      String typeName = typeVariable.name;
      TypeVariable typeNode = nodeLink.head;
      registry.useType(typeNode, typeVariable);
      if (nameSet.contains(typeName)) {
        reporter.reportErrorMessage(
            typeNode,
            MessageKind.DUPLICATE_TYPE_VARIABLE_NAME,
            {'typeVariableName': typeName});
      }
      nameSet.add(typeName);

      TypeVariableElementX variableElement = typeVariable.element;
      if (typeNode.bound != null) {
        ResolutionDartType boundType = typeResolver
            .resolveNominalTypeAnnotation(this, typeNode.bound, const []);
        variableElement.boundCache = boundType;

        void checkTypeVariableBound() {
          Link<TypeVariableElement> seenTypeVariables =
              const Link<TypeVariableElement>();
          seenTypeVariables = seenTypeVariables.prepend(variableElement);
          ResolutionDartType bound = boundType;
          while (bound.isTypeVariable) {
            TypeVariableElement element = bound.element;
            if (seenTypeVariables.contains(element)) {
              if (identical(element, variableElement)) {
                // Only report an error on the checked type variable to avoid
                // generating multiple errors for the same cyclicity.
                reporter.reportWarningMessage(
                    typeNode.name,
                    MessageKind.CYCLIC_TYPE_VARIABLE,
                    {'typeVariableName': variableElement.name});
              }
              break;
            }
            seenTypeVariables = seenTypeVariables.prepend(element);
            bound = element.bound;
          }
        }

        addDeferredAction(element, checkTypeVariableBound);
      } else {
        variableElement.boundCache = objectType;
      }
      nodeLink = nodeLink.tail;
    }
    assert(!types.moveNext());
  }
}

/**
 * The implementation of [ResolverTask.resolveClass].
 *
 * This visitor has to be extra careful as it is building the basic
 * element information, and cannot safely look at other elements as
 * this may lead to cycles.
 *
 * This visitor can assume that the supertypes have already been
 * resolved, but it cannot call [ResolverTask.resolveClass] directly
 * or indirectly (through [ClassElement.ensureResolved]) for any other
 * types.
 */
class ClassResolverVisitor extends TypeDefinitionVisitor {
  BaseClassElementX get element => enclosingElement;

  ClassResolverVisitor(Resolution resolution, ClassElement classElement,
      ResolutionRegistry registry)
      : super(resolution, classElement, registry);

  ResolutionDartType visitClassNode(ClassNode node) {
    if (element == null) {
      throw reporter.internalError(node, 'element is null');
    }
    if (element.resolutionState != STATE_STARTED) {
      throw reporter.internalError(
          element, 'cyclic resolution of class $element');
    }

    element.computeType(resolution);
    scope = new TypeDeclarationScope(scope, element);
    // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet.
    // As a side-effect, this may get us back here trying to
    // resolve this class again.
    resolveTypeVariableBounds(node.typeParameters);

    // Setup the supertype for the element (if there is a cycle in the
    // class hierarchy, it has already been set to Object).
    if (element.supertype == null && node.superclass != null) {
      MixinApplication superMixin = node.superclass.asMixinApplication();
      if (superMixin != null) {
        if (useOptimizedMixins) {
          element.supertype = createMixinsOptimized(element, superMixin);
        } else {
          element.supertype = createMixins(element, superMixin);
        }
      } else {
        element.supertype = resolveSupertype(element, node.superclass);
      }
    }
    // If the super type isn't specified, we provide a default.  The language
    // specifies [Object] but the backend can pick a specific 'implementation'
    // of Object - the JavaScript backend chooses between Object and
    // Interceptor.
    if (element.supertype == null) {
      ClassElement superElement = registry.defaultSuperclass(element);
      // Avoid making the superclass (usually Object) extend itself.
      if (element != superElement) {
        if (superElement == null) {
          reporter.internalError(
              node, "Cannot resolve default superclass for $element.");
        } else {
          superElement.ensureResolved(resolution);
        }
        element.supertype = superElement.computeType(resolution);
      }
    }

    if (element.interfaces == null) {
      element.interfaces = resolveInterfaces(node.interfaces, node.superclass);
    } else {
      assert(element.hasIncompleteHierarchy, failedAt(element));
    }
    calculateAllSupertypes(element);

    if (!element.hasConstructor) {
      Element superMember = element.superclass.localLookup('');
      if (superMember == null) {
        MessageKind kind = MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR;
        Map arguments = {'className': element.superclass.name};
        // TODO(ahe): Why is this a compile-time error? Or if it is an error,
        // why do we bother to registerThrowNoSuchMethod below?
        reporter.reportErrorMessage(node, kind, arguments);
        superMember = new ErroneousElementX(kind, arguments, '', element);
        registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      } else if (!superMember.isGenerativeConstructor) {
        MessageKind kind = MessageKind.SUPER_CALL_TO_FACTORY;
        Map arguments = {'className': element.superclass.name};
        // TODO(ahe): Why is this a compile-time error? Or if it is an error,
        // why do we bother to registerThrowNoSuchMethod below?
        reporter.reportErrorMessage(node, kind, arguments);
        superMember = new ErroneousElementX(kind, arguments, '', element);
        registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
      } else {
        ConstructorElement superConstructor = superMember;
        superConstructor.computeType(resolution);
        if (!CallStructure.NO_ARGS
            .signatureApplies(superConstructor.parameterStructure)) {
          MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT;
          reporter.reportErrorMessage(node, kind);
          superMember = new ErroneousElementX(kind, {}, '', element);
        }
      }
      FunctionElement constructor =
          new SynthesizedConstructorElementX.forDefault(superMember, element);
      if (superMember.isMalformed) {
        ErroneousElement erroneousElement = superMember;
        resolution.registerCompileTimeError(
            constructor,
            reporter.createMessage(node, erroneousElement.messageKind,
                erroneousElement.messageArguments));
      }
      element.setDefaultConstructor(constructor, reporter);
    }
    return element.computeType(resolution);
  }

  @override
  ResolutionDartType visitEnum(Enum node) {
    if (element == null) {
      throw reporter.internalError(node, 'element is null');
    }
    if (element.resolutionState != STATE_STARTED) {
      throw reporter.internalError(
          element, 'cyclic resolution of class $element');
    }

    ResolutionInterfaceType enumType = element.computeType(resolution);
    element.supertype = objectType;
    element.interfaces = const Link<ResolutionDartType>();
    calculateAllSupertypes(element);

    if (node.names.nodes.isEmpty) {
      reporter.reportErrorMessage(
          node, MessageKind.EMPTY_ENUM_DECLARATION, {'enumName': element.name});
    }

    EnumCreator creator =
        new EnumCreator(reporter, resolution.commonElements, element);
    creator.createMembers();
    return enumType;
  }

  /// Resolves the mixed type for [mixinNode] and checks that the mixin type
  /// is a valid, non-blacklisted interface type. The mixin type is returned.
  ResolutionDartType checkMixinType(NominalTypeAnnotation mixinNode) {
    ResolutionDartType mixinType = resolveNominalType(mixinNode);
    if (isBlackListed(mixinType)) {
      reporter.reportErrorMessage(
          mixinNode, MessageKind.CANNOT_MIXIN, {'type': mixinType});
    } else if (mixinType.isTypeVariable) {
      reporter.reportErrorMessage(mixinNode, MessageKind.CLASS_NAME_EXPECTED);
    } else if (mixinType.isMalformed) {
      reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED,
          {'className': element.name, 'malformedType': mixinType});
    } else if (mixinType.isEnumType) {
      reporter.reportErrorMessage(mixinNode, MessageKind.CANNOT_MIXIN_ENUM,
          {'className': element.name, 'enumType': mixinType});
    }
    return mixinType;
  }

  ResolutionDartType visitNamedMixinApplication(NamedMixinApplication node) {
    if (element == null) {
      throw reporter.internalError(node, 'element is null');
    }
    if (element.resolutionState != STATE_STARTED) {
      throw reporter.internalError(
          element, 'cyclic resolution of class $element');
    }

    element.computeType(resolution);
    scope = new TypeDeclarationScope(scope, element);
    resolveTypeVariableBounds(node.typeParameters);

    // Generate anonymous mixin application elements for the
    // intermediate mixin applications (excluding the last).
    if (useOptimizedMixins) {
      createMixinsOptimized(element, node, isNamed: true);
    } else {
      createMixins(element, node, isNamed: true);
    }
    return element.computeType(resolution);
  }

  /// Create the mixin applications for [superMixin].
  ///
  /// This algorithm is ported from
  /// `package:front_end/src/fasta/kernel/kernel_library_builder.dart` and
  /// added create allow for equivalence testing between the AST and kernel
  /// based compilations in face of shared mixins. It will be removed when we
  /// no longer need equivalence testing.
  ResolutionDartType createMixinsOptimized(
      BaseClassElementX element, MixinApplication superMixin,
      {bool isNamed: false}) {
    LibraryElementX library = element.library;
    Map<String, MixinApplicationElementX> mixinApplicationClasses =
        library.mixinApplicationCache;

    String name = element.isNamedMixinApplication ? element.name : null;
    ResolutionDartType supertype =
        resolveSupertype(element, superMixin.superclass);
    Link<Node> link = superMixin.mixins.nodes;
    List<ResolutionDartType> mixins = <ResolutionDartType>[];
    List<Node> mixinNodes = <Node>[];
    while (!link.isEmpty) {
      mixins.add(checkMixinType(link.head));
      mixinNodes.add(link.head);
      link = link.tail;
    }

    List<List<String>> signatureParts = <List<String>>[];
    Map<String, ResolutionDartType> freeTypes = <String, ResolutionDartType>{};

    {
      Map<String, String> unresolved = <String, String>{};
      int unresolvedCount = 0;

      /// Compute a signature of the type arguments used by the supertype and
      /// mixins. These types are free variables. At this point we can't
      /// trust that the number of type arguments match the type parameters,
      /// so we also need to be able to detect missing type arguments.  To do
      /// so, we separate each list of type arguments by `^` and type
      /// arguments by `&`. For example, the mixin `C<S> with M<T, U>` would
      /// look like this:
      ///
      ///     ^#U0^#U1&#U2
      ///
      /// Where `#U0`, `#U1`, and `#U2` are the free variables arising from
      /// `S`, `T`, and `U` respectively.
      ///
      /// As we can resolve any type parameters used at this point, those are
      /// named `#T0` and so forth. This reduces the number of free variables
      /// which is crucial for memory usage and the Dart VM's bootstrap
      /// sequence.
      ///
      /// For example, consider this use of mixin applications:
      ///
      ///     class _InternalLinkedHashMap<K, V> extends _HashVMBase
      ///         with
      ///             MapMixin<K, V>,
      ///             _LinkedHashMapMixin<K, V>,
      ///             _HashBase,
      ///             _OperatorEqualsAndHashCode {}
      ///
      /// In this case, only two variables are free, and we produce this
      /// signature: `^^#T0&#T1^#T0&#T1^^`. Assume another class uses the
      /// sames mixins but with missing type arguments for `MapMixin`, its
      /// signature would be: `^^^#T0&#T1^^`.
      ///
      /// Note that we do not need to compute a signature for a named mixin
      /// application with only one mixin as we don't have to invent a name
      /// for any classes in this situation.
      void analyzeArguments(ResolutionDartType type, {bool isLast}) {
        if (isNamed && isLast) {
          // The last mixin of a named mixin application doesn't contribute
          // to free variables.
          return;
        }
        if (type is GenericType) {
          List<String> part = <String>[];
          for (int i = 0; i < type.typeArguments.length; i++) {
            var argument = type.typeArguments[i];
            String name;
            if (argument is ResolutionTypeVariableType) {
              int index = element.typeVariables.indexOf(argument) ?? -1;
              if (index != -1) {
                name = "#T${index}";
              }
            } else if (argument is GenericType && argument.isRaw) {
              name = unresolved[argument.name] ??= "#U${unresolvedCount++}";
            }
            name ??= "#U${unresolvedCount++}";
            freeTypes[name] = argument;
            part.add(name);
          }
          signatureParts.add(part);
        }
      }

      analyzeArguments(supertype, isLast: false);
      for (int i = 0; i < mixins.length; i++) {
        analyzeArguments(mixins[i], isLast: i == mixins.length - 1);
      }
    }

    List<List<String>> currentSignatureParts = <List<String>>[];
    String computeSignature(int index) {
      if (freeTypes.isEmpty) return "";
      currentSignatureParts.add(signatureParts[index]);
      if (currentSignatureParts.any((l) => l.isNotEmpty)) {
        return "^${currentSignatureParts.map((l) => l.join('&')).join('^')}";
      } else {
        return "";
      }
    }

    Map<String, ResolutionTypeVariableType> computeTypeVariables(
        ClassElement cls, Node node) {
      Map<String, ResolutionTypeVariableType> variables =
          <String, ResolutionTypeVariableType>{};
      int index = 0;
      for (List<String> strings in currentSignatureParts) {
        for (String name in strings) {
          variables[name] ??= new ResolutionTypeVariableType(
              new TypeVariableElementX(name, cls, index++, node));
        }
      }
      return variables;
    }

    computeSignature(0); // This combines the supertype with the first mixin.

    for (int i = 0; i < mixins.length; i++) {
      int signatureIndex = i + 1;
      Set<String> supertypeArguments = new Set<String>();
      for (List<String> part in currentSignatureParts) {
        supertypeArguments.addAll(part);
      }
      Node node = mixinNodes[i];
      ResolutionDartType mixin = mixins[i];

      bool lastAndNamed = i == mixins.length - 1 && isNamed;

      ResolutionInterfaceType createMixinApplication() {
        Map<String, ResolutionDartType> variables;
        MixinApplicationElementX mixinElement;
        ResolutionInterfaceType mixinType;
        if (lastAndNamed) {
          mixinElement = element;
          variables = freeTypes;
        } else {
          String signature = computeSignature(signatureIndex);
          name = supertype.name;
          int index = name.indexOf("^");
          if (index != -1) {
            name = name.substring(0, index);
          }
          name = "_$name&${mixin.name}$signature";
          mixinElement = mixinApplicationClasses[name];
          if (mixinElement != null) return mixinElement.thisType;

          mixinElement = new UnnamedMixinApplicationElementX(
              name, element, resolution.idGenerator.getNextFreeId(), node);
          variables = computeTypeVariables(mixinElement, node);
          mixinElement.setThisAndRawTypes(variables.values.toList());
          mixinApplicationClasses[name] = mixinElement;
        }

        if (supertypeArguments.isNotEmpty) {
          List<ResolutionDartType> supertypeTypeArguments =
              <ResolutionDartType>[];
          for (String part in supertypeArguments) {
            supertypeTypeArguments.add(variables[part]);
          }
          supertype = new ResolutionInterfaceType(
              supertype.element, supertypeTypeArguments);
        }

        if (lastAndNamed) {
          mixinType = mixin;
        } else {
          List<ResolutionDartType> mixinTypeArguments = <ResolutionDartType>[];
          for (String part in signatureParts[signatureIndex]) {
            mixinTypeArguments.add(variables[part]);
          }
          mixinType =
              new ResolutionInterfaceType(mixin.element, mixinTypeArguments);
        }

        doApplyMixinTo(mixinElement, supertype, mixinType);
        mixinElement.resolutionState = STATE_DONE;
        mixinElement.supertypeLoadState = STATE_DONE;
        return mixinElement.thisType;
      }

      supertype = createMixinApplication();
    }

    return new ResolutionInterfaceType(
        supertype.element, freeTypes.values.toList());
  }

  ResolutionDartType createMixins(ClassElement element, MixinApplication node,
      {bool isNamed: false}) {
    ResolutionDartType supertype = resolveSupertype(element, node.superclass);
    Link<Node> link = node.mixins.nodes;
    while (!link.isEmpty) {
      if (isNamed && link.tail.isEmpty) {
        doApplyMixinTo(element, supertype, checkMixinType(link.head));
        return supertype;
      }
      supertype = applyMixin(supertype, checkMixinType(link.head), link.head);
      link = link.tail;
    }
    return supertype;
  }

  ResolutionDartType applyMixin(
      ResolutionDartType supertype, ResolutionDartType mixinType, Node node) {
    String superName = supertype.name;
    String mixinName = mixinType.name;
    MixinApplicationElementX mixinApplication =
        new UnnamedMixinApplicationElementX("${superName}+${mixinName}",
            element, resolution.idGenerator.getNextFreeId(), node);
    // Create synthetic type variables for the mixin application.
    List<ResolutionDartType> typeVariables = <ResolutionDartType>[];
    int index = 0;
    for (ResolutionTypeVariableType type in element.typeVariables) {
      TypeVariableElementX typeVariableElement = new TypeVariableElementX(
          type.name, mixinApplication, index, type.element.node);
      ResolutionTypeVariableType typeVariable =
          new ResolutionTypeVariableType(typeVariableElement);
      typeVariables.add(typeVariable);
      index++;
    }
    // Setup bounds on the synthetic type variables.
    for (ResolutionTypeVariableType type in element.typeVariables) {
      ResolutionTypeVariableType typeVariable =
          typeVariables[type.element.index];
      TypeVariableElementX typeVariableElement = typeVariable.element;
      typeVariableElement.typeCache = typeVariable;
      typeVariableElement.boundCache =
          type.element.bound.subst(typeVariables, element.typeVariables);
    }
    // Setup this and raw type for the mixin application.
    mixinApplication.computeThisAndRawType(resolution, typeVariables);
    // Substitute in synthetic type variables in super and mixin types.
    supertype = supertype.subst(typeVariables, element.typeVariables);
    mixinType = mixinType.subst(typeVariables, element.typeVariables);

    doApplyMixinTo(mixinApplication, supertype, mixinType);
    mixinApplication.resolutionState = STATE_DONE;
    mixinApplication.supertypeLoadState = STATE_DONE;
    // Replace the synthetic type variables by the original type variables in
    // the returned type (which should be the type actually extended).
    ResolutionInterfaceType mixinThisType = mixinApplication.thisType;
    return mixinThisType.subst(
        element.typeVariables, mixinThisType.typeArguments);
  }

  bool isDefaultConstructor(FunctionElement constructor) {
    if (constructor.name != '') return false;
    constructor.computeType(resolution);
    return constructor.functionSignature.parameterCount == 0;
  }

  FunctionElement createForwardingConstructor(
      ConstructorElement target, ClassElement enclosing) {
    FunctionElement constructor =
        new SynthesizedConstructorElementX.notForDefault(
            target.name, target, enclosing);
    constructor.computeType(resolution);
    return constructor;
  }

  void doApplyMixinTo(MixinApplicationElementX mixinApplication,
      ResolutionDartType supertype, ResolutionDartType mixinType) {
    Node node = mixinApplication.parseNode(resolution.parsingContext);

    if (mixinApplication.supertype != null) {
      // [supertype] is not null if there was a cycle.
      assert(reporter.hasReportedError, failedAt(node));
      supertype = mixinApplication.supertype;
      assert(supertype.isObject, failedAt(node));
    } else {
      mixinApplication.supertype = supertype;
    }

    // Named mixin application may have an 'implements' clause.
    NamedMixinApplication namedMixinApplication =
        node.asNamedMixinApplication();
    Link<ResolutionDartType> interfaces = (namedMixinApplication != null)
        ? resolveInterfaces(
            namedMixinApplication.interfaces, namedMixinApplication.superclass)
        : const Link<ResolutionDartType>();

    // The class that is the result of a mixin application implements
    // the interface of the class that was mixed in so always prepend
    // that to the interface list.
    if (mixinApplication.interfaces == null) {
      if (mixinType.isInterfaceType) {
        // Avoid malformed types in the interfaces.
        interfaces = interfaces.prepend(mixinType);
      }
      mixinApplication.interfaces = interfaces;
    } else {
      assert(
          mixinApplication.hasIncompleteHierarchy, failedAt(mixinApplication));
    }

    ClassElement superclass = supertype.element;
    if (mixinType.kind != ResolutionTypeKind.INTERFACE) {
      mixinApplication.hasIncompleteHierarchy = true;
      mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf;
      return;
    }

    assert(mixinApplication.mixinType == null);
    mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType);

    // Create forwarding constructors for constructor defined in the superclass
    // because they are now hidden by the mixin application.
    superclass.forEachLocalMember((Element member) {
      if (!member.isGenerativeConstructor) return;
      FunctionElement forwarder =
          createForwardingConstructor(member, mixinApplication);
      if (Name.isPrivateName(member.name) &&
          mixinApplication.library != superclass.library) {
        // Do not create a forwarder to the super constructor, because the mixin
        // application is in a different library than the constructor in the
        // super class and it is not possible to call that constructor from the
        // library using the mixin application.
        return;
      }
      mixinApplication.addConstructor(forwarder);
    });
    calculateAllSupertypes(mixinApplication);
  }

  ResolutionInterfaceType resolveMixinFor(
      MixinApplicationElement mixinApplication, ResolutionDartType mixinType) {
    ClassElement mixin = mixinType.element;
    mixin.ensureResolved(resolution);

    // Check for cycles in the mixin chain.
    ClassElement previous = mixinApplication; // For better error messages.
    ClassElement current = mixin;
    while (current != null && current.isMixinApplication) {
      MixinApplicationElement currentMixinApplication = current;
      if (currentMixinApplication == mixinApplication) {
        reporter.reportErrorMessage(
            mixinApplication,
            MessageKind.ILLEGAL_MIXIN_CYCLE,
            {'mixinName1': current.name, 'mixinName2': previous.name});
        // We have found a cycle in the mixin chain. Return null as
        // the mixin for this application to avoid getting into
        // infinite recursion when traversing members.
        return null;
      }
      previous = current;
      current = currentMixinApplication.mixin;
    }
    return mixinType;
  }

  ResolutionDartType resolveNominalType(NominalTypeAnnotation node) {
    return typeResolver.resolveNominalTypeAnnotation(this, node, const []);
  }

  ResolutionDartType resolveSupertype(
      ClassElement cls, NominalTypeAnnotation superclass) {
    ResolutionDartType supertype = resolveNominalType(superclass);
    if (supertype != null) {
      if (supertype.isMalformed) {
        reporter.reportErrorMessage(
            superclass,
            MessageKind.CANNOT_EXTEND_MALFORMED,
            {'className': element.name, 'malformedType': supertype});
        return objectType;
      } else if (supertype.isEnumType) {
        reporter.reportErrorMessage(superclass, MessageKind.CANNOT_EXTEND_ENUM,
            {'className': element.name, 'enumType': supertype});
        return objectType;
      } else if (!supertype.isInterfaceType) {
        reporter.reportErrorMessage(
            superclass.typeName, MessageKind.CLASS_NAME_EXPECTED);
        return objectType;
      } else if (isBlackListed(supertype)) {
        reporter.reportErrorMessage(
            superclass, MessageKind.CANNOT_EXTEND, {'type': supertype});
        return objectType;
      }
    }
    return supertype;
  }

  Link<ResolutionDartType> resolveInterfaces(
      NodeList interfaces, Node superclass) {
    Link<ResolutionDartType> result = const Link<ResolutionDartType>();
    if (interfaces == null) return result;
    for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) {
      ResolutionDartType interfaceType = resolveNominalType(link.head);
      if (interfaceType != null) {
        if (interfaceType.isMalformed) {
          reporter.reportErrorMessage(
              link.head,
              MessageKind.CANNOT_IMPLEMENT_MALFORMED,
              {'className': element.name, 'malformedType': interfaceType});
        } else if (interfaceType.isEnumType) {
          reporter.reportErrorMessage(
              link.head,
              MessageKind.CANNOT_IMPLEMENT_ENUM,
              {'className': element.name, 'enumType': interfaceType});
        } else if (!interfaceType.isInterfaceType) {
          // TODO(johnniwinther): Handle dynamic.
          NominalTypeAnnotation typeAnnotation = link.head;
          reporter.reportErrorMessage(
              typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED);
        } else {
          if (interfaceType == element.supertype) {
            reporter.reportErrorMessage(
                superclass,
                MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
                {'type': interfaceType});
            reporter.reportErrorMessage(
                link.head,
                MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
                {'type': interfaceType});
          }
          if (result.contains(interfaceType)) {
            reporter.reportErrorMessage(link.head,
                MessageKind.DUPLICATE_IMPLEMENTS, {'type': interfaceType});
          }
          result = result.prepend(interfaceType);
          if (isBlackListed(interfaceType)) {
            reporter.reportErrorMessage(link.head, MessageKind.CANNOT_IMPLEMENT,
                {'type': interfaceType});
          }
        }
      }
    }
    return result;
  }

  /**
   * Compute the list of all supertypes.
   *
   * The elements of this list are ordered as follows: first the supertype that
   * the class extends, then the implemented interfaces, and then the supertypes
   * of these.  The class [Object] appears only once, at the end of the list.
   *
   * For example, for a class `class C extends S implements I1, I2`, we compute
   *   supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1)
   *                   ++ supertypes(I2),
   * where ++ stands for list concatenation.
   *
   * This order makes sure that if a class implements an interface twice with
   * different type arguments, the type used in the most specific class comes
   * first.
   */
  void calculateAllSupertypes(BaseClassElementX cls) {
    if (cls.allSupertypesAndSelf != null) return;
    final ResolutionInterfaceType supertype = cls.supertype;
    if (supertype != null) {
      cls.allSupertypesAndSelf = new ResolutionOrderedTypeSetBuilder(cls,
              reporter: reporter, objectType: commonElements.objectType)
          .createOrderedTypeSet(supertype, cls.interfaces);
    } else {
      assert(cls == resolution.commonElements.objectClass);
      cls.allSupertypesAndSelf =
          new OrderedTypeSet.singleton(cls.computeType(resolution));
    }
  }

  isBlackListed(ResolutionDartType type) {
    LibraryElement lib = element.library;
    return !identical(lib, resolution.commonElements.coreLibrary) &&
        !resolution.target.isTargetSpecificLibrary(lib) &&
        (type.isDynamic ||
            type == commonElements.boolType ||
            type == commonElements.numType ||
            type == commonElements.intType ||
            type == commonElements.doubleType ||
            type == commonElements.stringType ||
            type == commonElements.nullType);
  }
}

class ClassSupertypeResolver extends CommonResolverVisitor {
  Scope context;
  ClassElement classElement;

  ClassSupertypeResolver(Resolution resolution, ClassElement cls)
      : context = Scope.buildEnclosingScope(cls),
        this.classElement = cls,
        super(resolution);

  CommonElements get commonElements => resolution.commonElements;

  void loadSupertype(ClassElement element, Node from) {
    if (!element.isResolved) {
      resolution.resolver.loadSupertypes(element, from);
      element.ensureResolved(resolution);
    }
  }

  void visitNodeList(NodeList node) {
    if (node != null) {
      for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
        link.head.accept(this);
      }
    }
  }

  void visitClassNode(ClassNode node) {
    if (node.superclass == null) {
      if (classElement != commonElements.objectClass) {
        loadSupertype(commonElements.objectClass, node);
      }
    } else {
      node.superclass.accept(this);
    }
    visitNodeList(node.interfaces);
  }

  void visitEnum(Enum node) {
    loadSupertype(commonElements.objectClass, node);
  }

  void visitMixinApplication(MixinApplication node) {
    node.superclass.accept(this);
    visitNodeList(node.mixins);
  }

  void visitNamedMixinApplication(NamedMixinApplication node) {
    node.superclass.accept(this);
    visitNodeList(node.mixins);
    visitNodeList(node.interfaces);
  }

  void visitNominalTypeAnnotation(NominalTypeAnnotation node) {
    node.typeName.accept(this);
  }

  void visitIdentifier(Identifier node) {
    Element element = lookupInScope(reporter, node, context, node.source);
    if (element != null && element.isClass) {
      loadSupertype(element, node);
    }
  }

  void visitSend(Send node) {
    Identifier prefix = node.receiver.asIdentifier();
    if (prefix == null) {
      reporter.reportErrorMessage(
          node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver});
      return;
    }
    Element element = lookupInScope(reporter, prefix, context, prefix.source);
    if (element == null || !identical(element.kind, ElementKind.PREFIX)) {
      reporter.reportErrorMessage(
          node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver});
      return;
    }
    PrefixElement prefixElement = element;
    Identifier selector = node.selector.asIdentifier();
    var e = prefixElement.lookupLocalMember(selector.source);
    if (e == null || !e.impliesType) {
      reporter.reportErrorMessage(node.selector,
          MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.selector});
      return;
    }
    loadSupertype(e, node);
  }
}
