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

package com.google.dart.compiler.resolver;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.dart.compiler.DartCompilationPhase;
import com.google.dart.compiler.DartCompilerContext;
import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.Source;
import com.google.dart.compiler.ast.ASTNodes;
import com.google.dart.compiler.ast.ASTVisitor;
import com.google.dart.compiler.ast.DartArrayLiteral;
import com.google.dart.compiler.ast.DartBinaryExpression;
import com.google.dart.compiler.ast.DartBlock;
import com.google.dart.compiler.ast.DartBooleanLiteral;
import com.google.dart.compiler.ast.DartBreakStatement;
import com.google.dart.compiler.ast.DartCase;
import com.google.dart.compiler.ast.DartCatchBlock;
import com.google.dart.compiler.ast.DartClass;
import com.google.dart.compiler.ast.DartClassTypeAlias;
import com.google.dart.compiler.ast.DartComment;
import com.google.dart.compiler.ast.DartCommentNewName;
import com.google.dart.compiler.ast.DartCommentRefName;
import com.google.dart.compiler.ast.DartContinueStatement;
import com.google.dart.compiler.ast.DartDirective;
import com.google.dart.compiler.ast.DartDoWhileStatement;
import com.google.dart.compiler.ast.DartDoubleLiteral;
import com.google.dart.compiler.ast.DartExprStmt;
import com.google.dart.compiler.ast.DartExpression;
import com.google.dart.compiler.ast.DartField;
import com.google.dart.compiler.ast.DartFieldDefinition;
import com.google.dart.compiler.ast.DartForInStatement;
import com.google.dart.compiler.ast.DartForStatement;
import com.google.dart.compiler.ast.DartFunction;
import com.google.dart.compiler.ast.DartFunctionExpression;
import com.google.dart.compiler.ast.DartFunctionObjectInvocation;
import com.google.dart.compiler.ast.DartFunctionTypeAlias;
import com.google.dart.compiler.ast.DartGotoStatement;
import com.google.dart.compiler.ast.DartIdentifier;
import com.google.dart.compiler.ast.DartIfStatement;
import com.google.dart.compiler.ast.DartImportDirective;
import com.google.dart.compiler.ast.DartInitializer;
import com.google.dart.compiler.ast.DartIntegerLiteral;
import com.google.dart.compiler.ast.DartInvocation;
import com.google.dart.compiler.ast.DartLabel;
import com.google.dart.compiler.ast.DartMapLiteral;
import com.google.dart.compiler.ast.DartMethodDefinition;
import com.google.dart.compiler.ast.DartMethodInvocation;
import com.google.dart.compiler.ast.DartNamedExpression;
import com.google.dart.compiler.ast.DartNativeBlock;
import com.google.dart.compiler.ast.DartNewExpression;
import com.google.dart.compiler.ast.DartNode;
import com.google.dart.compiler.ast.DartParameter;
import com.google.dart.compiler.ast.DartParameterizedTypeNode;
import com.google.dart.compiler.ast.DartPartOfDirective;
import com.google.dart.compiler.ast.DartPropertyAccess;
import com.google.dart.compiler.ast.DartRedirectConstructorInvocation;
import com.google.dart.compiler.ast.DartReturnStatement;
import com.google.dart.compiler.ast.DartStatement;
import com.google.dart.compiler.ast.DartStringInterpolation;
import com.google.dart.compiler.ast.DartStringLiteral;
import com.google.dart.compiler.ast.DartSuperConstructorInvocation;
import com.google.dart.compiler.ast.DartSuperExpression;
import com.google.dart.compiler.ast.DartSwitchMember;
import com.google.dart.compiler.ast.DartSwitchStatement;
import com.google.dart.compiler.ast.DartThisExpression;
import com.google.dart.compiler.ast.DartThrowExpression;
import com.google.dart.compiler.ast.DartTryStatement;
import com.google.dart.compiler.ast.DartTypeExpression;
import com.google.dart.compiler.ast.DartTypeNode;
import com.google.dart.compiler.ast.DartTypeParameter;
import com.google.dart.compiler.ast.DartUnaryExpression;
import com.google.dart.compiler.ast.DartUnit;
import com.google.dart.compiler.ast.DartUnqualifiedInvocation;
import com.google.dart.compiler.ast.DartVariable;
import com.google.dart.compiler.ast.DartVariableStatement;
import com.google.dart.compiler.ast.DartWhileStatement;
import com.google.dart.compiler.ast.LibraryImport;
import com.google.dart.compiler.ast.LibraryUnit;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.common.HasSourceInfo;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.parser.Token;
import com.google.dart.compiler.resolver.LabelElement.LabeledStatementType;
import com.google.dart.compiler.type.InterfaceType;
import com.google.dart.compiler.type.InterfaceType.Member;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.TypeAnalyzer;
import com.google.dart.compiler.type.TypeKind;
import com.google.dart.compiler.type.TypeQuality;
import com.google.dart.compiler.type.TypeVariable;
import com.google.dart.compiler.type.Types;

import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
 * Resolves unqualified elements in a compilation unit.
 */
public class Resolver {

  private final ResolutionContext topLevelContext;
  private final CoreTypeProvider typeProvider;
  private final InterfaceType rawArrayType;
  private final InterfaceType defaultLiteralMapType;


  private static final EnumSet<ElementKind> INVOKABLE_ELEMENTS = EnumSet.<ElementKind>of(
      ElementKind.FIELD,
      ElementKind.PARAMETER,
      ElementKind.VARIABLE,
      ElementKind.FUNCTION_OBJECT,
      ElementKind.METHOD);

  @VisibleForTesting
  public Resolver(DartCompilerContext compilerContext, Scope libraryScope,
                  CoreTypeProvider typeProvider) {
    compilerContext.getClass(); // Fast null-check.
    libraryScope.getClass(); // Fast null-check.
    typeProvider.getClass(); // Fast null-check.
    this.topLevelContext = new ResolutionContext(libraryScope, compilerContext, typeProvider);
    this.typeProvider = typeProvider;
    Type dynamicType = typeProvider.getDynamicType();
    Type stringType = typeProvider.getStringType();
    this.defaultLiteralMapType = typeProvider.getMapType(stringType, dynamicType);
    this.rawArrayType = typeProvider.getArrayType(dynamicType);
  }

  @VisibleForTesting
  public DartUnit exec(DartUnit unit) {
    // Visits all top level elements of a compilation unit and resolves names used in method
    // bodies.
    LibraryElement library = unit.getLibrary() != null ? unit.getLibrary().getElement() : null;
    unit.accept(new ResolveElementsVisitor(topLevelContext, library));
    return unit;
  }

  /**
   * Main entry point for IDE. Resolves a member (method or field)
   * incrementally in the given context.
   *
   * @param classElement the class enclosing the member.
   * @param member the member to resolve.
   * @param context a resolution context corresponding to classElement.
   */
  public void resolveMember(ClassNodeElement classElement, NodeElement member, ResolutionContext context) {
    ResolveElementsVisitor visitor;
    if(member == null) {
      return;
    }
    switch (member.getKind()) {
      case CONSTRUCTOR:
      case METHOD:
        ResolutionContext methodContext = context.extend(member.getName());
        visitor = new ResolveElementsVisitor(methodContext, classElement,
                                             (MethodElement) member);
        break;

        case FIELD:
          ResolutionContext fieldContext = context;
          if (member.getModifiers().isAbstractField()) {
            fieldContext = context.extend(member.getName());
          }
          visitor = new ResolveElementsVisitor(fieldContext, classElement);
          break;

      default:
        throw topLevelContext.internalError(member,
                                            "unexpected element kind: %s", member.getKind());
    }
    member.getNode().accept(visitor);
  }

  /**
   * Resolves names in a method body.
   *
   * TODO(ngeoffray): Errors reported:
   *  - A default implementation not providing the default methods.
   *  - An interface with default methods but without a default implementation.
   *  - A member method shadowing a super property.
   *  - A member property shadowing a super method.
   *  - A formal parameter in a non-constructor shadowing a member.
   *  - A local variable shadowing another variable.
   *  - A local variable shadowing a formal parameter.
   *  - A local variable shadowing a class member.
   *  - Using 'this' or 'super' in a static or factory method, or in an initializer.
   *  - Using 'super' in a class without a super class.
   *  - Incorrectly using a resolved element.
   */
  @VisibleForTesting
  public class ResolveElementsVisitor extends ResolveVisitor {
    private EnclosingElement currentHolder;
    private EnclosingElement enclosingElement;
    private MethodElement currentMethod;
    private boolean inInstanceVariableInitializer;
    private boolean inInitializer;
    private MethodElement innermostFunction;
    private ResolutionContext context;
    private Set<LabelElement> referencedLabels = Sets.newHashSet();
    private Set<LabelElement> labelsInScopes = Sets.newHashSet();
    private Set<FieldElement> finalsNeedingInitializing = Sets.newHashSet();
    private Set<FieldElement> resolvedFields = Sets.newHashSet();

    @VisibleForTesting
    public ResolveElementsVisitor(ResolutionContext context,
                                  EnclosingElement currentHolder,
                                  MethodElement currentMethod) {
      super(typeProvider);
      this.context = context;
      this.currentMethod = currentMethod;
      this.innermostFunction = currentMethod;
      this.currentHolder = currentHolder;
      this.enclosingElement = currentHolder;
      this.inInitializer = false;
    }

    private ResolveElementsVisitor(ResolutionContext context, EnclosingElement currentHolder) {
      this(context, currentHolder, null);
    }

    @Override
    ResolutionContext getContext() {
      return context;
    }

    @Override
    protected EnclosingElement getEnclosingElement() {
      return enclosingElement;
    }

    @Override
    public Element visitUnit(DartUnit unit) {
      List<DartImportDirective> importDirectives = Lists.newArrayList();
      for (DartDirective directive : unit.getDirectives()) {
        if (directive instanceof DartImportDirective) {
          importDirectives.add((DartImportDirective) directive);
        }
        if (directive instanceof DartPartOfDirective) {
          directive.accept(this);
        }
      }
      // set LibraryElement for "import" directives
      {
        LibraryUnit library = unit.getLibrary();
        if (library != null) {
          Iterator<LibraryImport> importIterator = library.getImports().iterator();
          Iterator<DartImportDirective> directiveIterator = importDirectives.iterator();
          while (importIterator.hasNext() && directiveIterator.hasNext()) {
            LibraryImport imp = importIterator.next();
            DartImportDirective dir = directiveIterator.next();
            DartStringLiteral uri = dir.getLibraryUri();
            LibraryUnit impLibrary = imp.getLibrary();
            if (uri != null && impLibrary != null) {
              uri.setElement(impLibrary.getElement());
            }
          }
        }
      }
      // visit top-level nodes
      for (DartNode node : unit.getTopLevelNodes()) {
        node.accept(this);
      }
      checkRedirectingFactoryConstructorsCycle(unit);
      return null;
    }

    private void checkRedirectingFactoryConstructorsCycle(DartUnit unit) {
      unit.accept(new ASTVisitor<Void>() {
        @Override
        public Void visitMethodDefinition(DartMethodDefinition node) {
          MethodNodeElement element = node.getElement();
          if (ElementKind.of(element) == ElementKind.CONSTRUCTOR) {
            ConstructorElement constructor = (ConstructorElement) element;
            if (hasRedirectingFactoryConstructorCycle(constructor)) {
              onError(constructor.getNameLocation(),
                  ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE);
            }
          }
          return super.visitMethodDefinition(node);
        }
      });
    }
    
    private boolean hasRedirectingFactoryConstructorCycle(ConstructorElement element) {
      Set<ConstructorElement> constructors = Sets.newHashSet();
      while (element != null) {
        if (constructors.contains(element)) {
          return true;
        }
        constructors.add(element);
        element = element.getRedirectingFactoryConstructor();
      }
      return false;
    }
    
    @Override
    public Element visitFunctionTypeAlias(DartFunctionTypeAlias alias) {
      alias.getMetadata().accept(this);
      getContext().pushFunctionAliasScope(alias);
      resolveFunctionAlias(alias);

      getContext().pushScope("<parameters>");
      try {
        List<DartParameter> parameters = alias.getParameters();
        for (DartParameter parameter : parameters) {
          assert parameter.getElement() != null;
          if (parameter.getQualifier() instanceof DartThisExpression) {
            onError(parameter.getName(), ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR);
          } else {
            if (DartIdentifier.isPrivateName(parameter.getElement().getName())) {
              if (parameter.getModifiers().isOptional()) {
                onError(parameter.getName(),
                    ResolverErrorCode.OPTIONAL_PARAMETERS_CANNOT_START_WITH_UNDER);
              }
              if (parameter.getModifiers().isNamed()) {
                onError(parameter.getName(),
                    ResolverErrorCode.NAMED_PARAMETERS_CANNOT_START_WITH_UNDER);
              }
            }
            getContext().declare(parameter.getElement(), ResolverErrorCode.DUPLICATE_PARAMETER);
          }
        }
      } finally {
        getContext().popScope();
      }

      getContext().popScope();
      return null;
    }

    @Override
    public Element visitCommentRefName(DartCommentRefName node) {
      Scope scope = getContext().getScope();
      String name = node.getName();
      Element element = scope.findElement(scope.getLibrary(), name);
      return recordElement(node, element);
    }

    @Override
    public Element visitCommentNewName(DartCommentNewName node) {
      String className = node.getClassName();
      String constructorName = node.getConstructorName();
      Scope scope = getContext().getScope();
      Element element = scope.findElement(scope.getLibrary(), className);
      if (ElementKind.of(element) == ElementKind.CLASS) {
        ClassElement classElement = (ClassElement) element;
        for (ConstructorElement constructor : classElement.getConstructors()) {
          if (constructor.getName().equals(constructorName)) {
            node.setElements(classElement, constructor);
            return constructor;
          }
        }
      }
      return null;
    }
    
    @Override
    public Element visitClassTypeAlias(DartClassTypeAlias cls) {
      ClassNodeElement classElement = cls.getElement();
      try {
        classElement.getAllSupertypes();
      } catch (CyclicDeclarationException e) {
        HasSourceInfo errorTarget = e.getElement();
        if (errorTarget == null) {
          errorTarget = cls;
        }
        onError(errorTarget, ResolverErrorCode.CYCLIC_CLASS, e.getElement().getName());
      }
      checkMixinObjectIsSupertype(cls.getMixins());
      checkMixinNoConstructors(cls.getMixins());
      checkMixinNoSuperInvocations(cls.getMixins());
      return classElement;
    }

    @Override
    public Element visitClass(DartClass cls) {
      assert currentMethod == null : "nested class?";
      ClassNodeElement classElement = cls.getElement();
      try {
        classElement.getAllSupertypes();
      } catch (CyclicDeclarationException e) {
        HasSourceInfo errorTarget = e.getElement();
        if (errorTarget == null) {
          errorTarget = cls;
        }
        onError(errorTarget, ResolverErrorCode.CYCLIC_CLASS, e.getElement().getName());
      }
      checkClassTypeVariables(classElement);
      cls.getMetadata().accept(this);

      // Push new resolution context.
      ResolutionContext previousContext = context;
      EnclosingElement previousHolder = currentHolder;
      EnclosingElement previousEnclosingElement = enclosingElement;
      currentHolder = classElement;
      enclosingElement = classElement;
      context = topLevelContext.extend(classElement);

      // members
      this.finalsNeedingInitializing.clear();
      for (DartNode member : cls.getMembers()) {
        if (ElementKind.of(member.getElement()) == ElementKind.CONSTRUCTOR) {
          continue;
        }
        member.accept(this);
      }

      // constructors
      boolean testForAllConstantFields = false;
      for (DartNode member : cls.getMembers()) {
        if (member instanceof DartMethodDefinition) {
          DartMethodDefinition method = (DartMethodDefinition) member;
          if (method.getElement().isConstructor()) {
            method.accept(this);
            if (method.getModifiers().isConstant()) {
              testForAllConstantFields = true;
            }
          }
        }
      }

      if (testForAllConstantFields) {
        InterfaceType interfaceType = classElement.getType();
        while (interfaceType != null && interfaceType != typeProvider.getObjectType()) {
          ClassElement interfaceElement = interfaceType.getElement();
          constVerifyMembers(interfaceElement.getMembers(), classElement, interfaceElement);
          interfaceType = interfaceElement.getSupertype();
        }
      }

      checkRedirectConstructorCycle(classElement.getConstructors(), context);
      if (Elements.needsImplicitDefaultConstructor(classElement)) {
        checkImplicitDefaultDefaultSuperInvocation(cls, classElement);
      }

      if (cls.getDefaultClass() != null && classElement.getDefaultClass() == null) {
        onError(cls.getDefaultClass(), ResolverErrorCode.NO_SUCH_TYPE, cls.getDefaultClass());
      } else if (classElement.getDefaultClass() != null) {
        recordElement(cls.getDefaultClass().getExpression(),
                      classElement.getDefaultClass().getElement());
        bindDefaultTypeParameters(classElement.getDefaultClass().getElement().getTypeParameters(),
                                  cls.getDefaultClass().getTypeParameters(),
                                  context);

        // Make sure the 'default' clause matches the referenced class type parameters
        checkDefaultClassTypeParamsToDefaultDecl(classElement.getDefaultClass(),
                                                 cls.getDefaultClass());

        ClassElement defaultClass = classElement.getDefaultClass().getElement();
        if (defaultClass.isInterface()) {
          onError(cls.getDefaultClass().getExpression(),
              ResolverErrorCode.DEFAULT_MUST_SPECIFY_CLASS);
        }

        // Make sure the default class matches the interface type parameters
        checkInterfaceTypeParamsToDefault(classElement, defaultClass);
      }

      if (!classElement.isInterface() && Elements.needsImplicitDefaultConstructor(classElement)) {
        // Check to see that all final fields are initialized when no explicit
        // generative constructor is declared
        cls.accept(new ASTVisitor<DartNode>() {
          @Override
          public DartNode visitField(DartField node) {
            FieldElement fieldElement = node.getElement();
            if (fieldElement != null && fieldElement.getModifiers().isFinal()
                && !fieldElement.isStatic()
                && !fieldElement.getModifiers().isConstant()
                && !fieldElement.getModifiers().isGetter()
                && !fieldElement.getModifiers().isSetter()
                && !fieldElement.getModifiers().isInitialized()) {
              onError(node, ResolverErrorCode.FINAL_FIELD_MUST_BE_INITIALIZED,
                  fieldElement.getName());
            }
            return null;
          }
        });
      }

      {
        DartComment comment = cls.getDartDoc();
        if (comment != null) {
          comment.accept(this);
        }
      }

      // check mixins
      checkMixinObjectIsSupertype(cls.getMixins());
      checkMixinNoConstructors(cls.getMixins());
      checkMixinNoSuperInvocations(cls.getMixins());

      context = previousContext;
      currentHolder = previousHolder;
      enclosingElement = previousEnclosingElement;
      return classElement;
    }

    /**
     * Checks that the types of the given mixin type node don't have explicit constructors.
     */
    private void checkMixinNoConstructors(List<DartTypeNode> mixins) {
      for (DartTypeNode mixNode : mixins) {
        if (mixNode.getType() instanceof InterfaceType) {
          InterfaceType mixType = (InterfaceType) mixNode.getType();
          for (ConstructorElement constructor : mixType.getElement().getConstructors()) {
            if (!constructor.getModifiers().isFactory()) {
              topLevelContext.onError(mixNode, ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR);
              break;
            }
          }
        }
      }
    }
    
    /**
     * Checks that the types of the given mixin type nodes se subtypes of Object.
     */
    private void checkMixinObjectIsSupertype(List<DartTypeNode> mixins) {
      for (DartTypeNode mixNode : mixins) {
        if (mixNode.getType() instanceof InterfaceType) {
          InterfaceType mixType = (InterfaceType) mixNode.getType();
          ClassElement mixElement = mixType.getElement();
          if (!mixElement.getMixins().isEmpty()) {
            topLevelContext.onError(mixNode, ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_MIXINS);
            continue;
          }
          if (!Objects.equal(mixElement.getSupertype(), typeProvider.getObjectType())) {
            topLevelContext.onError(mixNode, ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS);
            continue;
          }
        }
      }
    }
    
    /**
     * Checks that the types of the given mixin type nodes don't have super invocations.
     */
    private void checkMixinNoSuperInvocations(List<DartTypeNode> mixins) {
      for (DartTypeNode mixNode : mixins) {
        if (mixNode.getType() instanceof InterfaceType) {
          InterfaceType mixType = (InterfaceType) mixNode.getType();
          if (mixType.getElement() instanceof ClassElement) {
            ClassElement mixElement = (ClassElement) mixType.getElement();
            if (mixElement.hasSuperInvocation()) {
              topLevelContext.onError(mixNode, ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER);
              break;
            }
          }
        }
      }
    }

    private void constVerifyMembers(Iterable<? extends Element> members, ClassElement originalClass,
        ClassElement currentClass) {
      for (Element element : members) {
        Modifiers modifiers = element.getModifiers();
        if (ElementKind.of(element).equals(ElementKind.FIELD) && !modifiers.isFinal()
            && !modifiers.isStatic() && !modifiers.isAbstractField()) {
          FieldElement field = (FieldElement) element;
          HasSourceInfo errorNode = field.getSetter() == null ? element : field.getSetter();
          onError(errorNode, currentClass == originalClass
              ? ResolverErrorCode.CONST_CLASS_WITH_NONFINAL_FIELDS
              : ResolverErrorCode.CONST_CLASS_WITH_INHERITED_NONFINAL_FIELDS,
              originalClass.getName(), field.getName(), currentClass.getName());
        }
      }
    }

    /**
     * Sets the type in the AST of the default clause of an interface so that the type
     * parameters to resolve back to the default class.
     */
    private void bindDefaultTypeParameters(List<Type> parameterTypes,
                                           List<DartTypeParameter> parameterNodes,
                                           ResolutionContext classContext) {
      Iterator<? extends Type> typeIterator = parameterTypes.iterator();
      Iterator<DartTypeParameter> nodeIterator = parameterNodes.iterator();

      while(typeIterator.hasNext() && nodeIterator.hasNext()) {

        Type type = typeIterator.next();
        DartTypeParameter node = nodeIterator.next();

        if (type.getElement().getName().equals(node.getName().getName())) {
          node.setType(type);
          recordElement(node.getName(), type.getElement());
        } else {
          node.setType(typeProvider.getDynamicType());
        }

        DartTypeNode boundNode = node.getBound();
        if (boundNode != null) {
          Type bound =
              classContext.resolveType(
                  boundNode,
                  false,
                  false,
                  true,
                  ResolverErrorCode.NO_SUCH_TYPE,
                  ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
          boundNode.setType(bound);
        }
      }

      while (nodeIterator.hasNext()) {
        DartTypeParameter node = nodeIterator.next();
        node.setType(typeProvider.getDynamicType());
      }
    }
    /**
     * If type parameters are present, the type parameters of the default statement
     * must exactly match those of those declared in the class it references.
     *
     */
    private void checkDefaultClassTypeParamsToDefaultDecl(InterfaceType defaultClassType,
                                                          DartParameterizedTypeNode defaultClassRef) {
      if (defaultClassRef.getTypeParameters().isEmpty()) {
        return;
      }
      ClassElement defaultClassElement = defaultClassType.getElement();
      boolean match = true;
      if (defaultClassElement.getTypeParameters().isEmpty()) {
        match = false;
      } else {
        // TODO(zundel): This is effective in catching mistakes, but highlights the entire type
        // expression - A more specific indication of where the error started might be appreciated.
        String defaultClassSource = defaultClassElement.getDeclarationNameWithTypeParameters();
        String refSource = defaultClassRef.toSource();
        if (!refSource.equals(defaultClassSource)) {
          match = false;
        }
      }
      if (!match) {
        // TODO(zundel): work harder to point out where the type param match failure starts.
        onError(defaultClassRef, ResolverErrorCode.TYPE_PARAMETERS_MUST_MATCH_EXACTLY);
      }
    }

    private void checkInterfaceTypeParamsToDefault(ClassElement interfaceElement,
                                                   ClassElement defaultClassElement) {

      List<Type> interfaceTypeParams = interfaceElement.getTypeParameters();

      List<Type> defaultTypeParams = defaultClassElement.getTypeParameters();


      if (defaultTypeParams.size() != interfaceTypeParams.size()) {

        onError(interfaceElement.getNameLocation(),
                ResolverErrorCode.DEFAULT_CLASS_MUST_HAVE_SAME_TYPE_PARAMS);
      } else {
        Iterator<? extends Type> interfaceIterator = interfaceTypeParams.iterator();
        Iterator<? extends Type> defaultIterator = defaultTypeParams.iterator();
        while (interfaceIterator.hasNext()) {
          Type iVar = interfaceIterator.next();
          Type dVar = defaultIterator.next();
          String iVarName = iVar.getElement().getName();
          String dVarName = dVar.getElement().getName();
          if (!iVarName.equals(dVarName)) {
            onError(iVar.getElement(), ResolverErrorCode.TYPE_VARIABLE_DOES_NOT_MATCH,
                    iVarName, dVarName, defaultClassElement.getName());
          }
        }
      }
    }

    /**
     * Check that used type variables are unique and don't shadow and existing elements.
     */
    private void checkClassTypeVariables(ClassElement classElement) {
      Set<String> declaredVariableNames = Sets.newHashSet();
      for (Type type : classElement.getTypeParameters()) {
        if (type instanceof TypeVariable) {
          Element typeVariableElement = type.getElement();
          String name = typeVariableElement.getName();
          // Check that type variables are unique in this Class  declaration.
          if (declaredVariableNames.contains(name)) {
            onError(typeVariableElement, ResolverErrorCode.DUPLICATE_TYPE_VARIABLE, name);
          } else {
            declaredVariableNames.add(name);
          }
        }
      }
    }

    /**
     * Returns <code>true</code> if the {@link ClassElement} has an implicit or a declared
     * default constructor.
     */
    boolean hasDefaultConstructor(ClassElement classElement) {
      if (Elements.needsImplicitDefaultConstructor(classElement)) {
        return true;
      }

      ConstructorElement defaultCtor = Elements.lookupConstructor(classElement, "");
      if (defaultCtor != null) {
        return defaultCtor.getParameters().isEmpty();
      }

      return false;
    }

    private void checkImplicitDefaultDefaultSuperInvocation(DartClass cls,
        ClassElement classElement) {
      assert (Elements.needsImplicitDefaultConstructor(classElement));

      InterfaceType supertype = classElement.getSupertype();
      if (supertype != null) {
        ClassElement superElement = supertype.getElement();
        if (!superElement.isDynamic()) {
          ConstructorElement superCtor = Elements.lookupConstructor(superElement, "");
          boolean superHasDefaultCtor =
              (superCtor != null && superCtor.getParameters().isEmpty())
                  || (superCtor == null && Elements.needsImplicitDefaultConstructor(superElement));
          if (!superHasDefaultCtor) {
            onError(cls.getName(),
                ResolverErrorCode.CANNOT_RESOLVE_IMPLICIT_CALL_TO_SUPER_CONSTRUCTOR,
                cls.getSuperclass());
          }
          if (superCtor != null && superCtor.getModifiers().isFactory()) {
            onError(cls.getName(), ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, "<default>",
                supertype);
          }
        }
      }
    }

    private Element resolve(DartNode node) {
      if (node == null) {
        return null;
      } else {
        return node.accept(this);
      }
    }

    @Override
    public Element visitTypeParameter(DartTypeParameter node) {
      node.getMetadata().accept(this);
      return super.visitTypeParameter(node);
    }

    @Override
    public MethodElement visitMethodDefinition(DartMethodDefinition node) {
      node.getMetadata().accept(this);
      MethodElement member = node.getElement();
      ResolutionContext previousContext = context;
      context = context.extend(member.getName());
      assert currentMethod == null : "Nested methods?";
      innermostFunction = currentMethod = member;
      EnclosingElement previousEnclosingElement = enclosingElement;
      enclosingElement = member;

      DartFunction functionNode = node.getFunction();
      List<DartParameter> parameters = functionNode.getParameters();
      Set<FieldElement> initializedFields = Sets.newHashSet();
      
      // remember field with initializers
      if (previousEnclosingElement instanceof ClassElement) {
        ClassElement classElement = (ClassElement) previousEnclosingElement;
        for (Element classMember : classElement.getMembers()) {
          if (ElementKind.of(classMember) == ElementKind.FIELD) {
            FieldElement fieldMember = (FieldElement) classMember;
            if (fieldMember.getModifiers().isFinal() && fieldMember.getModifiers().isInitialized()) {
              initializedFields.add(fieldMember);
            }
          }
        }
      }

      // First declare all normal parameters in the scope, putting them in the
      // scope of the default expressions so we can report better errors.
      for (DartParameter parameter : parameters) {
        assert parameter.getElement() != null;
        parameter.getMetadata().accept(this);

        if (!(parameter.getQualifier() instanceof DartThisExpression)) {
          getContext().declare(
              parameter.getElement(),
              ResolverErrorCode.DUPLICATE_PARAMETER);
        }
      }
      for (DartParameter parameter : parameters) {
        // Then resolve the default values.
        resolve(parameter.getDefaultExpr());
        if (parameter.getQualifier() instanceof DartThisExpression && parameter.getElement() != null
            && !initializedFields.add(parameter.getElement().getParameterInitializerElement())) {
          onError(parameter, ResolverErrorCode.DUPLICATE_INITIALIZATION, parameter.getName());
        }
      }
      
      {
        DartComment comment = node.getDartDoc();
        if (comment != null) {
          comment.accept(this);
        }
      }

      DartBlock body = functionNode.getBody();
      if (body == null) {
        if (member.getModifiers().isStatic() && !member.getModifiers().isExternal()) {
          onError(functionNode, ResolverErrorCode.STATIC_METHOD_MUST_HAVE_BODY);
        }
      }
      resolve(functionNode.getBody());

      if (Elements.isNonFactoryConstructor(member) && !(body instanceof DartNativeBlock)) {
        resolveInitializers(node, initializedFields);
      }

      // only generative constructor can have initializers, so resolve them, but report error 
      if (!member.isConstructor() || member.getModifiers().isFactory()) {
        for (DartInitializer initializer : node.getInitializers()) {
          resolve(initializer);
          if (initializer.getName() != null) {
            onError(initializer, ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR);
          }
        }
      }
      
      // resolve redirecting factory constructor
      {
        DartTypeNode rcTypeName = node.getRedirectedTypeName();
        if (rcTypeName != null) {
          Type rcType = resolveType(rcTypeName, true, true, false,
              TypeErrorCode.NO_SUCH_TYPE, ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
          switch (TypeKind.of(rcType)) {
            case INTERFACE:
              ConstructorElement targetConstructor = null;
              Element element = recordType(rcTypeName, rcType);
              DartIdentifier rcName = node.getRedirectedConstructorName();
              if (rcName != null) {
                element = ((ClassElement) element).lookupConstructor(rcName.getName());
                switch (ElementKind.of(element)) {
                  case CONSTRUCTOR:
                    targetConstructor = (ConstructorElement) element;
                    recordElement(rcName, element);
                    if (member.getModifiers().isConstant() && !element.getModifiers().isConstant()) {
                      onError(rcName,
                          ResolverErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_CONST);
                    }
                    break;
                }
              } else {
                targetConstructor = ((ClassElement) element).lookupConstructor("");
              }
              Elements.setRedirectingFactoryConstructor(((ConstructorElement) member),
                  targetConstructor);
              break;
            default:
              onError(rcTypeName, ResolverErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_TYPE);
          }
        }
      }

      context = previousContext;
      innermostFunction = currentMethod = null;
      enclosingElement = previousEnclosingElement;
      return member;
    }

    @Override
    public Element visitField(DartField node) {
      DartExpression expression = node.getValue();
      Modifiers modifiers = node.getModifiers();
      boolean isFinal = modifiers.isFinal();
      boolean isTopLevel = ElementKind.of(currentHolder).equals(ElementKind.LIBRARY);
      boolean isStatic = modifiers.isStatic();

      if (expression != null) {
        inInstanceVariableInitializer = !isTopLevel;
        try {
          resolve(expression);
        } finally {
          inInstanceVariableInitializer = false;
        }
        // Now, this constant has a type. Save it for future reference.
        Element element = node.getElement();
        Type expressionType = expression.getType();
        if (isFinal && expressionType != null && TypeKind.of(element.getType()) == TypeKind.DYNAMIC) {
          TypeQuality typeQuality = TypeAnalyzer.getTypeQuality(expression);
          Type fieldType = Types.makeInferred(expressionType, typeQuality);
          Elements.setType(element, fieldType);
        }
      } else if (isFinal) {
        if (modifiers.isConstant()) {
          onError(node, ResolverErrorCode.CONST_REQUIRES_VALUE);
        } else if (isStatic) {
          onError(node, ResolverErrorCode.STATIC_FINAL_REQUIRES_VALUE);
        } else if (isTopLevel) {
          onError(node, ResolverErrorCode.TOPLEVEL_FINAL_REQUIRES_VALUE);
        } else {
          // If a final instance field wasn't initialized at declaration, we must check
          // at construction time.
          this.finalsNeedingInitializing.add(node.getElement());
        }
      }

      // If field is an accessor, both getter and setter need to be visited (if present).
      // We check for duplicates because top-level fields are visited twice - for each accessor.
      FieldNodeElement field = node.getElement();
      if (!resolvedFields.contains(field)) {
        resolvedFields.add(field);
        if (field.getGetter() != null) {
          resolve(field.getGetter().getNode());
        }
        if (field.getSetter() != null) {
          resolve(field.getSetter().getNode());
        }
      }
      return null;
    }

    @Override
    public Element visitFieldDefinition(DartFieldDefinition node) {
      node.getMetadata().accept(this);
      visit(node.getFields());
      return null;
    }

    @Override
    public Element visitFunction(DartFunction node) {
      throw context.internalError(node, "should not be called.");
    }

    @Override
    public Element visitParameter(DartParameter x) {
      x.getMetadata().accept(this);
      Element element = super.visitParameter(x);
      resolve(x.getDefaultExpr());
      getContext().declare(
          element,
          ResolverErrorCode.DUPLICATE_PARAMETER);
      return element;
    }

    @Override
    public Element visitVariable(DartVariable node) {
      node.getMetadata().accept(this);
      return super.visitVariable(node);
    }

    public VariableElement resolveVariable(DartVariable x, Modifiers modifiers) {
      final DartIdentifier nameNode = x.getName();
      final String name = nameNode.getName();
      // Visit the initializer first.
      DartExpression value = x.getValue();
      if (value != null) {
        // It is a compile-time error if e refers to the name v or the name v=.
        value.accept(new ASTVisitor<Void>() {
          @Override
          public Void visitIdentifier(DartIdentifier node) {
            // ignore cases when name is used with some qualifier
            if (node.getParent() instanceof DartPropertyAccess) {
              DartPropertyAccess x = (DartPropertyAccess) node.getParent();
              if (x.getName() == node) {
                return null;
              }
            }
            if (node.getParent() instanceof DartMethodInvocation) {
              DartMethodInvocation x = (DartMethodInvocation) node.getParent();
              if (x.getFunctionName() == node) {
                return null;
              }
            }
            // TODO(scheglov) remove this after http://code.google.com/p/dart/issues/detail?id=6869
            {
              Source source = node.getSourceInfo().getSource();
              if (Elements.isSourceName(source, "dart://json/json.dart/json.dart")) {
                return null;
              }
            }
            if (Objects.equal(node.getName(), name)) {
              onError(node, ResolverErrorCode.VARIABLE_REFERENCES_SAME_NAME_IN_INITIALIZER, name,
                  name);
              node.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
            }
            return null;
          }
        });
        // do resolve
        resolve(value);
      }
      // declare variable
      VariableElement element = Elements.variableElement(enclosingElement, x, name, modifiers);
      getContext().declare(recordElement(x, element),
          ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_ERROR);
      recordElement(nameNode, element);
      return element;
    }

    @Override
    public Element visitVariableStatement(DartVariableStatement node) {
      resolveVariableStatement(node, false);
      return null;
    }

    private void resolveVariableStatement(DartVariableStatement node,
                                          boolean isImplicitlyInitialized) {
      Type type =
          resolveType(
              node.getTypeNode(),
              ASTNodes.isStaticContext(node),
              ASTNodes.isFactoryContext(node),
              true,
              TypeErrorCode.NO_SUCH_TYPE,
              TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
      for (DartVariable variable : node.getVariables()) {
        String name = variable.getVariableName();
        getContext().getScope().removeDeclaredButNotReachedVariable(name);
        Elements.setType(resolveVariable(variable, node.getModifiers()), type);
        checkVariableStatement(node, variable, isImplicitlyInitialized);
      }
     }

    @Override
    public Element visitLabel(DartLabel x) {
      DartNode parent = x.getParent();
      if (!(parent instanceof DartSwitchMember && ((DartSwitchMember) parent).getLabels().contains(
          x))) {
        LabelElement labelElement;
        DartStatement childStatement = x.getStatement();
        while (childStatement instanceof DartLabel) {
          childStatement = ((DartLabel) childStatement).getStatement();
        }
        if (childStatement instanceof DartSwitchStatement) {
          labelElement = Elements.switchLabelElement(x, x.getName(), innermostFunction);
        } else {
          labelElement = Elements.statementLabelElement(x, x.getName(), innermostFunction);
        }
        recordElement(x.getLabel(), labelElement);
        recordElement(x, labelElement);
      }
      x.visitChildren(this);
      return null;
    }

    @Override
    public Element visitFunctionExpression(DartFunctionExpression x) {
      MethodElement element;
      if (x.isStatement()) {
        // Function statement names live in the outer scope.
        element = getContext().declareFunction(x);
        getContext().pushFunctionScope(x);
      } else {
        // Function expression names live in their own scope.
        getContext().pushFunctionScope(x);
        element = getContext().declareFunction(x);
      }
      // record element
      if (x.getName() != null) {
        recordElement(x.getName(), element);
      }
      recordElement(x, element);
      // visit function
      MethodElement previousFunction = innermostFunction;
      innermostFunction = element;
      {
        DartFunction functionNode = x.getFunction();
        EnclosingElement previousEnclosingElement = enclosingElement;
        enclosingElement = element;
        getContext().pushFunctionScope(x);
        try {
          resolveFunction(functionNode, element);
          resolve(functionNode.getBody());
        } finally {
          getContext().popScope();
          enclosingElement = previousEnclosingElement;
        }
      }
      innermostFunction = previousFunction;
      getContext().popScope();
      return element;
    }

    @Override
    public Element visitBlock(DartBlock x) {
      getContext().pushScope("<block>");
      addLabelToStatement(x);
      // Remember names of Block variables.
      for (DartStatement statement : x.getStatements()) {
        if (statement instanceof DartVariableStatement) {
          DartVariableStatement node = (DartVariableStatement) statement;
          List<DartVariable> variables = node.getVariables();
          for (DartVariable variable : variables) {
            String name = variable.getVariableName();
            getContext().getScope().addDeclaredButNotReachedVariable(name);
          }
        }
      }
      // Visit statements.
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    @Override
    public Element visitBreakStatement(DartBreakStatement x) {
      // Handle corner case of L: break L;
      DartNode parent = x.getParent();
      if (parent instanceof DartLabel && x.getLabel() != null) {
        if (((DartLabel) parent).getLabel().getName().equals(x.getLabel().getName())) {
          getContext().pushScope("<break>");
          addLabelToStatement(x);
          visitGotoStatement(x);
          getContext().popScope();
          return null;
        }
      }
      return visitGotoStatement(x);
    }

    @Override
    public Element visitTryStatement(DartTryStatement x) {
      getContext().pushScope("<try>");
      addLabelToStatement(x);
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    @Override
    public Element visitCatchBlock(DartCatchBlock x) {
      getContext().pushScope("<block>");
      addLabelToStatement(x);
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    @Override
    public Element visitDoWhileStatement(DartDoWhileStatement x) {
      getContext().pushScope("<do>");
      addLabelToStatement(x);
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    @Override
    public Element visitWhileStatement(DartWhileStatement x) {
      getContext().pushScope("<while>");
      addLabelToStatement(x);
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    @Override
    public Element visitIfStatement(DartIfStatement x) {
      getContext().pushScope("<if>");
      addLabelToStatement(x);
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    @Override
    public Element visitForInStatement(DartForInStatement x) {
      getContext().pushScope("<for in>");
      addLabelToStatement(x);

      x.getIterable().accept(this);
      if (x.introducesVariable()) {
        resolveVariableStatement(x.getVariableStatement(), true);
      } else {
        x.getIdentifier().accept(this);
      }
      x.getBody().accept(this);
      getContext().popScope();
      return null;
    }

    private void addLabelToStatement(DartNode x) {
      DartNode parent = x.getParent();
      while (parent instanceof DartLabel) {
        DartLabel label = (DartLabel) parent;
        LabelElement currentLabel = label.getElement();
        getContext().getScope().addLabel(currentLabel);
        labelsInScopes.add(currentLabel);
        parent = parent.getParent();
      }
    }

    @Override
    public Element visitForStatement(DartForStatement x) {
      getContext().pushScope("<for>");
      addLabelToStatement(x);
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }


    @Override
    public Element visitSwitchStatement(DartSwitchStatement x) {
      getContext().pushScope("<switch>");
      addLabelToStatement(x);
      // The scope of a label on the case statement is the case statement itself. These labels
      // need to be resolved before the continue <label>; statements can be resolved.
      for (DartSwitchMember member : x.getMembers()) {
        recordSwitchMemberLabel(member);
      }
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }

    private boolean isValidLastSwitchCaseStatement(DartStatement statement) {
      if (statement instanceof DartExprStmt) {
        DartExprStmt exprStmt = (DartExprStmt) statement;
        if (exprStmt.getExpression() instanceof DartThrowExpression) {
          return true;
        }
      }
      return statement instanceof DartBreakStatement || statement instanceof DartContinueStatement
          || statement instanceof DartReturnStatement;
    }

    @Override
    public Element visitSwitchMember(DartSwitchMember x) {
      getContext().pushScope("<switch member>");
      x.visitChildren(this);
      getContext().popScope();
      return null;
    }
    
    @Override
    public Element visitCase(DartCase x) {
      super.visitCase(x);
      // check fall-through
      {
        List<DartStatement> statements = x.getStatements();
        // the last statement should be: break, continue, return, throw
        if (!statements.isEmpty()) {
          DartStatement lastStatement = statements.get(statements.size() - 1);
          if (!isValidLastSwitchCaseStatement(lastStatement)) {
            onError(lastStatement, ResolverErrorCode.SWITCH_CASE_FALL_THROUGH);
          }
        }
      }
      return null;
    }

    private void recordSwitchMemberLabel(DartSwitchMember x) {
      List<DartLabel> labels = x.getLabels();
      for (DartLabel label : labels) {
        LabelElement labelElement =  Elements.switchMemberLabelElement(label, label.getName(),
            innermostFunction);
        recordElement(label.getLabel(), labelElement);
        recordElement(label, labelElement);
        if (getContext().getScope().hasLocalLabel(label.getName())) {
          onError(label, ResolverErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT);
        }
        getContext().getScope().addLabel(labelElement);
        labelsInScopes.add(labelElement);
      }
    }

    @Override
    public Element visitThisExpression(DartThisExpression x) {
      if (ElementKind.of(currentHolder).equals(ElementKind.LIBRARY)) {
        onError(x, ResolverErrorCode.THIS_ON_TOP_LEVEL);
      } else if (currentMethod == null) {
        onError(x, ResolverErrorCode.THIS_OUTSIDE_OF_METHOD);
      } else if (currentMethod.getModifiers().isStatic()) {
        onError(x, ResolverErrorCode.THIS_IN_STATIC_METHOD);
      } else if (currentMethod.getModifiers().isFactory()) {
        onError(x, ResolverErrorCode.THIS_IN_FACTORY_CONSTRUCTOR);
      } else if (inInitializer) {
        onError(x, ResolverErrorCode.THIS_IN_INITIALIZER_AS_EXPRESSION);
      }
      return null;
    }

    @Override
    public Element visitDirective(DartDirective node) {
      node.getMetadata().accept(this);
      return super.visitDirective(node);
    }

    @Override
    public Element visitPartOfDirective(DartPartOfDirective node) {
      node.getMetadata().accept(this);
      String elementName = "__library_" + node.getLibraryName();
      Element element = context.getScope().findElement(null, elementName);
      if (ElementKind.of(element) == ElementKind.LIBRARY) {
        node.getName().setElement(element);
        return element;
      }
      return null;
    }

    @Override
    public Element visitSuperExpression(DartSuperExpression x) {
      if (ElementKind.of(currentHolder).equals(ElementKind.LIBRARY)) {
        onError(x, ResolverErrorCode.SUPER_ON_TOP_LEVEL);
      } else if (currentMethod == null) {
        onError(x, ResolverErrorCode.SUPER_OUTSIDE_OF_METHOD);
      } else if (currentMethod.getModifiers().isStatic()) {
        onError(x, ResolverErrorCode.SUPER_IN_STATIC_METHOD);
      } else if  (currentMethod.getModifiers().isFactory()) {
        onError(x, ResolverErrorCode.SUPER_IN_FACTORY_CONSTRUCTOR);
      } else {
        return recordElement(x, Elements.superElement(
            x, ((ClassElement) currentHolder).getSupertype().getElement()));
      }
      return null;
    }

    @Override
    public Element visitSuperConstructorInvocation(DartSuperConstructorInvocation x) {
      visit(x.getArguments());
      // check if correct place for super()
      if (ElementKind.of(currentHolder) != ElementKind.CLASS || currentMethod == null
          || !currentMethod.isConstructor()) {
        onError(x, ResolverErrorCode.SUPER_OUTSIDE_OF_CONSTRUCTOR);
        return recordElement(x, null);
      }
      InterfaceType supertype = ((ClassElement) currentHolder).getSupertype();
      // prepare ConstructorElement
      String name = x.getName() == null ? "" : x.getName().getName();
      ConstructorElement element;
      if (supertype == null) {
        element = null;
      } else {
        ClassElement classElement = supertype.getElement();
        element = Elements.lookupConstructor(classElement, name);
        if (element != null && element.getModifiers().isFactory()) {
          onError(x, ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, name, supertype);
        }
        if (element == null && "".equals(name) && x.getArguments().isEmpty()
            && Elements.needsImplicitDefaultConstructor(classElement)) {
          element = new SyntheticDefaultConstructorElement(null, classElement, typeProvider);
        }
      }
      if (element == null) {
        onError(x, ResolverErrorCode.CANNOT_RESOLVE_SUPER_CONSTRUCTOR, name);
      }
      if (x.getName() != null) {
        recordElement(x.getName(), element);
      }
      return recordElement(x, element);
    }

    @Override
    public Element visitNamedExpression(DartNamedExpression node) {
      // Intentionally skip the expression's name -- it's stored as an identifier, but doesn't need
      // to be resolved.
      return node.getExpression().accept(this);
    }

    @Override
    public Element visitIdentifier(DartIdentifier x) {
      return resolveIdentifier(x, false);
    }

    private Element resolveIdentifier(DartIdentifier x, boolean isQualifier) {
      if (x.getParent() instanceof DartLabel) {
        return x.getElement();
      }
      Scope scope = getContext().getScope();
      String name = x.getName();
      Element element = scope.findElement(scope.getLibrary(), name);
      if (element == null) {
        element = scope.findElement(scope.getLibrary(), "setter " + name);
      }
      if (element == null) {
        // A private identifier could refer to a field in a different library. In this case
        // we want to provide a more useful error message in the type analyzer.
        if (DartIdentifier.isPrivateName(name)) {
          Element found = scope.findElement(null, name);
          if (found != null) {
            Element enclosingElement = found.getEnclosingElement();
            String referencedElementName = enclosingElement == null
                ? name : String.format("%s.%s", enclosingElement.getName(), name);
            onError(x, ResolverErrorCode.ILLEGAL_ACCESS_TO_PRIVATE_MEMBER,
                            name, referencedElementName);
          }
        }
        if (isStaticOrFactoryContextOrInitializer(x) && !isQualifier) {
          if (!x.isResolutionAlreadyReportedThatTheMethodCouldNotBeFound()) {
            onError(x, TypeErrorCode.CANNOT_BE_RESOLVED, name);
            x.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
          }
        }
      } else if (x.getParent() instanceof DartComment) {
      } else {
        element = checkResolvedIdentifier(x, isQualifier, scope, name, element);
      }
      
      if (ElementKind.of(element) == ElementKind.DUPLICATE) {
        DuplicateElement duplicateElement = (DuplicateElement) element;
        List<String> locations = duplicateElement.getLocations();
        onError(x, ResolverErrorCode.DUPLICATE_IMPORTED_NAME, element.getName(), locations.size(),
            locations);
        return null;
      }

      if (inInitializer && ElementKind.of(element) == ElementKind.FIELD) {
        if (!element.getModifiers().isStatic() && !Elements.isTopLevel(element)) {
          onError(x, ResolverErrorCode.CANNOT_ACCESS_FIELD_IN_INIT);
        }
      }

      if (ElementKind.of(element) == ElementKind.FIELD) {
        FieldElement fieldElement = (FieldElement) element;
        if (fieldElement.getModifiers().isAbstractField()) {
          if (fieldElement.getGetter() == null && ASTNodes.inGetterContext(x)) {
            topLevelContext.onError(x, ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER);
            x.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
          }
          if (fieldElement.getSetter() == null && ASTNodes.inSetterContext(x)) {
            topLevelContext.onError(x, ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER);
            x.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
          }
        }
      }

      // May be local variable declared in lexical scope, but its declaration is not visited yet.
      if (getContext().getScope().isDeclaredButNotReachedVariable(name)) {
        onError(x, ResolverErrorCode.USING_LOCAL_VARIABLE_BEFORE_DECLARATION, x);
      }

      if (!isQualifier && !(x.getParent() instanceof DartComment)) {
        switch (ElementKind.of(element)) {
          case FUNCTION_TYPE_ALIAS:
            onError(x, ResolverErrorCode.CANNOT_USE_TYPE, name);
            break;
          case TYPE_VARIABLE:
            onError(x, ResolverErrorCode.CANNOT_USE_TYPE_VARIABLE, name);
            break;
          case DUPLICATE:
            DuplicateElement duplicateElement = (DuplicateElement) element;
            List<String> locations = duplicateElement.getLocations();
            onError(x, ResolverErrorCode.DUPLICATE_IMPORTED_NAME, element.getName(),
                locations.size(), locations);
            return null;
        }
      }

      // If we we haven't resolved the identifier, it will be normalized to
      // this.<identifier>.

      checkDeprecated(x, element);
      return recordElement(x, element);
    }

    /**
     * Possibly recursive check on the resolved identifier.
     */
    private Element checkResolvedIdentifier(DartIdentifier x, boolean isQualifier, Scope scope,
                                            String name, Element element) {
      switch (element.getKind()) {
        case FIELD:
          if (!Elements.isStaticContext(element)) {
            if (!element.getModifiers().isConstant()) {
              if (inInstanceVariableInitializer) {
                onError(x, ResolverErrorCode.CANNOT_USE_INSTANCE_FIELD_IN_INSTANCE_FIELD_INITIALIZER);
              }
            }
            if (ASTNodes.isStaticContext(x)) {
              onError(x, ResolverErrorCode.ILLEGAL_FIELD_ACCESS_FROM_STATIC, name);
            }
            if (ASTNodes.isFactoryContext(x)) {
              onError(x, ResolverErrorCode.ILLEGAL_FIELD_ACCESS_FROM_FACTORY, name);
            }
          }
          if (isIllegalPrivateAccess(x, enclosingElement, element, x.getName())) {
            return null;
          }
          break;
        case METHOD:
          if (ASTNodes.isStaticContext(x) && !Elements.isStaticContext(element)) {
            onError(x, ResolverErrorCode.ILLEGAL_METHOD_ACCESS_FROM_STATIC,
                name);
          }
          if (isIllegalPrivateAccess(x, enclosingElement, element, x.getName())) {
            return null;
          }
          if (!element.getModifiers().isStatic() && !Elements.isTopLevel(element)) {
            if (referencedFromInitializer(x)) {
              onError(x, ResolverErrorCode.INSTANCE_METHOD_FROM_INITIALIZER);
            }
          }
          break;
        case CLASS:
          if (!isQualifier) {
            return typeProvider.getTypeType().getElement();
          }
          break;
        case FUNCTION_TYPE_ALIAS:
        case TYPE_VARIABLE:
          return typeProvider.getTypeType().getElement();
        default:
          break;
      }
      return element;
    }

    @Override
    public Element visitTypeNode(DartTypeNode x) {
      // prepare ErrorCode, depends on the context
      ErrorCode errorCode = ResolverErrorCode.NO_SUCH_TYPE;
      ErrorCode wrongNumberErrorCode = ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
      {
        DartNode p = x.getParent();
        if (p instanceof DartTypeExpression) {
          DartTypeExpression typeExpression = (DartTypeExpression) p;
          if (typeExpression.getTypeNode() == x) {
            DartNode pp = p.getParent();
            if (pp instanceof DartBinaryExpression) {
              Token operator = ((DartBinaryExpression) pp).getOperator();
              if (operator == Token.AS || operator == Token.IS) {
                errorCode = TypeErrorCode.NO_SUCH_TYPE;
              }
            }
          }
        }
      }
      // do Type resolve
      return resolveType(x, ASTNodes.isStaticContext(x), ASTNodes.isFactoryContext(x), false,
          errorCode, wrongNumberErrorCode).getElement();
    }

    @Override
    public Element visitPropertyAccess(DartPropertyAccess x) {
      Element qualifier = resolveQualifier(x.getRealTarget());
      Element element = null;
      switch (ElementKind.of(qualifier)) {
        case CLASS:
          // Must be a static field.
          element = Elements.findElement(((ClassElement) qualifier), x.getPropertyName());
          if (element == null) {
            element = Elements.findElement(((ClassElement) qualifier), "setter " + x.getPropertyName());
          }
          if (isIllegalPrivateAccess(x.getName(), qualifier, element, x.getPropertyName())) {
            // break;
            return null;
          }
          switch (ElementKind.of(element)) {
            case FIELD:
              FieldElement field = (FieldElement) element;
              x.setType(field.getType());
              if (!field.getModifiers().isStatic()) {
                onError(x.getName(), ResolverErrorCode.NOT_A_STATIC_FIELD,
                    x.getPropertyName());
              }
              if (ASTNodes.inSetterContext(x)) {
                if (field.getGetter() != null) {
                  if (field.getSetter() == null) {
                    onError(x.getName(), ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER);
                  }
                }
              }
              if (ASTNodes.inGetterContext(x)) {
                if (field.getSetter() != null) {
                  if (field.getGetter() == null) {
                    onError(x.getName(), ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER);
                  }
                }
              }
              break;

            case NONE:
              x.getName().markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
              onError(x.getName(), TypeErrorCode.CANNOT_BE_RESOLVED,
                  x.getPropertyName());
              break;

            case METHOD:
              MethodElement method = (MethodElement) element;
              if (!method.getModifiers().isStatic()) {
                onError(x.getName(), ResolverErrorCode.NOT_A_STATIC_METHOD,
                    x.getPropertyName());
              }
              break;

            default:
              onError(x.getName(), ResolverErrorCode.EXPECTED_STATIC_FIELD,
                  element.getKind());
              break;
          }
          break;

        case SUPER:
          if (isIllegalPrivateAccess(x.getName(), qualifier, element, x.getPropertyName())) {
            return null;
          }
          ClassElement cls = ((SuperElement) qualifier).getClassElement();
          Member member = cls.getType().lookupMember(x.getPropertyName());
          if (member != null) {
            element = member.getElement();
          }
          switch (ElementKind.of(element)) {
            case FIELD:
              FieldElement field = (FieldElement) element;
              if (field.getModifiers().isStatic()) {
                onError(x.getName(), ResolverErrorCode.NOT_AN_INSTANCE_FIELD,
                  x.getPropertyName());
              }
              break;
            case METHOD:
              MethodElement method = (MethodElement) element;
              if (method.isStatic()) {
                onError(x.getName(), ResolverErrorCode.NOT_AN_INSTANCE_FIELD,
                  x.getPropertyName());
              }
              break;

            case NONE:
              onError(x.getName(), TypeErrorCode.CANNOT_BE_RESOLVED,
                  x.getPropertyName());
              break;

            default:
              onError(x.getName(),
                ResolverErrorCode.EXPECTED_AN_INSTANCE_FIELD_IN_SUPER_CLASS,
                element.getKind());
              break;
          }
          break;

        case LIBRARY_PREFIX:
          // Library prefix, lookup the element in the referenced library.
          Scope scope = ((LibraryPrefixElement) qualifier).getScope();
          element = scope.findElement(scope.getLibrary(), x.getPropertyName());
          if (element != null) {
            recordElement(x.getQualifier(), element.getEnclosingElement());
          } else {
            onError(x, ResolverErrorCode.CANNOT_BE_RESOLVED_LIBRARY,
                x.getPropertyName(), qualifier.getName());
          }
          break;

        case NONE: {
          // TODO(zundel): This is a bit awkward.  Maybe it would be better to have an
          // ElementKind of THIS just like we have for SUPER?
          if (x.getRealTarget() instanceof DartThisExpression) {
            Element foundElement = Elements.findElement(currentHolder, x.getPropertyName());
            if (foundElement != null && !foundElement.getModifiers().isStatic()) {
              if (ElementKind.of(foundElement) == ElementKind.TYPE_VARIABLE) {
                onError(x.getRealTarget(), ResolverErrorCode.TYPE_VARIABLE_NOT_ALLOWED_IN_IDENTIFIER);
                break;
              }
              element = foundElement;
            }
          }
        }

        default:
          break;
      }
      if (ElementKind.of(element) == ElementKind.DUPLICATE) {
        DuplicateElement duplicateElement = (DuplicateElement) element;
        List<String> locations = duplicateElement.getLocations();
        onError(x.getName(), ResolverErrorCode.DUPLICATE_IMPORTED_NAME, duplicateElement.getName(),
            locations.size(), locations);
        return null;
      }
      return recordElement(x, element);
    }

    private boolean isIllegalPrivateAccess(DartNode diagnosticNode, Element qualifier,
        Element element, String name) {
      if (DartIdentifier.isPrivateName(name)) {
        if (element == null) {
          element = getContext().getScope().findElement(null, name);
        }
        if (!Elements.areSameLibrary(enclosingElement, element)) {
          onError(diagnosticNode, ResolverErrorCode.ILLEGAL_ACCESS_TO_PRIVATE, name);
          return true;
        }
      }
      return false;
    }

    private Element resolveQualifier(DartNode qualifier) {
      if (qualifier == null) {
        return null;
      }
      return (qualifier instanceof DartIdentifier)
          ? resolveIdentifier((DartIdentifier) qualifier, true)
          : qualifier.accept(this);
    }

    @Override
    public Element visitMethodInvocation(DartMethodInvocation x) {
      DartIdentifier name = x.getFunctionName();
      Element target = resolveQualifier(x.getRealTarget());
      Element element = null;

      switch (ElementKind.of(target)) {
        case CLASS: {
          // Must be a static method or field.
          ClassElement classElement = (ClassElement) target;
          element = Elements.lookupLocalMethod(classElement, x.getFunctionNameString());
          if (element == null) {
            element = Elements.lookupLocalField(classElement, x.getFunctionNameString());
          }
          if (element == null || !element.getModifiers().isStatic()) {
            diagnoseErrorInMethodInvocation(x, classElement, element);
          } else {
            if (isIllegalPrivateAccess(x.getFunctionName(), target, element,
                x.getFunctionNameString())) {
              break;
            }
          }
          break;
        }

        case SUPER: {
          if (x.getParent() instanceof DartInitializer) {
            onError(x, ResolverErrorCode.SUPER_METHOD_INVOCATION_IN_CONSTRUCTOR_INITIALIZER);
          }
          // Must be a superclass' method or field.
          ClassElement classElement = ((SuperElement) target).getClassElement();
          InterfaceType type = classElement.getType();
          Member member = type.lookupMember(x.getFunctionNameString());
          if (member != null) {
            if (!member.getElement().getModifiers().isStatic()) {
              element = member.getElement();
              // Must be accessible.
              if (!Elements.isAccessible(context.getScope().getLibrary(), element)) {
                name.markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
                onError(name, ResolverErrorCode.CANNOT_ACCESS_METHOD, x.getFunctionNameString());
              }
            }
          }
          break;
        }

        case LIBRARY_PREFIX:
          // Library prefix, lookup the element in the reference library.
          LibraryPrefixElement library = ((LibraryPrefixElement) target);
          element = library.getScope().findElement(context.getScope().getLibrary(),
                                                   x.getFunctionNameString());
          if (element == null) {
            diagnoseErrorInMethodInvocation(x, library, null);
          } else {
            recordElement(x.getTarget(), element.getEnclosingElement());
            name.setElement(element);
          }
          break;
      }

      checkInvocationTarget(x, currentMethod, target);
      visit(x.getArguments());
      if (name != null) {
        recordElement(name, element);
      }
      return recordElement(x, element);
    }

    @Override
    public Element visitUnqualifiedInvocation(DartUnqualifiedInvocation x) {
      Scope scope = getContext().getScope();
      Element element = scope.findElement(scope.getLibrary(), x.getTarget().getName());
      if (element == null) {
        element = scope.findElement(scope.getLibrary(), "setter " + x.getTarget().getName());
      }
      ElementKind kind = ElementKind.of(element);
      if (kind == ElementKind.DUPLICATE) {
        DuplicateElement duplicateElement = (DuplicateElement) element;
        List<String> locations = duplicateElement.getLocations();
        onError(x.getTarget(), ResolverErrorCode.DUPLICATE_IMPORTED_NAME, element.getName(),
            locations.size(), locations);
        return null;
      } else if (!INVOKABLE_ELEMENTS.contains(kind)) {
        diagnoseErrorInUnqualifiedInvocation(x);
      } else {
        checkInvocationTarget(x, currentMethod, element);
      }
      if (Elements.isAbstractFieldWithoutGetter(element)) {
        String name = element.getName();
        if (isStaticOrFactoryContextOrInitializer(x)) {
          onError(x.getTarget(), ResolverErrorCode.USE_ASSIGNMENT_ON_SETTER, name);
        } else {
          onError(x.getTarget(), TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, name);
        }
      }
      recordElement(x, element);
      recordElement(x.getTarget(), element);
      visit(x.getArguments());
      return null;
    }

    @Override
    public Element visitFunctionObjectInvocation(DartFunctionObjectInvocation x) {
      x.getTarget().accept(this);
      visit(x.getArguments());
      return null;
    }

    @Override
    public Element visitNewExpression(final DartNewExpression x) {
      this.visit(x.getArguments());

      Element element = x.getConstructor().accept(getContext().new Selector() {
        // Only 'new' expressions can have a type in a property access.
        @Override
        public Element visitTypeNode(DartTypeNode type) {
          ErrorCode errorCode = x.isConst() ? ResolverErrorCode.NO_SUCH_TYPE_CONST : TypeErrorCode.NO_SUCH_TYPE;
          return recordType(type, resolveType(type, ASTNodes.isStaticContext(x),
                                              ASTNodes.isFactoryContext(x),
                                              false,
                                              errorCode,
                                              ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS));
        }

        @Override public Element visitPropertyAccess(DartPropertyAccess node) {
          Element element = node.getQualifier().accept(this);
          if (ElementKind.of(element).equals(ElementKind.CLASS)) {
            assert node.getQualifier() instanceof DartTypeNode;
            recordType(node, node.getQualifier().getType());
            return Elements.lookupConstructor(((ClassElement) element), node.getPropertyName());
          } else {
            return null;
          }
        }
      });


      switch (ElementKind.of(element)) {
        case DYNAMIC:
          return null;
        case CLASS:
        // Check for default constructor.
        ClassElement classElement = (ClassElement) element;
        element = Elements.lookupConstructor(classElement, "");
        // If no default constructor, may be use implicit default constructor.
        if (element == null
            && x.getArguments().isEmpty()
            && Elements.needsImplicitDefaultConstructor(classElement)) {
          element = new SyntheticDefaultConstructorElement(null, classElement, typeProvider);
        }
        break;
        case CONSTRUCTOR:
          if (enclosingElement != null) {
            if (element != null && DartIdentifier.isPrivateName(element.getName())
                && !Elements.areSameLibrary(enclosingElement, element)) {
              onError(x.getConstructor(), ResolverErrorCode.ILLEGAL_ACCESS_TO_PRIVATE,
                  element.getName());
              return null;
            }
          }
        break;
        case TYPE_VARIABLE:
          if (x.isConst() ) {
            onError(x.getConstructor(), ResolverErrorCode.CONST_EXPRESSION_CANT_USE_TYPE_VAR);
          } else {
            onError(x.getConstructor(), ResolverErrorCode.NEW_EXPRESSION_CANT_USE_TYPE_VAR);
          }
          return null;
        default:
          break;
      }

      // Will check that element is not null.
      ConstructorElement constructor = checkIsConstructor(x, element);

      // Check constructor.
      if (constructor != null) {
        boolean constConstructor = constructor.getModifiers().isConstant();
        // Check for using "const" to non-const constructor.
        if (x.isConst() && !constConstructor) {
          onError(x, ResolverErrorCode.CONST_AND_NONCONST_CONSTRUCTOR);
        }
        // Check for using "const" with type variables as type arguments.
        if (x.isConst() && constConstructor) {
          DartTypeNode typeNode = Types.constructorTypeNode(x);
          List<DartTypeNode> typeArguments = typeNode.getTypeArguments();
          for (DartTypeNode typeArgument : typeArguments) {
            if (typeArgument.getType() instanceof TypeVariable) {
              onError(typeArgument, ResolverErrorCode.CONST_WITH_TYPE_VARIABLE);
            }
          }
        }
      }

      return recordElement(x, constructor);
    }

    @Override
    public Element visitGotoStatement(DartGotoStatement x) {
      // Don't bother unless there's a target.
      if (x.getTargetName() != null) {
        Element element = getContext().getScope().findLabel(x.getTargetName(), innermostFunction);
        if (ElementKind.of(element).equals(ElementKind.LABEL)) {
          LabelElement labelElement = (LabelElement) element;
          if (x instanceof DartBreakStatement
              && labelElement.getStatementType() == LabeledStatementType.SWITCH_MEMBER_STATEMENT) {
            onError(x.getLabel(), ResolverErrorCode.BREAK_LABEL_RESOLVES_TO_CASE_OR_DEFAULT);
            return null;
          }
          if (x instanceof DartContinueStatement
              && labelElement.getStatementType() == LabeledStatementType.SWITCH_STATEMENT) {
            onError(x.getLabel(), ResolverErrorCode.CONTINUE_LABEL_RESOLVES_TO_SWITCH);
            return null;
          }
          MethodElement enclosingFunction = (labelElement).getEnclosingFunction();
          if (enclosingFunction == innermostFunction) {
            referencedLabels.add(labelElement);
            return recordElement(x, element);
          }
        }
        diagnoseErrorInGotoStatement(x, element);
      }
      return null;
    }

    public void diagnoseErrorInGotoStatement(DartGotoStatement x, Element element) {
      if (element == null) {
        onError(x.getLabel(), ResolverErrorCode.CANNOT_RESOLVE_LABEL,
            x.getTargetName());
      } else if (ElementKind.of(element).equals(ElementKind.LABEL)) {
        onError(x.getLabel(), ResolverErrorCode.CANNOT_ACCESS_OUTER_LABEL,
            x.getTargetName());
      } else {
        onError(x.getLabel(), ResolverErrorCode.NOT_A_LABEL, x.getTargetName());
      }
    }

    private void diagnoseErrorInMethodInvocation(DartMethodInvocation node, Element classOrLibrary,
                                                 Element element) {
      String name = node.getFunctionNameString();
      ElementKind kind = ElementKind.of(element);
      DartNode errorNode = node.getFunctionName();
      switch (kind) {
        case NONE:
          switch (ElementKind.of(classOrLibrary)) {
            case CLASS:
              onError(errorNode, ResolverErrorCode.CANNOT_RESOLVE_METHOD_IN_CLASS, name,
                      classOrLibrary.getName());
              node.getFunctionName().markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
              break;
            case LIBRARY:
              onError(errorNode, ResolverErrorCode.CANNOT_RESOLVE_METHOD_IN_LIBRARY, name,
                      classOrLibrary.getName());
              break;
            default:
              onError(errorNode, ResolverErrorCode.CANNOT_RESOLVE_METHOD, name);
          }

          break;

        case CONSTRUCTOR:
          onError(errorNode, ResolverErrorCode.IS_A_CONSTRUCTOR, classOrLibrary.getName(),
              name);
          break;

        case METHOD: {
          assert !((MethodElement) element).getModifiers().isStatic();
          onError(errorNode, ResolverErrorCode.IS_AN_INSTANCE_METHOD,
              classOrLibrary.getName(), name);
          break;
        }

        case FIELD: {
          onError(errorNode, ResolverErrorCode.IS_AN_INSTANCE_FIELD,
              classOrLibrary.getName(), name);
          break;
        }

        default:
          throw context.internalError(errorNode, "Unexpected kind of element: %s", kind);
      }
    }

    private void diagnoseErrorInUnqualifiedInvocation(DartUnqualifiedInvocation node) {
      String name = node.getTarget().getName();
      Scope scope = getContext().getScope();
      Element element = scope.findElement(scope.getLibrary(), name);
      ElementKind kind = ElementKind.of(element);
      switch (kind) {
        case NONE:
          if (isStaticOrFactoryContextOrInitializer(node) || ASTNodes.isFactoryContext(node)) {
            node.getTarget().markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
            onError(node.getTarget(), ResolverErrorCode.CANNOT_RESOLVE_METHOD, name);
          }
          if (scope.findElement(null, name) != null) {
            node.getTarget().markResolutionAlreadyReportedThatTheMethodCouldNotBeFound();
            onError(node.getTarget(), ResolverErrorCode.CANNOT_ACCESS_METHOD, name);
          }
          break;

        case CONSTRUCTOR:
          onError(node, ResolverErrorCode.DID_YOU_MEAN_NEW, name, "constructor");
          break;

        case CLASS:
          onError(node, ResolverErrorCode.DID_YOU_MEAN_NEW, name, "class");
          break;

        case TYPE_VARIABLE:
          onError(node, ResolverErrorCode.DID_YOU_MEAN_NEW, name, "type variable");
          break;

        case FUNCTION_TYPE_ALIAS:
          onError(node, ResolverErrorCode.CANNOT_CALL_FUNCTION_TYPE_ALIAS);
          break;

        case LIBRARY_PREFIX:
          onError(node, ResolverErrorCode.CANNOT_CALL_LIBRARY_PREFIX);
          break;

        default:
          throw context.internalError(node, "Unexpected kind of element: %s", kind);
      }
    }

    private void diagnoseErrorInInitializer(DartIdentifier x) {
      String name = x.getName();
      Scope scope = getContext().getScope();
      Element element = scope.findElement(scope.getLibrary(), name);
      ElementKind kind = ElementKind.of(element);
      switch (kind) {
        case NONE:
          onError(x, ResolverErrorCode.CANNOT_RESOLVE_FIELD, name);
          break;

        case FIELD:
          FieldElement field = (FieldElement) element;
          recordElement(x, field);
          if (field.isStatic()) {
            onError(x, ResolverErrorCode.CANNOT_INIT_STATIC_FIELD_IN_INITIALIZER);
          } else if (field.getModifiers().isAbstractField()) {
            /*
             * If we get here then we know that this is a property accessor and not a true field.
             * If there was a field and property accessor with the same name a name collision error
             * would keep us from reaching this point.
             */
            onError(x, ResolverErrorCode.CANNOT_INIT_STATIC_FIELD_IN_INITIALIZER);
          } else {
            onError(x, ResolverErrorCode.INIT_FIELD_ONLY_IMMEDIATELY_SURROUNDING_CLASS);
          }
          break;

        case METHOD:
          onError(x, ResolverErrorCode.EXPECTED_FIELD_NOT_METHOD, name);
          break;

        case CLASS:
          onError(x, ResolverErrorCode.EXPECTED_FIELD_NOT_CLASS, name);
          break;

        case PARAMETER:
          onError(x, ResolverErrorCode.EXPECTED_FIELD_NOT_PARAMETER, name);
          break;

        case TYPE_VARIABLE:
          onError(x, ResolverErrorCode.EXPECTED_FIELD_NOT_TYPE_VAR, name);
          break;

        case VARIABLE:
        case LABEL:
        default:
          throw context.internalError(x, "Unexpected kind of element: %s", kind);
      }
    }

    @Override
    public Element visitInitializer(DartInitializer x) {
      if (x.getName() != null) {
        // Make sure the identifier is a local instance field.
        FieldElement element = Elements.lookupLocalField(
            (ClassElement) currentHolder, x.getName().getName());
        if (element == null || element.isStatic() || element.getModifiers().isAbstractField()) {
          diagnoseErrorInInitializer(x.getName());
       }
        recordElement(x.getName(), element);
      }

      assert !inInitializer;
      DartExpression value = x.getValue();
      if (value == null) {
        return null;
      }
      inInitializer = true;
      Element element = value.accept(this);
      inInitializer = false;
      return element;
    }

    @Override
    public Element visitRedirectConstructorInvocation(DartRedirectConstructorInvocation x) {

      visit(x.getArguments());
      String name = x.getName() != null ? x.getName().getName() : "";
      ConstructorElement element = Elements.lookupConstructor((ClassElement) currentHolder, name);
      if (element == null) {
        onError(x, ResolverErrorCode.CANNOT_RESOLVE_CONSTRUCTOR, name);
      }
      return recordElement(x, element);
    }

    @Override
    public Element visitReturnStatement(DartReturnStatement x) {
      if (x.getValue() != null) {
        // Dart Spec v0.03, section 11.10.
        // Generative constructors cannot return arbitrary expressions in the form: 'return e;'
        // they can though have return statement in the form: 'return;'
        if ((currentMethod == innermostFunction)
            && Elements.isNonFactoryConstructor(currentMethod)) {
          onError(x, ResolverErrorCode.INVALID_RETURN_IN_CONSTRUCTOR);
        }
        return x.getValue().accept(this);
      }
      return null;
    }

    @Override
    public Element visitIntegerLiteral(DartIntegerLiteral node) {
      recordType(node, typeProvider.getIntType());
      return null;
    }

    @Override
    public Element visitDoubleLiteral(DartDoubleLiteral node) {
      recordType(node, typeProvider.getDoubleType());
      return null;
    }

    @Override
    public Element visitBooleanLiteral(DartBooleanLiteral node) {
      recordType(node, typeProvider.getBoolType());
      return null;
    }

    @Override
    public Element visitStringLiteral(DartStringLiteral node) {
      recordType(node, typeProvider.getStringType());
      return null;
    }

    @Override
    public Element visitStringInterpolation(DartStringInterpolation node) {
      node.visitChildren(this);
      recordType(node, typeProvider.getStringType());
      return null;
    }

    Element recordType(DartNode node, Type type) {
      node.setType(type);
      return type.getElement();
    }

    @Override
    public Element visitBinaryExpression(DartBinaryExpression node) {
      Element lhs = resolve(node.getArg1());
      resolve(node.getArg2());
      if (node.getOperator().isAssignmentOperator()) {
        switch (ElementKind.of(lhs)) {
          case FIELD:
          case PARAMETER:
          case VARIABLE:
            if (lhs.getModifiers().isFinal()) {
              if (Elements.isFieldOfSameClassAsEnclosingConstructor(lhs, enclosingElement)) {
                topLevelContext.onError(node.getArg1(),
                    ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL_ERROR, lhs.getName());
              } else {
                topLevelContext.onError(node.getArg1(), ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL,
                    lhs.getName());
              }
            }
            break;
          case METHOD:
            if (!lhs.getModifiers().isSetter() && !lhs.getModifiers().isGetter()) {
              topLevelContext.onError(node.getArg1(), ResolverErrorCode.CANNOT_ASSIGN_TO_METHOD,
                  lhs.getName());
            }
            if (lhs.getModifiers().isSetter()) {
              node.setElement(lhs);
            }
            break;
        }
      }

      return null;
    }

    @Override
    public Element visitUnaryExpression(DartUnaryExpression node) {
      DartExpression arg = node.getArg();
      Element argElement = resolve(arg);
      if (node.getOperator().isCountOperator()) {
        switch (ElementKind.of(argElement)) {
          case FIELD:
          case PARAMETER:
          case VARIABLE:
            if (argElement.getModifiers().isFinal()) {
              topLevelContext.onError(arg, ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL,
                  argElement.getName());
            }
            break;
        }
      }
      if (node.getOperator() == Token.CONDITIONAL) {
        if (ElementKind.of(argElement) != ElementKind.PARAMETER) {
          onError(arg, ResolverErrorCode.FORMAL_PARAMETER_NAME_EXPECTED);
        }
      }
      return null;
    }

    @Override
    public Element visitMapLiteral(DartMapLiteral node) {
      List<DartTypeNode> originalTypeArgs = node.getTypeArguments();
      List<DartTypeNode> typeArgs = Lists.newArrayList();
      DartTypeNode implicitKey = new DartTypeNode(
          new DartIdentifier("String"));
      switch (originalTypeArgs.size()) {
        case 1:
          // Old (pre spec 0.11) map specification
          typeArgs.add(implicitKey);
          typeArgs.add(originalTypeArgs.get(0));
          // TODO(scheglov) enable this warning
//          topLevelContext.onError(originalTypeArgs.get(0), ResolverErrorCode.DEPRECATED_MAP_LITERAL_SYNTAX);
          break;
        case 2:
          typeArgs.add(originalTypeArgs.get(0));
          typeArgs.add(originalTypeArgs.get(1));
          break;
        default:
          topLevelContext.onError(node, ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
                                  defaultLiteralMapType,
                                  originalTypeArgs.size(), 1);
          // fall through
        case 0:
          typeArgs.add(implicitKey);
          DartTypeNode implicitValue = new DartTypeNode(new DartIdentifier("dynamic"));
          typeArgs.add(implicitValue);
          break;
      }

      InterfaceType type =
          context.instantiateParameterizedType(
              defaultLiteralMapType.getElement(),
              node,
              typeArgs,
              ASTNodes.isStaticContext(node),
              ASTNodes.isFactoryContext(node),
              ResolverErrorCode.NO_SUCH_TYPE,
              ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
      // instantiateParametersType() will complain for wrong number of parameters (!=2)
      if (node.isConst()) {
        checkTypeArgumentsInConstLiteral(typeArgs, ResolverErrorCode.CONST_MAP_WITH_TYPE_VARIABLE);
      }
      recordType(node, type);
      visit(node.getEntries());
      return null;
    }

    @Override
    public Element visitArrayLiteral(DartArrayLiteral node) {
      List<DartTypeNode> typeArgs = node.getTypeArguments();
      InterfaceType type =
          context.instantiateParameterizedType(
              rawArrayType.getElement(),
              node,
              typeArgs,
              ASTNodes.isStaticContext(node),
              ASTNodes.isFactoryContext(node),
              ResolverErrorCode.NO_SUCH_TYPE,
              ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
      // instantiateParametersType() will complain for wrong number of parameters (!=1)
      if (node.isConst()) {
        checkTypeArgumentsInConstLiteral(typeArgs, ResolverErrorCode.CONST_ARRAY_WITH_TYPE_VARIABLE);
      }
      recordType(node, type);
      visit(node.getExpressions());
      return null;
    }

    private void checkTypeArgumentsInConstLiteral(List<DartTypeNode> typeArgs, ErrorCode errorCode) {
      for (DartTypeNode typeNode : typeArgs) {
        Type type = typeNode.getType();
        if (type != null && type.getKind() == TypeKind.VARIABLE) {
          onError(typeNode, errorCode);
        }
      }
    }

    private ConstructorElement checkIsConstructor(DartNewExpression node, Element element) {
      if (!ElementKind.of(element).equals(ElementKind.CONSTRUCTOR)) {
        ErrorCode errorCode = node.isConst()
            ? ResolverErrorCode.NEW_EXPRESSION_NOT_CONST_CONSTRUCTOR
            : TypeErrorCode.NEW_EXPRESSION_NOT_CONSTRUCTOR;
        onError(ASTNodes.getConstructorNameNode(node), errorCode);
        return null;
      }
      return (ConstructorElement) element;
    }

    private void checkConstructor(DartMethodDefinition node,
                                  ConstructorElement superCall) {
      ClassElement currentClass = (ClassElement) currentHolder;
      if (superCall == null) {
        // Look for a default constructor in our super type
        InterfaceType supertype = currentClass.getSupertype();
        if (supertype != null) {
          superCall = Elements.lookupConstructor(supertype.getElement(), "");
        }
        if (superCall != null) {

          // Do positional parameters match?
          int superPositionalCount = Elements.getNumberOfRequiredParameters(superCall);
          if (superPositionalCount > 0) {
            onError(node, ResolverErrorCode.TOO_FEW_ARGUMENTS_IN_IMPLICIT_SUPER,
                superCall.getType().toString());
          }
        }
      }

      if (superCall == null
          && !currentClass.isObject()
          && !currentClass.isObjectChild()) {
        InterfaceType supertype = currentClass.getSupertype();
        if (supertype != null) {
          ClassElement superElement = supertype.getElement();
          if (superElement != null) {
            if (!hasDefaultConstructor(superElement)) {
              onError(node,
                  ResolverErrorCode.CANNOT_RESOLVE_IMPLICIT_CALL_TO_SUPER_CONSTRUCTOR,
                  superElement.getName());
            }
          }
        }
      } else if (superCall != null
          && node.getModifiers().isConstant()
          && !superCall.getModifiers().isConstant()) {
        onError(node.getName(),
            ResolverErrorCode.CONST_CONSTRUCTOR_MUST_CALL_CONST_SUPER);
      }
    }

    private void checkInvocationTarget(DartInvocation node,
                                       MethodElement callSite,
                                       Element target) {

      if (ElementKind.of(target).equals(ElementKind.METHOD)) {
        if (callSite != null && callSite.isStatic())
          if (!target.getModifiers().isStatic() && !Elements.isTopLevel(target)) {
            onError(node, ResolverErrorCode.INSTANCE_METHOD_FROM_STATIC);
          }
        if (!target.getModifiers().isStatic() && !Elements.isTopLevel(target)) {
          if (referencedFromRedirectConstructor(node)) {
            onError(node, ResolverErrorCode.INSTANCE_METHOD_FROM_REDIRECT);
          } else if (referencedFromInitializer(node)) {
            onError(node, ResolverErrorCode.INSTANCE_METHOD_FROM_INITIALIZER);
          }
        }
      }
    }

    private boolean referencedFromInitializer(DartNode node) {
      do {
        if (node instanceof DartInitializer) {
          return true;
        }
        node = node.getParent();
      } while (node != null);
      return false;
    }

    private boolean referencedFromRedirectConstructor(DartNode node) {
      do {
        if (node instanceof DartRedirectConstructorInvocation) {
          return true;
        }
        node = node.getParent();
      } while (node != null);
      return false;
    }

    private void checkVariableStatement(DartVariableStatement node,
                                        DartVariable variable,
                                        boolean isImplicitlyInitialized) {
      Modifiers modifiers = node.getModifiers();
      if (modifiers.isFinal()) {
        if (!isImplicitlyInitialized && (variable.getValue() == null)) {
          onError(variable.getName(), ResolverErrorCode.CONSTANTS_MUST_BE_INITIALIZED);
        } else if (modifiers.isStatic() && variable.getValue() != null) {
          resolve(variable.getValue());
          node.setType(variable.getValue().getType());
        }
      }
    }

    private void resolveInitializers(DartMethodDefinition node, Set<FieldElement> initializedFields) {
      ClassElement classElement = (ClassElement) enclosingElement.getEnclosingElement();

      ConstructorElement constructorElement = null;
      boolean hasSuperInvocation = false;
      for (DartInitializer initializer : node.getInitializers()) {
        hasSuperInvocation |= initializer.getValue() instanceof DartSuperConstructorInvocation;
        Element element = resolve(initializer);
        if ((ElementKind.of(element) == ElementKind.CONSTRUCTOR) && initializer.isInvocation()) {
          constructorElement = (ConstructorElement) element;
        } else if (initializer.getName() != null && initializer.getName().getElement() != null
            && initializer.getName().getElement().getModifiers() != null
            && !initializedFields.add((FieldElement)initializer.getName().getElement())) {
          onError(initializer, ResolverErrorCode.DUPLICATE_INITIALIZATION, initializer.getName());
        }
      }

      // If no explicit super() invocation, then implicit call of default super-type constructor.
      // Check that it is not factory, i.e. generative.
      if (!hasSuperInvocation && currentHolder instanceof ClassElement) {
        InterfaceType superType = classElement.getSupertype();
        if (superType != null) {
          ClassElement superElement = superType.getElement();
          ConstructorElement superConstructor = Elements.lookupConstructor(superElement, "");
          if (superConstructor != null && superConstructor.getModifiers().isFactory()) {
            onError(node.getName(), ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR,
                "<default>", superType);
          }
        }
      }

      // Look for final fields that are not initialized
      Element methodElement = node.getElement();
      if (classElement != null && methodElement != null
          && !classElement.isInterface()
          && !classElement.getModifiers().isNative()
          && !methodElement.getModifiers().isExternal()
          && !methodElement.getModifiers().isRedirectedConstructor()) {
        for (Element member : classElement.getMembers()) {
          switch (ElementKind.of(member)) {
            case FIELD:
              FieldElement fieldMember = (FieldElement)member;
              if (fieldMember.getModifiers().isFinal()
                  && !fieldMember.getModifiers().isInitialized()
                  && !initializedFields.contains(fieldMember)) {
                FieldNodeElement n = (FieldNodeElement)fieldMember;
                onError(n.getNode(), ResolverErrorCode.FINAL_FIELD_MUST_BE_INITIALIZED,
                    fieldMember.getName());
              }
          }
        }
      }

      checkConstructor(node, constructorElement);
    }

    private void onError(HasSourceInfo target, ErrorCode errorCode, Object... arguments) {
      context.onError(target, errorCode, arguments);
    }

    private void onError(SourceInfo target, ErrorCode errorCode, Object... arguments) {
      context.onError(target, errorCode, arguments);
    }

    boolean isStaticOrFactoryContextOrInitializer(DartNode x) {
      return ASTNodes.isStaticOrFactoryContext(x) || inInitializer;
    }
  }

  public static class Phase implements DartCompilationPhase {
    /**
     * Executes element resolution on the given compilation unit.
     *
     * @param context The listener through which compilation errors are reported
     *          (not <code>null</code>)
     */
    @Override
    public DartUnit exec(DartUnit unit, DartCompilerContext context,
                         CoreTypeProvider typeProvider) {
      Scope unitScope = unit.getLibrary().getElement().getScope();
      return new Resolver(context, unitScope, typeProvider).exec(unit);
    }
  }

  private void checkRedirectConstructorCycle(List<ConstructorNodeElement> constructors,
                                             ResolutionContext context) {
    for (ConstructorNodeElement element : constructors) {
      if (hasRedirectedConstructorCycle(element)) {
        context.onError(element, ResolverErrorCode.REDIRECTED_CONSTRUCTOR_CYCLE);
      }
    }
  }

  private boolean hasRedirectedConstructorCycle(ConstructorNodeElement constructorElement) {
    Set<ConstructorNodeElement> visited = Sets.newHashSet();
    ConstructorNodeElement next = getNextConstructorInvocation(constructorElement);
    while (next != null) {
      if (visited.contains(next)) {
        return true;
      }
      if (constructorElement.getName().equals(next.getName())) {
        return true;
      }
      visited.add(next);
      next = getNextConstructorInvocation(next);
    }
    return false;
  }

  private ConstructorNodeElement getNextConstructorInvocation(ConstructorNodeElement constructor) {
    List<DartInitializer> inits = ((DartMethodDefinition) constructor.getNode()).getInitializers();
    // Parser ensures that redirected constructors can be the only item in the initialization list.
    if (inits.size() == 1) {
      DartExpression value = inits.get(0).getValue();
      if (value != null) {
        Element element = value.getElement();
        if (ElementKind.of(element).equals(ElementKind.CONSTRUCTOR)) {
          ConstructorElement nextConstructorElement = (ConstructorElement) element;
          ClassElement nextClass = (ClassElement) nextConstructorElement.getEnclosingElement();
          ClassElement currentClass = (ClassElement) constructor.getEnclosingElement();
          if (nextClass == currentClass) {
            return (ConstructorNodeElement) nextConstructorElement;
          }
        }
      }
    }
    return null;
  }
}
