Adds some more support of reflection

This commit is contained in:
Alexey Andreev 2013-12-03 19:30:53 +04:00
parent b3fe2f6a29
commit 620d2cef62
7 changed files with 87 additions and 17 deletions

View File

@ -19,6 +19,9 @@ public class ClassNativeGenerator implements Generator {
case "isAssignable":
generateIsAssignableFrom(context, writer);
break;
case "getComponentType":
generateGetComponentType(context, writer);
break;
}
}
@ -31,4 +34,10 @@ public class ClassNativeGenerator implements Generator {
writer.append("return $rt_isAssignable(").append(context.getParameterName(1)).append(".$data, ")
.append(context.getParameterName(0)).append(".$data;").newLine();
}
private void generateGetComponentType(GeneratorContext context, SourceWriter writer) {
String thisArg = context.getParameterName(0);
writer.append("var item = " + thisArg + ".$data.$meta.item;").newLine();
writer.append("return item != null ? $rt_cls(item) : null;").newLine();
}
}

View File

@ -57,17 +57,7 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
private void generateGetClass(GeneratorContext context, SourceWriter writer) {
String thisArg = context.getParameterName(0);
String classClass = "java.lang.Class";
writer.append("var cls = ").append(thisArg).append(".$class.classObject;").newLine();
writer.append("if (cls === undefined) {").newLine().indent();
MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew",
ValueType.object(classClass)));
writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef)
.append("();").newLine();
writer.append("cls.$data = ").append(thisArg).append(".$class;").newLine();
writer.append(thisArg).append(".$class.classObject = cls;").newLine();
writer.outdent().append("}").newLine();
writer.append("return cls;").newLine();
writer.append("return $rt_cls(").append(thisArg).append(".$class);").newLine();
}
private void achieveGetClass(DependencyChecker checker) {

View File

@ -7,10 +7,39 @@ import org.teavm.javascript.ni.GeneratedBy;
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TClass<T> extends TObject {
String name;
boolean primitive;
boolean array;
private TClass<?> componentType;
private boolean componentTypeDirty = true;
static TClass<?> createNew() {
return new TClass<>();
}
@GeneratedBy(ClassNativeGenerator.class)
public native boolean isInstance(TObject obj);
public String getName() {
return name;
}
public boolean isPrimitive() {
return primitive;
}
public boolean isArray() {
return array;
}
public TClass<?> getComponentType() {
if (componentTypeDirty) {
componentType = getComponentType0();
componentTypeDirty = false;
}
return componentType;
}
@GeneratedBy(ClassNativeGenerator.class)
private native TClass<?> getComponentType0();
}

View File

@ -0,0 +1,30 @@
package org.teavm.classlib.java.lang;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
class TClassTests {
@Test
public void classNameEvaluated() {
assertEquals("java.lang.Object", Object.class.getName());
}
@Test
public void objectClassNameEvaluated() {
assertEquals("java.lang.Object", new Object().getClass().getName());
}
@Test
public void objectClassConsideredNotArray() {
assertFalse(Object.class.isArray());
}
@Test
public void arrayClassConsideredArray() {
assertFalse(Object[].class.isArray());
}
}

View File

@ -32,7 +32,7 @@ public class ClasslibTestGenerator {
private static List<MethodReference> testMethods = new ArrayList<>();
private static Map<String, List<MethodReference>> groupedMethods = new HashMap<>();
private static String[] testClasses = { "java.lang.ObjectTests", "java.lang.SystemTests",
"java.lang.StringBuilderTests" };
"java.lang.StringBuilderTests", "java.lang.ClassTests" };
public static void main(String[] args) throws IOException {
out = System.out;

View File

@ -52,16 +52,28 @@ public class Renderer implements ExprVisitor, StatementVisitor {
}
private void renderRuntimeCls() {
writer.append("$rt_cls = function(cls) {").indent().newLine();
writer.append("$rt_cls = function(clsProto) {").indent().newLine();
String classClass = "java.lang.Class";
writer.append("var cls = cls.classObject;").newLine();
writer.append("var cls = clsProto.classObject;").newLine();
writer.append("if (cls === undefined) {").newLine().indent();
MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew",
ValueType.object(classClass)));
writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef)
.append("();").newLine();
writer.append("cls.$data = cls;").newLine();
writer.append("cls.classObject = cls;").newLine();
writer.append("cls.$data = clsProto;").newLine();
if (classSource.getClassHolder(classClass).getField("name") != null) {
writer.append("cls.").appendField(new FieldReference(classClass, "name"))
.append(" = clsProto.$meta.name !== undefined ? $rt_str(clsProto.$meta.name) : null;").newLine();
}
if (classSource.getClassHolder(classClass).getField("primitive") != null) {
writer.append("cls.").appendField(new FieldReference(classClass, "primitive"))
.append(" = clsProto.$meta.primitive ? 1 : 0;").newLine();
}
if (classSource.getClassHolder(classClass).getField("array") != null) {
writer.append("cls.").appendField(new FieldReference(classClass, "array"))
.append(" = clsProto.$meta.item ? 1 : 0;").newLine();
}
writer.append("clsProto.classObject = cls;").newLine();
writer.outdent().append("}").newLine();
writer.append("return cls;").newLine();
writer.outdent().append("}").newLine();

View File

@ -50,7 +50,7 @@ $rt_arraycls = function(cls) {
this.$class = arraycls;
};
arraycls.prototype = new ($rt_objcls())();
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()] };
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false };
cls.$array = arraycls;
}
return cls.$array;