/*
 * 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.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.util.InstalledHelpInfo;
import com.google.gwt.dev.util.JsniRef;
import com.google.gwt.dev.util.collect.Sets;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
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.lookup.BaseTypeBinding;
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.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;

/**
 * Tests for access to Java from JSNI. Issues a warning for:
 * <ul>
 * <li>JSNI methods with a parameter or return type of long.</li>
 * <li>Access from JSNI to a field whose type is long.</li>
 * <li>Access from JSNI to a method with a parameter or return type of long.</li>
 * <li>JSNI references to anonymous classes.</li>
 * </ul>
 * All tests also apply for arrays of longs, arrays of arrays of longs, etc.
 */
public class JsniChecker {

  /**
   * A call-back interface to resolve types.
   */
  public interface TypeResolver {
    ReferenceBinding resolveType(String typeName);
  }

  private class JsniDeclChecker extends SafeASTVisitor implements
      ClassFileConstants {
    @Override
    public void endVisit(MethodDeclaration meth, ClassScope scope) {
      if (meth.isNative()) {
        boolean hasUnsafeLongsAnnotation = hasUnsafeLongsAnnotation(meth, scope);
        if (!hasUnsafeLongsAnnotation) {
          checkDecl(meth, scope);
        }
        JsniMethod jsniMethod = jsniMethods.get(meth);
        if (jsniMethod != null) {
          new JsniRefChecker(meth, hasUnsafeLongsAnnotation).check(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(getSuppressedWarnings(meth.annotations));
      return true;
    }

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

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

    @Override
    public boolean visitValid(TypeDeclaration typeDeclaration, BlockScope scope) {
      suppressWarningsStack.push(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) {
        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
          && JsniChecker.this.containsLong(type.resolveType(scope));
    }

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

  private class JsniRefChecker extends JsVisitor {

    private transient SourceInfo errorInfo;
    private final boolean hasUnsafeLongsAnnotation;
    private final MethodDeclaration method;

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

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

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      this.errorInfo = x.getSourceInfo();
      String ident = x.getIdent();
      if (ident.charAt(0) == '@') {
        JsniRef jsniRef = JsniRef.parse(ident);
        if (jsniRef == null) {
          emitError("Malformed JSNI identifier '" + ident + "'");
        } else {
          checkRef(jsniRef);
        }
      }
      this.errorInfo = null;
    }

    private void checkFieldRef(ReferenceBinding clazz, JsniRef jsniRef) {
      assert jsniRef.isField();
      if ("class".equals(jsniRef.memberName())) {
        return;
      }
      FieldBinding target = getField(clazz, jsniRef);
      if (target == null) {
        emitWarning("jsni", "Referencing field '" + jsniRef.className() + "."
            + jsniRef.memberName()
            + "': unable to resolve field, expect subsequent failures");
        return;
      }
      if (target.isDeprecated()) {
        emitWarning("deprecation", "Referencing deprecated field '"
            + jsniRef.className() + "." + jsniRef.memberName() + "'");
      }

      if (hasUnsafeLongsAnnotation) {
        return;
      }
      if (containsLong(target.type)) {
        emitError("Referencing field '" + jsniRef.className() + "."
            + jsniRef.memberName() + "': type '" + typeString(target.type)
            + "' is not safe to access in JSNI code");
      }
    }

    private void checkMethodRef(ReferenceBinding clazz, JsniRef jsniRef) {
      assert jsniRef.isMethod();
      MethodBinding target = getMethod(clazz, jsniRef);
      if (target == null) {
        emitWarning("jsni", "Referencing method '" + jsniRef.className() + "."
            + jsniRef.memberSignature()
            + "': unable to resolve method, expect subsequent failures");
        return;
      }
      if (target.isDeprecated()) {
        emitWarning("deprecation", "Referencing deprecated method '"
            + jsniRef.className() + "." + jsniRef.memberName() + "'");
      }

      if (hasUnsafeLongsAnnotation) {
        return;
      }
      if (containsLong(target.returnType)) {
        emitError("Referencing method '" + jsniRef.className() + "."
            + jsniRef.memberName() + "': return type '"
            + typeString(target.returnType)
            + "' is not safe to access in JSNI code");
      }

      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("Parameter " + i + " of method '" + jsniRef.className()
                + "." + jsniRef.memberName() + "': type '"
                + typeString(paramType)
                + "' may not be passed out of JSNI code");
          }
        }
      }
    }

    private void checkRef(JsniRef jsniRef) {
      String className = jsniRef.className();
      if ("null".equals(className)) {
        return;
      }

      boolean isArray = false;
      while (className.endsWith("[]")) {
        isArray = true;
        className = className.substring(0, className.length() - 2);
      }

      /*
       * TODO(bobv): OMG WTF LOL. Okay, but seriously, the LHS of a JSNI ref for
       * a primitive type should be the keyword, e.g. "int.class".
       */
      ReferenceBinding clazz = findClass(className);
      boolean isPrimitive = (clazz == null) && className.length() == 1
          && "ZBCDFIJSV".indexOf(className.charAt(0)) >= 0;

      if (isArray || isPrimitive) {
        if (!jsniRef.isField() || !jsniRef.memberName().equals("class")) {
          emitError("Referencing member '" + jsniRef.className() + "."
              + jsniRef.memberName()
              + "': 'class' is the only legal reference for "
              + (isArray ? "array" : "primitive") + " types");
          return;
        }
      }

      if (isPrimitive) {
        return;
      }

      // TODO(bobv): uncomment this.
      // ReferenceBinding clazz = findClass(className);
      if (looksLikeAnonymousClass(jsniRef)
          || (clazz != null && clazz.isAnonymousType())) {
        emitError("Referencing class '" + className
            + ": JSNI references to anonymous classes are illegal");
      } else if (clazz != null) {
        if (clazz.isDeprecated()) {
          emitWarning("deprecation", "Referencing deprecated class '"
              + className + "'");
        }

        if (jsniRef.isMethod()) {
          checkMethodRef(clazz, jsniRef);
        } else {
          checkFieldRef(clazz, jsniRef);
        }
      } else {
        emitWarning("jsni", "Referencing class '" + className
            + "': unable to resolve class, expect subsequent failures");
      }
    }

    private void emitError(String msg) {
      JsniCollector.reportJsniError(errorInfo, method, msg);
    }

    private void emitWarning(String category, String msg) {
      for (Set<String> suppressWarnings : suppressWarningsStack) {
        if (suppressWarnings.contains(category)
            || suppressWarnings.contains("all")) {
          return;
        }
      }
      JsniCollector.reportJsniWarning(errorInfo, method, msg);
    }

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

    private char[][] getCompoundName(JsniRef jsniRef) {
      String className = jsniRef.className().replace('$', '.');
      char[][] compoundName = CharOperation.splitOn('.',
          className.toCharArray());
      return compoundName;
    }

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

    private MethodBinding getMethod(ReferenceBinding clazz, JsniRef jsniRef) {
      assert jsniRef.isMethod();
      String methodName = jsniRef.memberName();
      if ("new".equals(methodName)) {
        for (MethodBinding findMethod : 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 (findMethod.parameters != null) {
            for (TypeBinding binding : findMethod.parameters) {
              methodSig.append(binding.signature());
            }
          }
          if (methodSig.toString().equals(jsniRef.paramTypesString())) {
            return findMethod;
          }
        }
      } else {
        Queue<ReferenceBinding> work = new LinkedList<ReferenceBinding>();
        work.add(clazz);
        while (!work.isEmpty()) {
          clazz = work.remove();
          for (MethodBinding findMethod : clazz.getMethods(methodName.toCharArray())) {
            if (paramTypesMatch(findMethod, jsniRef)) {
              return findMethod;
            }
          }
          ReferenceBinding[] superInterfaces = clazz.superInterfaces();
          if (superInterfaces != null) {
            work.addAll(Arrays.asList(superInterfaces));
          }
          ReferenceBinding superclass = clazz.superclass();
          if (superclass != null) {
            work.add(superclass);
          }
        }
      }
      return null;
    }

    private boolean looksLikeAnonymousClass(JsniRef jsniRef) {
      char[][] compoundName = getCompoundName(jsniRef);
      for (char[] part : compoundName) {
        if (Character.isDigit(part[0])) {
          return true;
        }
      }
      return false;
    }

    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 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());

  /**
   * Checks an entire
   * {@link org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration}.
   * 
   */
  public static void check(CompilationUnitDeclaration cud,
      Map<AbstractMethodDeclaration, JsniMethod> jsniMethods,
      TypeResolver typeResolver) {
    new JsniChecker(cud, typeResolver, jsniMethods).check();
  }

  static Set<String> getSuppressedWarnings(Annotation[] annotations) {
    if (annotations != null) {
      for (Annotation a : annotations) {
        if (SuppressWarnings.class.getName().equals(
            CharOperation.toString(((ReferenceBinding) a.resolvedType).compoundName))) {
          for (MemberValuePair pair : a.memberValuePairs()) {
            if (String.valueOf(pair.name).equals("value")) {
              Expression valueExpr = pair.value;
              if (valueExpr instanceof StringLiteral) {
                // @SuppressWarnings("Foo")
                return Sets.create(((StringLiteral) valueExpr).constant.stringValue().toLowerCase(
                    Locale.ENGLISH));
              } else if (valueExpr instanceof ArrayInitializer) {
                // @SuppressWarnings({ "Foo", "Bar"})
                ArrayInitializer ai = (ArrayInitializer) valueExpr;
                String[] values = new String[ai.expressions.length];
                for (int i = 0, j = values.length; i < j; i++) {
                  values[i] = ((StringLiteral) ai.expressions[i]).constant.stringValue().toLowerCase(
                      Locale.ENGLISH);
                }
                return Sets.create(values);
              } else {
                throw new InternalCompilerException(
                    "Unable to analyze SuppressWarnings annotation");
              }
            }
          }
        }
      }
    }
    return Sets.create();
  }

  private final CompilationUnitDeclaration cud;
  private final Map<AbstractMethodDeclaration, JsniMethod> jsniMethods;
  private final Stack<Set<String>> suppressWarningsStack = new Stack<Set<String>>();
  private final TypeResolver typeResolver;

  private JsniChecker(CompilationUnitDeclaration cud,
      TypeResolver typeResolver,
      Map<AbstractMethodDeclaration, JsniMethod> jsniMethods) {
    this.cud = cud;
    this.typeResolver = typeResolver;
    this.jsniMethods = jsniMethods;
  }

  private void check() {
    // First check 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) {
      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) {
      for (Annotation annot : meth.annotations) {
        if (isUnsafeLongAnnotation(annot, scope)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean isUnsafeLongAnnotation(Annotation annot, ClassScope scope) {
    if (annot.type != null) {
      TypeBinding resolved = annot.type.resolveType(scope);
      if (resolved != null) {
        if (resolved instanceof ReferenceBinding) {
          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"));
  }
}
