List of usage examples for com.google.gwt.dev.jjs.ast JClassLiteral getRefType
public JType getRefType()
From source file:xapi.dev.inject.MagicMethods.java
License:Open Source License
private static JDeclaredType injectSingletonAsync(TreeLogger logger, JClassLiteral classLiteral, JMethodCall methodCall, UnifyAstView ast) throws UnableToCompleteException { JDeclaredType type = (JDeclaredType) classLiteral.getRefType(); String[] names = type.getShortName().split("[$]"); // TODO: stop stripping the enclosing class name (need to update generators) // String reqType = JGwtCreate.nameOf(type); String answer = classLiteral.getRefType().getName(); answer = answer.substring(0, answer.lastIndexOf('.') + 1) + "impl.AsyncFor_" + names[names.length - 1]; JDeclaredType answerType = null;// w ww.j a v a 2 s. c o m JDeclaredType knownType = ast.getProgram().getFromTypeMap(answer); if (knownType != null) return ast.searchForTypeBySource(answer); else {// we need to generate the singleton on the fly, without updating rebind cache StandardGeneratorContext ctx = ast.getRebindPermutationOracle().getGeneratorContext(); // make sure the requested interface is compiled for the generator ast.searchForTypeBySource(type.getName()); try { // our hardcoded class is definitely a generator ;-} Class<? extends Generator> generator = AsyncInjectionGenerator.class; // (Class<? extends Generator>) Class // .forName("xapi.dev.generators.AsyncInjectionGenerator"); // creates the singleton and provider RebindResult rebindResult = 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 answerType = ast.searchForTypeBySource(rebindResult.getResultTypeName()); // sanity check if (answerType == null) { ast.error(methodCall, "Rebind result '" + answer + "' could not be found. Please be sure that " + type.getName() + " has a subclass on the classpath which contains @SingletonOverride or @SingletonDefault annotations."); throw new UnableToCompleteException(); } } catch (UnableToCompleteException e) { logger.log(Type.ERROR, "Error trying to generator 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(methodCall, "Rebind result '" + answer + "' could not be found"); throw new UnableToCompleteException(); } } if (!(answerType instanceof JClassType)) { ast.error(methodCall, "Rebind result '" + answer + "' must be a class"); throw new UnableToCompleteException(); } if (answerType.isAbstract()) { ast.error(methodCall, "Rebind result '" + answer + "' cannot be abstract"); throw new UnableToCompleteException(); } logger.log(logLevel(), "Injecting asynchronous singleton for " + type.getName() + " -> " + answerType); return answerType; }
From source file:xapi.dev.inject.MagicMethods.java
License:Open Source License
/** * Replaces a call from {@link X_Inject#singletonAsync(Class, xapi.util.api.ReceivesValue)} by first a) * generating an async provider, and then b) sending the value receiver into the async provider as a * callback. See the {@link AsyncProxy} class and {@link AsyncInjectionGenerator} for implementation. * * @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/*www . j a v a 2 s . c o m*/ */ public static JExpression rebindSingletonAndCallback(TreeLogger logger, JMethodCall methodCall, JMethod currentMethod, Context context, UnifyAstView ast) throws UnableToCompleteException { assert (methodCall.getArgs().size() == 2); JExpression classParam = methodCall.getArgs().get(0); JExpression receiveParam = methodCall.getArgs().get(1); if (!(classParam instanceof JClassLiteral)) { ast.error(methodCall, "Only class literals may be used as arguments to X_Inject.singletonAsync; you sent " + classParam.getClass() + " - " + classParam); return null; } logger.log(logLevel(), receiveParam.toString() + " : " + receiveParam.getClass() + " : " + receiveParam.toSource()); JClassLiteral classLiteral = (JClassLiteral) classParam; JClassLiteral receiverLiteral = (JClassLiteral) receiveParam; JDeclaredType type = (JDeclaredType) classLiteral.getRefType(); String[] names = type.getShortName().split("[$]"); // TODO: stop stripping the enclosing class name (need to update generators) // String reqType = JGwtCreate.nameOf(type); String answer = receiverLiteral.getRefType().getName(); answer = answer.substring(0, answer.lastIndexOf('.') + 1) + "impl.AsyncProxy_" + names[names.length - 1]; JDeclaredType answerType = null; JDeclaredType knownType = ast.getProgram().getFromTypeMap(answer); // ensure we have a service provider JDeclaredType provider = injectSingletonAsync(logger, classLiteral, methodCall, ast); StandardGeneratorContext ctx = ast.getRebindPermutationOracle().getGeneratorContext(); // ctx.finish(logger); if (knownType != null) {// if the singleton already exists, just use it answerType = ast.searchForTypeBySource(answer); // result = // JGwtCreate.createInstantiationExpression(methodCall.getSourceInfo(), (JClassType) answerType, // currentMethod.getEnclosingType()); } else {// we need to generate the singleton on the fly, without updating rebind cache // make sure the requested interface is compiled for the generator logger.log(logLevel(), "Rebinding singleton w/ callback: " + type + " -> " + provider.getName()); ast.searchForTypeBySource(type.getName()); ast.searchForTypeBySource(BinaryName.toSourceName(provider.getName())); try { InjectionCallbackArtifact rebindResult; try { logger.log(logLevel(), "Loading injected result: " + provider.getName()); rebindResult = AsyncProxyGenerator.setupAsyncCallback(logger, ctx, ctx.getTypeOracle().findType(BinaryName.toSourceName(type.getName())), ((JDeclaredType) receiverLiteral.getRefType())); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new UnableToCompleteException(); } // creates the singleton and provider // RebindResult rebindResult = // 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 answerType = ast.searchForTypeBySource(rebindResult.getAsyncInjectionName()); // sanity check if (answerType == null) { ast.error(methodCall, "Rebind result '" + answer + "' could not be found. Please be sure that " + type.getName() + " has a subclass on the classpath which contains @SingletonOverride or @SingletonDefault annotations."); return null; } } catch (UnableToCompleteException e) { logger.log(Type.ERROR, "Error trying to generator 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(methodCall, "Rebind result '" + answer + "' could not be found"); return null; } } for (JMethod method : answerType.getMethods()) { if (method.getName().equals("go")) // JExpression inst = JGwtCreate.createInstantiationExpression(answerType.getSourceInfo(), // (JClassType)answerType, answerType.getEnclosingType()); return new JMethodCall(method.getSourceInfo(), null, method); } throw new InternalCompilerException("Did not generate async proxy for " + answerType); }
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//from w ww.j av a 2 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 injectLazySingleton(TreeLogger logger, JClassLiteral classLiteral, JNode x, JDeclaredType enclosingType, UnifyAstView ast) throws UnableToCompleteException { JDeclaredType type = (JDeclaredType) classLiteral.getRefType(); String[] names = type.getShortName().split("[$]"); // TODO: stop stripping the enclosing class name (need to update generators) // String reqType = JGwtCreate.nameOf(type); String answer = classLiteral.getRefType().getName(); answer = answer.substring(0, answer.lastIndexOf('.') + 1) + "impl.SingletonFor_" + names[names.length - 1]; JDeclaredType answerType = null;/* w w w . j a v a2 s .co m*/ JDeclaredType knownType = ast.getProgram().getFromTypeMap(answer); if (knownType != null) {// if the singleton already exists, just use it answerType = ast.searchForTypeBySource(answer); } else {// we need to generate the singleton on the fly, without updating rebind cache StandardGeneratorContext ctx = ast.getRebindPermutationOracle().getGeneratorContext(); // make sure the requested interface is compiled for the generator ast.searchForTypeBySource(type.getName()); try { // our hardcoded class is definitely a generator ;-} Class<? extends Generator> generator = SyncInjectionGenerator.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()); answerType = ast.searchForTypeBySource(result.getResultTypeName()); // sanity check if (answerType == null) { ast.error(x, "Rebind result '" + answer + "' could not be found"); return null; } } catch (UnableToCompleteException e) { logger.log(Type.ERROR, "Error trying to generator 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 '" + 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; } logger.log(logLevel(), "Injecting lazy singleton for " + type.getName() + " -> " + answerType); 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; } return result; }
From source file:xapi.dev.inject.MagicMethods.java
License:Open Source License
private static JExpression injectSingleton(TreeLogger logger, JClassLiteral classLiteral, JNode x, UnifyAstView ast) throws UnableToCompleteException { // check for cached result. // inject our provider class JDeclaredType type = (JDeclaredType) classLiteral.getRefType(); if (cachedProviders.containsKey(type)) return cachedProviders.get(type); JExpression expr = injectLazySingleton(logger, classLiteral, x, type, ast); String[] names = type.getShortName().split("[$]"); String answer = classLiteral.getRefType().getName(); answer = answer.substring(0, answer.lastIndexOf('.') + 1) + "impl.SingletonFor_" + names[names.length - 1]; JDeclaredType enclosing = ast.searchForTypeBySource(answer); JDeclaredType lazyProvider = ast.searchForTypeBySource(SingletonProvider.class.getName()); for (JMethod method : lazyProvider.getMethods()) { if (method.getName().equals("get")) { // Create a new method for each singleton to access the desired provider SourceInfo info = null;//from ww w .j a va2s. c om JMethod getSingleton = null; String targetName = "singleton" + type.getShortName().replaceAll("[$]", "_"); for (JMethod existingMethod : enclosing.getMethods()) { if (existingMethod.getName().equals(existingMethod)) { getSingleton = existingMethod; info = getSingleton.getSourceInfo(); logger.log(logLevel(), "Reusing generated method " + getSingleton.toSource()); break; } } if (getSingleton == null) { info = expr.getSourceInfo().makeChild(SourceOrigin.UNKNOWN); JMethodBody body = new JMethodBody(info); getSingleton = new JMethod(info, targetName, enclosing, type, false, true, true, AccessModifier.PRIVATE); // insert our generated method into the enclosing type; needed for super dev mode enclosing.addMethod(getSingleton); // freeze this method getSingleton.setBody(body); getSingleton.freezeParamTypes(); getSingleton.setSynthetic(); info.addCorrelation(info.getCorrelator().by(getSingleton)); JMethodCall call = new JMethodCall(info, expr, method); JReturnStatement value = new JReturnStatement(x.getSourceInfo(), call); if (enclosing.getClinitTarget() != null) { JDeclaredType clinit = enclosing.getClinitTarget(); JMethod clinitMethod = clinit.getMethods().get(0); assert (JProgram.isClinit(clinitMethod)); JMethodCall doClinit = new JMethodCall(clinit.getSourceInfo(), null, clinitMethod); body.getBlock().addStmt(doClinit.makeStatement()); } body.getBlock().addStmt(value); if (logger.isLoggable(Type.DEBUG)) { logger = logger.branch(Type.DEBUG, "Generated magic singleton: "); for (String str : getSingleton.toSource().split("\n")) { logger.branch(Type.DEBUG, str); } } } expr = new JMethodCall(info, null, getSingleton); cachedProviders.put(type, expr); return expr; } } throw new InternalCompilerException("Unable to generate synchronous injected class access"); }
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;/* ww w . j a v a 2 s.c om*/ 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) }