// 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}) {
    if (missingConstructor) {
      registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
    } else {
      registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
    }
    if (isError || inConstContext) {
      reporter.reportErrorMessage(
          diagnosticNode, kind, arguments);
    } else {
      reporter.reportWarningMessage(
          diagnosticNode, kind, arguments);
    }
    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 = resolver.reportLookupErrorIfAny(
          lookupInScope(reporter, send, resolver.scope, name), node, 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 = resolver.reportLookupErrorIfAny(
        lookupInScope(reporter, node, resolver.scope, name), node, name);
    registry.useElement(node, element);
    // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
    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.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;
}
