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

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.dart.compiler.CommandLineOptions.CompilerOptions;
import com.google.dart.compiler.DartCompilationError;
import com.google.dart.compiler.DartCompilationPhase;
import com.google.dart.compiler.DartCompilerContext;
import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ErrorSeverity;
import com.google.dart.compiler.PackageLibraryManager;
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.DartArrayAccess;
import com.google.dart.compiler.ast.DartArrayLiteral;
import com.google.dart.compiler.ast.DartAssertStatement;
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.DartCascadeExpression;
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.DartComment;
import com.google.dart.compiler.ast.DartConditional;
import com.google.dart.compiler.ast.DartContinueStatement;
import com.google.dart.compiler.ast.DartDeclaration;
import com.google.dart.compiler.ast.DartDefault;
import com.google.dart.compiler.ast.DartDoWhileStatement;
import com.google.dart.compiler.ast.DartDoubleLiteral;
import com.google.dart.compiler.ast.DartEmptyStatement;
import com.google.dart.compiler.ast.DartExportDirective;
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.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.DartLibraryDirective;
import com.google.dart.compiler.ast.DartLiteral;
import com.google.dart.compiler.ast.DartMapLiteral;
import com.google.dart.compiler.ast.DartMapLiteralEntry;
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.DartNativeDirective;
import com.google.dart.compiler.ast.DartNewExpression;
import com.google.dart.compiler.ast.DartNode;
import com.google.dart.compiler.ast.DartNullLiteral;
import com.google.dart.compiler.ast.DartParameter;
import com.google.dart.compiler.ast.DartParameterizedTypeNode;
import com.google.dart.compiler.ast.DartParenthesizedExpression;
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.DartSourceDirective;
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.DartSyntheticErrorExpression;
import com.google.dart.compiler.ast.DartSyntheticErrorIdentifier;
import com.google.dart.compiler.ast.DartSyntheticErrorStatement;
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.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.ClassElement;
import com.google.dart.compiler.resolver.ClassNodeElement;
import com.google.dart.compiler.resolver.ConstructorElement;
import com.google.dart.compiler.resolver.CoreTypeProvider;
import com.google.dart.compiler.resolver.CyclicDeclarationException;
import com.google.dart.compiler.resolver.Element;
import com.google.dart.compiler.resolver.ElementKind;
import com.google.dart.compiler.resolver.Elements;
import com.google.dart.compiler.resolver.FieldElement;
import com.google.dart.compiler.resolver.FunctionAliasElement;
import com.google.dart.compiler.resolver.MethodElement;
import com.google.dart.compiler.resolver.ResolverErrorCode;
import com.google.dart.compiler.resolver.TypeErrorCode;
import com.google.dart.compiler.resolver.VariableElement;
import com.google.dart.compiler.type.InterfaceType.Member;
import com.google.dart.compiler.util.apache.ObjectUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Analyzer of static type information.
 */
public class TypeAnalyzer implements DartCompilationPhase {

  private final Set<ClassElement> diagnosedAbstractClasses = Sets.newHashSet();

  /**
   * Perform type analysis on the given AST rooted at <code>node</code>.
   *
   * @param node The root of the tree to analyze
   * @param typeProvider The source of pre-defined type definitions
   * @param context The compilation context (DartCompilerContext)
   * @param currentClass The class that contains <code>node</code>. Will be null
   *        for top-level declarations.
   * @return The type of <code>node</code>.
   */
  public static Type analyze(DartNode node, CoreTypeProvider typeProvider,
                             DartCompilerContext context, InterfaceType currentClass) {
    Set<ClassElement> diagnosed = Sets.newHashSet();
    Analyzer analyzer = new Analyzer(context, typeProvider, diagnosed);
    analyzer.setCurrentClass(currentClass);
    return node.accept(analyzer);
  }

  @Override
  public DartUnit exec(DartUnit unit, DartCompilerContext context, CoreTypeProvider typeProvider) {
    unit.accept(new Analyzer(context, typeProvider, diagnosedAbstractClasses));
    return unit;
  }

  @VisibleForTesting
  static class Analyzer extends ASTVisitor<Type> {
    private final DynamicType dynamicType;
    private final Type stringType;
    private final InterfaceType defaultLiteralMapType;
    private final Type voidType;
    private final DartCompilerContext context;
    private final Types types;
    private Type expected;
    private MethodElement currentMethod;
    private InterfaceType currentClass;
    private final InterfaceType objectType;
    private final InterfaceType boolType;
    private final InterfaceType numType;
    private final InterfaceType intType;
    private final InterfaceType doubleType;
    private final Type nullType;
    private final InterfaceType functionType;
    private final InterfaceType dynamicIteratorType;
    private final boolean developerModeChecks;
    private final boolean suppressSdkWarnings;
    private final boolean typeChecksForInferredTypes;
    private final boolean reportNoMemberWhenHasInterceptor;
    private final Map<DartBlock, VariableElementsRestorer> restoreOnBlockExit = Maps.newHashMap();
    /**
     * When we see variable assignment, we remember here old {@link Type} (if not done already) and
     * set new {@link Type} into {@link VariableElement}. On the exit from basic block we remove
     * first element and merge new types with old types.
     */
    private final LinkedList<BlockTypeContext> blockOldTypes = Lists.newLinkedList();
    private static class BlockTypeContext {
      final Map<VariableElement, Type> oldTypes = Maps.newHashMap();
      final Map<VariableElement, Type> newTypes = Maps.newHashMap();
      void rememberOldType(VariableElement element, Type oriType) {
        if (!oldTypes.containsKey(element)) {
          oldTypes.put(element, oriType);
        }
      }
      void setType(VariableElement element, Type newType) {
        if (canSetType(element)) {
          rememberOldType(element, element.getType());
          newTypes.put(element, newType);
          Elements.setType(element, newType);
        }
      }
      boolean canSetType(VariableElement element) {
        Type type = element.getType();
        // no type declared, no assignment yet
        if (TypeKind.of(type) == TypeKind.DYNAMIC) {
          return true;
        }
        // was assignment, inferred
        if (type != null && TypeQuality.isInferred(type)) {
          return true;
        }
        // was declared with type, keep it
        return false;
      }
      Map<VariableElement, Type> getNewTypesAndRestoreOld() {
        for (Entry<VariableElement, Type> entry : oldTypes.entrySet()) {
          VariableElement variable = entry.getKey();
          Elements.setType(variable, entry.getValue());
        }
        return newTypes;
      }
    }

    /**
     * Keeps track of the number of nested catches, used to detect re-throws
     * outside of any catch block.
     */
    private int catchDepth = 0;

    Analyzer(DartCompilerContext context, CoreTypeProvider typeProvider,
             Set<ClassElement> diagnosedAbstractClasses) {
      this.context = context;
      this.developerModeChecks = context.getCompilerConfiguration().developerModeChecks();
      this.types = Types.getInstance(typeProvider);
      this.dynamicType = typeProvider.getDynamicType();
      this.stringType = typeProvider.getStringType();
      this.defaultLiteralMapType = typeProvider.getMapType(stringType, dynamicType);
      this.voidType = typeProvider.getVoidType();
      this.objectType = typeProvider.getObjectType();
      this.boolType = typeProvider.getBoolType();
      this.numType = typeProvider.getNumType();
      this.intType = typeProvider.getIntType();
      this.doubleType = typeProvider.getDoubleType();
      this.nullType = typeProvider.getNullType();
      this.functionType = typeProvider.getFunctionType();
      this.dynamicIteratorType = typeProvider.getIteratorType(dynamicType);
      CompilerOptions compilerOptions = context.getCompilerConfiguration().getCompilerOptions();
      this.suppressSdkWarnings = compilerOptions.suppressSdkWarnings();
      this.typeChecksForInferredTypes = compilerOptions.typeChecksForInferredTypes();
      this.reportNoMemberWhenHasInterceptor = compilerOptions.reportNoMemberWhenHasInterceptor();
    }

    @VisibleForTesting
    void setCurrentClass(InterfaceType type) {
      currentClass = type;
    }

    @VisibleForTesting
    void pushBasicBlockContext() {
      blockOldTypes.addFirst(new BlockTypeContext());
    }

    private InterfaceType getCurrentClass() {
      return currentClass;
    }

    private DynamicType typeError(HasSourceInfo node, ErrorCode code, Object... arguments) {
      onError(node, code, arguments);
      return dynamicType;
    }

    private void onError(HasSourceInfo node, ErrorCode errorCode, Object... arguments) {
      onError(node.getSourceInfo(), errorCode, arguments);
    }

    private void onError(SourceInfo errorTarget, ErrorCode errorCode, Object... arguments) {
      if (suppressSdkWarnings) {
        ErrorSeverity errorSeverity = errorCode.getErrorSeverity();
        if (errorSeverity == ErrorSeverity.WARNING || errorSeverity == ErrorSeverity.INFO) {
          Source source = errorTarget.getSource();
          if (source != null && PackageLibraryManager.isDartUri(source.getUri())) {
            return;
          }
        }
      }
      context.onError(new DartCompilationError(errorTarget, errorCode, arguments));
    }

    AssertionError internalError(HasSourceInfo node, String message, Object... arguments) {
      message = String.format(message, arguments);
      context.onError(new DartCompilationError(node, TypeErrorCode.INTERNAL_ERROR,
                                                        message));
      return new AssertionError("Internal error: " + message);
    }

    private Type typeOfLiteral(DartLiteral node) {
      Type type = node.getType();
      return type == null ? voidType : type;
    }

    private Token getBasicOperator(DartNode diagnosticNode, Token op) {
      switch(op) {
        case INC:
          return Token.ADD;
        case DEC:
          return Token.SUB;
        case ASSIGN_BIT_OR:
          return Token.BIT_OR;
        case ASSIGN_BIT_XOR:
          return Token.BIT_XOR;
        case ASSIGN_BIT_AND:
          return Token.BIT_AND;
        case ASSIGN_SHL:
          return Token.SHL;
        case ASSIGN_SAR:
          return Token.SAR;
        case ASSIGN_ADD:
          return Token.ADD;
        case ASSIGN_SUB:
          return Token.SUB;
        case ASSIGN_MUL:
          return Token.MUL;
        case ASSIGN_DIV:
          return Token.DIV;
        case ASSIGN_MOD:
          return Token.MOD;
        case ASSIGN_TRUNC:
          return Token.TRUNC;
        default:
          internalError(diagnosticNode, "unexpected operator %s", op.name());
          return null;
      }
    }

    @Override
    public Type visitRedirectConstructorInvocation(DartRedirectConstructorInvocation node) {
      return checkConstructorForwarding(node, node.getElement());
    }

    private String methodNameForUnaryOperator(DartNode diagnosticNode, Token operator) {
      if (operator == Token.SUB) {
        return "operator -";
      } else if (operator == Token.BIT_NOT) {
        return "operator ~";
      }
      return "operator " + getBasicOperator(diagnosticNode, operator).getSyntax();
    }

    private String methodNameForBinaryOperator(Token operator) {
      if (operator.getSyntax().equals("-")) {
        return "operator -binary";
      }
      return "operator " + operator.getSyntax();
    }

    private Type analyzeBinaryOperator(DartNode node, Type lhsType, Token operator,
        DartNode diagnosticNode, DartExpression rhs) {
      Type rhsType = nonVoidTypeOf(rhs);
      String methodName = methodNameForBinaryOperator(operator);
      HasSourceInfo problemTarget = getOperatorHasSourceInfo(node);
      Member member = lookupMember(lhsType, methodName, problemTarget);
      if (member != null) {
        Element element = member.getElement();
        node.setElement(element);
        FunctionType methodType = getMethodType(lhsType, member, methodName, diagnosticNode);
        checkDeprecated(problemTarget, element);
        Type returnType = checkInvocation(Collections.<DartExpression> singletonList(rhs),
            Collections.<Type> singletonList(rhsType),
            diagnosticNode, methodName, methodType, null);
        // tweak return type for int/int and int/double operators
        {
          boolean lhsInt = intType.equals(lhsType);
          boolean rhsInt = intType.equals(rhsType);
          boolean lhsDouble = doubleType.equals(lhsType);
          boolean rhsDouble = doubleType.equals(rhsType);
          switch (operator) {
            case ADD:
            case SUB:
            case MUL:
            case TRUNC:
            case MOD:
              if (lhsInt && rhsInt) {
                return intType;
              }
            case DIV:
              if (lhsDouble || rhsDouble) {
                return doubleType;
              }
          }
        }
        // done
        return returnType;
      } else {
        return dynamicType;
      }
    }

    private Type analyzeTernaryOperator(DartNode node, Type lhsType, Token operator,
        DartNode diagnosticNode, DartExpression arg1, DartExpression arg2) {
      String methodName = methodNameForBinaryOperator(operator);
      HasSourceInfo problemTarget = getOperatorHasSourceInfo(node);
      Member member = lookupMember(lhsType, methodName, problemTarget);
      if (member != null) {
        Element element = member.getElement();
        node.setElement(element);
        FunctionType methodType = getMethodType(lhsType, member, methodName, diagnosticNode);
        checkDeprecated(problemTarget, element);
        return checkInvocation(ImmutableList.of(arg1, arg2), diagnosticNode, methodName,
            methodType, null);
      } else {
        return dynamicType;
      }
    }

    @Override
    public Type visitBinaryExpression(DartBinaryExpression node) {
      DartExpression lhsNode = node.getArg1();
      Type lhs = nonVoidTypeOf(lhsNode);
      DartExpression rhsNode = node.getArg2();
      Token operator = node.getOperator();
      switch (operator) {
        case ASSIGN: {
          // prepare RHS type
          Type rhs = getInvocationArgumentType(rhsNode);
          try {
            if (!hasInferredType(lhsNode)) {
              if (checkAssignable(rhsNode, lhs, rhs)) {
                inferFunctionLiteralParametersTypes(rhsNode, lhs);
              }
            }
          } finally {
            if (rhsNode instanceof DartFunctionExpression) {
              rhsNode.accept(this);
            }
          }
          // may be replace type of variable
          setVariableElementType(lhsNode.getElement(), rhs, getTypeQuality(rhsNode));
          checkAssignableElement(lhsNode);
          // if cascade, then use type of "lhs" qualifier
          if (lhsNode instanceof DartPropertyAccess) {
            DartPropertyAccess lhsAccess = (DartPropertyAccess) lhsNode;
            if (lhsAccess.isCascade()) {
              return lhsAccess.getRealTarget().getType();
            }
          }
          // use type or "rhs"
          return rhs;
        }

        case ASSIGN_ADD:
        case ASSIGN_SUB:
        case ASSIGN_MUL:
        case ASSIGN_DIV:
        case ASSIGN_MOD:
        case ASSIGN_TRUNC: {
          Token basicOperator = getBasicOperator(node, operator);
          Type type = analyzeBinaryOperator(node, lhs, basicOperator, lhsNode, rhsNode);
          checkAssignable(node, lhs, type);
          checkAssignableElement(lhsNode);
          return type;
        }

        case OR:
        case AND: {
          checkAssignable(lhsNode, boolType, lhs);
          checkAssignable(boolType, rhsNode);
          return boolType;
        }

        case ASSIGN_BIT_OR:
        case ASSIGN_BIT_XOR:
        case ASSIGN_BIT_AND:
        case ASSIGN_SHL:
        case ASSIGN_SAR: {
          // Bit operations are only supported by integers and
          // thus cannot be looked up on num. To ease usage of
          // bit operations, we currently allow them to be used
          // if the left-hand-side is of type num.
          // TODO(karlklose) find a clean solution, i.e., without a special case for num.
          checkAssignableElement(lhsNode);
          if (lhs.equals(numType)) {
            checkAssignable(rhsNode, numType, typeOf(rhsNode));
            return intType;
          } else {
            Token basicOperator = getBasicOperator(node, operator);
            Type type = analyzeBinaryOperator(node, lhs, basicOperator, lhsNode, rhsNode);
            checkAssignable(node, lhs, type);
            return type;
          }
        }

        case BIT_OR:
        case BIT_XOR:
        case BIT_AND:
        case SHL:
        case SAR: {
          // Bit operations are only supported by integers and
          // thus cannot be looked up on num. To ease usage of
          // bit operations, we currently allow them to be used
          // if the left-hand-side is of type num.
          // TODO(karlklose) find a clean solution, i.e., without a special case for num.
          if (lhs.equals(numType)) {
            checkAssignable(rhsNode, numType, typeOf(rhsNode));
            return intType;
          } else {
            return analyzeBinaryOperator(node, lhs, operator, lhsNode, rhsNode);
          }
        }

        case ADD:
        case SUB:
        case MUL:
        case DIV:
        case TRUNC:
        case MOD:
        case LT:
        case GT:
        case LTE:
        case GTE:
          return analyzeBinaryOperator(node, lhs, operator, lhsNode, rhsNode);

        case EQ: {
          // try to resolve "==" to "operator equals()", but don't complain if can not find it
          String methodName = methodNameForBinaryOperator(operator);
          InterfaceType itype = types.getInterfaceType(lhs);
          if (itype != null) {
            Member member = itype.lookupMember(methodName);
            if (member != null) {
              node.setElement(member.getElement());
            }
          }
        }
       case NE:
       case EQ_STRICT:
       case NE_STRICT:
         nonVoidTypeOf(rhsNode);
         return boolType;

       case AS:
         return typeOf(rhsNode);

       case IS:
         if (rhsNode instanceof DartUnaryExpression) {
           assert ((DartUnaryExpression) rhsNode).getOperator() == Token.NOT;
           nonVoidTypeOf(((DartUnaryExpression) rhsNode).getArg());
         } else {
           nonVoidTypeOf(rhsNode);
         }
         return boolType;

       case COMMA:
         return typeOf(rhsNode);

        default:
          throw new AssertionError("Unknown operator: " + operator);
      }
    }

    private void checkAssignableElement(DartExpression lhsNode) {
      Element lhsElement = lhsNode.getElement();
      switch (ElementKind.of(lhsElement)) {
        case DYNAMIC:
        case VARIABLE:
        case PARAMETER:
        case FIELD:
        case NONE:
          // OK or unknown
          break;

        case METHOD:
          if (lhsElement.getModifiers().isSetter()
           || lhsElement.getModifiers().isGetter()
           || lhsElement.getModifiers().isOperator()) {
            // The check for methods with setters is elsewhere.
            break;
          }
        default:
          onError(lhsNode, TypeErrorCode.CANNOT_ASSIGN_TO, ElementKind.of(lhsElement));
        break;
      }
    }

    /**
     * @return the best guess for operator token location in the given {@link DartNode}.
     */
    private static HasSourceInfo getOperatorHasSourceInfo(DartNode node) {
      Token operator = null;
      int offset = 0;
      if (node instanceof DartBinaryExpression) {
        DartBinaryExpression binary = (DartBinaryExpression) node;
        operator = binary.getOperator();
        offset = binary.getOperatorOffset();
      }
      if (node instanceof DartUnaryExpression) {
        DartUnaryExpression binary = (DartUnaryExpression) node;
        operator = binary.getOperator();
        offset = binary.getOperatorOffset();
      }
      if (operator != null) {
        Source source = node.getSourceInfo().getSource();
        int length = operator.getSyntax().length();
        final SourceInfo sourceInfo = new SourceInfo(source, offset, length);
        return new HasSourceInfo() {
          @Override
          public SourceInfo getSourceInfo() {
            return sourceInfo;
          }
        };
      }
      return node;
    }

    @Override
    public Type visitExprStmt(DartExprStmt node) {
      Type type = typeOf(node.getExpression());
      return type;
    }

    @Override
    public Type visitVariableStatement(DartVariableStatement node) {
      Type type = typeOf(node.getTypeNode());
      visit(node.getVariables());
      return type;
    }

    private Member lookupMember(Type receiver, String methodName, HasSourceInfo problemTarget) {
      InterfaceType itype = types.getInterfaceType(receiver);
      if (itype == null) {
        diagnoseNonInterfaceType(problemTarget, receiver);
        return null;
      }
      Member member = itype.lookupMember(methodName);
      if (member == null) {
        member = itype.lookupMember("setter " + methodName);
      }
      // is "receiver" is inferred, attempt to find member in one of the subtypes
      boolean hasMemberInSubClasses = false;
      if (member == null) {
        if (TypeQuality.of(receiver) == TypeQuality.INFERRED && receiver instanceof InterfaceType) {
          List<Member> subMembers = ((InterfaceType) receiver).lookupSubTypeMembers(methodName);
          hasMemberInSubClasses = !subMembers.isEmpty();
          if (subMembers.size() == 1) {
            member = subMembers.get(0);
          }
        }
      }
      // report problem
      if (member == null && problemTarget != null) {
        if (reportNoMemberWhenHasInterceptor || !Elements.handlesNoSuchMethod(itype)) {
          if (typeChecksForInferredTypes && !hasMemberInSubClasses
              && !isTooGenericInferredType(receiver) || !TypeQuality.isInferred(receiver)) {
            ErrorCode code = TypeQuality.isInferred(receiver)
                ? TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED_INFERRED
                : TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED;
            typeError(problemTarget, code, receiver, methodName);
          }
        }
        return null;
      }
      return member;
    }

    /**
     * If left-hand-side is {@link VariableElement} with propagated type, then remember type before
     * current "basic block" and set new type.
     */
    private void setVariableElementType(Element element, Type type, TypeQuality quality) {
      if (ElementKind.of(element) == ElementKind.VARIABLE) {
        VariableElement variableElement = (VariableElement) element;
        Type newType = Types.makeInferred(type, quality);
        blockOldTypes.getFirst().setType(variableElement, newType);
      }
    }

    /**
     * @return <code>true</code> if given {@link DartNode} has inferred {@link Type}.
     */
    private static boolean hasInferredType(DartNode node) {
      return node != null && hasInferredType(node.getElement());
    }

    /**
     * @return <code>true</code> if given {@link Element} is has inferred {@link Type}.
     */
    private static boolean hasInferredType(Element element) {
      return element != null && element.getType() != null
          && element.getType().getQuality() != TypeQuality.EXACT;
    }

    /**
     * Helper for visiting {@link DartNode} which happens only if "condition" is satisfied. Attempts
     * to infer types of {@link VariableElement}s from given "condition".
     */
    private void visitConditionalNode(DartExpression condition, DartNode node) {
      final VariableElementsRestorer variableRestorer = new VariableElementsRestorer();
      try {
        inferVariableTypesFromIsConditions(condition, variableRestorer);
        typeOf(node);
      } finally {
        variableRestorer.restore();
      }
    }

    /**
     * Helper for setting {@link Type}s of {@link VariableElement}s when given "condition" is
     * satisfied.
     */
    private void inferVariableTypesFromIsConditions(DartExpression condition,
        final VariableElementsRestorer variableRestorer) {
      if (condition != null) {
        condition.accept(new ASTVisitor<Void>() {
          boolean negation = false;
          @Override
          public Void visitUnaryExpression(DartUnaryExpression node) {
            boolean negationOld = negation;
            try {
              if (node.getOperator() == Token.NOT) {
                negation = !negation;
              }
              return super.visitUnaryExpression(node);
            } finally {
              negation = negationOld;
            }
          }

          @Override
          public Void visitBinaryExpression(DartBinaryExpression node) {
            // apply "as" always
            // apply "is" only if not negated
            if (node.getOperator() == Token.AS || node.getOperator() == Token.IS && !negation) {
              DartExpression arg1 = node.getArg1();
              DartExpression arg2 = node.getArg2();
              if (arg1 instanceof DartIdentifier && arg1.getElement() instanceof VariableElement
                  && arg2 instanceof DartTypeExpression) {
                VariableElement variableElement = (VariableElement) arg1.getElement();
                Type rhsType = arg2.getType();
                Type varType = Types.makeInferred(rhsType);
                variableRestorer.setType(variableElement, varType);
              }
            }
            // operator || means that we can not be sure about types
            if (node.getOperator() == Token.OR) {
              return null;
            }
            // continue
            return super.visitBinaryExpression(node);
          }
        });
      }
    }

    /**
     * Helper to temporarily set {@link Type} of {@link VariableElement} and restore original later.
     */
    private class VariableElementsRestorer {
      private final Map<VariableElement, Type> typesMap = Maps.newHashMap();
      void setType(VariableElement element, Type inferredType) {
        if (element == null) {
          return;
        }
        Type currentType = element.getType();
        // remember original if not yet
        if (!typesMap.containsKey(element)) {
          typesMap.put(element, currentType);
        }
        // apply inferred type
        if (inferredType != null) {
          if (TypeKind.of(currentType) == TypeKind.DYNAMIC && TypeQuality.isInferred(currentType)) {
            // if we fell back to Dynamic, keep it
          } else {
            Type unionType = getUnionType(currentType, inferredType);
            if (unionType != currentType) {
              unionType = Types.makeInferred(unionType);
            }
            blockOldTypes.getFirst().rememberOldType(element, element.getType());
            Elements.setType(element, unionType);
          }
        }
      }

      void restore() {
        for (Entry<VariableElement, Type> entry : typesMap.entrySet()) {
          Elements.setType(entry.getKey(), entry.getValue());
        }
      }
    }

    /**
     * @return the {@link Type} which is both "a" and "b" types. May be "dynamic" if "a" and "b"
     *         don't form hierarchy.
     */
    private Type getUnionType(Type curType, Type newType) {
      if (TypeKind.of(curType) == TypeKind.DYNAMIC) {
        return newType;
      }
      if (TypeKind.of(newType) == TypeKind.DYNAMIC) {
        return curType;
      }
      if (types.isSubtype(curType, newType)) {
        return curType;
      }
      if (types.isSubtype(newType, curType)) {
        return newType;
      }
      // if InterfaceType, use union
      if (curType instanceof InterfaceType && newType instanceof InterfaceType) {
        return types.unionTypes(ImmutableList.of((InterfaceType) curType, (InterfaceType) newType));
      }
      // keep type as is
      return curType;
    }

    /**
     * @return <code>true</code> if we can prove that given {@link DartStatement} always leads to
     *         the exit from the enclosing function.
     */
    private static boolean isExitFromFunction(DartStatement statement) {
      return isExitFromFunction(statement, false);
    }

    /**
     * @return <code>true</code> if we can prove that given {@link DartStatement} always leads to
     *         the exit from the enclosing function, or stops execution of the enclosing loop.
     */
    private static boolean isExitFromFunctionOrLoop(DartStatement statement) {
      return isExitFromFunction(statement, true);
    }

    /**
     * @return <code>true</code> if we can prove that given {@link DartStatement} always leads to
     *         the exit from the enclosing function, or stops enclosing loop execution.
     */
    private static boolean isExitFromFunction(DartStatement statement, boolean orLoop) {
      // "return" is always exit
      if (statement instanceof DartReturnStatement) {
        return true;
      }
      // "throw" is exit if no enclosing "try"
      if (statement instanceof DartExprStmt && (((DartExprStmt) statement).getExpression() instanceof DartThrowExpression)) {
        for (DartNode p = statement; p != null && !(p instanceof DartFunction); p = p.getParent()) {
          // TODO(scheglov) Can be enhanced:
          // 1. check if there is "catch" block which can catch this exception;
          // 2. even if there is such "catch", we will not visit the rest of the "try".
          if (p instanceof DartTryStatement) {
            return false;
          }
        }
        return true;
      }
      // "block" is exit if its last statement is exit
      if (statement instanceof DartBlock) {
        DartBlock block = (DartBlock) statement;
        List<DartStatement> statements = block.getStatements();
        if (!statements.isEmpty()) {
          return isExitFromFunction(statements.get(statements.size() - 1), orLoop);
        }
      }
      // check also if we stop execution of the loop body
      if (orLoop) {
        if (statement instanceof DartContinueStatement) {
          return true;
        }
        if (statement instanceof DartBreakStatement) {
          return true;
        }
      }
      // can not prove that given statement is always exit
      return false;
    }

    /**
     * Helper for setting {@link Type}s of {@link VariableElement}s when given "condition" is NOT
     * satisfied.
     */
    private static void inferVariableTypesFromIsNotConditions(DartExpression condition,
        final VariableElementsRestorer variableRestorer) {
      condition.accept(new ASTVisitor<Void>() {
        boolean negation = false;

        @Override
        public Void visitUnaryExpression(DartUnaryExpression node) {
          boolean negationOld = negation;
          try {
            if (node.getOperator() == Token.NOT) {
              negation = !negation;
            }
            return super.visitUnaryExpression(node);
          } finally {
            negation = negationOld;
          }
        }

        @Override
        public Void visitBinaryExpression(DartBinaryExpression node) {
          // analyze (v is Type)
          if (node.getOperator() == Token.IS) {
            DartExpression arg1 = node.getArg1();
            DartExpression arg2 = node.getArg2();
            if (arg1 instanceof DartIdentifier && arg1.getElement() instanceof VariableElement) {
              VariableElement variableElement = (VariableElement) arg1.getElement();
              // !(v is Type)
              if (negation && arg2 instanceof DartTypeExpression) {
                Type isType = arg2.getType();
                Type varType = Types.makeInferred(isType);
                variableRestorer.setType(variableElement, varType);
              }
              // (v is! Type)
              if (!negation) {
                if (arg2 instanceof DartUnaryExpression) {
                  DartUnaryExpression unary2 = (DartUnaryExpression) arg2;
                  if (unary2.getOperator() == Token.NOT
                      && unary2.getArg() instanceof DartTypeExpression) {
                    Type isType = unary2.getArg().getType();
                    Type varType = Types.makeInferred(isType);
                    variableRestorer.setType(variableElement, varType);
                  }
                }
              }
            }
          }
          // visit || expressions
          if (node.getOperator() == Token.OR) {
            return super.visitBinaryExpression(node);
          }
          // other operators, such as && - don't infer types
          return null;
        }
      });
    }

    /**
     * If type of variable-like {@link DartDeclaration} (i.e. variables, parameter, field) is not
     * specified and we know somehow this type, then use it.
     */
    private static void inferVariableDeclarationType(DartDeclaration<?> node, DartExpression value) {
      Type type = value.getType();
      TypeQuality quality = getTypeQuality(value);
      inferVariableDeclarationType(node, type, quality);
    }

    /**
     * If type of variable-like {@link DartDeclaration} (i.e. variables, parameter, field) is not
     * specified and we know somehow this type, then use it.
     */
    private static void inferVariableDeclarationType(DartDeclaration<?> node, Type type,
        TypeQuality typeQuality) {
      if (type != null && TypeKind.of(type) != TypeKind.DYNAMIC) {
        Element element = node.getElement();
        if (element != null && TypeKind.of(element.getType()) == TypeKind.DYNAMIC) {
          Type inferredType = Types.makeInferred(type, typeQuality);
          Elements.setType(element, inferredType);
          node.getName().setType(inferredType);
        }
      }
    }

    /**
     * If given "mayBeLiteral" is {@link DartFunctionExpression} without explicit parameters types
     * and its required type is {@link FunctionAliasType}, then infer parameters types from
     * {@link FunctionAliasType}.
     */
    private static void inferFunctionLiteralParametersTypes(DartExpression mayBeLiteral,
        Type mayBeFunctionType) {
      if (mayBeLiteral instanceof DartFunctionExpression) {
        // prepare required type of function literal
        FunctionType requiredType = null;
        if (TypeKind.of(mayBeFunctionType) == TypeKind.FUNCTION) {
          requiredType = (FunctionType) mayBeFunctionType;
        }
        if (TypeKind.of(mayBeFunctionType) == TypeKind.FUNCTION_ALIAS) {
          FunctionAliasType functionAliasType = (FunctionAliasType) mayBeFunctionType;
          requiredType = Types.asFunctionType(functionAliasType);
        }
        // OK, we can try to infer parameter types
        if (requiredType != null) {
          DartFunctionExpression literal = (DartFunctionExpression) mayBeLiteral;
          List<DartParameter> parameterNodes = literal.getFunction().getParameters();
          // try to infer types of "normal" parameters
          List<Type> requiredNormalParameterTypes = requiredType.getParameterTypes();
          int n = Math.min(requiredNormalParameterTypes.size(), parameterNodes.size());
          for (int i = 0; i < n; i++) {
            Type requiredNormalParameterType = requiredNormalParameterTypes.get(i);
            DartParameter parameterNode = parameterNodes.get(i);
            inferVariableDeclarationType(parameterNode, requiredNormalParameterType,
                TypeQuality.INFERRED);
          }
        }
      }
    }

    /**
     * When we cannot prove that node was visited, then type is intersection of old/new types.
     */
    private void setMergedVariableTypes(BlockTypeContext blockTypeContext) {
      for (VariableElement variable : blockTypeContext.newTypes.keySet()) {
        Type newType = blockTypeContext.newTypes.get(variable);
        Type oldType = blockTypeContext.oldTypes.get(variable);
        Type mergedType = types.intersection(newType, oldType);
        TypeQuality mergedTypeQuality = Types.getIntersectionQuality(newType, oldType);
        setVariableElementType(variable, mergedType, mergedTypeQuality);
      }
    }

    private boolean isAssignable(Type t, Type s) {
      t.getClass(); // Null check.
      s.getClass(); // Null check.
      // ignore inferred types, treat them as Dynamic
      if (!typeChecksForInferredTypes) {
        if (TypeQuality.isInferred(t) || TypeQuality.isInferred(s)) {
          return true;
        }
      }
      // do check
      return types.isAssignable(t, s);
    }

    private boolean checkAssignable(DartNode node, Type t, Type s) {
      if (!isAssignable(t, s)) {
        TypeErrorCode errorCode = TypeQuality.isInferred(t) || TypeQuality.isInferred(s)
            ? TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE_INFERRED
                : TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE;
        typeError(node, errorCode, s, t);
        return false;
      }
      return true;
    }

    private boolean checkAssignable(Type targetType, DartExpression node) {
      // analyze "node"
      Type nodeType = typeOf(node);
      // target is Dynamic, any source type is good, even "void"
      if (TypeKind.of(targetType) == TypeKind.DYNAMIC) {
        return true;
      }
      // source was Dynamic
      if (hasInferredType(node)) {
        return true;
      }
      // OK, check types
      checkNonVoid(node, nodeType);
      return checkAssignable(node, targetType, nodeType);
    }

    private FunctionType getMethodType(Type receiver, Member member, String name,
                                         DartNode diagnosticNode) {
      FunctionType functionType = getMethodType0(receiver, member, name, diagnosticNode);
      if (TypeQuality.isInferred(receiver)) {
        functionType = (FunctionType) Types.makeInferred(functionType);
      }
      return functionType;
    }

    private FunctionType getMethodType0(Type receiver, Member member, String name,
        DartNode diagnosticNode) {
      if (member == null) {
        return dynamicType;
      }
      Element element = member.getElement();
      switch (ElementKind.of(element)) {
        case METHOD: {
          MethodElement method = (MethodElement) element;
          if (method.getModifiers().isStatic()) {
            return typeError(diagnosticNode, TypeErrorCode.IS_STATIC_METHOD_IN,
                             name, receiver);
          }
          return (FunctionType) member.getType();
        }
        case FIELD: {
          FieldElement field = (FieldElement) element;
          if (field.getModifiers().isStatic()) {
            return typeError(diagnosticNode, TypeErrorCode.IS_STATIC_FIELD_IN,
                             name, receiver);
          }
          switch (TypeKind.of(member.getType())) {
            case FUNCTION:
              return (FunctionType) member.getType();
            case FUNCTION_ALIAS:
              return Types.asFunctionType((FunctionAliasType) member.getType());
            default:
              // target.field() as Function invocation.
              if (Elements.isFieldWithGetter(field)) {
                Type fieldType = field.getType();
                if (!types.isAssignable(functionType, fieldType)) {
                  onError(diagnosticNode, TypeErrorCode.NOT_A_FUNCTION_TYPE_FIELD, field.getName(), fieldType);
                }
              }
              return dynamicType;
          }
        }
        default:
          if (typeChecksForInferredTypes || !TypeQuality.isInferred(receiver)) {
            TypeErrorCode errorCode = TypeQuality.isInferred(receiver)
                ? TypeErrorCode.NOT_A_METHOD_IN_INFERRED : TypeErrorCode.NOT_A_METHOD_IN;
            typeError(diagnosticNode, errorCode, name, receiver);
          }
          return dynamicType;
      }
    }

    private Type diagnoseNonInterfaceType(HasSourceInfo node, Type type) {
      switch (TypeKind.of(type)) {
        case DYNAMIC:
          return type;

        case FUNCTION:
        case FUNCTION_ALIAS:
        case INTERFACE:
        case VARIABLE:
          // Cannot happen.
          throw internalError(node, type.toString());

        case NONE:
          throw internalError(node, "type is null");

        case VOID:
          return typeError(node, TypeErrorCode.VOID);

        default:
          throw internalError(node, type.getKind().name());
      }
    }

    private Type checkArguments(DartNode diagnosticNode,
                                List<DartExpression> argumentNodes,
                                Iterator<Type> argumentTypes, FunctionType ftype,
                                List<VariableElement> parameters) {
      int argumentIndex = 0;
      // Check positional parameters.
      {
        List<Type> parameterTypes = ftype.getParameterTypes();
        for (Type parameterType : parameterTypes) {
          parameterType.getClass(); // quick null check
          if (argumentTypes.hasNext()) {
            Type argumentType = argumentTypes.next();
            argumentType.getClass(); // quick null check
            DartExpression argumentNode = argumentNodes.get(argumentIndex);
            if (argumentNode instanceof DartNamedExpression) {
              onError(argumentNode, TypeErrorCode.EXPECTED_POSITIONAL_ARGUMENT, parameterType);
              return ftype.getReturnType();
            }
            if (parameters != null) {
              argumentNode.setInvocationParameterId(parameters.get(argumentIndex));
            } else {
              argumentNode.setInvocationParameterId(argumentIndex);
            }
            if (checkAssignable(argumentNode, parameterType, argumentType)) {
              inferFunctionLiteralParametersTypes(argumentNode, parameterType);
            }
            argumentIndex++;
          } else {
            onError(diagnosticNode, TypeErrorCode.MISSING_ARGUMENT, parameterType);
            return ftype.getReturnType();
          }
        }
      }

      // Check optional parameters.
      {
        Map<String, Type> optionalParameterTypes = ftype.getOptionalParameterTypes();
        Iterator<Entry<String, Type>> optionalParameterTypesIterator =
            optionalParameterTypes.entrySet().iterator();
        while (optionalParameterTypesIterator.hasNext()
            && argumentTypes.hasNext()
            && !(argumentNodes.get(argumentIndex) instanceof DartNamedExpression)) {
          Entry<String, Type> namedEntry = optionalParameterTypesIterator.next();
          Type optionalType = namedEntry.getValue();
          optionalType.getClass(); // quick null check
          Type argumentType = argumentTypes.next();
          argumentType.getClass(); // quick null check
          DartExpression argumentNode = argumentNodes.get(argumentIndex);
          if (parameters != null) {
            argumentNode.setInvocationParameterId(parameters.get(argumentIndex));
          } else {
            argumentNode.setInvocationParameterId(argumentIndex);
          }
          if (checkAssignable(argumentNode, optionalType, argumentType)) {
            inferFunctionLiteralParametersTypes(argumentNode, optionalType);
          }
          argumentIndex++;
        }
      }

      // Check named parameters.
      {
        Set<String> usedNamedParametersPositional = Sets.newHashSet();
        Set<String> usedNamedParametersNamed = Sets.newHashSet();
        Map<String, Type> namedParameterTypes = ftype.getNamedParameterTypes();
        while (argumentTypes.hasNext()
            && argumentNodes.get(argumentIndex) instanceof DartNamedExpression) {
          DartNamedExpression namedExpression =
              (DartNamedExpression) argumentNodes.get(argumentIndex);
          DartExpression argumentNode = namedExpression.getExpression();
          // Prepare parameter name.
          String parameterName = namedExpression.getName().getName();
          if (parameters != null) {
            for (VariableElement parameter : parameters) {
              if (Objects.equal(parameter.getName(), parameterName)) {
                namedExpression.setInvocationParameterId(parameter);
                namedExpression.getName().setInvocationParameterId(parameter);
                argumentNode.setInvocationParameterId(parameter);
                break;
              }
            }
          } else {
            namedExpression.setInvocationParameterId(parameterName);
            argumentNode.setInvocationParameterId(parameterName);
          }
          if (usedNamedParametersPositional.contains(parameterName)) {
            onError(namedExpression, TypeErrorCode.DUPLICATE_NAMED_ARGUMENT);
          } else if (usedNamedParametersNamed.contains(parameterName)) {
            onError(namedExpression, ResolverErrorCode.DUPLICATE_NAMED_ARGUMENT);
          } else {
            usedNamedParametersNamed.add(parameterName);
          }
          // Check parameter type.
          Type namedParameterType = namedParameterTypes.get(parameterName);
          Type argumentType = argumentTypes.next();
          if (namedParameterType != null) {
            argumentType.getClass(); // quick null check
            if (checkAssignable(argumentNode, namedParameterType, argumentType)) {
              inferFunctionLiteralParametersTypes(argumentNode, namedParameterType);
            }
          } else {
            onError(namedExpression, TypeErrorCode.NO_SUCH_NAMED_PARAMETER, parameterName);
          }
          argumentIndex++;
        }
      }
      // Check rest (currently removed from specification).
      if (ftype.hasRest()) {
        while (argumentTypes.hasNext()) {
          checkAssignable(argumentNodes.get(argumentIndex), ftype.getRest(), argumentTypes.next());
          argumentIndex++;
        }
      }
      // Report extra arguments.
      while (argumentTypes.hasNext()) {
        argumentTypes.next();
        onError(argumentNodes.get(argumentIndex), TypeErrorCode.EXTRA_ARGUMENT);
        argumentIndex++;
      }

      // Return type.
      Type type = ftype.getReturnType();
      type.getClass(); // quick null check
      return type;
    }

    @Override
    public Type visitTypeNode(DartTypeNode node) {
      return validateTypeNode(node);
    }

    private Type validateTypeNode(DartTypeNode node) {
      Type type = node.getType(); // Already calculated by resolver.
      switch (TypeKind.of(type)) {
        case NONE:
          return typeError(node, TypeErrorCode.INTERNAL_ERROR,
                           String.format("type \"%s\" is null", node));
        case INTERFACE: {
          InterfaceType itype = (InterfaceType) type;
          validateBounds(node.getTypeArguments(),
                         itype.getArguments(),
                         itype.getElement().getTypeParameters());
          return itype;
        }
        default:
          return type;
      }
    }

    private void validateBounds(List<? extends DartNode> diagnosticNodes,
                                List<Type> arguments,
                                List<Type> parameters) {
      if (arguments.size() == parameters.size() && arguments.size() == diagnosticNodes.size()) {
        List<Type> bounds = Lists.newArrayListWithCapacity(parameters.size());
        for (Type parameter : parameters) {
          TypeVariable variable = (TypeVariable) parameter;
          Type bound = variable.getTypeVariableElement().getBound();
          if (bound == null) {
            internalError(variable.getElement(), "bound is null");
          }
          bounds.add(bound);
        }
        bounds = Types.subst(bounds, arguments, parameters);
        for (int i = 0; i < arguments.size(); i++) {
          Type t = bounds.get(i);
          Type s = arguments.get(i);
          if (!types.isSubtype(s, t)) {
            onError(diagnosticNodes.get(i),
                TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, s, t);
          }
        }
      }
    }

    /* Check for a type variable is repeated in its own bounds:
     * e.g. Foo<T extends T>
     */
    private void checkCyclicBounds(List<? extends Type> arguments) {
      for (Type argument : arguments) {
        if (TypeKind.of(argument).equals(TypeKind.VARIABLE)) {
          TypeVariable typeVar = (TypeVariable) argument;
          checkCyclicBound(typeVar, typeVar.getTypeVariableElement().getBound());
        }
      }
    }

    private void checkCyclicBound(TypeVariable variable, Type bound) {
      switch(TypeKind.of(bound)) {
        case VARIABLE: {
          TypeVariable boundType = (TypeVariable)bound;
          if (boundType.equals(variable)) {
            onError(boundType.getElement(),
                    TypeErrorCode.CYCLIC_REFERENCE_TO_TYPE_VARIABLE,
                    boundType.getElement().getOriginalName());
          }
          break;
        }
        default:
          break;
      }
    }

    /**
     * Returns the type of a node.  If a type of an expression can't be resolved,
     * returns the dynamic type.
     *
     * @return a non-null type
     */
    Type typeOf(DartNode node) {
      if (node == null) {
        return dynamicType;
      }
      // prepare new type
      Type result = node.accept(this);
      if (result == null) {
         return dynamicType;
      }
      // set new type, or keep existing
      if (node.getType() == null) {
        node.setType(result);
      } else {
        result = node.getType();
      }
      // done
      return result;
    }

    /**
     * Returns the type of a node, registering an error if the type is unresolved or
     * void.
     *
     * @return a non-null type
     */
    private Type nonVoidTypeOf(DartNode node) {
      Type type = typeOf(node);
      return checkNonVoid(node, type);
    }

    /**
     * @return the given {@link Type}, registering an error if it is unresolved or void.
     */
    private Type checkNonVoid(HasSourceInfo errorTarget, Type type) {
      switch (TypeKind.of(type)) {
        case VOID:
        case NONE:
          return typeError(errorTarget, TypeErrorCode.VOID);
        default:
          return type;
      }
    }

    @Override
    public Type visitArrayAccess(DartArrayAccess node) {
      Type target = typeOf(node.getRealTarget());
      DartExpression argKey = node.getKey();
      // t[k] = v
      if (node.getParent() instanceof DartBinaryExpression) {
        DartBinaryExpression binary = (DartBinaryExpression) node.getParent();
        if (binary.getArg1() == node && binary.getOperator() == Token.ASSIGN) {
          DartExpression argValue = binary.getArg2();
          analyzeTernaryOperator(node, target, Token.ASSIGN_INDEX, node, argKey, argValue);
          binary.setElement(node.getElement());
          return argValue.getType();
        }
      }
      // print( t[k] )
      Type result = analyzeBinaryOperator(node, target, Token.INDEX, node, argKey);
      return Types.makeInferred(result, target.getQuality());
    }

    /**
     * Asserts that given {@link DartExpression} is valid for using in "assert" statement.
     */
    private void checkAssertCondition(DartExpression conditionNode) {
      Type condition = nonVoidTypeOf(conditionNode);
      switch (condition.getKind()) {
        case FUNCTION:
          FunctionType ftype = (FunctionType) condition;
          Type returnType = ftype.getReturnType();
          if (!types.isAssignable(boolType, returnType) || !ftype.getParameterTypes().isEmpty()) {
            typeError(conditionNode, TypeErrorCode.ASSERT_BOOL);
          }
          break;

        default:
          if (!types.isAssignable(boolType, condition)) {
            typeError(conditionNode, TypeErrorCode.ASSERT_BOOL);
          }
          break;
      }
    }

    @Override
    public Type visitBlock(DartBlock node) {
      try {
        return typeAsVoid(node);
      } finally {
        VariableElementsRestorer variableRestorer = restoreOnBlockExit.remove(node);
        if (variableRestorer != null) {
          variableRestorer.restore();
        }
      }
    }

    private Type typeAsVoid(DartNode node) {
      node.visitChildren(this);
      return voidType;
    }

    @Override
    public Type visitBreakStatement(DartBreakStatement node) {
      return voidType;
    }

    @Override
    public Type visitCascadeExpression(DartCascadeExpression node) {
      DartExpression target = node.getTarget();
      Type type = nonVoidTypeOf(target);
      node.setType(type);
      inferCascadeType(node);
      node.visitChildren(this);
      return type;
    }

    /**
     * Infers {@link Type} of {@link DartCascadeExpression} from context.
     */
    private void inferCascadeType(DartCascadeExpression node) {
      // field declaration
      if (node.getParent() instanceof DartField) {
        DartField field = (DartField) node.getParent();
        Type varType = field.getElement().getType();
        setCascadeUnionType(node, varType);
      }
      // variable declaration
      if (node.getParent() instanceof DartVariable) {
        DartVariable var = (DartVariable) node.getParent();
        Type varType = var.getElement().getType();
        setCascadeUnionType(node, varType);
      }
      // assignment
      if (node.getParent() instanceof DartBinaryExpression) {
        DartBinaryExpression binary = (DartBinaryExpression) node.getParent();
        if (binary.getOperator() == Token.ASSIGN && binary.getArg2() == node
            && binary.getArg1() != null) {
          Element leftElement = binary.getArg1().getElement();
          if (leftElement != null) {
            Type varType = leftElement.getType();
            setCascadeUnionType(node, varType);
          }
        }
      }
    }

    /**
     * Sets for given {@link DartCascadeExpression} and its target {@link Type} which is union of
     * existing type and "newType".
     */
    private void setCascadeUnionType(DartCascadeExpression node, Type newType) {
      DartExpression target = node.getTarget();
      Type type = node.getType();
      if (isExplicitlySpecifiedType(newType) && types.isAssignable(type, newType)) {
        Type unionType = getUnionType(type, newType);
        unionType = Types.makeInferred(unionType);
        node.setType(unionType);
        target.setType(unionType);
      }
    }

    @Override
    public Type visitFunctionObjectInvocation(DartFunctionObjectInvocation node) {
      ClassElement element = functionType.getElement();
      node.setElement(element);
      checkDeprecated(node, element);
      return checkInvocation(node, node, null, typeOf(node.getTarget()));
    }

    @Override
    public Type visitMethodInvocation(DartMethodInvocation node) {
      if (node.getFunctionName().isResolutionAlreadyReportedThatTheMethodCouldNotBeFound()) {
        return dynamicType;
      }
      DartNode target = node.getRealTarget();
      DartIdentifier nameNode = node.getFunctionName();
      String name = node.getFunctionNameString();
      Element element = node.getElement();
      if (element != null && (element.getModifiers().isStatic()
                              || Elements.isTopLevel(element))) {
        typeOf(target);
        node.setElement(element);
        checkDeprecated(nameNode, element);
        return checkInvocation(node, nameNode, name, element.getType());
      }
      Type receiver = nonVoidTypeOf(target);
      Member member = lookupMember(receiver, name, nameNode);
      if (member != null) {
        element = member.getElement();
        checkIllegalPrivateAccess(node.getFunctionName(), element, name);
        node.setElement(element);
        if (nameNode != null) {
          nameNode.setElement(element);
        }
      }
      if (Elements.isAbstractFieldWithoutGetter(element)) {
        onError(nameNode, TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, name);
      }
      checkDeprecated(nameNode, nameNode.getElement());
      FunctionType methodType = getMethodType(receiver, member, name, nameNode);
      Type returnType = checkInvocation(node, nameNode, name, methodType);
      returnType = ExternalTypeAnalyzers.resolve(types, node, element, returnType);
      warningEffectiveIntegerDivision(node, element);
      return returnType;
    }

    /**
     * http://code.google.com/p/dart/issues/detail?id=5652
     */
    private void warningEffectiveIntegerDivision(DartMethodInvocation node, Element element) {
      if (element != null && element.getName().equals("toInt")
          && element.getEnclosingElement() != null
          && element.getEnclosingElement().getName().equals("num")) {
        DartExpression target = node.getTarget();
        while (target instanceof DartParenthesizedExpression) {
          target = ((DartParenthesizedExpression) target).getExpression();
        }
        if (target instanceof DartBinaryExpression) {
          DartBinaryExpression binary = (DartBinaryExpression) target;
          if (binary.getOperator() == Token.DIV && intType.equals(binary.getArg1().getType())
              && intType.equals(binary.getArg2().getType())) {
            typeError(node, TypeErrorCode.USE_INTEGER_DIVISION);
          }
        }
      }
    }

    private void checkIllegalPrivateAccess(DartNode diagnosticNode, Element element, String name) {
      if (DartIdentifier.isPrivateName(name)) {
        if (!Elements.areSameLibrary(currentMethod, element)) {
          onError(diagnosticNode, TypeErrorCode.ILLEGAL_ACCESS_TO_PRIVATE, name);
        }
      }
    }

    @Override
    public Type visitSuperConstructorInvocation(DartSuperConstructorInvocation node) {
      return checkConstructorForwarding(node, node.getElement());
    }

    private Type checkConstructorForwarding(DartInvocation node, ConstructorElement element) {
      if (element == null) {
        visit(node.getArguments());
        return voidType;
      } else {
        node.setElement(element);
        checkDeprecated(node, element);
        checkInvocation(node, node, null, typeAsMemberOf(element, currentClass));
        return voidType;
      }
    }

    @Override
    public Type visitCase(DartCase node) {
      node.visitChildren(this);
      return voidType;
    }

    @Override
    public Type visitClass(DartClass node) {
      ClassNodeElement element = node.getElement();
      InterfaceType type = element.getType();
      checkCyclicBounds(type.getArguments());
      // remember unimplemented members
      {
        List<Element> unimplementedMembers = findUnimplementedMembers(element);
        if (!node.getModifiers().isAbstract() && !unimplementedMembers.isEmpty() &&
            (reportNoMemberWhenHasInterceptor || !Elements.handlesNoSuchMethod(type))) {
          StringBuilder sb = getUnimplementedMembersMessage(element, unimplementedMembers);
          onError(node.getName(), TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS,
              node.getName(), sb.toString());
        }
      }
      //
      setCurrentClass(type);
      visit(node.getTypeParameters());
      if (node.getSuperclass() != null) {
        validateTypeNode(node.getSuperclass());
      }
      if (node.getInterfaces() != null) {
        for (DartTypeNode interfaceNode : node.getInterfaces()) {
          validateTypeNode(interfaceNode);
        }
      }
      visit(node.getMembers());
      checkInterfaceConstructors(element);
      try {
        checkClassDuplicateInterfaces(node, element, element.getAllSupertypes());
      } catch (CyclicDeclarationException ignored) {
      }

      // Finish current class.
      setCurrentClass(null);
      return type;
    }

    /**
     * Check for duplicate interfaces that aren't assignable to each other due to parameterization.
     *
     * Issue 3803: This isn't in the spec as of 0.10, adding as a 'value added' check, because there is no
     * way to satisfy the method override rules without either causing errors in checked mode or
     * causing override errors for every method implemented for this interface.
     *
     * @param classElement
     */
    private void checkClassDuplicateInterfaces(DartClass node, ClassElement classElement,
        List<InterfaceType> allSupertypes) {
      Map<Element, InterfaceType> elementMap = Maps.newHashMap();
      for (InterfaceType supertype : allSupertypes) {
        Element e = supertype.getElement();
        if (e != null) {
          InterfaceType foundType = elementMap.get(e);
          if (foundType != null && ! types.isAssignable(supertype, foundType)) {
            typeError(node.getName(), TypeErrorCode.INCOMPATIBLE_TYPES_IN_HIERARCHY, foundType.toString(),
                supertype.toString());
          } else {
            elementMap.put(e, supertype);
          }
        }
      }
    }
    /**
     * Checks that interface constructors have corresponding methods in default class.
     */
    private void checkInterfaceConstructors(ClassElement interfaceElement) {
      // If no default class, do nothing.
      if (interfaceElement.getDefaultClass() == null) {
        return;
      }
      // Analyze all constructors.
      String interfaceClassName = interfaceElement.getName();
      String defaultClassName = interfaceElement.getDefaultClass().getElement().getName();
      for (ConstructorElement interfaceConstructor : interfaceElement.getConstructors()) {
        ConstructorElement defaultConstructor = interfaceConstructor.getDefaultConstructor();
        if (defaultConstructor != null) {
          // TODO(scheglov)
          // It is a compile-time error if kI and kF do not have identical type parameters
          // TODO /end
          // Validate types of required and optional parameters.
          {
            List<String> interfaceTypes = Elements.getParameterTypeNames(interfaceConstructor);
            List<String> defaultTypes = Elements.getParameterTypeNames(defaultConstructor);
            if (interfaceTypes.size() == defaultTypes.size()
                && !interfaceTypes.equals(defaultTypes)) {
              onError(
                  interfaceConstructor,
                  TypeErrorCode.DEFAULT_CONSTRUCTOR_TYPES,
                  Elements.getRawMethodName(interfaceConstructor),
                  interfaceClassName,
                  Joiner.on(",").join(interfaceTypes),
                  Elements.getRawMethodName(defaultConstructor),
                  defaultClassName,
                  Joiner.on(",").join(defaultTypes));
            }
          }
        }
      }
    }

    private List<Element> findUnimplementedMembers(ClassElement classElement) {
      // May be has members already (cached or already analyzed ClassNodeElement).
      List<Element> members = classElement.getUnimplementedMembers();
      if (members != null) {
        return members;
      }
      // If no cached result, then should be node based.
      ClassNodeElement classNodeElement = (ClassNodeElement) classElement;
      // Analyze ClassElement node.
      AbstractMethodFinder finder = new AbstractMethodFinder(classNodeElement.getType());
      classNodeElement.getNode().accept(finder);
      // Prepare unimplemented members.
      if (classNodeElement.isInterface()) {
        members = Collections.emptyList();
      } else {
        members = finder.unimplementedElements;
      }
      // Remember unimplemented methods.
      classNodeElement.setUnimplementedMembers(members);
      return members;
    }

    @Override
    public Type visitConditional(DartConditional node) {
      checkCondition(node.getCondition());
      Type left = typeOf(node.getThenExpression());
      Type right = typeOf(node.getElseExpression());
      return types.intersection(left, right);
    }

    private Type checkCondition(DartExpression condition) {
      Type type = nonVoidTypeOf(condition);
      checkAssignable(condition, boolType, type);
      return type;
    }

    @Override
    public Type visitContinueStatement(DartContinueStatement node) {
      return voidType;
    }

    @Override
    public Type visitDefault(DartDefault node) {
      node.visitChildren(this);
      return typeAsVoid(node);
    }

    @Override
    public Type visitDoWhileStatement(DartDoWhileStatement node) {
      checkCondition(node.getCondition());
      typeOf(node.getBody());
      return voidType;
    }

    @Override
    public Type visitEmptyStatement(DartEmptyStatement node) {
      return typeAsVoid(node);
    }

    @Override
    public Type visitFieldDefinition(DartFieldDefinition node) {
      node.visitChildren(this);
      return voidType;
    }

    @Override
    public Type visitForInStatement(DartForInStatement node) {
      Type variableType;
      VariableElement variableElement = null;
      if (node.introducesVariable()) {
        variableType = typeOf(node.getVariableStatement());
        variableElement = node.getVariableStatement().getVariables().get(0).getElement();
      } else {
        variableType = typeOf(node.getIdentifier());
        // in most cases variable, but sometimes field
        Element identifierElement = node.getIdentifier().getElement();
        if (identifierElement instanceof VariableElement) {
          variableElement = (VariableElement) identifierElement;
        }
      }
      // prepare Iterable type
      DartExpression iterableExpression = node.getIterable();
      Type iterableType = typeOf(iterableExpression);
      // analyze compatibility of variable and Iterator elements types
      Member iteratorMember = lookupMember(iterableType, "iterator", iterableExpression);
      Type elementType = null;
      if (iteratorMember != null) {
        Type memberReturnType = null;
        if (TypeKind.of(iteratorMember.getType()) == TypeKind.FUNCTION) {
          FunctionType iteratorMethod = (FunctionType) iteratorMember.getType();
          memberReturnType = iteratorMethod.getReturnType();
        } else if (ElementKind.of(iteratorMember.getElement()) == ElementKind.FIELD) {
          memberReturnType = iteratorMember.getType();
        }
        if (memberReturnType != null) {
          InterfaceType asInstanceOf = types.asInstanceOf(memberReturnType,
              dynamicIteratorType.getElement());
          if (asInstanceOf != null) {
            elementType = asInstanceOf.getArguments().get(0);
            checkAssignable(iterableExpression, variableType, elementType);
          } else {
            InterfaceType expectedIteratorType = dynamicIteratorType.subst(
                Arrays.asList(variableType), dynamicIteratorType.getElement().getTypeParameters());
            typeError(iterableExpression, TypeErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE,
                expectedIteratorType);
          }
        } else {
          // Not a function
          typeError(iterableExpression, TypeErrorCode.FOR_IN_WITH_ITERATOR_FIELD);
        }
      }
      // visit body with inferred variable type
      VariableElementsRestorer variableRestorer = new VariableElementsRestorer();
      try {
        if (variableElement != null && elementType != null) {
          variableRestorer.setType(variableElement, elementType);
        }
        BlockTypeContext blockTypeContext = new BlockTypeContext();
        blockOldTypes.addFirst(blockTypeContext);
        try {
          return typeAsVoid(node.getBody());
        } finally {
          blockOldTypes.removeFirst();
          setMergedVariableTypes(blockTypeContext);
        }
      } finally {
        variableRestorer.restore();
      }
    }

    @Override
    public Type visitForStatement(DartForStatement node) {
      typeOf(node.getInit());
      DartExpression condition = node.getCondition();
      checkCondition(condition);
      // visit body
      BlockTypeContext blockTypeContext = new BlockTypeContext();
      blockOldTypes.addFirst(blockTypeContext);
      try {
        visitConditionalNode(condition, node.getBody());
        visitConditionalNode(condition, node.getIncrement());
      } finally {
        blockOldTypes.removeFirst();
        setMergedVariableTypes(blockTypeContext);
      }
      // done
      return voidType;
    }

    @Override
    public Type visitFunction(DartFunction node) {
      blockOldTypes.addFirst(new BlockTypeContext());
      try {
        Type previous = expected;
        visit(node.getParameters());
        expected = typeOf(node.getReturnTypeNode());
        typeOf(node.getBody());
        expected = previous;
      } finally {
        blockOldTypes.removeFirst();
      }
      return voidType;
    }

    @Override
    public Type visitFunctionExpression(DartFunctionExpression node) {
      node.visitChildren(this);
      Type result = node.getElement().getType();
      result.getClass(); // quick null check
      return result;
    }

    @Override
    public Type visitFunctionTypeAlias(DartFunctionTypeAlias node) {
      FunctionAliasElement element = node.getElement();
      FunctionAliasType type = element.getType();
      if (TypeKind.of(type) == TypeKind.FUNCTION_ALIAS) {
        checkCyclicBounds(type.getElement().getTypeParameters());
        if (hasFunctionTypeAliasSelfReference(element)) {
          onError(node, TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF);
        }
      }
      return typeAsVoid(node);
    }

    @Override
    public Type visitSyntheticErrorIdentifier(DartSyntheticErrorIdentifier node) {
      return dynamicType;
    }

    @Override
    public Type visitIdentifier(DartIdentifier node) {
      if (node.getType() != null) {
        return node.getType();
      }
      if (node.getParent() instanceof DartDeclaration<?>
          && ((DartDeclaration<?>) node.getParent()).getName() == node) {
        return node.getType();
      }
      if (node.getParent() instanceof DartComment) {
        return dynamicType;
      }
      Element element = node.getElement();
      Type type;
      switch (ElementKind.of(element)) {
        case VARIABLE:
        case PARAMETER:
        case FUNCTION_OBJECT:
          type = element.getType();
          type.getClass(); // quick null check

          break;

        case CLASS:
          return element.getType();

        case FIELD:
          type = typeAsMemberOf(element, currentClass);
          // try to resolve as getter/setter
          FieldElement fieldElement = (FieldElement) element;
          DartNode properyAccess = ASTNodes.getPropertyAccessNode(node);
          if (ASTNodes.inGetterContext(properyAccess)) {
            MethodElement getter = fieldElement.getGetter();
            if (getter != null) {
              type = ((FunctionType) typeAsMemberOf(getter, currentClass)).getReturnType();
              node.setType(type);
            }
          } else if (ASTNodes.inSetterContext(properyAccess)) {
            MethodElement setter = fieldElement.getSetter();
            if (setter != null) {
              if (setter.getParameters().size() > 0) {
                type = setter.getParameters().get(0).getType();
                node.setType(type);
              }
            }
          }
          type.getClass(); // quick null check
          break;

        case METHOD:
          type = typeAsMemberOf(element, currentClass);
          type.getClass(); // quick null check
          break;

        case NONE:
          if (!node.isResolutionAlreadyReportedThatTheMethodCouldNotBeFound()) {
            typeError(node, TypeErrorCode.CANNOT_BE_RESOLVED, node.getName());
          }
          return dynamicType;

        case DYNAMIC:
          return element.getType();

        default:
          return voidType;
      }
      return type;
    }

    @Override
    public Type visitIfStatement(DartIfStatement node) {
      DartExpression condition = node.getCondition();
      checkCondition(condition);
      // visit "then"
      BlockTypeContext thenTypeContext = new BlockTypeContext();
      blockOldTypes.addFirst(thenTypeContext);
      DartStatement thenStatement = node.getThenStatement();
      visitConditionalNode(condition, thenStatement);
      blockOldTypes.removeFirst();
      Map<VariableElement, Type> thenVariableTypes = thenTypeContext.getNewTypesAndRestoreOld();
      // visit "else"
      DartStatement elseStatement = node.getElseStatement();
      BlockTypeContext elseTypeContext = new BlockTypeContext();
      {
        VariableElementsRestorer variableRestorer = new VariableElementsRestorer();
        // if has "else", then types inferred from "is! Type" applied only to "else"
        if (elseStatement != null) {
          blockOldTypes.addFirst(elseTypeContext);
          inferVariableTypesFromIsNotConditions(condition, variableRestorer);
          typeOf(elseStatement);
          variableRestorer.restore();
          blockOldTypes.removeFirst();
        }
        // if no "else", then inferred types applied to the end of the method/loop
        if (elseStatement == null) {
          if (isExitFromFunction(thenStatement)) {
            inferVariableTypesFromIsNotConditions(condition, variableRestorer);
          } else if (isExitFromFunctionOrLoop(thenStatement)) {
            DartBlock restoreBlock = getBlockForLoopTypesInference(node);
            variableRestorer = restoreOnBlockExit.get(restoreBlock);
            if (variableRestorer == null) {
              variableRestorer = new VariableElementsRestorer();
              restoreOnBlockExit.put(restoreBlock, variableRestorer);
            }
            restoreOnBlockExit.put(restoreBlock, variableRestorer);
            inferVariableTypesFromIsNotConditions(condition, variableRestorer);
          }
        }
      }
      Map<VariableElement, Type> elseVariableTypes = elseTypeContext.getNewTypesAndRestoreOld();
      // merge variable types
      {
        Set<VariableElement> variables = Sets.newHashSet();
        variables.addAll(thenVariableTypes.keySet());
        variables.addAll(elseVariableTypes.keySet());
        for (VariableElement variable : variables) {
          List<Type> possibleTypes = Lists.newArrayList();
          Type thenType = thenVariableTypes.get(variable);
          Type elseType = elseVariableTypes.get(variable);
          if (thenType != null && elseType != null) {
            possibleTypes.add(thenType);
            possibleTypes.add(elseType);
          }
          if (thenType != null && elseType == null) {
            possibleTypes.add(thenType);
            possibleTypes.add(variable.getType());
          }
          if (thenType == null && elseType != null) {
            possibleTypes.add(variable.getType());
            possibleTypes.add(elseType);
          }
          // do merge
          Type mergedType = types.intersection(possibleTypes);
          TypeQuality mergedTypeQuality = Types.getIntersectionQuality(possibleTypes);
          setVariableElementType(variable, mergedType, mergedTypeQuality);
        }
      }
      // done
      return voidType;
    }

    @Override
    public Type visitInitializer(DartInitializer node) {
      DartIdentifier name = node.getName();
      if (name != null) {
        checkAssignable(typeOf(name), node.getValue());
      } else {
        typeOf(node.getValue());
      }
      return voidType;
    }

    @Override
    public Type visitLabel(DartLabel node) {
      return typeAsVoid(node);
    }

    @Override
    public Type visitMapLiteral(DartMapLiteral node) {
      visit(node.getTypeArguments());
      InterfaceType type = node.getType();

      // The Map literal has an implicit key type of String, so only one parameter is
      // specified <V> where V is the type of the value.
      checkAssignable(node, defaultLiteralMapType, type);

      // Check the map literal entries against the return type.
      {
        Type valueType = type.getArguments().get(1);
        for (DartMapLiteralEntry literalEntry : node.getEntries()) {
          boolean isValueAssignable = checkAssignable(literalEntry, typeOf(literalEntry), valueType);
          if (developerModeChecks && !isValueAssignable) {
            typeError(literalEntry, ResolverErrorCode.MAP_LITERAL_ELEMENT_TYPE, valueType);
          }
        }
      }

      // Check that each key literal is unique.
      Set<String> keyValues = Sets.newHashSet();
      for (DartMapLiteralEntry literalEntry : node.getEntries()) {
        if (literalEntry.getKey() instanceof DartStringLiteral) {
          DartStringLiteral keyLiteral = (DartStringLiteral) literalEntry.getKey();
          String keyValue = keyLiteral.getValue();
          if (keyValues.contains(keyValue)) {
            typeError(keyLiteral, TypeErrorCode.MAP_LITERAL_KEY_UNIQUE);
          }
          keyValues.add(keyValue);
        }
      }

      return type;
    }

    @Override
    public Type visitMapLiteralEntry(DartMapLiteralEntry node) {
      nonVoidTypeOf(node.getKey());
      return nonVoidTypeOf(node.getValue());
    }

    @Override
    public Type visitMethodDefinition(DartMethodDefinition node) {
      MethodElement methodElement = node.getElement();
      Modifiers modifiers = methodElement.getModifiers();
      DartTypeNode returnTypeNode = node.getFunction().getReturnTypeNode();
      if (modifiers.isFactory()
          && ElementKind.of(methodElement).equals(ElementKind.CONSTRUCTOR)) {
        analyzeFactory(node, node.getName(), (ConstructorElement) methodElement);
      } else if (modifiers.isSetter()) {
        if (returnTypeNode != null && returnTypeNode.getType() != voidType) {
          typeError(returnTypeNode, TypeErrorCode.SETTER_RETURN_TYPE, methodElement.getName());
        }
        if (methodElement.getParameters().size() > 0) {
          Element parameterElement = methodElement.getParameters().get(0);
          Type setterType = parameterElement.getType();
          MethodElement getterElement = Elements.lookupFieldElementGetter(
              methodElement.getEnclosingElement(), methodElement.getName());

          if (getterElement != null) {
            // prepare "getter" type
            Type getterType;

            // prepare super types between "getter" and "setter" enclosing types
            Type getterDeclarationType = getterElement.getEnclosingElement().getType();
            List<InterfaceType> superTypes;
            if (currentClass != null) {
              superTypes = getIntermediateSuperTypes(currentClass, getterDeclarationType);
            } else {
              superTypes = Lists.newArrayList();
            }
            // convert "getter" function type to use "setter" type parameters
            FunctionType getterFunctionType = (FunctionType) getterElement.getType();
            for (InterfaceType superType : superTypes) {
              List<Type> superArguments = superType.getArguments();
              List<Type> superParameters = superType.getElement().getTypeParameters();
              getterFunctionType = (FunctionType) getterFunctionType.subst(superArguments,
                  superParameters);
            }
            // get return type
            getterType = getterFunctionType.getReturnType();

            // compare "getter" and "setter" types
            if (!types.isAssignable(setterType, getterType)) {
              typeError(parameterElement, TypeErrorCode.SETTER_TYPE_MUST_BE_ASSIGNABLE,
                  setterType.getElement().getName(), getterType.getElement().getName());
            }

            // getter and setter should have same "static" flag
            if (modifiers.isStatic() != getterElement.getModifiers().isStatic()) {
              onError(node.getName(), TypeErrorCode.FIELD_GETTER_SETTER_SAME_STATIC);
            }
          }
        }
      }
      // operator == should return "bool"
      if (modifiers.isOperator() && methodElement.getName().equals("==")
          && returnTypeNode != null) {
        Type returnType = node.getElement().getFunctionType().getReturnType();
        if (!Objects.equal(returnType, boolType)) {
          typeError(returnTypeNode, TypeErrorCode.OPERATOR_EQUALS_BOOL_RETURN_TYPE);

        }
      }
      // operator "[]=" should return void
      if (modifiers.isOperator() && methodElement.getName().equals("[]=")
          && returnTypeNode != null) {
        Type returnType = node.getElement().getFunctionType().getReturnType();
        if (TypeKind.of(returnType) != TypeKind.VOID) {
          typeError(returnTypeNode, TypeErrorCode.OPERATOR_INDEX_ASSIGN_VOID_RETURN_TYPE);
        }
      }
      // visit children
      MethodElement prevMethod = currentMethod;
      currentMethod = methodElement;
      try {
        return typeAsVoid(node);
      } finally {
        currentMethod = prevMethod;
      }
    }

    /**
     * @return "super" {@link InterfaceType}s used in declarations from "subType" to "superType",
     *         first item is given "superType". May be empty, but not <code>null</code>.
     */
    private List<InterfaceType> getIntermediateSuperTypes(InterfaceType subType, Type superType) {
      LinkedList<InterfaceType> superTypes = Lists.newLinkedList();
      InterfaceType t = subType.getElement().getSupertype();
      while (t != null) {
        superTypes.addFirst(t);
        if (Objects.equal(t.getElement().getType(), superType)) {
          break;
        }
        t = t.getElement().getSupertype();
      }
      return superTypes;
    }

    private void analyzeFactory(DartMethodDefinition node, DartExpression name,
        final ConstructorElement constructorElement) {
      ASTVisitor<Void> visitor = new ASTVisitor<Void>() {
        @Override
        public Void visitParameterizedTypeNode(DartParameterizedTypeNode node) {
          DartExpression expression = node.getExpression();
          Element e = null;
          if (expression instanceof DartIdentifier) {
            e = ((DartIdentifier) expression).getElement();
          } else if (expression instanceof DartPropertyAccess) {
            e = ((DartPropertyAccess) expression).getElement();
          }
          if (!ElementKind.of(e).equals(ElementKind.CLASS)) {
            return null;
          }
          List<DartTypeParameter> parameterNodes = node.getTypeParameters();
          assert (parameterNodes.size() == 0);
          return null;
        }
      };
      name.accept(visitor);
      // redirecting factory constructor
      {
        ConstructorElement targetElement = constructorElement.getRedirectingFactoryConstructor();
        if (targetElement != null) {
          ClassElement targetEnclosingClass = (ClassElement) targetElement.getEnclosingElement();
          Type sourceMethodType = constructorElement.getType();
          Type targetMethodType = targetElement.getType();
          InterfaceType targetClassType = (InterfaceType) node.getRedirectedTypeName().getType();
          targetMethodType = targetMethodType.subst(targetClassType.getArguments(),
              targetEnclosingClass.getTypeParameters());
          if (!types.isSubtype(targetMethodType, sourceMethodType)) {
            DartNode errorNode = node.getRedirectedConstructorName() != null
                ? node.getRedirectedConstructorName() : node.getRedirectedTypeName();
            typeError(errorNode, TypeErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE,
                targetMethodType, sourceMethodType);
          }
        }
      }
    }

    @Override
    public Type visitNewExpression(DartNewExpression node) {
      ConstructorElement constructorElement = node.getElement();

      DartTypeNode typeNode = Types.constructorTypeNode(node);
      Type type = null;

      // When using a constructor defined in an interface, the bounds can be tighter
      // in the default class than defined in the interface.
      if (TypeKind.of(typeNode.getType()).equals(TypeKind.INTERFACE)
          && ((InterfaceType)typeNode.getType()).getElement().isInterface()) {
        InterfaceType itype = (InterfaceType)typeNode.getType();
        ClassElement interfaceElement = itype.getElement();
        InterfaceType defaultClassType = interfaceElement.getDefaultClass();
        if (defaultClassType != null && defaultClassType.getElement() != null) {
          validateBounds(typeNode.getTypeArguments(),
                         itype.getArguments(),
                         defaultClassType.getElement().getTypeParameters());
          type = itype;
        }
      }
      if (type == null) {
        type = validateTypeNode(typeNode);
      }

      DartNode typeName = typeNode.getIdentifier();

      if (constructorElement == null) {
        visit(node.getArguments());
      } else {
        ClassElement cls = (ClassElement) constructorElement.getEnclosingElement();
        // Add warning for instantiating abstract class.
        if (cls.getModifiers().isAbstract()) {
          if (!constructorElement.getModifiers().isFactory()) {
            typeError(typeName, TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, cls.getName());
          }
        }
        // Check type arguments.
        FunctionType ftype = (FunctionType) constructorElement.getType();

        if (ftype != null && TypeKind.of(type).equals(TypeKind.INTERFACE)) {
          InterfaceType ifaceType = (InterfaceType) type;

          List<Type> substParams;
          if (ifaceType.getElement().isInterface()) {
            // The constructor in the interface is resolved to the type parameters declared in
            // the interface, but the constructor body has type parameters resolved to the type
            // parameters in the default class.  This substitution patches up the type variable
            // references used in parameters so they match the concrete class.
            substParams = ((ClassElement)constructorElement.getEnclosingElement()).getType().getArguments();
          } else {
            substParams = ifaceType.getElement().getTypeParameters();
          }
          List<Type> arguments = ifaceType.getArguments();
          ftype = (FunctionType) ftype.subst(arguments, substParams);
          checkDeprecated(ASTNodes.getConstructorNameNode(node), constructorElement);
          checkInvocation(node, node, constructorElement.getName(), ftype);
        }
      }
      type.getClass(); // quick null check
      return type;
    }

    /**
     * @param cls the {@link ClassElement}  which has unimplemented members.
     * @param unimplementedMembers the unimplemented members {@link Element}s.
     * @return the {@link StringBuilder} with message about unimplemented members.
     */
    private StringBuilder getUnimplementedMembersMessage(ClassElement cls,
        List<Element> unimplementedMembers) {
      // Prepare groups of unimplemented members for each type.
      Multimap<String, String> membersByTypes = ArrayListMultimap.create();
      for (Element member : unimplementedMembers) {
        ClassElement enclosingElement = (ClassElement) member.getEnclosingElement();
        InterfaceType instance = types.asInstanceOf(cls.getType(), enclosingElement);
        Type memberType = member.getType().subst(instance.getArguments(),
                                                 enclosingElement.getTypeParameters());
        if (memberType.getKind().equals(TypeKind.FUNCTION)) {
          FunctionType ftype = (FunctionType) memberType;
          StringBuilder sb = new StringBuilder();
          sb.append(ftype.getReturnType());
          sb.append(" ");
          sb.append(member.getName());
          String string = ftype.toString();
          sb.append(string, 0, string.lastIndexOf(" -> "));
          membersByTypes.put(enclosingElement.getName(), sb.toString());
        } else {
          StringBuilder sb = new StringBuilder();
          sb.append(memberType);
          sb.append(" ");
          sb.append(member.getName());
          membersByTypes.put(enclosingElement.getName(), sb.toString());
        }
      }
      // Output unimplemented members with grouping by class.
      StringBuilder sb = new StringBuilder();
      for (String typeName : membersByTypes.keySet()) {
        sb.append("\n    # From ");
        sb.append(typeName);
        sb.append(":");
        for (String memberString : membersByTypes.get(typeName)) {
          sb.append("\n        ");
          sb.append(memberString);
        }
      }
      return sb;
    }

    @Override
    public Type visitNullLiteral(DartNullLiteral node) {
      return nullType;
    }

    @Override
    public Type visitParameter(DartParameter node) {
      VariableElement parameter = node.getElement();
      FieldElement initializerElement = parameter.getParameterInitializerElement();
      if (initializerElement != null) {
        checkAssignable(node, parameter.getType(), initializerElement.getType());
      }
      return checkInitializedDeclaration(node, node.getDefaultExpr());
    }

    @Override
    public Type visitParenthesizedExpression(DartParenthesizedExpression node) {
      Type type = nonVoidTypeOf(node.getExpression());
      type.getClass(); // quick null check
      return type;
    }

    @Override
    public Type visitPropertyAccess(DartPropertyAccess node) {
      if (node.getType() != null) {
        return node.getType();
      }
      Element element = node.getElement();
      if (element != null) {
        return element.getType();
      }
      if (node.getName().isResolutionAlreadyReportedThatTheMethodCouldNotBeFound()) {
        return dynamicType;
      }
      DartNode qualifier = node.getRealTarget();
      Type receiver = nonVoidTypeOf(qualifier);
      // convert into InterfaceType
      InterfaceType cls = types.getInterfaceType(receiver);
      if (cls == null) {
        return diagnoseNonInterfaceType(qualifier, receiver);
      }
      // Do not visit the name, it may not have been resolved.
      String name = node.getPropertyName();
      InterfaceType.Member member;
      if (ASTNodes.inSetterContext(node)) {
        member = cls.lookupMember("setter " + name);
        if (member == null) {
          member = cls.lookupMember(name);
        }
      } else {
        member = cls.lookupMember(name);
        if (member == null) {
          member = cls.lookupMember("setter " + name);
        }
      }
      // is "receiver" is inferred, attempt to find member in one of the subtypes
      boolean hasMemberInSubClasses = false;
      if (member == null) {
        if (TypeQuality.of(receiver) == TypeQuality.INFERRED && receiver instanceof InterfaceType) {
          List<Member> subMembers = ((InterfaceType) receiver).lookupSubTypeMembers(name);
          hasMemberInSubClasses = !subMembers.isEmpty();
          if (subMembers.size() == 1) {
            member = subMembers.get(0);
          }
        }
      }
      // report "not a member"
      if (member == null) {
        if (reportNoMemberWhenHasInterceptor || !Elements.handlesNoSuchMethod(cls)) {
          if (typeChecksForInferredTypes && !hasMemberInSubClasses
              && !isTooGenericInferredType(receiver) || !TypeQuality.isInferred(receiver)) {
            TypeErrorCode errorCode = TypeQuality.isInferred(receiver)
                ? TypeErrorCode.NOT_A_MEMBER_OF_INFERRED : TypeErrorCode.NOT_A_MEMBER_OF;
            typeError(node.getName(), errorCode, name, cls);
          }
        }
        return dynamicType;
      }
      // set resolved element
      element = member.getElement();
      node.setElement(element);
      Modifiers modifiers = element.getModifiers();
      if (modifiers.isStatic()) {
        return typeError(node.getName(),
                         TypeErrorCode.STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE,
                         name, element.getName());
      }
      // @deprecated
      if (element != null && element.getMetadata().isDeprecated()) {
        onError(node.getName(), TypeErrorCode.DEPRECATED_ELEMENT,
            Elements.getDeprecatedElementTitle(element));
      }
      // analyze Element
      switch (element.getKind()) {
        case DYNAMIC:
          return dynamicType;
        case CONSTRUCTOR:
          return typeError(node.getName(), TypeErrorCode.MEMBER_IS_A_CONSTRUCTOR,
                           name, element.getName());

        case METHOD:
          return member.getType();

        case FIELD:
          FieldElement fieldElement = (FieldElement) element;
          Modifiers fieldModifiers = fieldElement.getModifiers();

          // Prepare getter/setter members.
          Member getterMember;
          Member setterMember;
          {
            getterMember = cls.lookupMember(name);
            if (getterMember == null && TypeQuality.of(cls) == TypeQuality.INFERRED) {
              List<Member> members = cls.lookupSubTypeMembers(name);
              if (members.size() == 1) {
                getterMember = members.get(0);
              }
            }
          }
          {
            setterMember = cls.lookupMember("setter " + name);
            if (setterMember == null) {
              setterMember = cls.lookupMember(name);
            }
          }
          boolean inSetterContext = ASTNodes.inSetterContext(node);
          boolean inGetterContext = ASTNodes.inGetterContext(node);

          // Implicit field declared as "final".
          if (!fieldModifiers.isAbstractField() && fieldModifiers.isFinal() && inSetterContext) {
            return typeError(node.getName(), TypeErrorCode.FIELD_IS_FINAL, node.getName());
          }

          Type result = member.getType();
          if (fieldModifiers.isAbstractField()) {
            if (inSetterContext) {
              result = setterMember != null ? setterMember.getSetterType() : null;
              if (result == null) {
                return typeError(node.getName(), TypeErrorCode.FIELD_HAS_NO_SETTER, node.getName());
              }
            }
            if (inGetterContext) {
              result = getterMember != null ? getterMember.getGetterType() : null;
              if (result == null) {
                return typeError(node.getName(), TypeErrorCode.FIELD_HAS_NO_GETTER, node.getName());
              }
            }
          }
          result = Types.makeInferred(result, receiver.getQuality());
          node.setType(result);
          return result;

        default:
          throw internalError(node.getName(), "unexpected kind %s", element.getKind());
      }
    }

    @Override
    public Type visitReturnStatement(DartReturnStatement node) {
      DartExpression value = node.getValue();
      if (value == null) {
        if (!types.isSubtype(voidType, expected)) {
          typeError(node, TypeErrorCode.MISSING_RETURN_VALUE, expected);
        }
      } else {
        checkAssignable(value == null ? node : value, expected, typeOf(value));
      }
      return voidType;
    }

    @Override
    public Type visitSuperExpression(DartSuperExpression node) {
      if (currentClass == null) {
        return dynamicType;
      }
      Type type = currentClass.getElement().getSupertype();
      type.getClass(); // quick null check
      return type;
    }

    @Override
    public Type visitSwitchStatement(DartSwitchStatement node) {
      node.visitChildren(this);
      // analyze "expression"
      DartExpression expression = node.getExpression();
      Type switchType = nonVoidTypeOf(expression);
      // check "case" expressions compatibility
      Type sameCaseType = null;
      for (DartSwitchMember switchMember : node.getMembers()) {
        if (switchMember instanceof DartCase) {
          DartCase caseMember = (DartCase) switchMember;
          DartExpression caseExpr = caseMember.getExpr();
          // no expression, parser already reported about this
          if (caseExpr == null) {
            continue;
          }
          Type caseType = nonVoidTypeOf(caseExpr);
          // all "case expressions" should be same type
          if (sameCaseType == null) {
            sameCaseType = caseType;
          }
          if (!Objects.equal(caseType, sameCaseType)) {
            onError(caseExpr, TypeErrorCode.CASE_EXPRESSIONS_SHOULD_BE_SAME_TYPE, sameCaseType,
                caseType);
          }
          // compatibility of "switch expression" and "case expression" types
          checkAssignable(caseExpr, switchType, caseType);
          // should not have "operator =="
          if (!Objects.equal(caseType, intType) && !Objects.equal(caseType, doubleType)
              && !Objects.equal(caseType, stringType)) {
            Member operator = lookupMember(caseType, methodNameForBinaryOperator(Token.EQ), null);
            if (operator != null && !Objects.equal(operator.getHolder(), objectType)) {
              onError(caseExpr, TypeErrorCode.CASE_EXPRESSION_TYPE_SHOULD_NOT_HAVE_EQUALS, caseType);
            }
          }
        }
      }
      return voidType;
    }

    @Override
    public Type visitSyntheticErrorExpression(DartSyntheticErrorExpression node) {
      return dynamicType;
    }

    @Override
    public Type visitSyntheticErrorStatement(DartSyntheticErrorStatement node) {
      return dynamicType;
    }

    @Override
    public Type visitThisExpression(DartThisExpression node) {
      Type type = getCurrentClass();
      if (type == null) {
        // this was used in a static context, so it should have already generated a fatal error
        return voidType;
      }
      return type;
    }

    @Override
    public Type visitThrowExpression(DartThrowExpression node) {
      if (catchDepth == 0 && node.getException() == null) {
        context.onError(new DartCompilationError(node,
            ResolverErrorCode.RETHROW_NOT_IN_CATCH));
      }
      return typeAsVoid(node);
    }

    @Override
    public Type visitCatchBlock(DartCatchBlock node) {
      ++catchDepth;
      typeOf(node.getException());
      // TODO(karlklose) Check type of stack trace variable.
      typeOf(node.getStackTrace());
      typeOf(node.getBlock());
      --catchDepth;
      return voidType;
    }

    @Override
    public Type visitTryStatement(DartTryStatement node) {
      return typeAsVoid(node);
    }

    @Override
    public Type visitUnaryExpression(DartUnaryExpression node) {
      DartExpression expression = node.getArg();
      Type type = nonVoidTypeOf(expression);
      Token operator = node.getOperator();
      switch (operator) {
        case BIT_NOT:
          // Bit operations are only supported by integers and
          // thus cannot be looked up on num. To ease usage of
          // bit operations, we currently allow them to be used
          // if the left-hand-side is of type num.
          // TODO(karlklose) find a clean solution, i.e., without a special case for num.
          if (type.equals(numType)) {
            return intType;
          } else {
            String name = methodNameForUnaryOperator(node, operator);
            HasSourceInfo problemTarget = getOperatorHasSourceInfo(node);
            Member member = lookupMember(type, name, problemTarget);
            if (member != null) {
              Element element = member.getElement();
              node.setElement(element);
              FunctionType methodType = getMethodType(type, member, name, node);
              checkDeprecated(problemTarget, element);
              return checkInvocation(Collections.<DartExpression>emptyList(), node, name, methodType, null);
            } else {
              return dynamicType;
            }
          }
        case NOT:
          checkAssignable(boolType, expression);
          return boolType;
        case SUB:
        case INC:
        case DEC: {
          if (type.getElement().isDynamic()) {
            return type;
          }
          InterfaceType itype = types.getInterfaceType(type);
          String operatorMethodName = methodNameForUnaryOperator(node, operator);
          if (operator == Token.DEC) {
            operatorMethodName = "operator -binary";
          }
          Member member = itype.lookupMember(operatorMethodName);
          if (member == null) {
            HasSourceInfo errorTarget = getOperatorHasSourceInfo(node);
            return typeError(errorTarget, TypeErrorCode.CANNOT_BE_RESOLVED,
                             operatorMethodName);
          }
          MethodElement element = ((MethodElement) member.getElement());
          node.setElement(element);
          Type returnType = ((FunctionType) member.getType()).getReturnType();
          if (operator == Token.INC || operator == Token.DEC) {
            // For INC and DEC, "operator +" and "operator -" are used to add and subtract one,
            // respectively. Check that the resolved operator has a compatible parameter type.
            Iterator<VariableElement> it = element.getParameters().iterator();
            Type operandType = it.next().getType();
            if  (!types.isAssignable(numType, operandType)) {
              typeError(node, TypeErrorCode.OPERATOR_WRONG_OPERAND_TYPE,
                  operatorMethodName, numType.toString(), operandType.toString());
            }
            // Check that the return type of the operator is compatible with the receiver.
            checkAssignable(node, type, returnType);
          }
          return node.isPrefix() ? returnType : type;
        }
        case CONDITIONAL:
          return boolType;
        default:
          throw internalError(node, "unknown operator %s", operator.toString());
      }
    }

    @Override
    public Type visitUnit(DartUnit node) {
      blockOldTypes.addFirst(new BlockTypeContext());
      return typeAsVoid(node);
    }

    @Override
    public Type visitAssertStatement(DartAssertStatement node) {
      DartExpression condition = node.getCondition();
      checkAssertCondition(condition);
      // infer types, which are valid until the end of the enclosing control block
      if (node.getParent() instanceof DartBlock) {
        DartBlock restoreBlock = getBlockForAssertTypesInference(node);
        VariableElementsRestorer variableRestorer = restoreOnBlockExit.get(restoreBlock);
        if (variableRestorer == null) {
          variableRestorer = new VariableElementsRestorer();
          restoreOnBlockExit.put(restoreBlock, variableRestorer);
        }
        restoreOnBlockExit.put(restoreBlock, variableRestorer);
        inferVariableTypesFromIsConditions(condition, variableRestorer);
      }
      // done for "assert"
      return voidType;
    }

    @Override
    public Type visitUnqualifiedInvocation(DartUnqualifiedInvocation node) {
      DartIdentifier target = node.getTarget();
      String name = target.getName();
      Element element = target.getElement();
      node.setElement(element);
      Type type;
      switch (ElementKind.of(element)) {
        case FIELD:
        case METHOD:
          type = typeAsMemberOf(element, currentClass);
          break;
        case NONE:
          if (!target.isResolutionAlreadyReportedThatTheMethodCouldNotBeFound()) {
            onError(target, TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, currentClass, target);
          }
          return dynamicType;
        default:
          type = element.getType();
          // attempt to resolve to "call()" method invocation
          if (type instanceof InterfaceType) {
            InterfaceType interfaceType = (InterfaceType) type;
            Element callElement = interfaceType.getElement().lookupLocalElement("call");
            if (ElementKind.of(callElement) == ElementKind.METHOD) {
              node.setElement(callElement);
              type = typeAsMemberOf(callElement, interfaceType);
            }
          }
          break;
      }
      checkDeprecated(target, element);
      Type returnType = checkInvocation(node, target, name, type);
      returnType = ExternalTypeAnalyzers.resolve(types, node, element, returnType);
      return returnType;
    }

    private static DartBlock getBlockForAssertTypesInference(DartNode node) {
      while (node != null) {
        if (node instanceof DartBlock) {
          DartBlock block = (DartBlock) node;
          DartNode p = block.getParent();
          if (p instanceof DartIfStatement || p instanceof DartForStatement
              || p instanceof DartForInStatement || p instanceof DartWhileStatement) {
            return block;
          }
        }
        node = node.getParent();
      }
      return null;
    }

    private static DartBlock getBlockForLoopTypesInference(DartNode node) {
      while (node != null) {
        if (node instanceof DartBlock) {
          DartBlock block = (DartBlock) node;
          DartNode p = block.getParent();
          if (p instanceof DartForStatement || p instanceof DartForInStatement
              || p instanceof DartWhileStatement) {
            return block;
          }
        }
        node = node.getParent();
      }
      return null;
    }

    /**
     * Report warning if given {@link Element} is deprecated.
     */
    private void checkDeprecated(HasSourceInfo nameNode, Element element) {
      if (element != null && element.getMetadata() != null && element.getMetadata().isDeprecated()) {
        onError(nameNode, TypeErrorCode.DEPRECATED_ELEMENT,
            Elements.getDeprecatedElementTitle(element));
      }
    }

    private Type checkInvocation(DartInvocation node, DartNode diagnosticNode, String name,
        Type type) {
      List<DartExpression> argumentNodes = node.getArguments();
      List<VariableElement> parameters;
      if (node.getElement() instanceof MethodElement) {
        MethodElement methodElement = (MethodElement) node.getElement();
        parameters = methodElement.getParameters();
      } else {
        parameters = null;
      }
      return checkInvocation(argumentNodes, diagnosticNode, name, type, parameters);
    }

    private Type checkInvocation(List<DartExpression> argumentNodes, DartNode diagnosticNode,
        String name, Type type, List<VariableElement> parameters) {
      // Prepare argument types.
      List<Type> argumentTypes = Lists.newArrayListWithCapacity(argumentNodes.size());
      for (DartExpression argumentNode : argumentNodes) {
        Type argumentType = getInvocationArgumentType(argumentNode);
        argumentTypes.add(argumentType);
      }
      return checkInvocation(argumentNodes, argumentTypes, diagnosticNode, name, type, parameters);
    }

    private Type checkInvocation(List<DartExpression> argumentNodes, List<Type> argumentTypes,
        DartNode diagnosticNode, String name, Type type, List<VariableElement> parameters) {
      // Check that argument types are compatible with type of invoked object.
      try {
        switch (TypeKind.of(type)) {
          case FUNCTION_ALIAS:
            return checkArguments(diagnosticNode, argumentNodes, argumentTypes.iterator(),
                Types.asFunctionType((FunctionAliasType) type), parameters);
          case FUNCTION:
            return checkArguments(diagnosticNode, argumentNodes, argumentTypes.iterator(),
                (FunctionType) type, parameters);
          case DYNAMIC:
            return type;
          default:
            if (isAssignable(functionType, type)) {
              // A subtype of interface Function.
              return dynamicType;
            } else if (name == null || currentClass == null) {
              if (reportNoMemberWhenHasInterceptor || !(type instanceof InterfaceType)
                  || !Elements.handlesNoSuchMethod((InterfaceType) type)) {
                return typeError(diagnosticNode, TypeErrorCode.NOT_A_FUNCTION_TYPE, type);
              }
              return dynamicType;
            } else {
              return typeError(diagnosticNode, TypeErrorCode.NOT_A_METHOD_IN, name, currentClass);
            }
        }
      } finally {
        // In any case visit body of function literals, so use inferred parameter types.
        for (DartExpression argument : argumentNodes) {
          if (argument instanceof DartNamedExpression) {
            argument = ((DartNamedExpression) argument).getExpression();
          }
          if (argument instanceof DartFunctionExpression) {
            argument.accept(this);
          }
        }
      }
    }

    /**
     * Almost same as {@link #nonVoidTypeOf(DartNode)}, but does not visit
     * {@link DartFunctionExpression}, because we know its type already and want to infer types of
     * arguments, and then propagate them into body.
     */
    private Type getInvocationArgumentType(DartExpression argument) {
      // We are interesting in the type of expression, without name.
      if (argument instanceof DartNamedExpression) {
        argument = ((DartNamedExpression) argument).getExpression();
      }
      // Don't visit function literal, we know its "declared" type.
      // But we want to visit it later, to use "inferred" type in body.
      if (argument instanceof DartFunctionExpression) {
        return argument.getElement().getType();
      }
      // General case - visit and prepare type.
      return nonVoidTypeOf(argument);
    }

    /**
     * Return the type of member as if it was a member of subtype. For example, the type of t in Sub
     * should be String, not T:
     *
     * <pre>
     *   class Super&lt;T> {
     *     T t;
     *   }
     *   class Sub extends Super&lt;String> {
     *   }
     * </pre>
     */
    private Type typeAsMemberOf(Element member, InterfaceType subtype) {
      Element holder = member.getEnclosingElement();
      if (!ElementKind.of(holder).equals(ElementKind.CLASS)) {
        return member.getType();
      }
      ClassElement superclass = (ClassElement) holder;
      InterfaceType supertype = types.asInstanceOf(subtype, superclass);
      Type type = member.getType().subst(supertype.getArguments(),
                                         supertype.getElement().getTypeParameters());
      type.getClass(); // quick null check
      return type;
    }

    @Override
    public Type visitVariable(DartVariable node) {
      DartExpression value = node.getValue();
      // if type is declared and right side is closure, infer its parameter types
      if (value != null) {
        Type varType = node.getElement().getType();
        if (isExplicitlySpecifiedType(varType)) {
          inferFunctionLiteralParametersTypes(value, varType);
        }
      }
      // prepare type of value
      Type result = checkInitializedDeclaration(node, value);
      // if no type declared for variables, try to use type of value
      if (value != null) {
        inferVariableDeclarationType(node, value);
      }
      // done
      return result;
    }

    @Override
    public Type visitWhileStatement(DartWhileStatement node) {
      DartExpression condition = node.getCondition();
      checkCondition(condition);
      // visit body
      BlockTypeContext blockTypeContxt = new BlockTypeContext();
      blockOldTypes.addFirst(blockTypeContxt);
      try {
        visitConditionalNode(condition, node.getBody());
      } finally {
        blockOldTypes.removeFirst();
        setMergedVariableTypes(blockTypeContxt);
      }
      // done
      return voidType;
    }

    @Override
    public Type visitNamedExpression(DartNamedExpression node) {
      // TODO(jgw): Checking of named parameters in progress.

      // Intentionally skip the expression's name -- it's stored as an identifier, but doesn't need
      // to be resolved or type-checked.
      Type type = nonVoidTypeOf(node.getExpression());
      type.getClass(); // quick null check
      return type;
    }

    @Override
    public Type visitTypeExpression(DartTypeExpression node) {
      return typeOf(node.getTypeNode());
    }

    @Override
    public Type visitTypeParameter(DartTypeParameter node) {
      if (node.getBound() != null) {
        validateTypeNode(node.getBound());
      }
      return voidType;
    }

    @Override
    public Type visitNativeBlock(DartNativeBlock node) {
      return typeAsVoid(node);
    }

    @Override
    public void visit(List<? extends DartNode> nodes) {
      if (nodes != null) {
        for (DartNode node : nodes) {
          node.accept(this);
        }
      }
    }

    @Override
    public Type visitArrayLiteral(DartArrayLiteral node) {
      visit(node.getTypeArguments());
      InterfaceType interfaceType = node.getType();
      if (interfaceType != null
          && interfaceType.getArguments() != null
          && interfaceType.getArguments().size() > 0) {
        Type elementType = interfaceType.getArguments().get(0);
        for (DartExpression expression : node.getExpressions()) {
          boolean isValueAssignable = checkAssignable(elementType, expression);
          if (developerModeChecks && !isValueAssignable) {
            typeError(expression, ResolverErrorCode.LIST_LITERAL_ELEMENT_TYPE, elementType);
          }
        }
      }
      return interfaceType;
    }

    @Override
    public Type visitBooleanLiteral(DartBooleanLiteral node) {
      return typeOfLiteral(node);
    }

    @Override
    public Type visitDoubleLiteral(DartDoubleLiteral node) {
      return typeOfLiteral(node);
    }

    @Override
    public Type visitField(DartField node) {
      DartMethodDefinition accessor = node.getAccessor();
      if (accessor != null) {
        return typeOf(accessor);
      } else {
        DartExpression value = node.getValue();
        // if type is declared and right side is closure, infer its parameter types
        if (value != null) {
          Type fieldType = node.getElement().getType();
          if (isExplicitlySpecifiedType(fieldType)) {
            inferFunctionLiteralParametersTypes(value, fieldType);
          }
        }
        // prepare type of value
        Type result = checkInitializedDeclaration(node, value);
        // if no type declared for field, try to use type of value
        // only final fields, because only in this case we can be sure that field is not assigned
        // somewhere, may be even not in this unit
        if (node.getModifiers().isFinal() && value != null) {
          inferVariableDeclarationType(node, value);
        }
        // done
        return result;
      }
    }

    private Type checkInitializedDeclaration(DartDeclaration<?> node, DartExpression value) {
      if (value != null && node.getElement() != null) {
        checkAssignable(node.getElement().getType(), value);
      }
      return voidType;
    }

    /**
     * @return <code>true</code> if given {@link FunctionAliasElement} has direct or indirect
     *         reference to itself using other {@link FunctionAliasElement}s.
     */
    private boolean hasFunctionTypeAliasSelfReference(FunctionAliasElement target) {
      Set<FunctionAliasElement> visited = Sets.newHashSet();
      return hasFunctionTypeAliasReference(visited, target, target);
    }

    /**
     * Checks if "target" is referenced by "current".
     */
    private boolean hasFunctionTypeAliasReference(Set<FunctionAliasElement> visited,
        FunctionAliasElement target, FunctionAliasElement current) {
      FunctionType type = current.getFunctionType();
      // prepare Types directly referenced by "current"
      Set<Type> referencedTypes = Sets.newHashSet();
      if (type != null) {
        // type parameters
        for (Type typeParameter : current.getTypeParameters()) {
          if (typeParameter instanceof TypeVariable) {
            TypeVariable typeVariable = (TypeVariable) typeParameter;
            Type bound = typeVariable.getTypeVariableElement().getBound();
            referencedTypes.add(bound);
          }
        }
        // return type
        referencedTypes.add(type.getReturnType());
        // parameters
        referencedTypes.addAll(type.getParameterTypes());
        referencedTypes.addAll(type.getOptionalParameterTypes().values());
        referencedTypes.addAll(type.getNamedParameterTypes().values());
      }
      // check that referenced types do not have references on "target"
      for (Type referencedType : referencedTypes) {
        if (referencedType != null
            && hasFunctionTypeAliasReference(visited, target, referencedType.getElement())) {
          return true;
        }
      }
      // no
      return false;
    }

    /**
     * Checks if "target" is referenced by "current".
     */
    private boolean hasFunctionTypeAliasReference(Set<FunctionAliasElement> visited,
        FunctionAliasElement target, Element currentElement) {
      // only if "current" in function type alias
      if (!(currentElement instanceof FunctionAliasElement)) {
        return false;
      }
      FunctionAliasElement current = (FunctionAliasElement) currentElement;
      // found "target"
      if (Objects.equal(target, current)) {
        return true;
      }
      // prevent recursion
      if (visited.contains(current)) {
        return false;
      }
      visited.add(current);
      // check type of "current" function type alias
      return hasFunctionTypeAliasReference(visited, target, current);
    }

    @Override
    public Type visitIntegerLiteral(DartIntegerLiteral node) {
      return typeOfLiteral(node);
    }

    @Override
    public Type visitStringLiteral(DartStringLiteral node) {
      return typeOfLiteral(node);
    }

    @Override
    public Type visitStringInterpolation(DartStringInterpolation node) {
      visit(node.getExpressions());
      return typeOfLiteral(node);
    }

    @Override
    public Type visitParameterizedTypeNode(DartParameterizedTypeNode node) {
      visit(node.getTypeParameters());
      Type type = node.getType();
      type.getClass(); // quick null check
      return type;
    }

    @Override
    public Type visitImportDirective(DartImportDirective node) {
      return voidType;
    }

    @Override
    public Type visitExportDirective(DartExportDirective node) {
      return voidType;
    }

    @Override
    public Type visitLibraryDirective(DartLibraryDirective node) {
      //return typeAsVoid(node);
      return voidType;
    }

    @Override
    public Type visitNativeDirective(DartNativeDirective node) {
      return typeAsVoid(node);
    }

    @Override
    public Type visitSourceDirective(DartSourceDirective node) {
      return typeAsVoid(node);
    }

    private class AbstractMethodFinder extends ASTVisitor<Void> {
      private final InterfaceType currentClass;
      private final Multimap<String, Element> superMembers = LinkedListMultimap.create();
      private final List<Element> unimplementedElements = Lists.newArrayList();

      private AbstractMethodFinder(InterfaceType currentClass) {
        this.currentClass = currentClass;
      }

      @Override
      public Void visitNode(DartNode node) {
        throw new AssertionError();
      }

      @Override
      public Void visitClass(DartClass node) {
        assert node.getElement().getType() == currentClass;

        // Prepare supertypes - all superclasses and interfaces.
        List<InterfaceType> supertypes = Collections.emptyList();
        boolean hasCyclicDeclaration = false;
        try {
          supertypes = currentClass.getElement().getAllSupertypes();
        } catch (CyclicDeclarationException e) {
          // Already reported by resolver.
          hasCyclicDeclaration = true;
        }

        // Add all super members to resolve.
        Element currentLibrary = currentClass.getElement().getEnclosingElement();

        // cull out duplicate elements in the supertype list - inheriting more than one interface
        // of the same type is valid.
        Set<ClassElement> typesForAbstractMembers = Sets.newHashSet();
        for (InterfaceType supertype : supertypes) {
          typesForAbstractMembers.add(supertype.getElement());
        }
        Set<String> artificialNames = Sets.newHashSet();
        for (ClassElement interfaceElement : typesForAbstractMembers) {
          for (Element member : interfaceElement.getMembers()) {
            if (interfaceElement == currentClass.getElement() && !Elements.isAbstractElement(member)) {
              continue;
            }
            String name = member.getName();
            if (DartIdentifier.isPrivateName(name)) {
              if (currentLibrary != member.getEnclosingElement().getEnclosingElement()) {
                continue;
              }
            }
            superMembers.put(name, member);
            if (member instanceof FieldElement) {
              FieldElement field = (FieldElement) member;
              if (!field.getModifiers().isAbstractField()) {
                artificialNames.add("setter " + name);
                superMembers.put("setter " + name, member);
              } else if (field.getSetter() != null && !name.startsWith("setter ")) {
                superMembers.put("setter " + name, member);
              }
            }
          }
        }

        // Visit members, so resolve methods declared in this class.
        this.visit(node.getMembers());

        // If interface, we don't care about unimplemented methods.
        if (currentClass.getElement().isInterface()) {
          return null;
        }

        // If we have cyclic declaration, hierarchy is broken, no reason to report unimplemented.
        if (hasCyclicDeclaration) {
          return null;
        }

        // Visit superclasses (without interfaces) and mark methods as implemented.
        {
          List<InterfaceType> superTypes = Lists.newArrayList();
          superTypes.add(currentClass.getElement().getSupertype());
          for (InterfaceType supertype : superTypes) {
            while (supertype != null) {
              ClassElement superclass = supertype.getElement();
              for (Element member : superclass.getMembers()) {
                removeSuperMemberIfNotAbstract(member);
              }
              supertype = supertype.getElement().getSupertype();
            }
          }
        }

        // visit mixins
        for (InterfaceType mixType : currentClass.getElement().getMixins()) {
          ClassElement mixElement = mixType.getElement();
          for (Element member : mixElement.getMembers()) {
            removeSuperMemberIfNotAbstract(member);
          }
        }

        // Remove artificial "setter " members.
        for (String name : artificialNames) {
          superMembers.removeAll(name);
        }

        // All remaining methods are unimplemented.
        List<String> keys = new ArrayList<String>(superMembers.keys());
        for (int i = 0; i < keys.size(); i++) {
          String name = keys.get(i);
          Collection<Element> elements = superMembers.removeAll(name);
          for (Element element : elements) {
            if (!element.getModifiers().isStatic()) {
              unimplementedElements.add(element);
              break; // Only report the first unimplemented element with this name.
            }
          }
        }

        // add abstract members of current class
        for (Element member : currentClass.getElement().getMembers()) {
          if (ElementKind.of(member) == ElementKind.FIELD && member.getModifiers().isAbstractField()) {
            FieldElement field = (FieldElement) member;
            MethodElement getter = field.getGetter();
            MethodElement setter = field.getSetter();
            if (getter != null && Elements.isAbstractElement(getter)) {
              unimplementedElements.add(getter);
            }
            if (setter != null && Elements.isAbstractElement(setter)) {
              unimplementedElements.add(setter);
            }
          } else if (Elements.isAbstractElement(member)) {
            unimplementedElements.add(member);
          }
        }

        return null;
      }

      private void removeSuperMemberIfNotAbstract(Element member) {
        String name = member.getName();
        if (ElementKind.of(member) == ElementKind.FIELD && member.getModifiers().isAbstractField()) {
          FieldElement field = (FieldElement) member;
          MethodElement getter = field.getGetter();
          MethodElement setter = field.getSetter();
          if (getter != null && !Elements.isAbstractElement(getter)) {
            superMembers.removeAll(name);
          }
          if (setter != null && !Elements.isAbstractElement(setter)) {
            if (!name.startsWith("setter ")) {
              superMembers.removeAll("setter " + name);
            } else {
              superMembers.removeAll(name);
            }
          }
        } else if (!Elements.isAbstractElement(member)) {
          superMembers.removeAll(name);
        }
      }

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

      @Override
      public Void visitField(DartField node) {
        if (superMembers == null) {
          return null;
        }
        FieldElement field = node.getElement();
        // prepare overridden elements
        String name = field.getName();
        Set<Element> overridden = Sets.newHashSet();
        if (node.getAccessor() != null) {
          if (node.getAccessor().getModifiers().isSetter()) {
            if (!name.startsWith("setter ")) {
              name = "setter " + name;
            }
          }
          overridden.addAll(superMembers.removeAll(name));
        } else {
          overridden.addAll(superMembers.removeAll(name));
          overridden.addAll(superMembers.removeAll("setter " + name));
        }
        // check override
        for (Element superElement : overridden) {
          if (!(field.isStatic() && superElement.getModifiers().isStatic())) {
            if (canOverride(node.getName(), field.getModifiers(), superElement)
                && !superElement.getModifiers().isStatic()) {
              switch (superElement.getKind()) {
                case FIELD:
                  checkOverride(node.getName(), field, superElement);
                  break;
                case METHOD:
                  typeError(node.getName(), TypeErrorCode.SUPERTYPE_HAS_METHOD, name,
                      superElement.getEnclosingElement().getName());
                  break;

                default:
                  typeError(node, TypeErrorCode.INTERNAL_ERROR, superElement);
                  break;
              }
            }
          }
        }
        // set super-elements for FieldElement
        Elements.setOverridden(field, ImmutableSet.copyOf(overridden));
        // set super-elements for getter/setter
        if (node.getAccessor() != null) {
          Set<Element> superGetters = Sets.newHashSet();
          Set<Element> superSetters = Sets.newHashSet();
          for (Element superElement : overridden) {
            if (superElement instanceof FieldElement) {
              FieldElement superField = (FieldElement) superElement;
              if (superField.getGetter() != null) {
                superGetters.add(superField.getGetter());
              } else if (superField.getSetter() != null) {
                superSetters.add(superField.getSetter());
              } else {
                superGetters.add(superField);
                superSetters.add(superField);
              }
            }
          }
          if (node.getAccessor().getModifiers().isGetter()) {
            Elements.setOverridden(node.getAccessor().getElement(), superGetters);
          }
          if (node.getAccessor().getModifiers().isSetter()) {
            Elements.setOverridden(node.getAccessor().getElement(), superSetters);
          }
        }
        return null;
      }

      @Override
      public Void visitMethodDefinition(DartMethodDefinition node) {
        MethodElement method = node.getElement();
        String name = method.getName();
        if (superMembers != null && !method.isConstructor()) {
          Collection<Element> overridden = superMembers.removeAll(name);
          Elements.setOverridden(method, ImmutableSet.copyOf(overridden));
          // Check for invalid @override metadata.
          if (overridden.isEmpty() && node.getObsoleteMetadata().isOverride()) {
            typeError(node.getName(), ResolverErrorCode.INVALID_OVERRIDE_METADATA);
          }
          // Check that override is valid.
          for (Element superElement : overridden) {
            if (!(method.isStatic() && superElement.getModifiers().isStatic())) {
              if (canOverride(node.getName(), method.getModifiers(), superElement)
                  && !superElement.getModifiers().isStatic()) {
                switch (superElement.getKind()) {
                  case METHOD:
                    checkOverride(node.getName(), method, superElement);
                    break;

                  case FIELD:
                    typeError(node.getName(), TypeErrorCode.SUPERTYPE_HAS_FIELD, superElement.getName(),
                        superElement.getEnclosingElement().getName());
                    break;

                  default:
                    typeError(node, TypeErrorCode.INTERNAL_ERROR, superElement);
                    break;
                }
              }
            }
          }
        }
        return null;
      }

      /**
       * Report a compile-time error if a static member tries to override an instance member
       * @returns true if no compile-time error was reported
       */
      private boolean canOverride(HasSourceInfo errorTarget, Modifiers modifiers,
          Element superElement) {
        if (!superElement.getModifiers().isStatic() && modifiers.isStatic()) {
          onError(errorTarget, ResolverErrorCode.CANNOT_OVERRIDE_INSTANCE_MEMBER,
                          superElement.getName(), superElement.getEnclosingElement().getName());
          return false;
        } else if (superElement.getModifiers().isStatic() && !modifiers.isStatic()) {
            onError(errorTarget, TypeErrorCode.OVERRIDING_STATIC_MEMBER,
                superElement.getName(), superElement.getEnclosingElement().getName());
          // Although a warning, override is allowed anyway
          return true;
        }
        return true;
      }

      /**
       * Report a static type error if member cannot override superElement, that
       * is, they are not assignable.
       */
      private void checkOverride(HasSourceInfo errorTarget, Element member, Element superElement) {
        String name = member.getName();
        Type superMember = typeAsMemberOf(superElement, currentClass);
        if (member.getKind() == ElementKind.METHOD && superElement.getKind() == ElementKind.METHOD) {
          MethodElement method = (MethodElement) member;
          MethodElement superMethod = (MethodElement) superElement;
          if (hasLegalMethodOverrideSignature(errorTarget, method, superMethod)) {
            if (!types.isSubtype(member.getType(), superMember)) {
              typeError(errorTarget,
                        TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE,
                        name,
                        superElement.getEnclosingElement().getName(),
                        member.getType(),
                        superMember);
            }
          }
        } else {
          if (ElementKind.of(member) == ElementKind.FIELD
              && ElementKind.of(superElement) == ElementKind.FIELD) {
            FieldElement field = (FieldElement) member;
            FieldElement superField = (FieldElement) superElement;
            //
            MethodElement fGetter = field.getGetter();
            MethodElement sGetter = superField.getGetter();
            if (fGetter != null && sGetter != null) {
              checkOverride(errorTarget, fGetter, sGetter);
            } else if (fGetter != null && sGetter == null || fGetter == null && sGetter != null) {
            } else {
              if (!types.isAssignable(superMember, member.getType())) {
                typeError(errorTarget, TypeErrorCode.CANNOT_OVERRIDE_TYPED_MEMBER, name,
                    superElement.getEnclosingElement().getName(), member.getType(), superMember);
                return;
              }
            }
            //
            MethodElement fSetter = field.getSetter();
            MethodElement sSetter = superField.getSetter();
            if (fSetter != null && sSetter != null) {
              checkOverride(errorTarget, fSetter, sSetter);
            } else if (fSetter != null && sSetter == null || fSetter == null && sSetter != null) {
            } else {
              if (!types.isAssignable(superMember, member.getType())) {
                typeError(errorTarget, TypeErrorCode.CANNOT_OVERRIDE_TYPED_MEMBER, name,
                    superElement.getEnclosingElement().getName(), member.getType(), superMember);
                return;
              }
            }
            return;
          }
          if (!types.isAssignable(superMember, member.getType())) {
            typeError(errorTarget, TypeErrorCode.CANNOT_OVERRIDE_TYPED_MEMBER, name,
                superElement.getEnclosingElement().getName(), member.getType(), superMember);
          }
        }
      }

      /**
       * @return <code>true</code> if given "method" has signature compatible with "superMethod".
       */
      private boolean hasLegalMethodOverrideSignature(HasSourceInfo errorTarget,
                                                      MethodElement method,
                                                      MethodElement superMethod) {
        // Prepare parameters.
        List<VariableElement> parameters = method.getParameters();
        List<VariableElement> superParameters = superMethod.getParameters();
        // Number of required parameters should be same.
        {
          int numRequired = Elements.getNumberOfRequiredParameters(method);
          int superNumRequired = Elements.getNumberOfRequiredParameters(superMethod);
          if (numRequired != superNumRequired) {
            onError(errorTarget,
                    ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NUM_REQUIRED_PARAMS,
                    getMethodSignature(superMethod),
                    superMethod.getEnclosingElement().getName());
            return false;
          }
        }
        // "method" should have at least same number of optional positional parameters as "superMethod"
        {
          LinkedHashMap<VariableElement, DartExpression> defMethod = getParametersDefaultsOptional(parameters);
          LinkedHashMap<VariableElement, DartExpression> defSuper = getParametersDefaultsOptional(superParameters);
          if (defMethod.size() < defSuper.size()) {
            onError(errorTarget,
                    ResolverErrorCode.CANNOT_OVERRIDE_METHOD_OPTIONAL_PARAMS,
                    getMethodSignature(superMethod),
                    superMethod.getEnclosingElement().getName());
            return false;
          }
          Iterator<Entry<VariableElement, DartExpression>> defMethodIter = defMethod.entrySet().iterator();
          Iterator<Entry<VariableElement, DartExpression>> defSuperIter = defSuper.entrySet().iterator();
          while (defSuperIter.hasNext()) {
            Entry<VariableElement, DartExpression> methodEntry = defMethodIter.next();
            Entry<VariableElement, DartExpression> superEntry = defSuperIter.next();
            DartExpression methodValue = methodEntry.getValue();
            DartExpression superValue = superEntry.getValue();
            if (superValue != null
                && !Objects.equal(ObjectUtils.toString(methodValue),
                    ObjectUtils.toString(superValue))) {
              onError(methodEntry.getKey().getSourceInfo(),
                  TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, method.getName(),
                  superValue);
            }
          }
        }
        // "method" should have at least all named parameters of "superMethod".
        {
          Map<String, VariableElement> methodNames = getParametersNamed(parameters);
          Map<String, VariableElement> superNames = getParametersNamed(superParameters);
          if (!methodNames.keySet().containsAll(superNames.keySet())) {
            onError(errorTarget, ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NAMED_PARAMS, method.getName());
            return false;
          }
          Map<String, DartExpression> methodDefs = getParametersDefaultsNamed(parameters);
          Map<String, DartExpression> superDefs = getParametersDefaultsNamed(superParameters);
          for (Entry<String, DartExpression> entry : superDefs.entrySet()) {
            String name = entry.getKey();
            DartExpression defValue = methodDefs.get(name);
            DartExpression superDefValue = superDefs.get(name);
            if (superDefValue != null
                && !Objects.equal(ObjectUtils.toString(defValue),
                    ObjectUtils.toString(superDefValue))) {
              onError(methodNames.get(name).getSourceInfo(),
                  TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, method.getName(),
                  superDefValue);
            }
          }
        }
//        List<VariableElement> named = getNamedParameters(parameters);
//        List<VariableElement> superNamed = getNamedParameters(superParameters);
//        Iterator<VariableElement> namedIterator = named.iterator();
//        Iterator<VariableElement> superNamedIterator = superNamed.iterator();
//        while (superNamedIterator.hasNext()) {
//          VariableElement superParameter = superNamedIterator.next();
//          if (namedIterator.hasNext()) {
//            VariableElement parameter = namedIterator.next();
//            if (Objects.equal(parameter.getName(), superParameter.getName())) {
//              DartExpression superDefValue = superParameter.getDefaultValue();
//              DartExpression defValue = parameter.getDefaultValue();
//              if (superDefValue != null
//                  && !Objects.equal(ObjectUtils.toString(defValue),
//                      ObjectUtils.toString(superDefValue))) {
//                onError(parameter.getSourceInfo(),
//                    TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, method.getName(),
//                    superDefValue);
//              }
//              continue;
//            }
//          }
//          onError(errorTarget, ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NAMED_PARAMS, method.getName());
//          return false;
//        }
        return true;
      }

      private String getMethodSignature(MethodElement method) {
        StringBuilder builder = new StringBuilder();
        builder.append(method.getName());
        builder.append("(");
        boolean inOptional = false;
        boolean inNamed = false;
        List<VariableElement> superParameters = method.getParameters();
        int parameterCount = superParameters.size();
        for (int i = 0; i < parameterCount; i++) {
          if (i > 0) {
            builder.append(", ");
          }
          VariableElement parameter = superParameters.get(i);
          if (!inOptional && parameter.isOptional()) {
            builder.append("[");
            inOptional = true;
          }
          if (!inNamed && parameter.isNamed()) {
            builder.append("{");
            inNamed = true;
          }
          builder.append(parameter.getType().toString());
        }
        if (inOptional) {
          builder.append("]");
        }
        if (inNamed) {
          builder.append("}");
        }
        builder.append(")");
        String methodSignature = builder.toString();
        return methodSignature;
      }

      private LinkedHashMap<VariableElement, DartExpression> getParametersDefaultsOptional(List<VariableElement> parameters) {
        LinkedHashMap<VariableElement, DartExpression> defaults = Maps.newLinkedHashMap();
        for (VariableElement parameter : parameters) {
          if (parameter.isOptional()) {
            defaults.put(parameter, parameter.getDefaultValue());
          }
        }
        return defaults;
      }

      private Map<String, VariableElement> getParametersNamed(List<VariableElement> parameters) {
        Map<String, VariableElement> namedParameters = Maps.newHashMap();
        for (VariableElement parameter : parameters) {
          if (parameter.isNamed()) {
            namedParameters.put(parameter.getName(), parameter);
          }
        }
        return namedParameters;
      }

      private Map<String, DartExpression> getParametersDefaultsNamed(List<VariableElement> parameters) {
        Map<String, DartExpression> defaults = Maps.newHashMap();
        for (VariableElement parameter : parameters) {
          if (parameter.isNamed()) {
            defaults.put(parameter.getName(), parameter.getDefaultValue());
          }
        }
        return defaults;
      }
    }
  }

  private static boolean isExplicitlySpecifiedType(Type type) {
    return type != null && TypeKind.of(type) != TypeKind.DYNAMIC
        && !TypeQuality.isInferred(type);
  }

  /**
   * @return the {@link TypeQuality} of given {@link DartExpression}.
   */
  public static TypeQuality getTypeQuality(DartExpression expr) {
    if (expr != null) {
      if (expr instanceof DartIdentifier) {
        Type varType = expr.getType();
        if (varType != null) {
          TypeQuality varTypeQuality = varType.getQuality();
          if (varTypeQuality == TypeQuality.EXACT) {
            varTypeQuality = TypeQuality.INFERRED_EXACT;
          }
          return varTypeQuality;
        }
      }
      if (expr instanceof DartLiteral) {
        return TypeQuality.INFERRED_EXACT;
      }
      if (expr instanceof DartUnaryExpression) {
        DartUnaryExpression unary = (DartUnaryExpression) expr;
        if (hasTypeBoolIntDouble(unary.getArg())) {
          return TypeQuality.INFERRED_EXACT;
        }
        return TypeQuality.INFERRED;
      }
      if (expr instanceof DartBinaryExpression) {
        DartBinaryExpression binary = (DartBinaryExpression) expr;
        if (hasTypeBoolIntDouble(binary.getArg1()) && hasTypeBoolIntDouble(binary.getArg2())) {
          return TypeQuality.INFERRED_EXACT;
        }
        return TypeQuality.INFERRED;
      }
      if (expr instanceof DartNewExpression) {
        DartNewExpression newExpression = (DartNewExpression) expr;
        ConstructorElement constructorElement = newExpression.getElement();
        if (constructorElement != null && !constructorElement.getModifiers().isFactory()) {
          return TypeQuality.INFERRED_EXACT;
        }
        return TypeQuality.INFERRED;
      }
    }
    return TypeQuality.INFERRED;
  }

  private static boolean hasTypeBoolIntDouble(DartExpression expr) {
    Type type = expr.getType();
    return isCoreType(type, "bool") || isCoreType(type, "int") || isCoreType(type, "double");
  }

  private static boolean isCoreType(Type type, String name) {
    return type != null
        && Elements.isCoreLibrarySource(type.getElement().getSourceInfo().getSource())
        && type.getElement().getName().equals(name);
  }

  /**
   * Sometimes inferred type is too generic - such as "Object" or "Collection", so there are no
   * reason to reports problems.
   */
  private static boolean isTooGenericInferredType(Type type) {
    if (TypeQuality.of(type) == TypeQuality.INFERRED) {
      String typeName = type.getElement().getName();
      if ("Object".equals(typeName) || "Collection".equals(typeName)) {
        return true;
      }
    }
    return false;
  }
}
