/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.javac;

import com.google.gwt.core.client.UnsafeNativeLong;
import com.google.gwt.dev.jdt.SafeASTVisitor;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.util.InstalledHelpInfo;
import com.google.gwt.dev.util.JsniRef;
import com.google.gwt.dev.util.collect.Stack;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

/**
 * Resolves JSNI references to fields and methods and gives a informative errors if the references
 * cannot be resolved.
 * <p>
 *  * JSNI references consist of two parts @ClassDescriptor::memberDescriptor. Class descriptors
 * are source names and memberDescriptors are either a field name or a method name with a signature
 * specification. Signature specification a full signature or a wildcard (*).
 * <p>
 *  * The result of resolution will be a modified JSNI AST where all the resolved references will
 * carry the fully qualified class name and the full member reference, along with a mapping from
 * jsni references to JDT binding.
 * <p>
 * In addition in the following instances involving longs warning will be emitted to remind uses
 * that GWT longs are not JavaScript numbers:
 * <ul>
 * <li>JSNI methods with a parameter or return type of long or an array whose base type is long.
 * </li>
 * <li>Access from JSNI to a field whose type is long or an array whose base type is long.</li>
 * <li>Access from JSNI to a method with a parameter or return type of long or an array whose base
 * type is long.</li>
 * <li>JSNI references to anonymous classes.</li>
 * </ul>
 */
public class JsniReferenceResolver {

  /**
   * A call-back interface to resolve types.
   */
  public interface TypeResolver {
    /**
     * @param sourceOrBinaryName Either source or binary names are allowed in JSNI.
     */
    ReferenceBinding resolveType(String sourceOrBinaryName);
  }

  private class JsniDeclChecker extends SafeASTVisitor implements
      ClassFileConstants {

    @Override
    public void endVisit(MethodDeclaration method, ClassScope scope) {
      if (method.isNative()) {
        boolean hasUnsafeLongsAnnotation = hasUnsafeLongsAnnotation(method, scope);
        if (!hasUnsafeLongsAnnotation) {
          checkDecl(method, scope);
        }
        JsniMethod jsniMethod = jsniMethods.get(method);
        if (jsniMethod != null) {
          new JsniReferenceResolverVisitor(method, hasUnsafeLongsAnnotation).resolve(
              jsniMethod.function());
        }
      }
      suppressWarningsStack.pop();
    }

    @Override
    public void endVisit(TypeDeclaration typeDeclaration, ClassScope scope) {
      suppressWarningsStack.pop();
    }

    @Override
    public void endVisit(TypeDeclaration typeDeclaration,
        CompilationUnitScope scope) {
      suppressWarningsStack.pop();
    }

    @Override
    public void endVisitValid(TypeDeclaration typeDeclaration, BlockScope scope) {
      suppressWarningsStack.pop();
    }

    @Override
    public boolean visit(MethodDeclaration meth, ClassScope scope) {
      suppressWarningsStack.push(JdtUtil.getSuppressedWarnings(meth.annotations));
      return true;
    }

    @Override
    public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
      suppressWarningsStack.push(JdtUtil.getSuppressedWarnings(typeDeclaration.annotations));
      return true;
    }

    @Override
    public boolean visit(TypeDeclaration typeDeclaration,
        CompilationUnitScope scope) {
      suppressWarningsStack.push(JdtUtil.getSuppressedWarnings(typeDeclaration.annotations));
      return true;
    }

    @Override
    public boolean visitValid(TypeDeclaration typeDeclaration, BlockScope scope) {
      suppressWarningsStack.push(JdtUtil.getSuppressedWarnings(typeDeclaration.annotations));
      return true;
    }

    private void checkDecl(MethodDeclaration meth, ClassScope scope) {
      TypeReference returnType = meth.returnType;
      if (containsLong(returnType, scope)) {
        longAccessError(meth, "Type '" + typeString(returnType)
            + "' may not be returned from a JSNI method");
      }

      if (meth.arguments == null) {
        return;
      }

      for (Argument arg : meth.arguments) {
        if (containsLong(arg.type, scope)) {
          longAccessError(arg, "Parameter '" + String.valueOf(arg.name)
              + "': type '" + typeString(arg.type)
              + "' is not safe to access in JSNI code");
        }
      }
    }

    private boolean containsLong(final TypeReference type, ClassScope scope) {
      return type != null
          && JsniReferenceResolver.this.containsLong(type.resolveType(scope));
    }

    private String typeString(TypeReference type) {
      return type.toString();
    }
  }

  private class JsniReferenceResolverVisitor extends JsModVisitor {

    private final boolean hasUnsafeLongsAnnotation;
    private final MethodDeclaration method;

    public JsniReferenceResolverVisitor(MethodDeclaration method,
        boolean hasUnsafeLongsAnnotation) {
      this.method = method;
      this.hasUnsafeLongsAnnotation = hasUnsafeLongsAnnotation;
    }

    public void resolve(JsFunction function) {
      this.accept(function);
    }

    @Override
    public void endVisit(JsBinaryOperation x, JsContext ctx) {
      // Look for the patern a.f = o.@C::m();
      if (!x.getOperator().isAssignment()) {
        return;
      }
      if (!(x.getArg1() instanceof JsNameRef) || !(x.getArg2() instanceof JsNameRef)) {
        return;
      }

      JsNameRef lhs = (JsNameRef) x.getArg1();
      JsNameRef rhs = (JsNameRef) x.getArg2();

      if (!rhs.isJsniReference() || !(jsniRefs.get(rhs.getIdent()) instanceof MethodBinding)) {
        // Not a reference to a JSNI method.
        return;
      }

      if (rhs.getQualifier() == null) {
        // Unqualified JSNI reference is OK.
        return;
      }

      if (lhs.getQualifier() == null) {
        // Assignment to unqualified variable is OK.
        return;
      }

      // Here we have a qualified JSNI method reference assigned to a field.
      JsniRef jsniRef = JsniRef.parse(rhs.getIdent());
      emitWarning("unsafe", WARN_NOT_CAPTURING_QUALIFIER, x.getSourceInfo(), jsniRef,
          rhs.getQualifier().toSource());
    }

    @Override
    public void endVisit(JsNameRef x, JsContext ctx) {
      String ident = x.getIdent();
      if (!x.isJsniReference()) {
        // Not a jsni reference.
        return;
      }

      JsniRef jsniRef = JsniRef.parse(ident);
      if (jsniRef == null) {
        emitError(ERR_MALFORMED_JSNI_IDENTIFIER, x.getSourceInfo(), null, ident);
        return;
      }

      Binding binding = resolveReference(x.getSourceInfo(), jsniRef, x.getQualifier() != null,
          ctx.isLvalue());

      assert !x.isResolved();
      if (!ident.equals(jsniRef.getResolvedReference())) {
        // Replace by the resolved reference (consisting of the fully qualified classname and the
        // method description including actual signature) so that dispatch everywhere is consistent
        // with the one resolved here.
        ident = jsniRef.getResolvedReference();
        JsNameRef newRef = new JsNameRef(x.getSourceInfo(), ident);
        newRef.setQualifier(x.getQualifier());
        ctx.replaceMe(newRef);
      }
      if (binding != null) {
        jsniRefs.put(ident, binding);
      }
    }

    private void resolveClassReference(JsniRef jsniRef) {
      // Precedence rules as of JLS 6.4.1.
      // 1. Enclosing type.
      // 2. Visible type in same compilation unit.
      // 3. Named import.
      // 4. Same package.
      // 5. Import on demand.

      String originalName = jsniRef.className();
      String importedClassName = originalName;
      if (importedClassName.contains(".")) {
        // Only retain up the first dot to support innerclasses. E.g. import c.g.A and reference
        // @A.I::f.
        importedClassName = importedClassName.substring(0,importedClassName.indexOf("."));
      }

      // 1 & 2. Check to see if this name refers to the enclosing class or is directly accessible
      // from it.
      ReferenceBinding declaringClass = method.binding.declaringClass;
      while (declaringClass != null) {
        String declaringClassName = JdtUtil.getSourceName(declaringClass);
        if (declaringClassName.equals(importedClassName) ||
            declaringClassName.endsWith("." + importedClassName)) {
          // Referring to declaring class name using unqualified name.
          jsniRef.setResolvedClassName(declaringClassName +
              originalName.substring(importedClassName.length()));
          return;
        }
        String fullClassName =
            JdtUtil.getBinaryName(declaringClass) + "$" + originalName.replace('.', '$');
        if (typeResolver.resolveType(fullClassName) != null) {
          jsniRef.setResolvedClassName(JdtUtil.getSourceName(declaringClass) + "." + originalName);
          return;
        }
        declaringClass = declaringClass.enclosingTypeAt(1);
      }

      // 3. Check to see if this name is one of the named imports.
      for (ImportReference importReference : cudImports) {
        String nameFromImport = JdtUtil.asDottedString(importReference.getImportName());
        if (!importReference.isStatic()  && importReference.trailingStarPosition == 0 &&
           nameFromImport.endsWith("." + importedClassName)) {
          jsniRef.setResolvedClassName(
              nameFromImport + originalName.substring(importedClassName.length()));
          return;
        }
      }

      // 4. Check to see if this name is resolvable from the current package.
      String currentPackageBinaryClassName =
          JdtUtil.getBinaryName(
              CharOperation.charToString(method.binding.declaringClass.qualifiedPackageName()),
              originalName);

      if (typeResolver.resolveType(currentPackageBinaryClassName) != null) {
        jsniRef.setResolvedClassName(
            JdtUtil.getSourceName(
                CharOperation.charToString(method.binding.declaringClass.qualifiedPackageName()),
                originalName));
        return;
      }

      // 5. Check to see if this name is resolvable as an import on demand.
      List<String> importPackages = Lists.newArrayList("java.lang");
      for (ImportReference importReference : cudImports) {
        if (importReference.isStatic() || importReference.trailingStarPosition == 0) {
          continue;
        }
        importPackages.add(JdtUtil.asDottedString(importReference.getImportName()));
      }
      for (String importPackage : importPackages) {
        String fullClassName = importPackage + "." + originalName.replace('.', '$');
        if (typeResolver.resolveType(fullClassName) != null) {
          jsniRef.setResolvedClassName(importPackage + "." + originalName);
          return;
        }
      }

      // Otherwise leave it as it is.
      // TODO(rluble): Maybe we should leave it null here.
      jsniRef.setResolvedClassName(jsniRef.className());
    }

    private boolean isEnclosingClass(TypeBinding clazz, TypeBinding maybeEnclosingClass) {
      for (TypeBinding currentClass = clazz; currentClass != null;
          currentClass = currentClass.enclosingType()) {
        if (currentClass == maybeEnclosingClass) {
          return true;
        }
      }
      return false;
    }

    private FieldBinding checkAndResolveFieldRef(SourceInfo errorInfo, ReferenceBinding clazz,
        JsniRef jsniRef, boolean hasQualifier, boolean isLvalue) {
      assert jsniRef.isField();
      FieldBinding target = getField(clazz, jsniRef);
      if (target == null) {
        emitError(ERR_UNABLE_TO_RESOLVE_FIELD, errorInfo, jsniRef);
        return null;
      }
      resolveJsniRef(jsniRef, target);
      if (target.isDeprecated() &&
          !isEnclosingClass(method.binding.declaringClass, target.declaringClass)) {
        emitWarning("deprecation", WARN_DEPRECATED_FIELD, errorInfo, jsniRef);
      }
      if (isLvalue && target.constant() != Constant.NotAConstant) {
        emitError(ERR_ILLEGAL_ASSIGNMENT_TO_COMPILE_TIME_CONSTANT, errorInfo, jsniRef);
      }
      if (target.isStatic() && hasQualifier) {
        emitError(ERR_UNNECESSARY_QUALIFIER_STATIC_FIELD, errorInfo, jsniRef);
      } else if (!target.isStatic() && !hasQualifier) {
        emitError(ERR_MISSING_QUALIFIER_INSTANCE_FIELD, errorInfo, jsniRef);
      }

      if (hasUnsafeLongsAnnotation) {
        return target;
      }
      if (containsLong(target.type)) {
        emitError(ERR_UNSAFE_FIELD_ACCESS, errorInfo, jsniRef, typeString(target.type));
      }
      return target;
    }

    private MethodBinding checkAndResolveMethodRef(SourceInfo errorInfo, ReferenceBinding clazz,
        JsniRef jsniRef, boolean hasQualifier, boolean isLvalue) {
      assert jsniRef.isMethod();
      List<MethodBinding> targets = getMatchingMethods(clazz, jsniRef);
      if (targets.size() > 1) {
          emitError(ERR_AMBIGUOUS_WILDCARD_MATCH, errorInfo, jsniRef,
              JdtUtil.formatBinding(targets.get(0)),
              JdtUtil.formatBinding(targets.get(1)));
        return null;
      } else if (targets.isEmpty()) {
        emitError(ERR_UNABLE_TO_RESOLVE_METHOD, errorInfo, jsniRef);
        return null;
      }
      MethodBinding target = targets.get(0);
      resolveJsniRef(jsniRef, target);
      if (target.isDeprecated() &&
          !isEnclosingClass(method.binding.declaringClass, target.declaringClass)) {
        emitWarning("deprecation", WARN_DEPRECATED_METHOD, errorInfo, jsniRef);
      }
      if (isLvalue) {
        emitError(ERR_ILLEGAL_ASSIGNMENT_TO_METHOD, errorInfo, jsniRef);
      }
      boolean needsQualifer = !target.isStatic() && !target.isConstructor();
      if (!needsQualifer && hasQualifier) {
        emitError(ERR_UNNECESSARY_QUALIFIER_STATIC_METHOD, errorInfo, jsniRef);
      } else if (needsQualifer && !hasQualifier) {
        emitError(ERR_MISSING_QUALIFIER_INSTANCE_METHOD, errorInfo, jsniRef);
      }

      if (hasUnsafeLongsAnnotation) {
        return target;
      }
      if (containsLong(target.returnType)) {
        emitError(ERR_ILLEGAL_RETURN_TYPE, errorInfo, jsniRef, typeString(target.returnType));
      }

      if (target.parameters != null) {
        int i = 0;
        for (TypeBinding paramType : target.parameters) {
          ++i;
          if (containsLong(paramType)) {
            // It would be nice to print the parameter name, but how to find it?
            emitError(ERR_ILLEGAL_PARAMETER, errorInfo, jsniRef, i, typeString(paramType));
          }
        }
      }
      return target;
    }

    private Binding resolveReference(SourceInfo errorInfo, JsniRef jsniRef, boolean hasQualifier,
        boolean isLvalue) {

      resolveClassReference(jsniRef);
      String className = jsniRef.getResolvedClassName();

      boolean isPrimitive;
      ReferenceBinding clazz;
      TypeBinding binding = method.scope.getBaseType(className.toCharArray());
      if (binding != null) {
        isPrimitive = true;
        clazz = null;
      } else {
        isPrimitive = false;
        binding = clazz = findClass(className);
      }

      if (binding != null && binding.isAnonymousType()) {
        // There seems that there is no way to write a JSNI reference to an anonymous class as
        // it will require to accept a source name of the form A.1 where one of the identifier parts
        // consists only of digits and therefore is not a valid identifier.
        // This error case is left here in case names of that form start appearing from the JSNI
        // parser.
        emitError(ERR_ILLEGAL_ANONYMOUS_INNER_CLASS, errorInfo, jsniRef);
        return null;
      } else if (binding == null) {
        emitError(ERR_UNABLE_TO_RESOLVE_CLASS, errorInfo, jsniRef);
        return null;
      }

      if (clazz != null && clazz.isDeprecated() &&
          !isEnclosingClass(method.binding.declaringClass, clazz)) {
        emitWarning("deprecation", WARN_DEPRECATED_CLASS, errorInfo, jsniRef);
      }

      if (jsniRef.isField() && "class".equals(jsniRef.memberName())) {
        if (isLvalue) {
          emitError(ERR_ILLEGAL_ASSIGNMENT_TO_CLASS_LITERAL, errorInfo, jsniRef);
          return null;
        }
        // Reference to the class itself.
        jsniRef.setResolvedClassName(JdtUtil.getSourceName(binding));
        jsniRef.setResolvedMemberWithSignature(jsniRef.memberSignature());
        if (jsniRef.isArray()) {
          ArrayBinding arrayBinding =
              method.scope.createArrayType(binding, jsniRef.getDimensions());
          return arrayBinding;
        } else {
          return binding;
        }
      }

      if (jsniRef.isArray() || isPrimitive) {
        emitError(ERR_ILLEGAL_ARRAY_OR_PRIMITIVE_REFERENCE, errorInfo, jsniRef);
        return null;
      }

      assert clazz != null;
      if (jsniRef.isMethod()) {
        return checkAndResolveMethodRef(errorInfo, clazz, jsniRef, hasQualifier, isLvalue);
      } else {
        return checkAndResolveFieldRef(errorInfo, clazz, jsniRef, hasQualifier, isLvalue);
      }
    }
    private static final String WARN_NOT_CAPTURING_QUALIFIER =
        "Instance method reference '%2$s.%3$s' loses its instance ('%8$s') when assigned; "
            + "to remove this warning either assign to a local variable or construct "
            + "the proper closure using an anonymous function or by calling "
            + "Function.prototype.bind";
    private static final String ERR_ILLEGAL_ARRAY_OR_PRIMITIVE_REFERENCE =
        "Referencing member '%2$s.%4$s': 'class' is " +
        "the only legal reference for arrays and primitive types";
    private static final String ERR_ILLEGAL_ASSIGNMENT_TO_CLASS_LITERAL =
        "Illegal assignment to class literal '%2$s.%3$s'";
    private static final String ERR_UNABLE_TO_RESOLVE_CLASS =
        "Referencing class '%2$s': unable to resolve class";
    private static final String ERR_ILLEGAL_ANONYMOUS_INNER_CLASS =
        "Referencing class '%2$s': JSNI references to anonymous classes are illegal";
    private static final String ERR_ILLEGAL_PARAMETER =
        "Parameter %8$d of method '%2$s.%3$s': type '%9$s' may not be passed out of JSNI code";
    private static final String ERR_ILLEGAL_RETURN_TYPE =
        "Referencing method '%2$s.%3$s': return type '%8$s' is not safe to access in JSNI code";
    private static final String ERR_MISSING_QUALIFIER_INSTANCE_METHOD =
        "Missing qualifier on instance method '%2$s.%3$s'";
    private static final String ERR_UNNECESSARY_QUALIFIER_STATIC_METHOD =
        "Unnecessary qualifier on static method '%2$s.%3$s'";
    private static final String ERR_MISSING_QUALIFIER_INSTANCE_FIELD =
        "Missing qualifier on instance field '%2$s.%3$s'";
    private static final String ERR_UNNECESSARY_QUALIFIER_STATIC_FIELD =
        "Unnecessary qualifier on static field '%2$s.%3$s'";
    private static final String ERR_ILLEGAL_ASSIGNMENT_TO_METHOD =
        "Illegal assignment to method '%2$s.%3$s'";
    private static final String ERR_UNABLE_TO_RESOLVE_METHOD =
        "Referencing method '%2$s.%4$s': unable to resolve method in class '%6$s'";
    private static final String ERR_UNABLE_TO_RESOLVE_FIELD =
        "Referencing field '%2$s.%4$s': unable to resolve field in class '%6$s'";
    private static final String ERR_AMBIGUOUS_WILDCARD_MATCH =
        "Referencing method '%2$s.%4$s': ambiguous wildcard match; "
            + "both '%8$s' and '%9$s' match";
    private static final String ERR_UNSAFE_FIELD_ACCESS =
        "Referencing field '%2$s.%3$s': type '%8$s' is not safe to access in JSNI code";
    private static final String ERR_ILLEGAL_ASSIGNMENT_TO_COMPILE_TIME_CONSTANT =
        "Illegal assignment to compile-time constant '%2$s.%3$s'";
    private static final String ERR_MALFORMED_JSNI_IDENTIFIER =
        "Malformed JSNI identifier '%8$s'";
    private static final String WARN_DEPRECATED_CLASS =
        "Referencing deprecated class '%2$s'";
    private static final String WARN_DEPRECATED_METHOD =
        "Referencing method '%2$s.%3$s': method '%6$s.%7$s' is deprecated";
    private static final String WARN_DEPRECATED_FIELD =
        "Referencing field '%2$s.%3$s': field '%6$s.%7$s' is deprecated";

    /**
     * Formats messages for {@link #emitError} and {@link #emitWarning}, substituting as follows:
     * <ul>
     * <li> %1$s -> full original jsni string </li>
     * <li> %2$s -> full original jsni classname </li>
     * <li> %3$s -> full original jsni membername </li>
     * <li> %4$s -> full original jsni memberspec </li>
     * <li> %5$s -> full resolved jsni string </li>
     * <li> %6$s -> full resolved jsni classname </li>
     * <li> %7$s -> full resolved jsni member with signature </li>
     * </ul>
     */
    private String formatMessage(String msg, JsniRef jsniRef, Object... extraPars) {
      Object[] formatParameters = new Object[extraPars.length + 7];
      if (jsniRef != null) {
        formatParameters[0] = jsniRef.toString();
        formatParameters[1] = jsniRef.fullClassName();
        formatParameters[2] = jsniRef.memberName();
        formatParameters[3] = jsniRef.memberSignature();
        formatParameters[4] = jsniRef.getResolvedReference();
        formatParameters[5] = jsniRef.getFullResolvedClassName();
        formatParameters[6] = jsniRef.getResolvedMemberSignature();
      }

      for (int i = 0; i < extraPars.length; i++) {
        formatParameters[i + 7] = extraPars[i];
      }

      return String.format(msg, formatParameters);
    }


    private void emitError(String msg, SourceInfo errorInfo, JsniRef jsniRef, Object... extraPars) {
      JsniMethodCollector.reportJsniError(errorInfo, method, formatMessage(msg, jsniRef, extraPars));
    }

    private void emitWarning(String category, String msg, SourceInfo errorInfo, JsniRef jsniRef,
        Object... extraPars) {
      for (Set<String> suppressWarnings : suppressWarningsStack) {
        if (suppressWarnings.contains(category)
            || suppressWarnings.contains("all")) {
          return;
        }
      }
      JsniMethodCollector
          .reportJsniWarning(errorInfo, method, formatMessage(msg, jsniRef, extraPars));
    }

    private ReferenceBinding findClass(String className) {
      ReferenceBinding binding = typeResolver.resolveType(className);
      assert !(binding instanceof ProblemReferenceBinding);
      assert !(binding instanceof UnresolvedReferenceBinding);
      return binding;
    }

    private FieldBinding getField(ReferenceBinding clazz, JsniRef jsniRef) {
      assert jsniRef.isField();
      return clazz.getField(jsniRef.memberName().toCharArray(), false);
    }

    private MethodBinding getMatchingConstructor(ReferenceBinding clazz, JsniRef jsniRef) {
      for (MethodBinding constructorBinding : clazz.getMethods(INIT_CTOR_CHARS)) {
        StringBuilder methodSig = new StringBuilder();
        if (clazz instanceof NestedTypeBinding) {
          // Match synthetic args for enclosing instances.
          NestedTypeBinding nestedBinding = (NestedTypeBinding) clazz;
          if (nestedBinding.enclosingInstances != null) {
            for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
              SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
              methodSig.append(arg.type.signature());
            }
          }
        }
        if (constructorBinding.parameters != null) {
          for (TypeBinding binding : constructorBinding.parameters) {
            methodSig.append(binding.signature());
          }
        }
        if (methodSig.toString().equals(jsniRef.paramTypesString())) {
          return constructorBinding;
        }
      }
      return null;
    }

    /**
     * Returns true if {@code method}, is a method in {@code jsniClassQualifier} (to support current
     * private method access} or is a visible method in the super class per Java import rules.
     */
    private boolean isMethodVisibleToJsniRef(ReferenceBinding jsniClassQualifier,
        MethodBinding targetMethod) {
      return
          // All methods are visible (regardless of access) as long as the JSNI class reference is
          // explicit.
          jsniClassQualifier == targetMethod.declaringClass ||
          // All public superclass methods are visible.
          targetMethod.isPublic()
          // Protected and package private are visible from the same package.
          || !targetMethod.isPrivate() && method.binding.declaringClass.getPackage() ==
          targetMethod.declaringClass.getPackage()
          // Protected super class methods are visible from any subclass.
          || targetMethod.isProtected() &&
          targetMethod.declaringClass.isSuperclassOf(method.binding.declaringClass);
    }

    private List<MethodBinding> getMatchingMethods(ReferenceBinding clazz, JsniRef jsniRef) {
      assert jsniRef.isMethod();
      List<MethodBinding> foundMethods = Lists.newArrayList();
      String methodName = jsniRef.memberName();
      if ("new".equals(methodName)) {
        MethodBinding constructorBinding = getMatchingConstructor(clazz, jsniRef);
        if (constructorBinding != null) {
          foundMethods.add(constructorBinding);
        }
      } else {
        Queue<ReferenceBinding> work = Lists.newLinkedList();
        work.add(clazz);
        while (!work.isEmpty()) {
          ReferenceBinding currentClass = work.remove();
          NEXT_METHOD:
          for (MethodBinding findMethod : currentClass.getMethods(methodName.toCharArray())) {
            if (!isMethodVisibleToJsniRef(clazz, findMethod)) {
              continue;
            }
            if (!paramTypesMatch(findMethod, jsniRef)) {
              continue;
            }
            for (MethodBinding alreadyFound : foundMethods) {
              // Only collect methods with different signatures (same signatures are overloads
              // hence they are ok.
              if (paramTypesMatch(alreadyFound, findMethod)) {
                break NEXT_METHOD;
              }
            }
            foundMethods.add(findMethod);
          }
          ReferenceBinding[] superInterfaces = currentClass.superInterfaces();
          if (superInterfaces != null) {
            work.addAll(Arrays.asList(superInterfaces));
          }
          ReferenceBinding superclass = currentClass.superclass();
          if (superclass != null) {
            work.add(superclass);
          }
        }
      }
      return foundMethods;
    }

    private boolean paramTypesMatch(MethodBinding method, JsniRef jsniRef) {
      if (jsniRef.matchesAnyOverload()) {
        return true;
      }
      StringBuilder methodSig = new StringBuilder();
      if (method.parameters != null) {
        for (TypeBinding binding : method.parameters) {
          methodSig.append(binding.signature());
        }
      }
      return methodSig.toString().equals(jsniRef.paramTypesString());
    }

    private boolean paramTypesMatch(MethodBinding thisMethod, MethodBinding thatMethod) {
      int thisParameterCount = thisMethod.parameters == null ? 0 : thisMethod.parameters.length;
      int thatParameterCount = thatMethod.parameters == null ? 0 : thatMethod.parameters.length;

      if (thisParameterCount != thatParameterCount) {
        return false;
      }

      for (int i = 0; i < thisParameterCount; i++) {
        TypeBinding thisBinding = thisMethod.parameters[i];
        TypeBinding thatBinding = thatMethod.parameters[i];
        if (!new String(thisBinding.signature()).equals(new String(thatBinding.signature()))) {
          return false;
        }
      }
      return true;
    }

    private String typeString(TypeBinding type) {
      return String.valueOf(type.shortReadableName());
    }
  }

  private static final char[] INIT_CTOR_CHARS = "<init>".toCharArray();

  private static final char[][] UNSAFE_LONG_ANNOTATION_CHARS = CharOperation.splitOn(
      '.', UnsafeNativeLong.class.getName().toCharArray());

  /**
   * Resolve JSNI references in an entire
   * {@link org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration}.
   */
  public static void resolve(CompilationUnitDeclaration cud,
      List<ImportReference> cudOriginalImports,
      Map<MethodDeclaration, JsniMethod> jsniMethods,
      Map<String, Binding> jsniRefs, TypeResolver typeResolver) {
    new JsniReferenceResolver(cud, cudOriginalImports, typeResolver, jsniMethods, jsniRefs)
        .resolve();
  }

  private final CompilationUnitDeclaration cud;
  private final List<ImportReference> cudImports;
  private final Map<MethodDeclaration, JsniMethod> jsniMethods;
  private final Map<String, Binding> jsniRefs;
  private final Stack<Set<String>> suppressWarningsStack = new Stack<Set<String>>();
  private final TypeResolver typeResolver;

  private JsniReferenceResolver(CompilationUnitDeclaration cud, List<ImportReference> cudImports,
      TypeResolver typeResolver, Map<MethodDeclaration, JsniMethod> jsniMethods,
      Map<String, Binding> jsniRefs) {
    this.cud = cud;
    this.cudImports = cudImports;
    this.typeResolver = typeResolver;
    this.jsniMethods = jsniMethods;
    this.jsniRefs = jsniRefs;
  }

  private void resolve() {
    // First resolve the declarations.
    cud.traverse(new JsniDeclChecker(), cud.scope);
  }

  /**
   * Check whether the argument type is the <code>long</code> primitive type. If
   * the argument is <code>null</code>, returns <code>false</code>.
   */
  private boolean containsLong(TypeBinding type) {
    if (!(type instanceof BaseTypeBinding)) {
      return false;
    }

    BaseTypeBinding btb = (BaseTypeBinding) type;
    if (btb.id == TypeIds.T_long) {
        return true;
    }

    return false;
  }

  private boolean hasUnsafeLongsAnnotation(MethodDeclaration meth,
      ClassScope scope) {
    if (meth.annotations == null) {
      return false;
    }

    for (Annotation annot : meth.annotations) {
      if (isUnsafeLongAnnotation(annot, scope)) {
        return true;
      }
    }
    return false;
  }

  private boolean isUnsafeLongAnnotation(Annotation annot, ClassScope scope) {
    if (annot.type == null) {
      return false;
    }

    TypeBinding resolved = annot.type.resolveType(scope);
    if (resolved == null || !(resolved instanceof ReferenceBinding)) {
      return false;
    }

    ReferenceBinding rb = (ReferenceBinding) resolved;
    if (CharOperation.equals(rb.compoundName, UNSAFE_LONG_ANNOTATION_CHARS)) {
      return true;
    }
    return false;
  }

  private void longAccessError(ASTNode node, String message) {
    GWTProblem.recordError(node, cud, message, new InstalledHelpInfo(
        "longJsniRestriction.html"));
  }

  private static void resolveJsniRef(JsniRef jsniRef, FieldBinding fieldBinding) {
    if (fieldBinding  == null) {
      return;
    }
    jsniRef.setResolvedClassName(JdtUtil.getSourceName(fieldBinding.declaringClass));
    jsniRef.setResolvedMemberWithSignature(new String(fieldBinding.name));
  }

  private static void resolveJsniRef(JsniRef jsniRef, MethodBinding methodBinding) {
    if (methodBinding  == null) {
      return;
    }
    ReferenceBinding declaringClassBinding = methodBinding.declaringClass;

    jsniRef.setResolvedClassName(JdtUtil.getSourceName(declaringClassBinding));
    jsniRef.setResolvedMemberWithSignature(JdtUtil.formatMethodSignature(methodBinding));
  }
}
