Add async support in Class.newInstance()
This commit is contained in:
Alexey Andreev 2015-02-24 15:51:27 +04:00
parent 7a573efde1
commit 4908293e50
3 changed files with 65 additions and 17 deletions

View File

@ -1955,13 +1955,16 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
private Injector getInjector(MethodReference ref) {
InjectorHolder holder = injectorMap.get(ref);
if (holder == null) {
MethodHolder method = classSource.get(ref.getClassName()).getMethod(ref.getDescriptor());
holder = new InjectorHolder(null);
if (method != null) {
AnnotationHolder injectedByAnnot = method.getAnnotations().get(InjectedBy.class.getName());
if (injectedByAnnot != null) {
ValueType type = injectedByAnnot.getValues().get("value").getJavaClass();
holder = new InjectorHolder(instantiateInjector(((ValueType.Object)type).getClassName()));
ClassHolder cls = classSource.get(ref.getClassName());
if (cls != null) {
MethodHolder method = cls.getMethod(ref.getDescriptor());
if (method != null) {
AnnotationHolder injectedByAnnot = method.getAnnotations().get(InjectedBy.class.getName());
if (injectedByAnnot != null) {
ValueType type = injectedByAnnot.getValues().get("value").getJavaClass();
holder = new InjectorHolder(instantiateInjector(((ValueType.Object)type).getClassName()));
}
}
}
injectorMap.put(ref, holder);

View File

@ -47,13 +47,14 @@ public class NewInstanceDependencySupport implements DependencyListener {
}
@Override
public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) {
public void methodAchieved(final DependencyAgent agent, MethodDependency method, CallLocation location) {
MethodReader reader = method.getMethod();
if (reader.getOwnerName().equals(Platform.class.getName()) && reader.getName().equals("newInstance")) {
allClassesNode.connect(method.getResult());
final MethodReference methodRef = reader.getReference();
method.getResult().addConsumer(new DependencyConsumer() {
@Override public void consume(DependencyAgentType type) {
attachConstructor(agent, type.getName(), location);
attachConstructor(agent, type.getName(), new CallLocation(methodRef));
}
});
}

View File

@ -91,24 +91,68 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
private void generateNewInstance(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
throws IOException {
writer.append("var c").ws().append("=").ws().append("'$$constructor$$';").softNewLine();
if (context.isAsync()) {
writer.append("function async(cls, init) {").indent().softNewLine();
writer.append("return function($return) {").indent().softNewLine();
writer.append("var r = new cls;").softNewLine();
writer.append("init(r, $rt_guardAsync(function($restore) {").indent().softNewLine();
writer.append("$restore();").softNewLine();
writer.append("$return($rt_asyncResult(r))").softNewLine();
writer.outdent().append("}));").softNewLine();
writer.outdent().append("};").softNewLine();
writer.outdent().append("}").softNewLine();
writer.append("function sync(cls, init) {").indent().softNewLine();
writer.append("return function($return) {").indent().softNewLine();
writer.append("var r = new cls;").softNewLine();
writer.append("try {").indent().softNewLine();
writer.append("init(r);").softNewLine();
writer.append("$return($rt_asyncResult(r));").softNewLine();
writer.outdent().append("} catch (e) {").indent().softNewLine();
writer.append("$return($rt_asyncError(e));").softNewLine();
writer.outdent().append("}").softNewLine();
writer.outdent().append("};").softNewLine();
writer.outdent().append("}").softNewLine();
}
for (String clsName : context.getClassSource().getClassNames()) {
ClassReader cls = context.getClassSource().get(clsName);
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", void.class));
if (method != null) {
writer.appendClass(clsName).append("[c]").ws().append("=").ws()
.append(writer.getNaming().getNameForInit(method.getReference()))
.append(";").softNewLine();
writer.appendClass(clsName).append("[c]").ws().append("=").ws();
if (!context.isAsync()) {
writer.append(writer.getNaming().getNameForInit(method.getReference()));
} else {
String function = context.isAsync(method.getReference()) ? "async" : "sync";
writer.append(function).append("(").appendClass(clsName).append(',').ws()
.appendMethodBody(method.getReference()).append(")");
}
writer.append(";").softNewLine();
}
}
writer.appendMethodBody(methodRef).ws().append("=").ws().append("function(cls)").ws().append("{")
.softNewLine().indent();
writer.appendMethodBody(methodRef).ws().append("=").ws().append("function(cls");
if (context.isAsync()) {
writer.append(',').ws().append("$return");
}
writer.append(")").ws().append("{").softNewLine().indent();
writer.append("if").ws().append("(!cls.hasOwnProperty(c))").ws().append("{").indent().softNewLine();
writer.append("return null;").softNewLine();
if (!context.isAsync()) {
writer.append("return null;").softNewLine();
} else {
writer.append("return $return($rt_asyncResult(null));").softNewLine();
}
writer.outdent().append("}").softNewLine();
writer.append("return cls[c]();").softNewLine();
if (!context.isAsync()) {
writer.append("return cls[c]();").softNewLine();
} else {
writer.append("return cls[c]($return);").softNewLine();
}
writer.outdent().append("}").softNewLine();
writer.append("return ").appendMethodBody(methodRef).append("(")
.append(context.getParameterName(1)).append(");").softNewLine();
writer.append("return ").appendMethodBody(methodRef).append("(").append(context.getParameterName(1));
if (context.isAsync()) {
writer.append(',').ws().append("$return");
}
writer.append(");").softNewLine();
}
private void generateLookup(GeneratorContext context, SourceWriter writer) throws IOException {