mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Most of TClass now uses Platform instead of code generation
This commit is contained in:
parent
d93fa6cf41
commit
2ae7b587d1
|
@ -15,18 +15,26 @@
|
|||
*/
|
||||
package org.teavm.classlib.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.metadata.MetadataGenerator;
|
||||
import org.teavm.platform.metadata.MetadataGeneratorContext;
|
||||
import org.teavm.platform.metadata.Resource;
|
||||
import org.teavm.platform.metadata.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class DeclaringClassMetadataGenerator implements MetadataGenerator {
|
||||
public class DeclaringClassMetadataGenerator implements ClassScopedMetadataGenerator {
|
||||
@Override
|
||||
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||
return null;
|
||||
public Map<String, Resource> generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||
Map<String, Resource> result = new HashMap<>();
|
||||
for (String clsName : context.getClassSource().getClassNames()) {
|
||||
ClassReader cls = context.getClassSource().get(clsName);
|
||||
if (cls.getOwnerName() != null) {
|
||||
result.put(clsName, context.createClassResource(cls.getOwnerName()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.impl;
|
|||
import java.util.ServiceLoader;
|
||||
import org.teavm.classlib.impl.unicode.CLDRReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
import org.teavm.vm.spi.TeaVMHost;
|
||||
import org.teavm.vm.spi.TeaVMPlugin;
|
||||
|
||||
|
@ -30,12 +31,11 @@ public class JCLPlugin implements TeaVMPlugin {
|
|||
public void install(TeaVMHost host) {
|
||||
host.add(new EnumDependencySupport());
|
||||
host.add(new EnumTransformer());
|
||||
host.add(new ClassLookupDependencySupport());
|
||||
host.add(new ObjectEnrichRenderer());
|
||||
ServiceLoaderSupport serviceLoaderSupp = new ServiceLoaderSupport(host.getClassLoader());
|
||||
host.add(serviceLoaderSupp);
|
||||
MethodReference loadServicesMethod = new MethodReference(ServiceLoader.class, "loadServices",
|
||||
Class.class, Object[].class);
|
||||
PlatformClass.class, Object[].class);
|
||||
host.add(loadServicesMethod, serviceLoaderSupp);
|
||||
JavacSupport javacSupport = new JavacSupport();
|
||||
host.add(javacSupport);
|
||||
|
|
|
@ -65,7 +65,7 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
|
|||
}
|
||||
writer.outdent().append("}").softNewLine();
|
||||
String param = context.getParameterName(1);
|
||||
writer.append("var cls = " + param + ".$data;").softNewLine();
|
||||
writer.append("var cls = " + param + ";").softNewLine();
|
||||
writer.append("if (!cls.$$serviceList$$) {").indent().softNewLine();
|
||||
writer.append("return $rt_createArray($rt_objcls(), 0);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
|
|
@ -16,12 +16,6 @@
|
|||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyPlugin;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.spi.Generator;
|
||||
import org.teavm.javascript.spi.GeneratorContext;
|
||||
import org.teavm.javascript.spi.Injector;
|
||||
import org.teavm.javascript.spi.InjectorContext;
|
||||
import org.teavm.model.*;
|
||||
|
@ -30,70 +24,13 @@ import org.teavm.model.*;
|
|||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ClassNativeGenerator implements Generator, Injector, DependencyPlugin {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||
throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "forNameImpl":
|
||||
generateForName(context, writer);
|
||||
break;
|
||||
case "getDeclaringClass":
|
||||
generateGetDeclaringClass(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassNativeGenerator implements Injector {
|
||||
@Override
|
||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "getEnumConstantsImpl":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(".$data.values()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateForName(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String param = context.getParameterName(1);
|
||||
writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent();
|
||||
for (String name : context.getClassSource().getClassNames()) {
|
||||
writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ")
|
||||
.append("return $rt_cls(").appendClass(name).append(");").softNewLine();
|
||||
}
|
||||
writer.append("default: return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
|
||||
private void generateGetDeclaringClass(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String self = context.getParameterName(0);
|
||||
writer.append("if (!").appendClass("java.lang.Class").append(".$$owners$$) {").indent().softNewLine();
|
||||
writer.appendClass("java.lang.Class").append(".$$owners$$ = true;").softNewLine();
|
||||
for (String clsName : context.getClassSource().getClassNames()) {
|
||||
ClassReader cls = context.getClassSource().get(clsName);
|
||||
writer.appendClass(clsName).append(".$$owner$$ = ");
|
||||
if (cls.getOwnerName() != null) {
|
||||
writer.appendClass(cls.getOwnerName());
|
||||
} else {
|
||||
writer.append("null");
|
||||
}
|
||||
writer.append(";").softNewLine();
|
||||
}
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("var cls = " + self + ".$data;").softNewLine();
|
||||
writer.append("return cls.$$owner$$ != null ? $rt_cls(cls.$$owner$$) : null;").softNewLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency graph, CallLocation location) {
|
||||
switch (graph.getReference().getName()) {
|
||||
case "forNameImpl":
|
||||
case "getDeclaringClass":
|
||||
graph.getResult().propagate(agent.getType("java.lang.Class"));
|
||||
break;
|
||||
case "newInstance":
|
||||
agent.linkMethod(new MethodReference(InstantiationException.class, "<init>", void.class),
|
||||
location).use();
|
||||
context.getWriter().append(".values()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
|
|||
import org.teavm.javascript.spi.InjectedBy;
|
||||
import org.teavm.platform.Platform;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
import org.teavm.platform.metadata.MetadataProvider;
|
||||
import org.teavm.platform.metadata.ClassResource;
|
||||
import org.teavm.platform.metadata.ClassScopedMetadataProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -36,7 +37,7 @@ public class TClass<T> extends TObject {
|
|||
platformClass.setJavaClass(Platform.getPlatformObject(this));
|
||||
}
|
||||
|
||||
static TClass<?> getClass(PlatformClass cls) {
|
||||
public static TClass<?> getClass(PlatformClass cls) {
|
||||
if (cls == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -47,7 +48,7 @@ public class TClass<T> extends TObject {
|
|||
return result;
|
||||
}
|
||||
|
||||
PlatformClass getPlatformClass() {
|
||||
public PlatformClass getPlatformClass() {
|
||||
return platformClass;
|
||||
}
|
||||
|
||||
|
@ -71,7 +72,7 @@ public class TClass<T> extends TObject {
|
|||
}
|
||||
|
||||
public boolean isArray() {
|
||||
return platformClass.getMetadata().isArray();
|
||||
return platformClass.getMetadata().getArrayItem() != null;
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
|
@ -141,12 +142,13 @@ public class TClass<T> extends TObject {
|
|||
return (TClass<? super T>)getClass(platformClass.getMetadata().getSuperclass());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T[] getEnumConstants() {
|
||||
return isEnum() ? getEnumConstantsImpl() : null;
|
||||
return isEnum() ? (T[])getEnumConstantsImpl(platformClass) : null;
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
public native T[] getEnumConstantsImpl();
|
||||
private static native Object[] getEnumConstantsImpl(PlatformClass cls);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T cast(TObject obj) {
|
||||
|
@ -175,12 +177,22 @@ public class TClass<T> extends TObject {
|
|||
return forName(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T newInstance() throws TInstantiationException, TIllegalAccessException {
|
||||
return Platform.newInstance(platformClass);
|
||||
Object instance = Platform.newInstance(platformClass);
|
||||
if (instance == null) {
|
||||
throw new TInstantiationException();
|
||||
}
|
||||
return (T)instance;
|
||||
}
|
||||
|
||||
@MetadataProvider(DeclaringClassMetadataGenerator.class)
|
||||
public native TClass<?> getDeclaringClass();
|
||||
public TClass<?> getDeclaringClass() {
|
||||
ClassResource res = getDeclaringClass(platformClass);
|
||||
return res != null ? getClass(Platform.classFromResource(res)) : null;
|
||||
}
|
||||
|
||||
@ClassScopedMetadataProvider(DeclaringClassMetadataGenerator.class)
|
||||
private static native ClassResource getDeclaringClass(PlatformClass cls);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <U> TClass<? extends U> asSubclass(TClass<U> clazz) {
|
||||
|
|
|
@ -93,15 +93,14 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
|||
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String type = context.getParameterName(1);
|
||||
String length = context.getParameterName(2);
|
||||
writer.append("var cls = " + type + ".$data;").softNewLine();
|
||||
writer.append("if (cls.primitive) {").softNewLine().indent();
|
||||
writer.append("if (").append(type).append(".$meta.primitive) {").softNewLine().indent();
|
||||
for (String primitive : primitives) {
|
||||
writer.append("if (cls == $rt_" + primitive.toLowerCase() + "cls()) {").indent().softNewLine();
|
||||
writer.append("if (" + type + " == $rt_" + primitive.toLowerCase() + "cls()) {").indent().softNewLine();
|
||||
writer.append("return $rt_create" + primitive + "Array(" + length + ");").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
writer.outdent().append("} else {").indent().softNewLine();
|
||||
writer.append("return $rt_createArray(cls, " + length + ")").softNewLine();
|
||||
writer.append("return $rt_createArray(" + type + ", " + length + ")").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.lang.reflect;
|
|||
import org.teavm.classlib.java.lang.*;
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.spi.GeneratedBy;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -38,12 +39,12 @@ public final class TArray extends TObject {
|
|||
if (length < 0) {
|
||||
throw new TNegativeArraySizeException();
|
||||
}
|
||||
return newInstanceImpl(componentType, length);
|
||||
return newInstanceImpl(componentType.getPlatformClass(), length);
|
||||
}
|
||||
|
||||
@GeneratedBy(ArrayNativeGenerator.class)
|
||||
@PluggableDependency(ArrayNativeGenerator.class)
|
||||
private static native TObject newInstanceImpl(TClass<?> componentType, int length);
|
||||
private static native TObject newInstanceImpl(PlatformClass componentType, int length);
|
||||
|
||||
public static TObject get(TObject array, int index) throws TIllegalArgumentException,
|
||||
TArrayIndexOutOfBoundsException {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.classlib.java.util;
|
||||
|
||||
import org.teavm.classlib.java.lang.*;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -48,7 +49,7 @@ public final class TServiceLoader<S> extends TObject implements TIterable<S> {
|
|||
}
|
||||
|
||||
public static <S> TServiceLoader<S> load(TClass<S> service) {
|
||||
return new TServiceLoader<>(loadServices(service));
|
||||
return new TServiceLoader<>(loadServices(service.getPlatformClass()));
|
||||
}
|
||||
|
||||
public static <S> TServiceLoader<S> load(TClass<S> service, @SuppressWarnings("unused") TClassLoader loader) {
|
||||
|
@ -59,7 +60,7 @@ public final class TServiceLoader<S> extends TObject implements TIterable<S> {
|
|||
return load(service);
|
||||
}
|
||||
|
||||
private static native <T> T[] loadServices(TClass<T> serviceType);
|
||||
private static native <T> T[] loadServices(PlatformClass cls);
|
||||
|
||||
public void reload() {
|
||||
// Do nothing, services are bound at build time
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.teavm.common.ServiceRepository;
|
|||
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||
import org.teavm.debugging.information.DeferredCallSite;
|
||||
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.javascript.ast.*;
|
||||
import org.teavm.javascript.spi.GeneratorContext;
|
||||
import org.teavm.javascript.spi.InjectedBy;
|
||||
|
@ -54,6 +55,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
private DeferredCallSite lastCallSite;
|
||||
private DeferredCallSite prevCallSite;
|
||||
private Set<MethodReference> asyncMethods;
|
||||
private Diagnostics diagnostics;
|
||||
private boolean async;
|
||||
|
||||
private static class InjectorHolder {
|
||||
|
@ -77,13 +79,14 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
}
|
||||
|
||||
public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader,
|
||||
ServiceRepository services, Set<MethodReference> asyncMethods) {
|
||||
ServiceRepository services, Set<MethodReference> asyncMethods, Diagnostics diagnostics) {
|
||||
this.naming = writer.getNaming();
|
||||
this.writer = writer;
|
||||
this.classSource = classSource;
|
||||
this.classLoader = classLoader;
|
||||
this.services = services;
|
||||
this.asyncMethods = new HashSet<>(asyncMethods);
|
||||
this.diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,43 +170,11 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
}
|
||||
|
||||
private void renderRuntimeCls() throws IOException {
|
||||
writer.append("function $rt_cls").ws().append("(clsProto)").ws().append("{")
|
||||
.indent().softNewLine();
|
||||
String classClass = "java.lang.Class";
|
||||
writer.append("var cls").ws().append("=").ws().append("clsProto.classObject;").softNewLine();
|
||||
writer.append("if").ws().append("(typeof cls").ws().append("===").ws().append("'undefined')").ws()
|
||||
.append("{").softNewLine().indent();
|
||||
MethodReference createMethodRef = new MethodReference(classClass, "createNew", ValueType.object(classClass));
|
||||
writer.append("cls").ws().append("=").ws().appendMethodBody(createMethodRef).append("();").softNewLine();
|
||||
writer.append("cls.$data = clsProto;").softNewLine();
|
||||
if (classSource.get(classClass).getField("name") != null) {
|
||||
writer.append("cls.").appendField(new FieldReference(classClass, "name")).ws().append("=").ws()
|
||||
.append("clsProto.$meta.name").ws().append("!==").ws().append("undefined").ws().append("?").ws()
|
||||
.append("$rt_str(clsProto.$meta.name)").ws().append(":").ws().append("null;").softNewLine();
|
||||
}
|
||||
if (classSource.get(classClass).getField("name") != null) {
|
||||
writer.append("cls.").appendField(new FieldReference(classClass, "binaryName")).ws().append("=").ws()
|
||||
.append("clsProto.$meta.binaryName").ws().append("!==").ws().append("undefined").ws()
|
||||
.append("?").ws()
|
||||
.append("$rt_str(clsProto.$meta.binaryName)").ws().append(":").ws().append("null;").softNewLine();
|
||||
}
|
||||
if (classSource.get(classClass).getField("primitive") != null) {
|
||||
writer.append("cls.").appendField(new FieldReference(classClass, "primitive"))
|
||||
.append(" = clsProto.$meta.primitive ? 1 : 0;").newLine();
|
||||
}
|
||||
if (classSource.get(classClass).getField("array") != null) {
|
||||
writer.append("cls.").appendField(new FieldReference(classClass, "array")).ws()
|
||||
.append("=").ws().append("clsProto.$meta.item").ws().append("?").ws()
|
||||
.append("1").ws().append(":").ws().append("0;").softNewLine();
|
||||
}
|
||||
if (classSource.get(classClass).getField("isEnum") != null) {
|
||||
writer.append("cls.").appendField(new FieldReference(classClass, "isEnum")).ws()
|
||||
.append("=").ws().append("clsProto.$meta.enum").ws().append("?").ws()
|
||||
.append("1").ws().append(":").ws().append("0;").softNewLine();
|
||||
}
|
||||
writer.append("clsProto.classObject").ws().append("=").ws().append("cls;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return cls;").softNewLine();
|
||||
writer.append("function $rt_cls(cls)").ws().append("{").softNewLine().indent();
|
||||
writer.append("return ").appendMethodBody("java.lang.Class", "getClass",
|
||||
ValueType.object("org.teavm.platform.PlatformClass"),
|
||||
ValueType.object("java.lang.Class")).append("(cls);")
|
||||
.softNewLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
}
|
||||
|
||||
|
@ -706,6 +677,11 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
public String getCompleteContinuation() {
|
||||
return "$return";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Diagnostics getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
private void pushLocation(NodeLocation location) {
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.javascript.spi;
|
|||
|
||||
import java.util.Properties;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -38,4 +39,6 @@ public interface GeneratorContext extends ServiceRepository {
|
|||
String getCompleteContinuation();
|
||||
|
||||
boolean isAsync(MethodReference method);
|
||||
|
||||
Diagnostics getDiagnostics();
|
||||
}
|
||||
|
|
|
@ -334,7 +334,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
return progressListener.progressReached(0) == TeaVMProgressFeedback.CONTINUE;
|
||||
}
|
||||
});
|
||||
dependencyChecker.linkMethod(new MethodReference(Class.class, "createNew", Class.class), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(Class.class.getName(), "getClass",
|
||||
ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(String.class, "<init>", char[].class, void.class),
|
||||
null).use();
|
||||
dependencyChecker.linkMethod(new MethodReference(String.class, "getChars", int.class, int.class, char[].class,
|
||||
|
@ -396,7 +397,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||
builder.setMinified(minifying);
|
||||
SourceWriter sourceWriter = builder.build(writer);
|
||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader, this, asyncMethods);
|
||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader, this, asyncMethods, diagnostics);
|
||||
renderer.setProperties(properties);
|
||||
if (debugEmitter != null) {
|
||||
int classIndex = 0;
|
||||
|
|
|
@ -130,15 +130,18 @@ function $rt_arraycls(cls) {
|
|||
}
|
||||
var name = "[" + cls.$meta.binaryName;
|
||||
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false, superclass : $rt_objcls(),
|
||||
name : name, binaryName : name };
|
||||
name : name, binaryName : name, enum : false };
|
||||
arraycls.classObject = null;
|
||||
cls.$array = arraycls;
|
||||
}
|
||||
return cls.$array;
|
||||
}
|
||||
function $rt_createcls() {
|
||||
return {
|
||||
classObject : null,
|
||||
$meta : {
|
||||
supertypes : []
|
||||
supertypes : [],
|
||||
superclass : null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -147,6 +150,8 @@ function $rt_createPrimitiveCls(name, binaryName) {
|
|||
cls.$meta.primitive = true;
|
||||
cls.$meta.name = name;
|
||||
cls.$meta.binaryName = binaryName;
|
||||
cls.$meta.enum = false;
|
||||
cls.$meta.item = null;
|
||||
return cls;
|
||||
}
|
||||
var $rt_booleanclsCache = null;
|
||||
|
@ -365,18 +370,21 @@ function $rt_putStderr(ch) {
|
|||
}
|
||||
function $rt_declClass(cls, data) {
|
||||
cls.$meta = {};
|
||||
cls.$meta.superclass = data.superclass;
|
||||
cls.$meta.supertypes = data.interfaces ? data.interfaces.slice() : [];
|
||||
var m = cls.$meta
|
||||
m.superclass = typeof(data.superclass) !== 'undefined' ? data.superclass : null;
|
||||
m.supertypes = data.interfaces ? data.interfaces.slice() : [];
|
||||
if (data.superclass) {
|
||||
cls.$meta.supertypes.push(data.superclass);
|
||||
m.supertypes.push(data.superclass);
|
||||
cls.prototype = new data.superclass();
|
||||
} else {
|
||||
cls.prototype = new Object();
|
||||
}
|
||||
cls.$meta.name = data.name;
|
||||
cls.$meta.binaryName = "L" + data.name + ";";
|
||||
cls.$meta.enum = data.enum;
|
||||
m.name = data.name;
|
||||
m.binaryName = "L" + data.name + ";";
|
||||
m.enum = data.enum;
|
||||
m.item = null;
|
||||
cls.prototype.constructor = cls;
|
||||
cls.classObject = null;
|
||||
cls.$clinit = data.clinit ? data.clinit : function() {};
|
||||
}
|
||||
function $rt_virtualMethods(cls) {
|
||||
|
|
|
@ -370,11 +370,11 @@ var JUnitClient = {};
|
|||
JUnitClient.run = function() {
|
||||
var handler = window.addEventListener("message", function() {
|
||||
window.removeEventListener("message", handler);
|
||||
var message = {};
|
||||
try {
|
||||
var instance = new TestClass();
|
||||
initInstance(instance);
|
||||
runTest(instance, function(restore) {
|
||||
var message = {};
|
||||
try {
|
||||
var result = restore();
|
||||
message.status = "ok";
|
||||
|
|
|
@ -88,7 +88,7 @@ public class JSNativeGenerator implements Injector, DependencyPlugin {
|
|||
}
|
||||
writer.append("))");
|
||||
break;
|
||||
case "pass":
|
||||
case "marshall":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
break;
|
||||
case "wrap":
|
||||
|
|
|
@ -72,7 +72,7 @@ public final class Platform {
|
|||
@PluggableDependency(PlatformGenerator.class)
|
||||
public static native void initClass(PlatformClass cls);
|
||||
|
||||
@GeneratedBy(PlatformGenerator.class)
|
||||
@InjectedBy(PlatformGenerator.class)
|
||||
@PluggableDependency(PlatformGenerator.class)
|
||||
public static native PlatformClass classFromResource(ClassResource resource);
|
||||
}
|
||||
|
|
|
@ -17,13 +17,12 @@ package org.teavm.platform;
|
|||
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.JSProperty;
|
||||
import org.teavm.platform.metadata.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformClass extends JSObject, Resource {
|
||||
public interface PlatformClass extends JSObject {
|
||||
@JSProperty("$meta")
|
||||
PlatformClassMetadata getMetadata();
|
||||
|
||||
|
|
|
@ -38,9 +38,6 @@ public interface PlatformClassMetadata extends JSObject {
|
|||
@JSProperty
|
||||
boolean isPrimitive();
|
||||
|
||||
@JSProperty
|
||||
boolean isArray();
|
||||
|
||||
@JSProperty
|
||||
boolean isEnum();
|
||||
}
|
||||
|
|
|
@ -15,38 +15,38 @@
|
|||
*/
|
||||
package org.teavm.platform;
|
||||
|
||||
import org.teavm.jso.JSMethod;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.JSProperty;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformPrimitives extends JSObject {
|
||||
@JSProperty("$rt_voidcls")
|
||||
@JSMethod("$rt_voidcls")
|
||||
PlatformClass getVoidClass();
|
||||
|
||||
@JSProperty("$rt_booleancls")
|
||||
@JSMethod("$rt_booleancls")
|
||||
PlatformClass getBooleanClass();
|
||||
|
||||
@JSProperty("$rt_bytecls")
|
||||
@JSMethod("$rt_bytecls")
|
||||
PlatformClass getByteClass();
|
||||
|
||||
@JSProperty("$rt_shortcls")
|
||||
@JSMethod("$rt_shortcls")
|
||||
PlatformClass getShortClass();
|
||||
|
||||
@JSProperty("$rt_charcls")
|
||||
@JSMethod("$rt_charcls")
|
||||
PlatformClass getCharClass();
|
||||
|
||||
@JSProperty("$rt_intcls")
|
||||
@JSMethod("$rt_intcls")
|
||||
PlatformClass getIntClass();
|
||||
|
||||
@JSProperty("$rt_longcls")
|
||||
@JSMethod("$rt_longcls")
|
||||
PlatformClass getLongClass();
|
||||
|
||||
@JSProperty("$rt_floatcls")
|
||||
@JSMethod("$rt_floatcls")
|
||||
PlatformClass getFloatClass();
|
||||
|
||||
@JSProperty("$rt_doublecls")
|
||||
@JSMethod("$rt_doublecls")
|
||||
PlatformClass getDoubleClass();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.teavm.jso.JSProperty;
|
|||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformSequence<T> extends JSObject {
|
||||
public interface PlatformSequence<T extends JSObject> extends JSObject {
|
||||
@JSProperty
|
||||
int getLength();
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2015 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.platform.metadata;
|
||||
|
||||
import java.util.Map;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
|
||||
/**
|
||||
* <p>Behaviour of this class is similar to {@link MetadataGenerator}. The difference is that method, marked with
|
||||
* {@link ClassScopedMetadataProvider} must take one argument of type {@link PlatformClass}. It will
|
||||
* return different resource for each given class, corresponding to map entries, produced by
|
||||
* {@link #generateMetadata(MetadataGeneratorContext, MethodReference)}.
|
||||
*
|
||||
* @see ClassScopedMetadataProvider
|
||||
* @see MetadataGenerator
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface ClassScopedMetadataGenerator {
|
||||
Map<String, Resource> generateMetadata(MetadataGeneratorContext context, MethodReference method);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2015 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.platform.metadata;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <p>Binds a {@link ClassScopedMetadataGenerator} to a native method.</p>
|
||||
*
|
||||
* @see MetadataProvider
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ClassScopedMetadataProvider {
|
||||
Class<? extends ClassScopedMetadataGenerator> value();
|
||||
}
|
|
@ -50,6 +50,8 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* <p>All other types are not considered to be resources and therefore are not accepted.</p>
|
||||
*
|
||||
* @see ClassScopedMetadataGenerator
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface MetadataGenerator {
|
||||
|
|
|
@ -102,8 +102,8 @@ class BuildTimeResourceProxyBuilder {
|
|||
|
||||
private void scanIface(Class<?> iface) {
|
||||
if (!Resource.class.isAssignableFrom(iface)) {
|
||||
throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() +
|
||||
". This type does not implement the " + Resource.class.getName() + " interface");
|
||||
throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() + "." +
|
||||
" This type does not implement the " + Resource.class.getName() + " interface");
|
||||
}
|
||||
|
||||
// Scan methods
|
||||
|
|
|
@ -36,7 +36,7 @@ class BuildTimeResourceWriterMethod implements BuildTimeResourceMethod {
|
|||
if (i > 0) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
ResourceWriterHelper.writeString(writer, propertyNames[i]);
|
||||
ResourceWriterHelper.writeIdentifier(writer, propertyNames[i]);
|
||||
writer.ws().append(':').ws();
|
||||
ResourceWriterHelper.write(writer, proxy.data[i]);
|
||||
}
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.impl;
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.platform.Platform;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -38,14 +39,14 @@ public class ClassLookupDependencySupport implements DependencyListener {
|
|||
@Override
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) {
|
||||
MethodReference ref = method.getReference();
|
||||
if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) {
|
||||
if (ref.getClassName().equals(Platform.class.getName()) && ref.getName().equals("lookupClass")) {
|
||||
allClasses.addConsumer(new DependencyConsumer() {
|
||||
@Override public void consume(DependencyAgentType type) {
|
||||
ClassReader cls = agent.getClassSource().get(type.getName());
|
||||
if (cls == null) {
|
||||
return;
|
||||
}
|
||||
MethodReader initMethod = cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID));
|
||||
MethodReader initMethod = cls.getMethod(new MethodDescriptor("<clinit>", void.class));
|
||||
if (initMethod != null) {
|
||||
agent.linkMethod(initMethod.getReference(), location).use();
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2015 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.platform.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.Renderer;
|
||||
import org.teavm.javascript.spi.Generator;
|
||||
import org.teavm.javascript.spi.GeneratorContext;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.platform.metadata.ClassScopedMetadataGenerator;
|
||||
import org.teavm.platform.metadata.ClassScopedMetadataProvider;
|
||||
import org.teavm.platform.metadata.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ClassScopedMetadataProviderNativeGenerator implements Generator {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
// Validate method
|
||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||
AnnotationReader providerAnnot = method.getAnnotations().get(ClassScopedMetadataProvider.class.getName());
|
||||
if (providerAnnot == null) {
|
||||
return;
|
||||
}
|
||||
if (!method.hasModifier(ElementModifier.NATIVE)) {
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Method {{m0}} is marked with " +
|
||||
"{{c1}} annotation, but it is not native", methodRef, ClassScopedMetadataProvider.class.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
// Find and instantiate metadata generator
|
||||
ValueType generatorType = providerAnnot.getValue("value").getJavaClass();
|
||||
String generatorClassName = ((ValueType.Object)generatorType).getClassName();
|
||||
Class<?> generatorClass;
|
||||
try {
|
||||
generatorClass = Class.forName(generatorClassName, true, context.getClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Can't find metadata provider class {{c0}}",
|
||||
generatorClassName);
|
||||
return;
|
||||
}
|
||||
Constructor<?> cons;
|
||||
try {
|
||||
cons = generatorClass.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Metadata generator {{c0}} does not have " +
|
||||
"a public no-arg constructor", generatorClassName);
|
||||
return;
|
||||
}
|
||||
ClassScopedMetadataGenerator generator;
|
||||
try {
|
||||
generator = (ClassScopedMetadataGenerator)cons.newInstance();
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Error instantiating metadata " +
|
||||
"generator {{c0}}", generatorClassName);
|
||||
return;
|
||||
}
|
||||
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
||||
context.getClassLoader(), context.getProperties(), context);
|
||||
|
||||
Map<String, Resource> resourceMap = generator.generateMetadata(metadataContext, methodRef);
|
||||
writer.append("var p").ws().append("=").ws().append("\"" + Renderer.escapeString("$$res_" +
|
||||
writer.getNaming().getNameFor(methodRef)) + "\"").append(";").softNewLine();
|
||||
for (Map.Entry<String, Resource> entry : resourceMap.entrySet()) {
|
||||
writer.appendClass(entry.getKey()).append("[p]").ws().append("=").ws();
|
||||
ResourceWriterHelper.write(writer, entry.getValue());
|
||||
writer.append(";").softNewLine();
|
||||
}
|
||||
writer.appendMethodBody(methodRef).ws().append('=').ws().append("function(cls)").ws().append("{")
|
||||
.softNewLine().indent();
|
||||
writer.append("return cls.hasOwnProperty(p)").ws().append("?").ws().append("cls[p]").ws().append(":")
|
||||
.ws().append("null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return ").appendMethodBody(methodRef).append("(").append(context.getParameterName(1))
|
||||
.append(");").softNewLine();
|
||||
}
|
||||
}
|
|
@ -41,8 +41,9 @@ public class MetadataProviderNativeGenerator implements Generator {
|
|||
return;
|
||||
}
|
||||
if (!method.hasModifier(ElementModifier.NATIVE)) {
|
||||
throw new IllegalStateException("Method " + method.getReference() + " was marked with " +
|
||||
MetadataProvider.class.getName() + " but it is not native");
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Method {{m0}} is marked with " +
|
||||
"{{c1}} annotation, but it is not native", methodRef, MetadataProvider.class.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
// Find and instantiate metadata generator
|
||||
|
@ -52,23 +53,25 @@ public class MetadataProviderNativeGenerator implements Generator {
|
|||
try {
|
||||
generatorClass = Class.forName(generatorClassName, true, context.getClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Can't find metadata generator class: " + generatorClassName, e);
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Can't find metadata provider class {{c0}}",
|
||||
generatorClassName);
|
||||
return;
|
||||
}
|
||||
Constructor<?> cons;
|
||||
try {
|
||||
cons = generatorClass.getConstructor();
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Metadata generator " + generatorClassName + " does not have a public " +
|
||||
"no-arg constructor", e);
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Metadata generator {{c0}} does not have " +
|
||||
"a public no-arg constructor", generatorClassName);
|
||||
return;
|
||||
}
|
||||
MetadataGenerator generator;
|
||||
try {
|
||||
generator = (MetadataGenerator)cons.newInstance();
|
||||
} catch (IllegalAccessException | InstantiationException e) {
|
||||
throw new RuntimeException("Error instantiating metadata generator " + generatorClassName, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException("Error instantiating metadata generator " + generatorClassName,
|
||||
e.getTargetException());
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
context.getDiagnostics().error(new CallLocation(methodRef), "Error instantiating metadata " +
|
||||
"generator {{c0}}", generatorClassName);
|
||||
return;
|
||||
}
|
||||
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
||||
context.getClassLoader(), context.getProperties(), context);
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.teavm.platform.plugin;
|
|||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.javascript.spi.GeneratedBy;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
import org.teavm.platform.metadata.ClassScopedMetadataProvider;
|
||||
import org.teavm.platform.metadata.MetadataProvider;
|
||||
|
||||
/**
|
||||
|
@ -29,13 +31,26 @@ class MetadataProviderTransformer implements ClassHolderTransformer {
|
|||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
|
||||
if (providerAnnot == null) {
|
||||
continue;
|
||||
if (providerAnnot != null) {
|
||||
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
||||
MetadataProviderNativeGenerator.class.getName())));
|
||||
method.getAnnotations().add(genAnnot);
|
||||
}
|
||||
providerAnnot = method.getAnnotations().get(ClassScopedMetadataProvider.class.getName());
|
||||
if (providerAnnot != null) {
|
||||
ValueType[] params = method.getParameterTypes();
|
||||
if (params.length != 1 && params[0].isObject(PlatformClass.class.getName())) {
|
||||
diagnostics.error(new CallLocation(method.getReference()), "Method {{m0}} marked with {{c1}} " +
|
||||
"must take exactly one parameter of type {{c2}}",
|
||||
method.getReference(), ClassScopedMetadataProvider.class.getName(),
|
||||
PlatformClass.class.getName());
|
||||
}
|
||||
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
||||
ClassScopedMetadataProviderNativeGenerator.class.getName())));
|
||||
method.getAnnotations().add(genAnnot);
|
||||
}
|
||||
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
||||
MetadataProviderNativeGenerator.class.getName())));
|
||||
method.getAnnotations().add(genAnnot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.teavm.javascript.spi.GeneratorContext;
|
|||
import org.teavm.javascript.spi.Injector;
|
||||
import org.teavm.javascript.spi.InjectorContext;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.platform.Platform;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -45,6 +44,7 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "asJavaClass":
|
||||
case "classFromResource":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
return;
|
||||
}
|
||||
|
@ -54,34 +54,45 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
|
|||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "newInstance":
|
||||
generateNewInstance(context, writer);
|
||||
generateNewInstance(context, writer, methodRef);
|
||||
break;
|
||||
case "lookupClass":
|
||||
generateLookup(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String self = context.getParameterName(0);
|
||||
writer.append("if").ws().append("(!").appendClass(Platform.class).append(".$$constructors$$)").ws()
|
||||
.append("{").indent().softNewLine();
|
||||
writer.appendClass(Platform.class).append(".$$constructors$$").ws().append("=").append("true;").softNewLine();
|
||||
private void generateNewInstance(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||
throws IOException {
|
||||
writer.append("var c").ws().append("=").ws().append("'$$constructor$$';").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(".$$constructor$$").ws().append("=").ws()
|
||||
.appendMethodBody(method.getReference()).append(";").softNewLine();
|
||||
writer.appendClass(clsName).append("[c]").ws().append("=").ws()
|
||||
.append(writer.getNaming().getNameForInit(method.getReference()))
|
||||
.append(";").softNewLine();
|
||||
}
|
||||
}
|
||||
writer.appendMethodBody(methodRef).ws().append("=").ws().append("function(cls)").ws().append("{")
|
||||
.softNewLine().indent();
|
||||
writer.append("if").ws().append("(!cls.hasOwnProperty(c))").ws().append("{").indent().softNewLine();
|
||||
writer.append("return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("var cls = " + self + ".$data;").softNewLine();
|
||||
writer.append("var ctor = cls.$$constructor$$;").softNewLine();
|
||||
writer.append("if (!ctor) {").indent().softNewLine();
|
||||
writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();").softNewLine();
|
||||
writer.appendMethodBody(new MethodReference(InstantiationException.class, "<init>", void.class))
|
||||
.append("(ex);").softNewLine();
|
||||
writer.append("$rt_throw(ex);").softNewLine();
|
||||
writer.append("return cls[c]();").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return ").appendMethodBody(methodRef).append("(")
|
||||
.append(context.getParameterName(1)).append(");").softNewLine();
|
||||
}
|
||||
|
||||
private void generateLookup(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String param = context.getParameterName(1);
|
||||
writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent();
|
||||
for (String name : context.getClassSource().getClassNames()) {
|
||||
writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ")
|
||||
.append("return ").appendClass(name).append(";").softNewLine();
|
||||
}
|
||||
writer.append("default: return null;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("var instance = new cls();").softNewLine();
|
||||
writer.append("ctor(instance);").softNewLine();
|
||||
writer.append("return instance;").softNewLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,5 +31,6 @@ public class PlatformPlugin implements TeaVMPlugin {
|
|||
host.add(new ResourceAccessorDependencyListener());
|
||||
host.add(new AsyncMethodProcessor());
|
||||
host.add(new NewInstanceDependencySupport());
|
||||
host.add(new ClassLookupDependencySupport());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,34 @@ final class ResourceWriterHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static void writeIdentifier(SourceWriter writer, String id) throws IOException {
|
||||
if (id.isEmpty() || !isIdentifierStart(id.charAt(0))) {
|
||||
writeString(writer, id);
|
||||
return;
|
||||
}
|
||||
for (int i = 1; i < id.length(); ++i) {
|
||||
if (isIdentifierPart(id.charAt(i))) {
|
||||
writeString(writer, id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
writer.append(id);
|
||||
}
|
||||
|
||||
private static boolean isIdentifierStart(char c) {
|
||||
if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
|
||||
return true;
|
||||
}
|
||||
return c == '$' || c == '_';
|
||||
}
|
||||
|
||||
private static boolean isIdentifierPart(char c) {
|
||||
if (isIdentifierStart(c)) {
|
||||
return true;
|
||||
}
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
public static void writeString(SourceWriter writer, String s) throws IOException {
|
||||
writer.append('"');
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user