All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.reflect.rebind.generators.FieldGenerator Maven / Gradle / Ivy

package com.google.gwt.reflect.rebind.generators;

import java.util.List;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.jjs.MagicMethodGenerator;
import com.google.gwt.dev.jjs.UnifyAstView;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.reflect.rebind.ReflectionManifest;
import com.google.gwt.reflect.rebind.ReflectionUtilAst;
import com.google.gwt.reflect.rebind.ReflectionUtilType;

public abstract class FieldGenerator extends MemberGenerator implements MagicMethodGenerator {

  protected abstract boolean isDeclared();

  protected JMethodCall getFactoryMethod(TreeLogger logger, JMethodCall callSite,
      JMethod enclosingMethod, Context context, JClassLiteral classLit, JExpression inst, JExpression arg0, UnifyAstView ast)
          throws UnableToCompleteException {

    if (classLit == null) {
      if (logger.isLoggable(logLevel()))
        logger.log(logLevel(),
            "Non-final class literal used to invoke reflection field; "
                + ReflectionUtilAst.debug(callSite.getInstance()));
      return checkConstPool(ast, callSite, inst, arg0);
    }
    
    JStringLiteral stringLit = ReflectionUtilAst.extractImmutableNode(logger, JStringLiteral.class, arg0, ast, false);
    if (stringLit == null) {
      if (logger.isLoggable(logLevel()))
        logger.log(logLevel(),
            "Non-final string arg used to retrieve reflection field; "
                + ReflectionUtilAst.debug(arg0));
      return checkConstPool(ast, callSite, inst, arg0);
    }
    String name = stringLit.getValue();
    
    // We got all our literals; the class, method name and parameter classes
    // now get the requested method

    JType ref = classLit.getRefType();
    JClassType oracleType = ast.getTypeOracle().findType(ref.getName().replace('$', '.'));
    com.google.gwt.core.ext.typeinfo.JField field = 
        ReflectionUtilType.findField(logger, oracleType, name, isDeclared()); 
    
    if (field == null) {
      // We fail here because the requested method is not findable.
      if (shouldFailIfMissing(logger, ast, classLit)) {
        logger.log(Type.ERROR, "Unable to find field " + oracleType.getQualifiedSourceName()+"."+name+ ";");
        logger.log(Type.ERROR, "Did you forget to call StandardGeneratorContext.finish()?");
        throw new UnableToCompleteException();
      } else {
        return checkConstPool(ast, callSite, inst, arg0);
      }
    }
    if (logger.isLoggable(logLevel())) {
      logger.log(logLevel(), "Found injectable field " + field);
    }
    
    // now, get or make a handle to the requested method,
    return getFieldProvider(logger, ast, field, classLit, isDeclared());
  }
  
  @Override
  public JExpression injectMagic(TreeLogger logger, JMethodCall callSite,
      JMethod enclosingMethod, Context context, UnifyAstView ast)
      throws UnableToCompleteException {
    
    boolean isFromGwtReflect = callSite.getArgs().size() == 2;
    JExpression inst = isFromGwtReflect ? callSite.getArgs().get(0) : callSite.getInstance();
    JClassLiteral classLit = ReflectionUtilAst.extractClassLiteral(logger, inst, ast, false);
    List args = callSite.getArgs();
    JExpression arg0 = args.get(isFromGwtReflect?1:0);
    
    // and return a call to the generated Method provider
    return 
        getFactoryMethod(logger, callSite, enclosingMethod, context, classLit, inst, arg0, ast)
        .makeStatement().getExpr();
  }
  
  public JMethodCall getFieldProvider(TreeLogger logger, UnifyAstView ast, com.google.gwt.core.ext.typeinfo.JField field,
      JClassLiteral classLit, boolean declaredOnly) throws UnableToCompleteException {
    String clsName = classLit.getRefType().getName();
    ReflectionManifest manifest = ReflectionManifest.getReflectionManifest(logger, clsName, ast.getGeneratorContext());
    String factoryCls = getOrMakeFieldFactory(logger, ast.getRebindPermutationOracle().getGeneratorContext(), field, field.getEnclosingType(), manifest, declaredOnly);
    ast.getGeneratorContext().finish(logger);
    JDeclaredType factory = ast.searchForTypeBySource(factoryCls);
    // pull out the static accessor method
    for (JMethod factoryMethod : factory.getMethods()) {
      if (factoryMethod.isStatic() && factoryMethod.getName().equals("instantiate")) {
        return new JMethodCall(factoryMethod.getSourceInfo(), null, factoryMethod);
      }
    }
    logger.log(Type.ERROR, "Unable to find static initializer for Field subclass "+factoryCls);
    throw new UnableToCompleteException();
  }
  
  public String getOrMakeFieldFactory(TreeLogger logger, GeneratorContext ctx, com.google.gwt.core.ext.typeinfo.JField field,
      com.google.gwt.core.ext.typeinfo.JType classType, ReflectionManifest manifest, boolean declaredOnly) throws UnableToCompleteException {
    // get cached manifest for this type
    String clsName = classType.getQualifiedSourceName();
    TypeOracle oracle = ctx.getTypeOracle();
    String name = field.getName();
    JClassType cls = oracle.findType(clsName);
    if (cls == null) {
      logger.log(Type.ERROR, "Unable to find enclosing class "+clsName);
      throw new UnableToCompleteException();
    }
      
    String fieldFactoryName = getFieldFactoryName(cls, name);
    JClassType factory;
    String pkgName = field.getEnclosingType().getPackage().getName();
    factory = oracle.findType(pkgName, fieldFactoryName);
    if (factory == null) {
      return generateFieldFactory(logger, ctx, field, fieldFactoryName, manifest);
    } else 
      return (pkgName.length()==0?"":pkgName+".")+ fieldFactoryName;
  }

  @Override
  protected String memberGetter() {
    return "get"+(isDeclared()?"Declared":"")+"Field";
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy