/*
 * Copyright 2010 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.jjs.impl;

import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;

import java.util.List;

/**
 * This class will identify instances of an implicit upcast between
 * non-primitive types, and call the overridable processImplicitUpcast method.
 * 
 * TODO(jbrosenberg): Consider extending to handle implicit upcasts between
 * primitive types. This is not as straightforward as for reference types,
 * because primitives can be boxed and unboxed implicitly as well.
 */
public class ImplicitUpcastAnalyzer extends JVisitor {

  protected JMethod currentMethod;
  private final JType javaScriptObjectType;
  private final JType nullType;
  private final JType throwableType;

  public ImplicitUpcastAnalyzer(JProgram program) {
    this.throwableType = program.getIndexedType("Throwable");
    this.javaScriptObjectType = program.getJavaScriptObject();
    this.nullType = program.getTypeNull();
  }

  @Override
  public void endVisit(JBinaryOperation x, Context ctx) {
    if (x.isAssignment()) {
      processIfTypesNotEqual(x.getRhs().getType(), x.getLhs().getType(), x.getSourceInfo());
    } else if (x.getRhs().getType() == nullType) {
      processIfTypesNotEqual(nullType, x.getLhs().getType(), x.getSourceInfo());
    } else if (x.getLhs().getType() == nullType) {
      processIfTypesNotEqual(nullType, x.getRhs().getType(), x.getSourceInfo());
    } else if (x.getOp() == JBinaryOperator.CONCAT || x.getOp() == JBinaryOperator.EQ
        || x.getOp() == JBinaryOperator.NEQ) {
      /*
       * Since we are not attempting to handle detection of upcasts between
       * primitive types, we limit handling here to CONCAT, EQ and NEQ. Need to
       * do both directions.
       */
      processIfTypesNotEqual(x.getLhs().getType(), x.getRhs().getType(), x.getSourceInfo());
      processIfTypesNotEqual(x.getRhs().getType(), x.getLhs().getType(), x.getSourceInfo());
    }
  }

  @Override
  public void endVisit(JConditional x, Context ctx) {
    processIfTypesNotEqual(x.getThenExpr().getType(), x.getType(), x.getSourceInfo());
    processIfTypesNotEqual(x.getElseExpr().getType(), x.getType(), x.getSourceInfo());
  }

  @Override
  public void endVisit(JDeclarationStatement x, Context ctx) {
    if (x.getInitializer() != null) {
      processIfTypesNotEqual(x.getInitializer().getType(), x.getVariableRef().getType(), x
          .getSourceInfo());
    }
  }

  @Override
  public void endVisit(JField x, Context ctx) {
    if (x.getInitializer() == null && !x.isFinal()) {
      if (!(x.getType() instanceof JPrimitiveType)) {
        // if it is declared without an initial value, it defaults to null
        processIfTypesNotEqual(nullType, x.getType(), x.getSourceInfo());
      }
    }
  }

  @Override
  public void endVisit(JMethod x, Context ctx) {
    // check for upcast in return type as compared to an overridden method
    List<JMethod> overrides = x.getOverrides();
    if (overrides != null && overrides.size() > 0) {
      // only check the first one, since other ones will be checked when those
      // overridden methods are visited, don't want to do redundant work
      processIfTypesNotEqual(x.getType(), overrides.get(0).getType(), x.getSourceInfo());
    }

    if (x.getBody() != null && x.getBody().isNative()) {
      /*
       * Check if this method has a native (jsni) method body, in which case all
       * arguments passed in are implicitly cast to JavaScriptObject
       */
      List<JParameter> params = x.getParams();
      for (int i = 0; i < params.size(); i++) {
        processIfTypesNotEqual(params.get(i).getType(), javaScriptObjectType, x.getSourceInfo());
      }

      /*
       * Check if this method has a non-void return type, in which case it will
       * be implicitly cast from JavaScriptObject
       */
      if (x.getType() != JPrimitiveType.VOID) {
        processIfTypesNotEqual(javaScriptObjectType, x.getType(), x.getSourceInfo());
      }
    }
  }

  @Override
  public void endVisit(JMethodCall x, Context ctx) {
    // check for upcast in argument passing
    List<JExpression> args = x.getArgs();
    List<JParameter> params = x.getTarget().getParams();

    for (int i = 0; i < args.size(); i++) {
      // make sure the param wasn't pruned
      if (i < params.size()) {
        processIfTypesNotEqual(args.get(i).getType(), params.get(i).getType(), x.getSourceInfo());
      }
    }
  }

  @Override
  public void endVisit(JNewArray x, Context ctx) {
    JType elementType = x.getArrayType().getElementType();
    if (x.initializers != null) {
      for (JExpression init : x.initializers) {
        processIfTypesNotEqual(init.getType(), elementType, x.getSourceInfo());
      }
    }
  }

  @Override
  public void endVisit(JReturnStatement x, Context ctx) {
    if (x.getExpr() != null) {
      // check against the current method return type
      processIfTypesNotEqual(x.getExpr().getType(), currentMethod.getType(), x.getSourceInfo());
    }
  }

  @Override
  public void endVisit(JsniMethodRef x, Context ctx) {
    // the return type of this method ref will be cast to JavaScriptObject
    if (x.getTarget().getType() != JPrimitiveType.VOID) {
      processIfTypesNotEqual(x.getTarget().getType(), javaScriptObjectType, x.getSourceInfo());
    }

    // check referenced method's params, which are passed as JavaScriptObjects
    List<JParameter> params = x.getTarget().getParams();
    for (int i = 0; i < params.size(); i++) {
      processIfTypesNotEqual(javaScriptObjectType, params.get(i).getType(), x.getSourceInfo());
    }
  }

  @Override
  public void endVisit(JThrowStatement x, Context ctx) {
    // all things thrown are upcast to a Throwable
    JType type = x.getExpr().getType();
    if (type instanceof JReferenceType) {
      type = ((JReferenceType) type).getUnderlyingType();
    }
    processIfTypesNotEqual(type, throwableType, x.getSourceInfo());
  }

  @Override
  public boolean visit(JMethod x, Context ctx) {
    // save this, so can use it later for checking JReturnStatement
    currentMethod = x;
    return true;
  }

  /**
   * An overriding method will be called for each detected implicit upcast.
   * 
   * @param fromType
   * @param destType
   */
  protected void processImplicitUpcast(JType fromType, JType destType, SourceInfo info) {
    // override
  }

  private void processIfTypesNotEqual(JType fromType, JType destType, SourceInfo info) {
    if (fromType != destType) {
      processImplicitUpcast(fromType, destType, info);
    }
  }
}
