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

import '../common.dart';
import '../common/resolution.dart' show
    Feature;
import '../compiler.dart' show
    Compiler;
import '../constants/constructors.dart' show
    GenerativeConstantConstructor,
    RedirectingGenerativeConstantConstructor;
import '../constants/expressions.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart' show
    ConstructorElementX,
    ErroneousConstructorElementX,
    ErroneousElementX,
    ErroneousFieldElementX,
    FieldElementX,
    InitializingFormalElementX,
    ParameterElementX;
import '../tree/tree.dart';
import '../util/util.dart' show
    Link;
import '../universe/call_structure.dart' show
    CallStructure;
import '../universe/use.dart' show
    StaticUse;

import 'members.dart' show
    lookupInScope,
    ResolverVisitor;
import 'registry.dart' show
    ResolutionRegistry;
import 'resolution_common.dart' show
    CommonResolverVisitor;
import 'resolution_result.dart';

class InitializerResolver {
  final ResolverVisitor visitor;
  final ConstructorElementX constructor;
  final FunctionExpression functionNode;
  final Map<FieldElement, Node> initialized = <FieldElement, Node>{};
  final Map<FieldElement, ConstantExpression> fieldInitializers =
      <FieldElement, ConstantExpression>{};
  Link<Node> initializers;
  bool hasSuper = false;
  bool isValidAsConstant = true;

  bool get isConst => constructor.isConst;

  InitializerResolver(this.visitor, this.constructor, this.functionNode);

  ResolutionRegistry get registry => visitor.registry;

  DiagnosticReporter get reporter => visitor.reporter;

  bool isFieldInitializer(SendSet node) {
    if (node.selector.asIdentifier() == null) return false;
    if (node.receiver == null) return true;
    if (node.receiver.asIdentifier() == null) return false;
    return node.receiver.asIdentifier().isThis();
  }

  reportDuplicateInitializerError(Element field, Node init, Node existing) {
    reporter.reportError(
        reporter.createMessage(
            init,
            MessageKind.DUPLICATE_INITIALIZER,
            {'fieldName': field.name}),
        <DiagnosticMessage>[
            reporter.createMessage(
                existing,
                MessageKind.ALREADY_INITIALIZED,
                {'fieldName': field.name}),
        ]);
    isValidAsConstant = false;
  }

  void checkForDuplicateInitializers(FieldElementX field, Node init) {
    // [field] can be null if it could not be resolved.
    if (field == null) return;
    if (initialized.containsKey(field)) {
      reportDuplicateInitializerError(field, init, initialized[field]);
    } else if (field.isFinal) {
      field.parseNode(visitor.resolution.parsing);
      Expression initializer = field.initializer;
      if (initializer != null) {
        reportDuplicateInitializerError(field, init, initializer);
      }
    }
    initialized[field] = init;
  }

  void resolveFieldInitializer(SendSet init) {
    // init is of the form [this.]field = value.
    final Node selector = init.selector;
    final String name = selector.asIdentifier().source;
    // Lookup target field.
    Element target;
    FieldElement field;
    if (isFieldInitializer(init)) {
      target = constructor.enclosingClass.lookupLocalMember(name);
      if (target == null) {
        reporter.reportErrorMessage(
            selector, MessageKind.CANNOT_RESOLVE, {'name': name});
        target = new ErroneousFieldElementX(
            selector.asIdentifier(), constructor.enclosingClass);
      } else if (target.kind != ElementKind.FIELD) {
        reporter.reportErrorMessage(
            selector, MessageKind.NOT_A_FIELD, {'fieldName': name});
        target = new ErroneousFieldElementX(
            selector.asIdentifier(), constructor.enclosingClass);
      } else if (!target.isInstanceMember) {
        reporter.reportErrorMessage(
            selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name});
      } else {
        field = target;
      }
    } else {
      reporter.reportErrorMessage(
          init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
    }
    if (target != null) {
      registry.useElement(init, target);
      checkForDuplicateInitializers(target, init);
    }
    if (field != null) {
      registry.registerStaticUse(new StaticUse.fieldInit(field));
    }
    // Resolve initializing value.
    ResolutionResult result = visitor.visitInStaticContext(
        init.arguments.head,
        inConstantInitializer: isConst);
    if (isConst) {
      if (result.isConstant && field != null) {
        // TODO(johnniwinther): Report error if `result.constant` is `null`.
        fieldInitializers[field] = result.constant;
      } else {
        isValidAsConstant = false;
      }
    }
  }

  InterfaceType getSuperOrThisLookupTarget(Node diagnosticNode,
                                           {bool isSuperCall}) {
    if (isSuperCall) {
      // Calculate correct lookup target and constructor name.
      if (constructor.enclosingClass.isObject) {
        reporter.reportErrorMessage(
            diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
        isValidAsConstant = false;
      } else {
        return constructor.enclosingClass.supertype;
      }
    }
    return constructor.enclosingClass.thisType;
  }

  ResolutionResult resolveSuperOrThisForSend(Send node) {
    // Resolve the selector and the arguments.
    ArgumentsResult argumentsResult = visitor.inStaticContext(() {
      // TODO(johnniwinther): Remove this when [SendStructure] is used directly.
      visitor.resolveSelector(node, null);
      return visitor.resolveArguments(node.argumentsNode);
    }, inConstantInitializer: isConst);

    bool isSuperCall = Initializers.isSuperConstructorCall(node);
    InterfaceType targetType =
        getSuperOrThisLookupTarget(node, isSuperCall: isSuperCall);
    ClassElement lookupTarget = targetType.element;
    String constructorName =
        visitor.getRedirectingThisOrSuperConstructorName(node).text;
    ConstructorElement foundConstructor = findConstructor(
        constructor.library, lookupTarget, constructorName);

    final bool isImplicitSuperCall = false;
    final String className = lookupTarget.name;
    CallStructure callStructure = argumentsResult.callStructure;
    ConstructorElement calledConstructor = verifyThatConstructorMatchesCall(
        node,
        foundConstructor,
        callStructure,
        className,
        constructorName: constructorName,
        isThisCall: !isSuperCall,
        isImplicitSuperCall: false);
    // TODO(johnniwinther): Remove this when information is pulled from an
    // [InitializerStructure].
    registry.useElement(node, calledConstructor);
    if (!calledConstructor.isError) {
      registry.registerStaticUse(
          new StaticUse.superConstructorInvoke(
              calledConstructor, callStructure));
    }
    if (isConst) {
      if (isValidAsConstant &&
          calledConstructor.isConst &&
          argumentsResult.isValidAsConstant) {
        List<ConstantExpression> arguments = argumentsResult.constantArguments;
        return new ConstantResult(
            node,
            new ConstructedConstantExpression(
                targetType,
                calledConstructor,
                callStructure,
                arguments),
            element: calledConstructor);
      } else {
        isValidAsConstant = false;
      }
    }
    return new ResolutionResult.forElement(calledConstructor);
  }

  ConstructedConstantExpression resolveImplicitSuperConstructorSend() {
    // If the class has a super resolve the implicit super call.
    ClassElement classElement = constructor.enclosingClass;
    ClassElement superClass = classElement.superclass;
    if (!classElement.isObject) {
      assert(superClass != null);
      assert(superClass.isResolved);

      InterfaceType targetType =
          getSuperOrThisLookupTarget(functionNode, isSuperCall: true);
      ClassElement lookupTarget = targetType.element;
      ConstructorElement calledConstructor =
          findConstructor(constructor.library, lookupTarget, '');

      final String className = lookupTarget.name;
      CallStructure callStructure = CallStructure.NO_ARGS;
      ConstructorElement result = verifyThatConstructorMatchesCall(
          functionNode,
          calledConstructor,
          callStructure,
          className,
          isImplicitSuperCall: true);
      if (!result.isError) {
        registry.registerStaticUse(
            new StaticUse.constructorInvoke(calledConstructor, callStructure));
      }

      if (isConst && isValidAsConstant) {
        return new ConstructedConstantExpression(
            targetType,
            result,
            CallStructure.NO_ARGS,
            const <ConstantExpression>[]);
      }
    }
    return null;
  }

  ConstructorElement reportAndCreateErroneousConstructor(
      Spannable diagnosticNode,
      String name,
      MessageKind kind,
      Map arguments) {
    isValidAsConstant = false;
    reporter.reportErrorMessage(
        diagnosticNode, kind, arguments);
    return new ErroneousConstructorElementX(
        kind, arguments, name, visitor.currentClass);
  }

  /// Checks that [lookedupConstructor] is valid as a target for the super/this
  /// constructor call using with the given [callStructure].
  ///
  /// If [lookedupConstructor] is valid it is returned, otherwise an error is
  /// reported and an [ErroneousConstructorElement] is returned.
  ConstructorElement verifyThatConstructorMatchesCall(
      Node node,
      ConstructorElementX lookedupConstructor,
      CallStructure callStructure,
      String className,
      {String constructorName: '',
       bool isImplicitSuperCall: false,
       bool isThisCall: false}) {
    Element result = lookedupConstructor;
    if (lookedupConstructor == null) {
      String fullConstructorName =
          Elements.constructorNameForDiagnostics(className, constructorName);
      MessageKind kind = isImplicitSuperCall
          ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
          : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
      result = reportAndCreateErroneousConstructor(
          node, constructorName,
          kind, {'constructorName': fullConstructorName});
    } else if (!lookedupConstructor.isGenerativeConstructor) {
      MessageKind kind = isThisCall
          ? MessageKind.THIS_CALL_TO_FACTORY
          : MessageKind.SUPER_CALL_TO_FACTORY;
      result = reportAndCreateErroneousConstructor(
          node, constructorName, kind, {});
    } else {
      lookedupConstructor.computeType(visitor.resolution);
      if (!callStructure.signatureApplies(
               lookedupConstructor.functionSignature)) {
        MessageKind kind = isImplicitSuperCall
            ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
            : MessageKind.NO_MATCHING_CONSTRUCTOR;
        result = reportAndCreateErroneousConstructor(
            node, constructorName, kind, {});
      } else if (constructor.isConst && !lookedupConstructor.isConst) {
        MessageKind kind = isImplicitSuperCall
            ? MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT
            : MessageKind.CONST_CALLS_NON_CONST;
        result = reportAndCreateErroneousConstructor(
            node, constructorName, kind, {});
      }
    }
    return result;
  }

  /**
   * Resolve all initializers of this constructor. In the case of a redirecting
   * constructor, the resolved constructor's function element is returned.
   */
  ConstructorElement resolveInitializers() {
    Map<dynamic/*String|int*/, ConstantExpression> defaultValues =
        <dynamic/*String|int*/, ConstantExpression>{};
    ConstructedConstantExpression constructorInvocation;
    // Keep track of all "this.param" parameters specified for constructor so
    // that we can ensure that fields are initialized only once.
    FunctionSignature functionParameters = constructor.functionSignature;
    functionParameters.forEachParameter((ParameterElementX element) {
      if (isConst) {
        if (element.isOptional) {
          if (element.constantCache == null) {
            // TODO(johnniwinther): Remove this when all constant expressions
            // can be computed during resolution.
            isValidAsConstant = false;
          } else {
            ConstantExpression defaultValue = element.constant;
            if (defaultValue != null) {
              if (element.isNamed) {
                defaultValues[element.name] = defaultValue;
              } else {
                int index =
                    element.functionDeclaration.parameters.indexOf(element);
                defaultValues[index] = defaultValue;
              }
            } else {
              isValidAsConstant = false;
            }
          }
        }
      }
      if (element.isInitializingFormal) {
        InitializingFormalElementX initializingFormal = element;
        FieldElement field = initializingFormal.fieldElement;
        checkForDuplicateInitializers(field, element.initializer);
        if (isConst) {
          if (element.isNamed) {
            fieldInitializers[field] = new NamedArgumentReference(element.name);
          } else {
            int index = element.functionDeclaration.parameters.indexOf(element);
            fieldInitializers[field] = new PositionalArgumentReference(index);
          }
        } else {
          isValidAsConstant = false;
        }
      }
    });

    if (functionNode.initializers == null) {
      initializers = const Link<Node>();
    } else {
      initializers = functionNode.initializers.nodes;
    }
    bool resolvedSuper = false;
    for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) {
      if (link.head.asSendSet() != null) {
        final SendSet init = link.head.asSendSet();
        resolveFieldInitializer(init);
      } else if (link.head.asSend() != null) {
        final Send call = link.head.asSend();
        if (call.argumentsNode == null) {
          reporter.reportErrorMessage(
              link.head, MessageKind.INVALID_INITIALIZER);
          continue;
        }
        if (Initializers.isSuperConstructorCall(call)) {
          if (resolvedSuper) {
            reporter.reportErrorMessage(
                call, MessageKind.DUPLICATE_SUPER_INITIALIZER);
          }
          ResolutionResult result = resolveSuperOrThisForSend(call);
          if (isConst) {
            if (result.isConstant) {
              constructorInvocation = result.constant;
            } else {
              isValidAsConstant = false;
            }
          }
          resolvedSuper = true;
        } else if (Initializers.isConstructorRedirect(call)) {
          // Check that there is no body (Language specification 7.5.1).  If the
          // constructor is also const, we already reported an error in
          // [resolveMethodElement].
          if (functionNode.hasBody() && !constructor.isConst) {
            reporter.reportErrorMessage(
                functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY);
          }
          // Check that there are no other initializers.
          if (!initializers.tail.isEmpty) {
            reporter.reportErrorMessage(
                call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER);
          } else {
            constructor.isRedirectingGenerative = true;
          }
          // Check that there are no field initializing parameters.
          FunctionSignature signature = constructor.functionSignature;
          signature.forEachParameter((ParameterElement parameter) {
            if (parameter.isInitializingFormal) {
              Node node = parameter.node;
              reporter.reportErrorMessage(
                  node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED);
              isValidAsConstant = false;
            }
          });
          ResolutionResult result = resolveSuperOrThisForSend(call);
          if (isConst) {
            if (result.isConstant) {
              constructorInvocation = result.constant;
            } else {
              isValidAsConstant = false;
            }
            if (isConst && isValidAsConstant) {
              constructor.constantConstructor =
                  new RedirectingGenerativeConstantConstructor(
                      defaultValues,
                      constructorInvocation);
            }
          }
          return result.element;
        } else {
          reporter.reportErrorMessage(
              call, MessageKind.CONSTRUCTOR_CALL_EXPECTED);
          return null;
        }
      } else {
        reporter.reportErrorMessage(
            link.head, MessageKind.INVALID_INITIALIZER);
      }
    }
    if (!resolvedSuper) {
      constructorInvocation = resolveImplicitSuperConstructorSend();
    }
    if (isConst && isValidAsConstant) {
      constructor.constantConstructor = new GenerativeConstantConstructor(
          constructor.enclosingClass.thisType,
          defaultValues,
          fieldInitializers,
          constructorInvocation);
    }
    return null;  // If there was no redirection always return null.
  }
}

class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> {
  final ResolverVisitor resolver;
  final bool inConstContext;

  ConstructorResolver(Compiler compiler, this.resolver,
                      {bool this.inConstContext: false})
      : super(compiler);

  ResolutionRegistry get registry => resolver.registry;

  visitNode(Node node) {
    throw 'not supported';
  }

  ConstructorResult reportAndCreateErroneousConstructorElement(
      Spannable diagnosticNode,
      ConstructorResultKind resultKind,
      DartType type,
      Element enclosing,
      String name,
      MessageKind kind,
      Map arguments,
      {bool isError: false,
       bool missingConstructor: false,
       List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) {
    if (missingConstructor) {
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    } else {
      registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
    }
    DiagnosticMessage message =
        reporter.createMessage(diagnosticNode, kind, arguments);
    if (isError || inConstContext) {
      reporter.reportError(message, infos);
    } else {
      reporter.reportWarning(message, infos);
    }
    ErroneousElement error = new ErroneousConstructorElementX(
        kind, arguments, name, enclosing);
    if (type == null) {
      type = new MalformedType(error, null);
    }
    return new ConstructorResult.forError(resultKind, error, type);
  }

  ConstructorResult resolveConstructor(
      PrefixElement prefix,
      InterfaceType type,
      Node diagnosticNode,
      String constructorName) {
    ClassElement cls = type.element;
    cls.ensureResolved(resolution);
    ConstructorElement constructor = findConstructor(
        resolver.enclosingElement.library, cls, constructorName);
    if (constructor == null) {
      MessageKind kind = constructorName.isEmpty
          ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR
          : MessageKind.CANNOT_FIND_CONSTRUCTOR;
      return reportAndCreateErroneousConstructorElement(
          diagnosticNode,
          ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type,
          cls, constructorName, kind,
          {'className': cls.name, 'constructorName': constructorName},
          missingConstructor: true);
    } else if (inConstContext && !constructor.isConst) {
      reporter.reportErrorMessage(
          diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
      return new ConstructorResult(
          ConstructorResultKind.NON_CONSTANT, prefix, constructor, type);
    } else {
      if (cls.isEnumClass && resolver.currentClass != cls) {
        return reportAndCreateErroneousConstructorElement(
            diagnosticNode,
            ConstructorResultKind.INVALID_TYPE, type,
            cls, constructorName,
            MessageKind.CANNOT_INSTANTIATE_ENUM,
            {'enumName': cls.name},
            isError: true);
      }
      if (constructor.isGenerativeConstructor) {
        if (cls.isAbstract) {
          reporter.reportWarningMessage(
              diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
          registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION);
          return new ConstructorResult(
              ConstructorResultKind.ABSTRACT, prefix, constructor, type);
        } else {
          return new ConstructorResult(
              ConstructorResultKind.GENERATIVE, prefix, constructor, type);
        }
      } else {
        assert(invariant(diagnosticNode, constructor.isFactoryConstructor,
            message: "Unexpected constructor $constructor."));
        return new ConstructorResult(
            ConstructorResultKind.FACTORY, prefix, constructor, type);
      }
    }
  }

  ConstructorResult visitNewExpression(NewExpression node) {
    Node selector = node.send.selector;
    ConstructorResult result = visit(selector);
    assert(invariant(selector, result != null,
        message: 'No result returned for $selector.'));
    return finishConstructorReference(result, node.send.selector, node);
  }

  /// Finishes resolution of a constructor reference and records the
  /// type of the constructed instance on [expression].
  ConstructorResult finishConstructorReference(
      ConstructorResult result,
      Node diagnosticNode,
      Node expression) {
    assert(invariant(diagnosticNode, result != null,
        message: 'No result returned for $diagnosticNode.'));

    if (result.kind != null) {
      resolver.registry.setType(expression, result.type);
      return result;
    }

    // Find the unnamed constructor if the reference resolved to a
    // class.
    if (result.type != null) {
      // The unnamed constructor may not exist, so [e] may become unresolved.
      result = resolveConstructor(
          result.prefix, result.type, diagnosticNode, '');
    } else {
      Element element = result.element;
      if (element.isMalformed) {
        result = constructorResultForErroneous(diagnosticNode, element);
      } else {
        result = reportAndCreateErroneousConstructorElement(
            diagnosticNode,
            ConstructorResultKind.INVALID_TYPE, null,
            element, element.name,
            MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
      }
    }
    resolver.registry.setType(expression, result.type);
    return result;
  }

  ConstructorResult visitTypeAnnotation(TypeAnnotation node) {
    // This is not really resolving a type-annotation, but the name of the
    // constructor. Therefore we allow deferred types.
    DartType type = resolver.resolveTypeAnnotation(
        node,
        malformedIsError: inConstContext,
        deferredIsMalformed: false);
    Send send = node.typeName.asSend();
    PrefixElement prefix;
    if (send != null) {
      // The type name is of the form [: prefix . identifier :].
      String name = send.receiver.asIdentifier().source;
      Element element = lookupInScope(reporter, send, resolver.scope, name);
      if (element != null && element.isPrefix) {
        prefix = element;
      }
    }
    return constructorResultForType(node, type, prefix: prefix);
  }

  ConstructorResult visitSend(Send node) {
    ConstructorResult receiver = visit(node.receiver);
    assert(invariant(node.receiver, receiver != null,
        message: 'No result returned for $node.receiver.'));
    if (receiver.kind != null) {
      assert(invariant(node, receiver.element.isMalformed,
          message: "Unexpected prefix result: $receiver."));
      // We have already found an error.
      return receiver;
    }

    Identifier name = node.selector.asIdentifier();
    if (name == null) {
      reporter.internalError(node.selector, 'unexpected node');
    }

    if (receiver.type != null) {
      if (receiver.type.isInterfaceType) {
        return resolveConstructor(
            receiver.prefix, receiver.type, name, name.source);
      } else {
        // TODO(johnniwinther): Update the message for the different types.
        return reportAndCreateErroneousConstructorElement(
            name,
            ConstructorResultKind.INVALID_TYPE, null,
            resolver.enclosingElement, name.source,
            MessageKind.NOT_A_TYPE, {'node': name});
      }
    } else if (receiver.element.isPrefix) {
      PrefixElement prefix = receiver.element;
      Element member = prefix.lookupLocalMember(name.source);
      return constructorResultForElement(
          node, name.source, member, prefix: prefix);
    } else {
      return reporter.internalError(
          node.receiver, 'unexpected receiver $receiver');
    }
  }

  ConstructorResult visitIdentifier(Identifier node) {
    String name = node.source;
    Element element = lookupInScope(reporter, node, resolver.scope, name);
    registry.useElement(node, element);
    return constructorResultForElement(node, name, element);
  }

  /// Assumed to be called by [resolveRedirectingFactory].
  ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
    Node constructorReference = node.constructorReference;
    return finishConstructorReference(visit(constructorReference),
        constructorReference, node);
  }

  ConstructorResult constructorResultForElement(
      Node node, String name, Element element,
      {PrefixElement prefix}) {
    element = Elements.unwrap(element, reporter, node);
    if (element == null) {
      return reportAndCreateErroneousConstructorElement(
          node,
          ConstructorResultKind.INVALID_TYPE, null,
          resolver.enclosingElement, name,
          MessageKind.CANNOT_RESOLVE,
          {'name': name});
    } else if (element.isAmbiguous) {
      AmbiguousElement ambiguous = element;
      return reportAndCreateErroneousConstructorElement(
          node,
          ConstructorResultKind.INVALID_TYPE, null,
          resolver.enclosingElement, name,
          ambiguous.messageKind,
          ambiguous.messageArguments,
          infos: ambiguous.computeInfos(resolver.enclosingElement, reporter));
    } else if (element.isMalformed) {
      return constructorResultForErroneous(node, element);
    } else if (element.isClass) {
      ClassElement cls = element;
      cls.computeType(resolution);
      return constructorResultForType(node, cls.rawType, prefix: prefix);
    } else if (element.isPrefix) {
      return new ConstructorResult.forPrefix(element);
    } else if (element.isTypedef) {
      TypedefElement typdef = element;
      typdef.ensureResolved(resolution);
      return constructorResultForType(node, typdef.rawType);
    } else if (element.isTypeVariable) {
      TypeVariableElement typeVariableElement = element;
      return constructorResultForType(node, typeVariableElement.type);
    } else {
      return reportAndCreateErroneousConstructorElement(
          node,
          ConstructorResultKind.INVALID_TYPE, null,
          resolver.enclosingElement, name,
          MessageKind.NOT_A_TYPE, {'node': name});
    }
  }

  ConstructorResult constructorResultForErroneous(
      Node node, Element error) {
    if (error is! ErroneousElementX) {
      // Parser error. The error has already been reported.
      error = new ErroneousConstructorElementX(
          MessageKind.NOT_A_TYPE, {'node': node},
          error.name, error);
      registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
    }
    return new ConstructorResult.forError(
        ConstructorResultKind.INVALID_TYPE,
        error,
        new MalformedType(error, null));
  }

  ConstructorResult constructorResultForType(
      Node node,
      DartType type,
      {PrefixElement prefix}) {
    String name = type.name;
    if (type.isMalformed) {
      return new ConstructorResult.forError(
          ConstructorResultKind.INVALID_TYPE, type.element, type);
    } else if (type.isInterfaceType) {
      return new ConstructorResult.forType(prefix, type);
    } else if (type.isTypedef) {
      return reportAndCreateErroneousConstructorElement(
          node,
          ConstructorResultKind.INVALID_TYPE, type,
          resolver.enclosingElement, name,
          MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name});
    } else if (type.isTypeVariable) {
      return reportAndCreateErroneousConstructorElement(
          node,
          ConstructorResultKind.INVALID_TYPE, type,
          resolver.enclosingElement, name,
          MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
          {'typeVariableName': name});
    }
    return reporter.internalError(node, "Unexpected constructor type $type");
  }

}

/// The kind of constructor found by the [ConstructorResolver].
enum ConstructorResultKind {
  /// A generative or redirecting generative constructor.
  GENERATIVE,
  /// A factory or redirecting factory constructor.
  FACTORY,
  /// A generative or redirecting generative constructor on an abstract class.
  ABSTRACT,
  /// No constructor was found because the type was invalid, for instance
  /// unresolved, an enum class, a type variable, a typedef or a non-type.
  INVALID_TYPE,
  /// No constructor of the sought name was found on the class.
  UNRESOLVED_CONSTRUCTOR,
  /// A non-constant constructor was found for a const constructor invocation.
  NON_CONSTANT,
}

/// The (partial) result of the resolution of a new expression used in
/// [ConstructorResolver].
class ConstructorResult {
  /// The prefix used to access the constructor. For instance `prefix` in `new
  /// prefix.Class.constructorName()`.
  final PrefixElement prefix;

  /// The kind of the found constructor.
  final ConstructorResultKind kind;

  /// The currently found element. Since [ConstructorResult] is used for partial
  /// results, this might be a [PrefixElement], a [ClassElement], a
  /// [ConstructorElement] or in the negative cases an [ErroneousElement].
  final Element element;

  /// The type of the new expression. For instance `Foo<String>` in
  /// `new prefix.Foo<String>.constructorName()`.
  final DartType type;

  /// Creates a fully resolved constructor access where [element] is resolved
  /// to a constructor and [type] to an interface type.
  ConstructorResult(this.kind,
                    this.prefix,
                    ConstructorElement this.element,
                    InterfaceType this.type);

  /// Creates a fully resolved constructor access where [element] is an
  /// [ErroneousElement].
  // TODO(johnniwinther): Do we still need the prefix for cases like
  // `new deferred.Class.unresolvedConstructor()` ?
  ConstructorResult.forError(
      this.kind, ErroneousElement this.element, this.type)
      : prefix = null;

  /// Creates a constructor access that is partially resolved to a prefix. For
  /// instance `prefix` of `new prefix.Class()`.
  ConstructorResult.forPrefix(this.element)
      : prefix = null,
        kind = null,
        type = null;

  /// Creates a constructor access that is partially resolved to a type. For
  /// instance `Foo<String>` of `new Foo<String>.constructorName()`.
  ConstructorResult.forType(this.prefix, this.type)
      : kind = null,
        element = null;

  bool get isDeferred => prefix != null && prefix.isDeferred;

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('ConstructorResult(');
    if (kind != null) {
      sb.write('kind=$kind,');
      if (prefix != null) {
        sb.write('prefix=$prefix,');
      }
      sb.write('element=$element,');
      sb.write('type=$type');
    } else if (element != null) {
      sb.write('element=$element');
    } else {
      if (prefix != null) {
        sb.write('prefix=$prefix,');
      }
      sb.write('type=$type');
    }
    sb.write(')');
    return sb.toString();
  }
}

/// Lookup the [constructorName] constructor in [cls] and normalize the result
/// with respect to privacy and patching.
ConstructorElement findConstructor(
    LibraryElement currentLibrary,
    ClassElement cls,
    String constructorName) {
  if (Name.isPrivateName(constructorName) &&
      currentLibrary.library != cls.library) {
    // TODO(johnniwinther): Report a special error on unaccessible private
    // constructors.
    return null;
  }
  // TODO(johnniwinther): Use [Name] for lookup.
  ConstructorElement constructor = cls.lookupConstructor(constructorName);
  if (constructor != null) {
    constructor = constructor.declaration;
  }
  return constructor;
}
