Example usage for com.google.gwt.dev.jjs.ast JMethod getEnclosingType

List of usage examples for com.google.gwt.dev.jjs.ast JMethod getEnclosingType

Introduction

In this page you can find the example usage for com.google.gwt.dev.jjs.ast JMethod getEnclosingType.

Prototype

public JDeclaredType getEnclosingType() 

Source Link

Usage

From source file:xapi.dev.inject.MagicMethods.java

License:Open Source License

/**
 * Replaces a call from {@link X_Inject#singletonLazy(Class)} by first a-0) generating a provider which will
 * be synchronous if an async call hasn't already been made, or a-1) generating a provider which will route
 * through the async provider, and return null before inited. then b) returning a simple lazy provider which
 * will poll the actual provider until it is set. If you use the
 * {@link X_Inject#singletonAsync(Class, xapi.util.api.ReceivesValue)} once, you should not use the
 * other two synchronous provider methods, as they may return null if you happen to request them before the
 * code split containing the service is downloaded.
 *
 * @param logger - The logger to log to.
 * @param methodCall - The method call we are overwriting
 * @param currentMethod - The encapsulated method itself
 * @param context - The method call context, so you can insert clinits / whatnot
 * @param ast - A view over UnifyAst, exposing our basic needs
 * @return - A JExpression to replace this method call with
 * @throws UnableToCompleteException//ww  w .  j av  a2 s.co m
 */

public static JExpression rebindSingletonLazy(TreeLogger logger, JMethodCall x, JMethod currentMethod,
        Context context, UnifyAstView ast) throws UnableToCompleteException {
    assert (x.getArgs().size() == 1);
    JExpression arg = x.getArgs().get(0);
    if (!(arg instanceof JClassLiteral)) {
        ast.error(x, "Only class literals may be used as arguments to X_Inject.lazySingleton; you sent "
                + arg.getClass() + " - " + arg);
        return null;
    }
    JClassLiteral classLiteral = (JClassLiteral) arg;
    if (!(classLiteral.getRefType() instanceof JDeclaredType)) {
        ast.error(x, "Only classes and interfaces may be used as arguments to X_Inject.singletonLazy()");
        return null;
    }
    return injectLazySingleton(logger, classLiteral, x, currentMethod.getEnclosingType(), ast);
}

From source file:xapi.dev.inject.MagicMethods.java

License:Open Source License

private static JExpression injectInstance(TreeLogger logger, JClassLiteral classLiteral, JMethodCall x,
        JMethod method, UnifyAstView ast) throws UnableToCompleteException {
    JDeclaredType type = (JDeclaredType) classLiteral.getRefType();
    // JExpression expr = injectLazySingleton(logger, classLiteral, x, type, ast);
    // String[] names = type.getShortName().split("[$]");

    String instanceType = classLiteral.getRefType().getName();
    StandardGeneratorContext ctx = ast.getRebindPermutationOracle().getGeneratorContext();
    // make sure the requested interface is compiled for the generator
    ast.searchForTypeBySource(type.getName());
    JDeclaredType injectedInstance;/*from  www .j a v  a2s  .co  m*/
    try {
        // our hardcoded class is definitely a generator ;-}
        Class<? extends Generator> generator = InstanceInjectionGenerator.class;
        // creates the singleton and provider
        RebindResult result = ctx.runGeneratorIncrementally(logger, generator, type.getName());
        // commit the generator result, w/out updating rebind cache (to allow GWT.create() rebinds)
        ctx.finish(logger);
        // pull back the LazySingeton provider
        logger.log(logLevel(), "Loading injected result: " + result.getResultTypeName());
        injectedInstance = ast.searchForTypeBySource(result.getResultTypeName());
        // sanity check
        if (injectedInstance == null) {
            ast.error(x, "Rebind result '" + instanceType + "' could not be found");
            throw new InternalCompilerException("Unable to generate instance provider");
        }
    } catch (UnableToCompleteException e) {
        logger.log(Type.ERROR, "Error trying to generate provider for " + type.getName() + ". "
                + "\nPlease make sure this class is non-abstract, or that a concrete class on the classpath "
                + "is annotated with @SingletonOverride or @SingletonDefault", e);
        ast.error(x, "Rebind result '" + instanceType + "' could not be found");
        throw new InternalCompilerException("Unable to generate instance provider");
    }
    if (!(injectedInstance instanceof JClassType)) {
        ast.error(x, "Rebind result '" + instanceType + "' must be a class");
        throw new InternalCompilerException("Unable to generate instance provider");
    }
    if (injectedInstance.isAbstract()) {
        ast.error(x, "Rebind result '" + instanceType + "' cannot be abstract");
        throw new InternalCompilerException("Unable to generate instance provider");
    }
    // now that we have our injected answer,
    // let's run it through normal gwt deferred binding as well

    // copied from UnifyAst#handleGwtCreate
    String reqType = BinaryName.toSourceName(injectedInstance.getName());
    List<String> answers;
    try {
        answers = Lists.create(ast.getRebindPermutationOracle().getAllPossibleRebindAnswers(logger, reqType));
        ast.getRebindPermutationOracle().getGeneratorContext().finish(logger);
    } catch (UnableToCompleteException e) {
        ast.error(x, "Failed to resolve '" + reqType + "' via deferred binding");
        return null;
    }
    ArrayList<JExpression> instantiationExpressions = new ArrayList<JExpression>(answers.size());
    for (String answer : answers) {
        JDeclaredType answerType = ast.searchForTypeBySource(answer);
        if (answerType == null) {
            ast.error(x, "Rebind result '" + answer + "' could not be found");
            return null;
        }
        if (!(answerType instanceof JClassType)) {
            ast.error(x, "Rebind result '" + answer + "' must be a class");
            return null;
        }
        if (answerType.isAbstract()) {
            ast.error(x, "Rebind result '" + answer + "' cannot be abstract");
            return null;
        }
        JDeclaredType enclosing = injectedInstance.getEnclosingType();
        if (enclosing == null) {
            enclosing = method.getEnclosingType();
        }
        JExpression result = JGwtCreate.createInstantiationExpression(x.getSourceInfo(),
                (JClassType) answerType);
        if (result == null) {
            ast.error(x, "Rebind result '" + answer + "' has no default (zero argument) constructors");
            return null;
        }
        instantiationExpressions.add(result);
    }
    assert answers.size() == instantiationExpressions.size();
    if (answers.size() == 1)
        return instantiationExpressions.get(0);
    else
        return new JGwtCreate(x.getSourceInfo(), reqType, answers, ast.getProgram().getTypeJavaLangObject(),
                instantiationExpressions);

    // TODO: cache each injection to detect the first time a class is injected,
    // then see if the given injection target is Preloadable,
    // so we can call it's clinit before it is ever accessed,
    // to reduce the bloat of clinits by visiting preloadable methods before
    // any client code can possibly access them (less clinit in runtime code)

}