// Copyright (c) 2012, 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;

import 'dart:collection' show Queue;

import '../common.dart';
import '../common/names.dart' show Identifiers;
import '../common/resolution.dart'
    show ParsingContext, Resolution, ResolutionImpact, Target;
import '../common/tasks.dart' show CompilerTask, Measurer;
import '../compile_time_constants.dart' show ConstantCompiler;
import '../constants/expressions.dart'
    show
        ConstantExpression,
        ConstantExpressionKind,
        ConstructedConstantExpression,
        ErroneousConstantExpression;
import '../constants/values.dart' show ConstantValue;
import '../core_types.dart' show CoreClasses, CoreTypes, CommonElements;
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart'
    show
        BaseClassElementX,
        BaseFunctionElementX,
        ConstructorElementX,
        FieldElementX,
        FunctionElementX,
        GetterElementX,
        MetadataAnnotationX,
        MixinApplicationElementX,
        ParameterMetadataAnnotation,
        SetterElementX,
        TypedefElementX;
import '../enqueue.dart';
import '../options.dart';
import '../tokens/token.dart'
    show
        isBinaryOperator,
        isMinusOperator,
        isTernaryOperator,
        isUnaryOperator,
        isUserDefinableOperator;
import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../universe/feature.dart' show Feature;
import '../universe/use.dart' show StaticUse, TypeUse;
import '../universe/world_impact.dart' show WorldImpact;
import '../util/util.dart' show Link, Setlet;
import '../world.dart';
import 'class_hierarchy.dart';
import 'class_members.dart' show MembersCreator;
import 'constructors.dart';
import 'members.dart';
import 'registry.dart';
import 'resolution_result.dart';
import 'signatures.dart';
import 'tree_elements.dart';
import 'typedefs.dart';

class ResolverTask extends CompilerTask {
  final ConstantCompiler constantCompiler;
  final Resolution resolution;
  final OpenWorld world;

  ResolverTask(
      this.resolution, this.constantCompiler, this.world, Measurer measurer)
      : super(measurer);

  String get name => 'Resolver';

  DiagnosticReporter get reporter => resolution.reporter;
  Target get target => resolution.target;
  CoreTypes get coreTypes => resolution.coreTypes;
  CoreClasses get coreClasses => resolution.coreClasses;
  CommonElements get commonElements => resolution.commonElements;
  ParsingContext get parsingContext => resolution.parsingContext;
  CompilerOptions get options => resolution.options;
  ResolutionEnqueuer get enqueuer => resolution.enqueuer;

  ResolutionImpact resolve(Element element) {
    return measure(() {
      if (Elements.isMalformed(element)) {
        // TODO(johnniwinther): Add a predicate for this.
        assert(invariant(element, element is! ErroneousElement,
            message: "Element $element expected to have parse errors."));
        _ensureTreeElements(element);
        return const ResolutionImpact();
      }

      WorldImpact processMetadata([WorldImpact result]) {
        for (MetadataAnnotation metadata in element.implementation.metadata) {
          metadata.ensureResolved(resolution);
        }
        return result;
      }

      if (element.isConstructor ||
          element.isFunction ||
          element.isGetter ||
          element.isSetter) {
        return processMetadata(resolveMethodElement(element));
      }

      if (element.isField) {
        return processMetadata(resolveField(element));
      }
      if (element.isClass) {
        ClassElement cls = element;
        cls.ensureResolved(resolution);
        return processMetadata(const ResolutionImpact());
      } else if (element.isTypedef) {
        TypedefElement typdef = element;
        return processMetadata(resolveTypedef(typdef));
      }

      reporter.internalError(element, "resolve($element) not implemented.");
    });
  }

  void resolveRedirectingConstructor(InitializerResolver resolver, Node node,
      FunctionElement constructor, FunctionElement redirection) {
    assert(invariant(node, constructor.isImplementation,
        message: 'Redirecting constructors must be resolved on implementation '
            'elements.'));
    Setlet<FunctionElement> seen = new Setlet<FunctionElement>();
    seen.add(constructor);
    while (redirection != null) {
      // Ensure that we follow redirections through implementation elements.
      redirection = redirection.implementation;
      if (redirection.isError) {
        break;
      }
      if (seen.contains(redirection)) {
        reporter.reportErrorMessage(
            node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
        return;
      }
      seen.add(redirection);
      redirection = resolver.visitor.resolveConstructorRedirection(redirection);
    }
  }

  static void processAsyncMarker(Resolution resolution,
      BaseFunctionElementX element, ResolutionRegistry registry) {
    DiagnosticReporter reporter = resolution.reporter;
    CoreClasses coreClasses = resolution.coreClasses;
    FunctionExpression functionExpression = element.node;
    AsyncModifier asyncModifier = functionExpression.asyncModifier;
    if (asyncModifier != null) {
      if (!resolution.target.supportsAsyncAwait) {
        reporter.reportErrorMessage(functionExpression.asyncModifier,
            MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
      } else {
        if (asyncModifier.isAsynchronous) {
          element.asyncMarker = asyncModifier.isYielding
              ? AsyncMarker.ASYNC_STAR
              : AsyncMarker.ASYNC;
        } else {
          element.asyncMarker = AsyncMarker.SYNC_STAR;
        }
        if (element.isAbstract) {
          reporter.reportErrorMessage(
              asyncModifier,
              MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
              {'modifier': element.asyncMarker});
        } else if (element.isConstructor) {
          reporter.reportErrorMessage(
              asyncModifier,
              MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR,
              {'modifier': element.asyncMarker});
        } else {
          if (element.isSetter) {
            reporter.reportErrorMessage(
                asyncModifier,
                MessageKind.ASYNC_MODIFIER_ON_SETTER,
                {'modifier': element.asyncMarker});
          }
          if (functionExpression.body.asReturn() != null &&
              element.asyncMarker.isYielding) {
            reporter.reportErrorMessage(
                asyncModifier,
                MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
                {'modifier': element.asyncMarker});
          }
        }
        switch (element.asyncMarker) {
          case AsyncMarker.ASYNC:
            registry.registerFeature(Feature.ASYNC);
            coreClasses.futureClass.ensureResolved(resolution);
            break;
          case AsyncMarker.ASYNC_STAR:
            registry.registerFeature(Feature.ASYNC_STAR);
            coreClasses.streamClass.ensureResolved(resolution);
            break;
          case AsyncMarker.SYNC_STAR:
            registry.registerFeature(Feature.SYNC_STAR);
            coreClasses.iterableClass.ensureResolved(resolution);
            break;
        }
      }
    }
  }

  bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) {
    assert(classElement != null);
    while (classElement != null) {
      if (target.isNative(classElement)) return true;
      classElement = classElement.superclass;
    }
    return false;
  }

  WorldImpact resolveMethodElementImplementation(
      FunctionElement element, FunctionExpression tree) {
    return reporter.withCurrentElement(element, () {
      if (element.isExternal && tree.hasBody) {
        reporter.reportErrorMessage(element, MessageKind.EXTERNAL_WITH_BODY,
            {'functionName': element.name});
      }
      if (element.isConstructor) {
        if (tree.returnType != null) {
          reporter.reportErrorMessage(
              tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE);
        }
        if (tree.hasBody && element.isConst) {
          if (element.isGenerativeConstructor) {
            reporter.reportErrorMessage(
                tree, MessageKind.CONST_CONSTRUCTOR_WITH_BODY);
          } else if (!tree.isRedirectingFactory) {
            reporter.reportErrorMessage(tree, MessageKind.CONST_FACTORY);
          }
        }
      }

      ResolverVisitor visitor = visitorFor(element);
      ResolutionRegistry registry = visitor.registry;
      registry.defineFunction(tree, element);
      visitor.setupFunction(tree, element); // Modifies the scope.
      processAsyncMarker(resolution, element, registry);

      if (element.isGenerativeConstructor) {
        // Even if there is no initializer list we still have to do the
        // resolution in case there is an implicit super constructor call.
        InitializerResolver resolver =
            new InitializerResolver(visitor, element, tree);
        FunctionElement redirection = resolver.resolveInitializers();
        if (redirection != null) {
          resolveRedirectingConstructor(resolver, tree, element, redirection);
        }
      } else if (tree.initializers != null) {
        reporter.reportErrorMessage(
            tree, MessageKind.FUNCTION_WITH_INITIALIZER);
      }

      if (!options.analyzeSignaturesOnly || tree.isRedirectingFactory) {
        // We need to analyze the redirecting factory bodies to ensure that
        // we can analyze compile-time constants.
        visitor.visit(tree.body);
      }

      // Get the resolution tree and check that the resolved
      // function doesn't use 'super' if it is mixed into another
      // class. This is the part of the 'super' mixin check that
      // happens when a function is resolved after the mixin
      // application has been performed.
      TreeElements resolutionTree = registry.mapping;
      ClassElement enclosingClass = element.enclosingClass;
      if (enclosingClass != null) {
        // TODO(johnniwinther): Find another way to obtain mixin uses.
        Iterable<MixinApplicationElement> mixinUses =
            world.allMixinUsesOf(enclosingClass);
        ClassElement mixin = enclosingClass;
        for (MixinApplicationElement mixinApplication in mixinUses) {
          checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
        }
      }

      // TODO(9631): support noSuchMethod on native classes.
      if (element.isFunction &&
          element.isInstanceMember &&
          element.name == Identifiers.noSuchMethod_ &&
          _isNativeClassOrExtendsNativeClass(enclosingClass)) {
        reporter.reportErrorMessage(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE);
      }

      resolution.target.resolveNativeElement(element, registry.impactBuilder);

      return registry.impactBuilder;
    });
  }

  WorldImpact resolveMethodElement(FunctionElementX element) {
    assert(invariant(element, element.isDeclaration));
    return reporter.withCurrentElement(element, () {
      if (enqueuer.hasBeenProcessed(element)) {
        // TODO(karlklose): Remove the check for [isConstructor]. [elememts]
        // should never be non-null, not even for constructors.
        assert(invariant(element, element.isConstructor,
            message: 'Non-constructor element $element '
                'has already been analyzed.'));
        return const ResolutionImpact();
      }
      if (element.isSynthesized) {
        if (element.isGenerativeConstructor) {
          ResolutionRegistry registry =
              new ResolutionRegistry(this.target, _ensureTreeElements(element));
          ConstructorElement constructor = element.asFunctionElement();
          ConstructorElement target = constructor.definingConstructor;
          // Ensure the signature of the synthesized element is
          // resolved. This is the only place where the resolver is
          // seeing this element.
          FunctionType type = element.computeType(resolution);
          if (!target.isMalformed) {
            registry.registerStaticUse(new StaticUse.superConstructorInvoke(
                // TODO(johnniwinther): Provide the right call structure for
                // forwarding constructors.
                target,
                CallStructure.NO_ARGS));
          }
          // TODO(johnniwinther): Remove this substitution when synthesized
          // constructors handle type variables correctly.
          type = type.substByContext(
              constructor.enclosingClass.asInstanceOf(target.enclosingClass));
          type.parameterTypes.forEach(registry.registerCheckedModeCheck);
          type.optionalParameterTypes
              .forEach(registry.registerCheckedModeCheck);
          type.namedParameterTypes.forEach(registry.registerCheckedModeCheck);
          return registry.impactBuilder;
        } else {
          assert(element.isDeferredLoaderGetter || element.isMalformed);
          _ensureTreeElements(element);
          return const ResolutionImpact();
        }
      } else {
        element.parseNode(resolution.parsingContext);
        element.computeType(resolution);
        FunctionElementX implementation = element;
        if (element.isExternal) {
          implementation = target.resolveExternalFunction(element);
        }
        return resolveMethodElementImplementation(
            implementation, implementation.node);
      }
    });
  }

  /// Creates a [ResolverVisitor] for resolving an AST in context of [element].
  /// If [useEnclosingScope] is `true` then the initial scope of the visitor
  /// does not include inner scope of [element].
  ///
  /// This method should only be used by this library (or tests of
  /// this library).
  ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) {
    return new ResolverVisitor(resolution, element,
        new ResolutionRegistry(target, _ensureTreeElements(element)),
        useEnclosingScope: useEnclosingScope);
  }

  WorldImpact resolveField(FieldElementX element) {
    return reporter.withCurrentElement(element, () {
      VariableDefinitions tree = element.parseNode(parsingContext);
      if (element.modifiers.isStatic && element.isTopLevel) {
        reporter.reportErrorMessage(element.modifiers.getStatic(),
            MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC);
      }
      ResolverVisitor visitor = visitorFor(element);
      ResolutionRegistry registry = visitor.registry;
      // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates
      // to the backend ast.
      registry.defineElement(element.definition, element);
      // TODO(johnniwinther): Share the resolved type between all variables
      // declared in the same declaration.
      if (tree.type != null) {
        DartType type = visitor.resolveTypeAnnotation(tree.type);
        assert(invariant(
            element,
            element.variables.type == null ||
                // Crude check but we have no equivalence relation that
                // equates malformed types, like matching creations of type
                // `Foo<Unresolved>`.
                element.variables.type.toString() == type.toString(),
            message: "Unexpected type computed for $element. "
                "Was ${element.variables.type}, computed $type."));
        element.variables.type = type;
      } else if (element.variables.type == null) {
        // Only assign the dynamic type if the element has no known type. This
        // happens for enum fields where the type is known but is not in the
        // synthesized AST.
        element.variables.type = const DynamicType();
      } else {
        registry.registerCheckedModeCheck(element.variables.type);
      }

      Expression initializer = element.initializer;
      Modifiers modifiers = element.modifiers;
      if (initializer != null) {
        // TODO(johnniwinther): Avoid analyzing initializers if
        // [Compiler.analyzeSignaturesOnly] is set.
        ResolutionResult result = visitor.visit(initializer);
        if (result.isConstant) {
          element.constant = result.constant;
        }
      } else if (modifiers.isConst) {
        reporter.reportErrorMessage(
            element, MessageKind.CONST_WITHOUT_INITIALIZER);
      } else if (modifiers.isFinal && !element.isInstanceMember) {
        reporter.reportErrorMessage(
            element, MessageKind.FINAL_WITHOUT_INITIALIZER);
      } else {
        registry.registerFeature(Feature.FIELD_WITHOUT_INITIALIZER);
      }

      if (Elements.isStaticOrTopLevelField(element)) {
        visitor.addDeferredAction(element, () {
          if (element.modifiers.isConst) {
            element.constant = constantCompiler.compileConstant(element);
          } else {
            element.constant = constantCompiler.compileVariable(element);
          }
        });
        if (initializer != null) {
          if (!element.modifiers.isConst &&
              initializer.asLiteralNull() == null) {
            // TODO(johnniwinther): Determine the const-ness eagerly to avoid
            // unnecessary registrations.
            registry.registerFeature(Feature.LAZY_FIELD);
          }
        }
      }

      // Perform various checks as side effect of "computing" the type.
      element.computeType(resolution);

      resolution.target.resolveNativeElement(element, registry.impactBuilder);

      return registry.impactBuilder;
    });
  }

  DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) {
    DartType type = _resolveReturnType(element, annotation);
    if (type.isVoid) {
      reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED);
    }
    return type;
  }

  DartType _resolveReturnType(Element element, TypeAnnotation annotation) {
    if (annotation == null) return const DynamicType();
    DartType result = visitorFor(element).resolveTypeAnnotation(annotation);
    assert(invariant(annotation, result != null,
        message: "No type computed for $annotation."));
    if (result == null) {
      // TODO(karklose): warning.
      return const DynamicType();
    }
    return result;
  }

  void resolveRedirectionChain(ConstructorElement constructor, Spannable node) {
    ConstructorElement target = constructor;
    DartType targetType;
    List<ConstructorElement> seen = new List<ConstructorElement>();
    bool isMalformed = false;
    // Follow the chain of redirections and check for cycles.
    while (target.isRedirectingFactory) {
      if (target.hasEffectiveTarget) {
        // We found a constructor that already has been processed.
        // TODO(johnniwinther): Should `effectiveTargetType` be part of the
        // interface?
        targetType =
            target.computeEffectiveTargetType(target.enclosingClass.thisType);
        assert(invariant(target, targetType != null,
            message: 'Redirection target type has not been computed for '
                '$target'));
        target = target.effectiveTarget;
        break;
      }

      Element nextTarget = target.immediateRedirectionTarget;

      if (seen.contains(nextTarget)) {
        reporter.reportErrorMessage(
            node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
        targetType = target.enclosingClass.thisType;
        isMalformed = true;
        break;
      }
      seen.add(target);
      target = nextTarget;
    }

    if (target.isGenerativeConstructor && target.enclosingClass.isAbstract) {
      isMalformed = true;
    }
    if (target.isMalformed) {
      isMalformed = true;
    }

    if (targetType == null) {
      assert(!target.isRedirectingFactory);
      targetType = target.enclosingClass.thisType;
    }

    // [target] is now the actual target of the redirections.  Run through
    // the constructors again and set their [redirectionTarget], so that we
    // do not have to run the loop for these constructors again. Furthermore,
    // compute [redirectionTargetType] for each factory by computing the
    // substitution of the target type with respect to the factory type.
    while (!seen.isEmpty) {
      ConstructorElementX factory = seen.removeLast();
      ResolvedAst resolvedAst = factory.resolvedAst;
      assert(invariant(node, resolvedAst != null,
          message: 'No ResolvedAst for $factory.'));
      FunctionExpression functionNode = resolvedAst.node;
      RedirectingFactoryBody redirectionNode = resolvedAst.body;
      DartType factoryType = resolvedAst.elements.getType(redirectionNode);
      if (!factoryType.isDynamic) {
        targetType = targetType.substByContext(factoryType);
      }
      factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed);
    }
  }

  /**
   * Load and resolve the supertypes of [cls].
   *
   * Warning: do not call this method directly. It should only be
   * called by [resolveClass] and [ClassSupertypeResolver].
   */
  void loadSupertypes(BaseClassElementX cls, Spannable from) {
    measure(() {
      if (cls.supertypeLoadState == STATE_DONE) return;
      if (cls.supertypeLoadState == STATE_STARTED) {
        reporter.reportErrorMessage(
            from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name});
        cls.supertypeLoadState = STATE_DONE;
        cls.hasIncompleteHierarchy = true;
        cls.allSupertypesAndSelf = coreClasses.objectClass.allSupertypesAndSelf
            .extendClass(cls.computeType(resolution));
        cls.supertype = cls.allSupertypes.head;
        assert(invariant(from, cls.supertype != null,
            message: 'Missing supertype on cyclic class $cls.'));
        cls.interfaces = const Link<DartType>();
        return;
      }
      cls.supertypeLoadState = STATE_STARTED;
      reporter.withCurrentElement(cls, () {
        // TODO(ahe): Cache the node in cls.
        cls
            .parseNode(parsingContext)
            .accept(new ClassSupertypeResolver(resolution, cls));
        if (cls.supertypeLoadState != STATE_DONE) {
          cls.supertypeLoadState = STATE_DONE;
        }
      });
    });
  }

  // TODO(johnniwinther): Remove this queue when resolution has been split into
  // syntax and semantic resolution.
  TypeDeclarationElement currentlyResolvedTypeDeclaration;
  Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
  Queue<ClassElement> pendingClassesToBePostProcessed =
      new Queue<ClassElement>();

  /// Resolve [element] using [resolveTypeDeclaration].
  ///
  /// This methods ensure that class declarations encountered through type
  /// annotations during the resolution of [element] are resolved after
  /// [element] has been resolved.
  // TODO(johnniwinther): Encapsulate this functionality in a
  // 'TypeDeclarationResolver'.
  _resolveTypeDeclaration(
      TypeDeclarationElement element, resolveTypeDeclaration()) {
    return reporter.withCurrentElement(element, () {
      return measure(() {
        TypeDeclarationElement previousResolvedTypeDeclaration =
            currentlyResolvedTypeDeclaration;
        currentlyResolvedTypeDeclaration = element;
        var result = resolveTypeDeclaration();
        if (previousResolvedTypeDeclaration == null) {
          do {
            while (!pendingClassesToBeResolved.isEmpty) {
              pendingClassesToBeResolved
                  .removeFirst()
                  .ensureResolved(resolution);
            }
            while (!pendingClassesToBePostProcessed.isEmpty) {
              _postProcessClassElement(
                  pendingClassesToBePostProcessed.removeFirst());
            }
          } while (!pendingClassesToBeResolved.isEmpty);
          assert(pendingClassesToBeResolved.isEmpty);
          assert(pendingClassesToBePostProcessed.isEmpty);
        }
        currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration;
        return result;
      });
    });
  }

  /**
   * Resolve the class [element].
   *
   * Before calling this method, [element] was constructed by the
   * scanner and most fields are null or empty. This method fills in
   * these fields and also ensure that the supertypes of [element] are
   * resolved.
   *
   * Warning: Do not call this method directly. Instead use
   * [:element.ensureResolved(resolution):].
   */
  TreeElements resolveClass(BaseClassElementX element) {
    return _resolveTypeDeclaration(element, () {
      // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
      ResolutionRegistry registry = new ResolutionRegistry(
          resolution.target, _ensureTreeElements(element));
      resolveClassInternal(element, registry);
      return element.treeElements;
    });
  }

  void ensureClassWillBeResolvedInternal(ClassElement element) {
    if (currentlyResolvedTypeDeclaration == null) {
      element.ensureResolved(resolution);
    } else {
      pendingClassesToBeResolved.add(element);
    }
  }

  void resolveClassInternal(
      BaseClassElementX element, ResolutionRegistry registry) {
    if (!element.isPatch) {
      reporter.withCurrentElement(
          element,
          () => measure(() {
                assert(element.resolutionState == STATE_NOT_STARTED);
                element.resolutionState = STATE_STARTED;
                Node tree = element.parseNode(parsingContext);
                loadSupertypes(element, tree);

                ClassResolverVisitor visitor =
                    new ClassResolverVisitor(resolution, element, registry);
                visitor.visit(tree);
                element.resolutionState = STATE_DONE;
                pendingClassesToBePostProcessed.add(element);
              }));
      if (element.isPatched) {
        // Ensure handling patch after origin.
        element.patch.ensureResolved(resolution);
      }
    } else {
      // Handle patch classes:
      element.resolutionState = STATE_STARTED;
      // Ensure handling origin before patch.
      element.origin.ensureResolved(resolution);
      // Ensure that the type is computed.
      element.computeType(resolution);
      // Copy class hierarchy from origin.
      element.supertype = element.origin.supertype;
      element.interfaces = element.origin.interfaces;
      element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf;
      // Stepwise assignment to ensure invariant.
      element.supertypeLoadState = STATE_STARTED;
      element.supertypeLoadState = STATE_DONE;
      element.resolutionState = STATE_DONE;
      // TODO(johnniwinther): Check matching type variables and
      // empty extends/implements clauses.
    }
  }

  void _postProcessClassElement(BaseClassElementX element) {
    for (MetadataAnnotation metadata in element.implementation.metadata) {
      metadata.ensureResolved(resolution);
      ConstantValue value =
          resolution.constants.getConstantValue(metadata.constant);
      if (!element.isProxy && resolution.isProxyConstant(value)) {
        element.isProxy = true;
      }
    }

    // Force resolution of metadata on non-instance members since they may be
    // inspected by the backend while emitting. Metadata on instance members is
    // handled as a result of processing instantiated class members in the
    // enqueuer.
    // TODO(ahe): Avoid this eager resolution.
    element.forEachMember((_, Element member) {
      if (!member.isInstanceMember) {
        reporter.withCurrentElement(member, () {
          for (MetadataAnnotation metadata in member.implementation.metadata) {
            metadata.ensureResolved(resolution);
          }
        });
      }
    });

    computeClassMember(element, Identifiers.call);
  }

  void computeClassMembers(ClassElement element) {
    MembersCreator.computeAllClassMembers(resolution, element);
  }

  void computeClassMember(ClassElement element, String name) {
    MembersCreator.computeClassMembersByName(resolution, element, name);
  }

  void checkClass(ClassElement element) {
    computeClassMembers(element);
    if (element.isMixinApplication) {
      checkMixinApplication(element);
    } else {
      checkClassMembers(element);
    }
  }

  void checkMixinApplication(MixinApplicationElementX mixinApplication) {
    Modifiers modifiers = mixinApplication.modifiers;
    int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT;
    if (illegalFlags != 0) {
      Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags);
      reporter.reportErrorMessage(
          modifiers,
          MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS,
          {'modifiers': illegalModifiers});
    }

    // In case of cyclic mixin applications, the mixin chain will have
    // been cut. If so, we have already reported the error to the
    // user so we just return from here.
    ClassElement mixin = mixinApplication.mixin;
    if (mixin == null) return;

    // Check that we're not trying to use Object as a mixin.
    if (mixin.superclass == null) {
      reporter.reportErrorMessage(
          mixinApplication, MessageKind.ILLEGAL_MIXIN_OBJECT);
      // Avoid reporting additional errors for the Object class.
      return;
    }

    if (mixin.isEnumClass) {
      // Mixing in an enum has already caused a compile-time error.
      return;
    }

    // Check that the mixed in class has Object as its superclass.
    if (!mixin.superclass.isObject) {
      reporter.reportErrorMessage(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS);
    }

    // Check that the mixed in class doesn't have any constructors and
    // make sure we aren't mixing in methods that use 'super'.
    mixin.forEachLocalMember((AstElement member) {
      if (member.isGenerativeConstructor && !member.isSynthesized) {
        reporter.reportErrorMessage(
            member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR);
      } else {
        // Get the resolution tree and check that the resolved member
        // doesn't use 'super'. This is the part of the 'super' mixin
        // check that happens when a function is resolved before the
        // mixin application has been performed.
        // TODO(johnniwinther): Obtain the [TreeElements] for [member]
        // differently.
        if (resolution.enqueuer.hasBeenProcessed(member)) {
          if (member.resolvedAst.kind == ResolvedAstKind.PARSED) {
            checkMixinSuperUses(
                member.resolvedAst.elements, mixinApplication, mixin);
          }
        }
      }
    });
  }

  void checkMixinSuperUses(TreeElements elements,
      MixinApplicationElement mixinApplication, ClassElement mixin) {
    // TODO(johnniwinther): Avoid the use of [TreeElements] here.
    Iterable<SourceSpan> superUses = elements.superUses;
    if (superUses.isEmpty) return;
    DiagnosticMessage error = reporter.createMessage(mixinApplication,
        MessageKind.ILLEGAL_MIXIN_WITH_SUPER, {'className': mixin.name});
    // Show the user the problematic uses of 'super' in the mixin.
    List<DiagnosticMessage> infos = <DiagnosticMessage>[];
    for (SourceSpan use in superUses) {
      infos.add(
          reporter.createMessage(use, MessageKind.ILLEGAL_MIXIN_SUPER_USE));
    }
    reporter.reportError(error, infos);
  }

  void checkClassMembers(ClassElement cls) {
    assert(invariant(cls, cls.isDeclaration));
    if (cls.isObject) return;
    // TODO(johnniwinther): Should this be done on the implementation element as
    // well?
    List<Element> constConstructors = <Element>[];
    List<Element> nonFinalInstanceFields = <Element>[];
    cls.forEachMember((holder, member) {
      reporter.withCurrentElement(member, () {
        // Perform various checks as side effect of "computing" the type.
        member.computeType(resolution);

        // Check modifiers.
        if (member.isFunction && member.modifiers.isFinal) {
          reporter.reportErrorMessage(
              member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER);
        }
        if (member.isConstructor) {
          final mismatchedFlagsBits = member.modifiers.flags &
              (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT);
          if (mismatchedFlagsBits != 0) {
            final mismatchedFlags =
                new Modifiers.withFlags(null, mismatchedFlagsBits);
            reporter.reportErrorMessage(
                member,
                MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS,
                {'modifiers': mismatchedFlags});
          }
          if (member.modifiers.isConst) {
            constConstructors.add(member);
          }
        }
        if (member.isField) {
          if (member.modifiers.isConst && !member.modifiers.isStatic) {
            reporter.reportErrorMessage(
                member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER);
          }
          if (!member.modifiers.isStatic && !member.modifiers.isFinal) {
            nonFinalInstanceFields.add(member);
          }
        }
        checkAbstractField(member);
        checkUserDefinableOperator(member);
      });
    });
    if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) {
      Spannable span =
          constConstructors.length > 1 ? cls : constConstructors[0];
      DiagnosticMessage error = reporter.createMessage(
          span,
          MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
          {'className': cls.name});
      List<DiagnosticMessage> infos = <DiagnosticMessage>[];
      if (constConstructors.length > 1) {
        for (Element constructor in constConstructors) {
          infos.add(reporter.createMessage(constructor,
              MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR));
        }
      }
      for (Element field in nonFinalInstanceFields) {
        infos.add(reporter.createMessage(
            field, MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD));
      }
      reporter.reportError(error, infos);
    }
  }

  void checkAbstractField(Element member) {
    // Only check for getters. The test can only fail if there is both a setter
    // and a getter with the same name, and we only need to check each abstract
    // field once, so we just ignore setters.
    if (!member.isGetter) return;

    // Find the associated abstract field.
    ClassElement classElement = member.enclosingClass;
    Element lookupElement = classElement.lookupLocalMember(member.name);
    if (lookupElement == null) {
      reporter.internalError(member, "No abstract field for accessor");
    } else if (!lookupElement.isAbstractField) {
      if (lookupElement.isMalformed || lookupElement.isAmbiguous) return;
      reporter.internalError(
          member, "Inaccessible abstract field for accessor");
    }
    AbstractFieldElement field = lookupElement;

    GetterElementX getter = field.getter;
    if (getter == null) return;
    SetterElementX setter = field.setter;
    if (setter == null) return;
    int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
    int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
    if (getterFlags != setterFlags) {
      final mismatchedFlags =
          new Modifiers.withFlags(null, getterFlags ^ setterFlags);
      reporter.reportWarningMessage(field.getter, MessageKind.GETTER_MISMATCH,
          {'modifiers': mismatchedFlags});
      reporter.reportWarningMessage(field.setter, MessageKind.SETTER_MISMATCH,
          {'modifiers': mismatchedFlags});
    }
  }

  void checkUserDefinableOperator(Element member) {
    FunctionElement function = member.asFunctionElement();
    if (function == null) return;
    String value = member.name;
    if (value == null) return;
    if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return;

    bool isMinus = false;
    int requiredParameterCount;
    MessageKind messageKind;
    if (identical(value, 'unary-')) {
      isMinus = true;
      messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
      requiredParameterCount = 0;
    } else if (isMinusOperator(value)) {
      isMinus = true;
      messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
      requiredParameterCount = 1;
    } else if (isUnaryOperator(value)) {
      messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY;
      requiredParameterCount = 0;
    } else if (isBinaryOperator(value)) {
      messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY;
      requiredParameterCount = 1;
      if (identical(value, '==')) checkOverrideHashCode(member);
    } else if (isTernaryOperator(value)) {
      messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY;
      requiredParameterCount = 2;
    } else {
      reporter.internalError(
          function, 'Unexpected user defined operator $value');
    }
    checkArity(function, requiredParameterCount, messageKind, isMinus);
  }

  void checkOverrideHashCode(FunctionElement operatorEquals) {
    if (operatorEquals.isAbstract) return;
    ClassElement cls = operatorEquals.enclosingClass;
    Element hashCodeImplementation = cls.lookupLocalMember('hashCode');
    if (hashCodeImplementation != null) return;
    reporter.reportHintMessage(operatorEquals,
        MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, {'class': cls.name});
  }

  void checkArity(FunctionElement function, int requiredParameterCount,
      MessageKind messageKind, bool isMinus) {
    FunctionExpression node = function.node;
    FunctionSignature signature = function.functionSignature;
    if (signature.requiredParameterCount != requiredParameterCount) {
      Node errorNode = node;
      if (node.parameters != null) {
        if (isMinus ||
            signature.requiredParameterCount < requiredParameterCount) {
          // If there are too few parameters, point to the whole parameter list.
          // For instance
          //
          //     int operator +() {}
          //                   ^^
          //
          //     int operator []=(value) {}
          //                     ^^^^^^^
          //
          // For operator -, always point the whole parameter list, like
          //
          //     int operator -(a, b) {}
          //                   ^^^^^^
          //
          // instead of
          //
          //     int operator -(a, b) {}
          //                       ^
          //
          // since the correction might not be to remove 'b' but instead to
          // remove 'a, b'.
          errorNode = node.parameters;
        } else {
          errorNode = node.parameters.nodes.skip(requiredParameterCount).head;
        }
      }
      reporter.reportErrorMessage(
          errorNode, messageKind, {'operatorName': function.name});
    }
    if (signature.optionalParameterCount != 0) {
      Node errorNode =
          node.parameters.nodes.skip(signature.requiredParameterCount).head;
      if (signature.optionalParametersAreNamed) {
        reporter.reportErrorMessage(
            errorNode,
            MessageKind.OPERATOR_NAMED_PARAMETERS,
            {'operatorName': function.name});
      } else {
        reporter.reportErrorMessage(
            errorNode,
            MessageKind.OPERATOR_OPTIONAL_PARAMETERS,
            {'operatorName': function.name});
      }
    }
  }

  reportErrorWithContext(Element errorneousElement, MessageKind errorMessage,
      Element contextElement, MessageKind contextMessage) {
    reporter.reportError(
        reporter.createMessage(errorneousElement, errorMessage, {
          'memberName': contextElement.name,
          'className': contextElement.enclosingClass.name
        }),
        <DiagnosticMessage>[
          reporter.createMessage(contextElement, contextMessage),
        ]);
  }

  FunctionSignature resolveSignature(FunctionElementX element) {
    MessageKind defaultValuesError = null;
    if (element.isFactoryConstructor) {
      FunctionExpression body = element.parseNode(parsingContext);
      if (body.isRedirectingFactory) {
        defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT;
      }
    }
    return reporter.withCurrentElement(element, () {
      FunctionExpression node = element.parseNode(parsingContext);
      return measure(() => SignatureResolver.analyze(
          resolution,
          element.enclosingElement.buildScope(),
          node.typeVariables,
          node.parameters,
          node.returnType,
          element,
          new ResolutionRegistry(
              resolution.target, _ensureTreeElements(element)),
          defaultValuesError: defaultValuesError,
          createRealParameters: true));
    });
  }

  WorldImpact resolveTypedef(TypedefElementX element) {
    if (element.isResolved) return const ResolutionImpact();
    world.registerTypedef(element);
    return _resolveTypeDeclaration(element, () {
      ResolutionRegistry registry = new ResolutionRegistry(
          resolution.target, _ensureTreeElements(element));
      return reporter.withCurrentElement(element, () {
        return measure(() {
          assert(element.resolutionState == STATE_NOT_STARTED);
          element.resolutionState = STATE_STARTED;
          Typedef node = element.parseNode(parsingContext);
          TypedefResolverVisitor visitor =
              new TypedefResolverVisitor(resolution, element, registry);
          visitor.visit(node);
          element.resolutionState = STATE_DONE;
          return registry.impactBuilder;
        });
      });
    });
  }

  void resolveMetadataAnnotation(MetadataAnnotationX annotation) {
    reporter.withCurrentElement(
        annotation.annotatedElement,
        () => measure(() {
              assert(annotation.resolutionState == STATE_NOT_STARTED);
              annotation.resolutionState = STATE_STARTED;

              Node node = annotation.parseNode(parsingContext);
              Element annotatedElement = annotation.annotatedElement;
              AnalyzableElement context = annotatedElement.analyzableElement;
              ClassElement classElement = annotatedElement.enclosingClass;
              if (classElement != null) {
                // The annotation is resolved in the scope of [classElement].
                classElement.ensureResolved(resolution);
              }
              assert(invariant(node, context != null,
                  message: "No context found for metadata annotation "
                      "on $annotatedElement."));
              ResolverVisitor visitor =
                  visitorFor(context, useEnclosingScope: true);
              ResolutionRegistry registry = visitor.registry;
              node.accept(visitor);
              // TODO(johnniwinther): Avoid passing the [TreeElements] to
              // [compileMetadata].
              ConstantExpression constant = constantCompiler.compileMetadata(
                  annotation, node, registry.mapping);
              switch (constant.kind) {
                case ConstantExpressionKind.CONSTRUCTED:
                  ConstructedConstantExpression constructedConstant = constant;
                  if (constructedConstant.type.isGeneric &&
                      !constructedConstant.type.isRaw) {
                    // Const constructor calls cannot have type arguments.
                    // TODO(24312): Remove this.
                    reporter.reportErrorMessage(
                        node, MessageKind.INVALID_METADATA_GENERIC);
                    constant = new ErroneousConstantExpression();
                  }
                  break;
                case ConstantExpressionKind.VARIABLE:
                case ConstantExpressionKind.ERRONEOUS:
                  break;
                default:
                  reporter.reportErrorMessage(
                      node, MessageKind.INVALID_METADATA);
                  constant = new ErroneousConstantExpression();
                  break;
              }
              annotation.constant = constant;

              constantCompiler.evaluate(annotation.constant);
              // TODO(johnniwinther): Register the relation between the annotation
              // and the annotated element instead. This will allow the backend to
              // retrieve the backend constant and only register metadata on the
              // elements for which it is needed. (Issue 17732).
              annotation.resolutionState = STATE_DONE;
            }));
  }

  List<MetadataAnnotation> resolveMetadata(
      Element element, VariableDefinitions node) {
    List<MetadataAnnotation> metadata = <MetadataAnnotation>[];
    for (Metadata annotation in node.metadata.nodes) {
      ParameterMetadataAnnotation metadataAnnotation =
          new ParameterMetadataAnnotation(annotation);
      metadataAnnotation.annotatedElement = element;
      metadata.add(metadataAnnotation.ensureResolved(resolution));
    }
    return metadata;
  }
}

TreeElements _ensureTreeElements(AnalyzableElementX element) {
  if (element._treeElements == null) {
    element._treeElements = new TreeElementMapping(element);
  }
  return element._treeElements;
}

abstract class AnalyzableElementX implements AnalyzableElement {
  TreeElements _treeElements;

  bool get hasTreeElements => _treeElements != null;

  TreeElements get treeElements {
    assert(invariant(this, _treeElements != null,
        message: "TreeElements have not been computed for $this."));
    return _treeElements;
  }

  void reuseElement() {
    _treeElements = null;
  }
}
