mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Adds support of Class.getDeclaringClass method
This commit is contained in:
parent
9cdc099b1a
commit
3195879467
|
@ -24,6 +24,7 @@ import org.teavm.model.*;
|
|||
*/
|
||||
public class NewInstanceDependencySupport implements DependencyListener {
|
||||
private DependencyNode allClassesNode;
|
||||
private DependencyStack newInstanceStack;
|
||||
|
||||
@Override
|
||||
public void started(DependencyChecker dependencyChecker) {
|
||||
|
@ -36,17 +37,29 @@ public class NewInstanceDependencySupport implements DependencyListener {
|
|||
if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||
return;
|
||||
}
|
||||
if (cls.getMethod(new MethodDescriptor("<init>", ValueType.VOID)) != null) {
|
||||
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", ValueType.VOID));
|
||||
if (method != null) {
|
||||
allClassesNode.propagate(className);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
||||
public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) {
|
||||
MethodReader reader = method.getMethod();
|
||||
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
||||
newInstanceStack = method.getStack();
|
||||
allClassesNode.connect(method.getResult());
|
||||
method.getResult().addConsumer(new DependencyConsumer() {
|
||||
@Override public void consume(String type) {
|
||||
attachConstructor(dependencyChecker, type);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void attachConstructor(DependencyChecker checker, String type) {
|
||||
MethodReference ref = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
|
||||
checker.linkMethod(ref, newInstanceStack).use();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,6 +47,9 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "newInstance":
|
||||
generateNewInstance(context, writer);
|
||||
break;
|
||||
case "getDeclaringClass":
|
||||
generateGetDeclaringClass(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,8 +144,27 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
writer.append("$rt_throw(ex);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("var instance = new cls();").softNewLine();
|
||||
writer.append("ctor(instance)");
|
||||
writer.append("return instance");
|
||||
writer.append("ctor(instance);").softNewLine();
|
||||
writer.append("return instance;").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
|
||||
|
@ -154,6 +176,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "getSuperclass":
|
||||
case "getComponentType0":
|
||||
case "forNameImpl":
|
||||
case "getDeclaringClass":
|
||||
graph.getResult().propagate("java.lang.Class");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -134,4 +134,8 @@ public class TClass<T extends TObject> extends TObject {
|
|||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
public native T newInstance() throws TInstantiationException, TIllegalAccessException;
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public native TClass<?> getDeclaringClass();
|
||||
}
|
||||
|
|
|
@ -97,4 +97,12 @@ public class ClassTest {
|
|||
assertEquals(TestObject.class, instance.getClass());
|
||||
assertEquals(1, ((TestObject)instance).getCounter());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void declaringClassFound() {
|
||||
assertEquals(ClassTest.class, new A().getClass().getDeclaringClass());
|
||||
}
|
||||
|
||||
private static class A {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ public class ClassHolder extends ElementHolder implements ClassReader {
|
|||
private Set<String> interfaces = new HashSet<>();
|
||||
private Map<MethodDescriptor, MethodHolder> methods = new HashMap<>();
|
||||
private Map<String, FieldHolder> fields = new HashMap<>();
|
||||
private String ownerName;
|
||||
|
||||
public ClassHolder(String name) {
|
||||
super(name);
|
||||
|
@ -106,4 +107,13 @@ public class ClassHolder extends ElementHolder implements ClassReader {
|
|||
fields.remove(field.getName());
|
||||
field.setOwner(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOwnerName() {
|
||||
return ownerName;
|
||||
}
|
||||
|
||||
public void setOwnerName(String ownerName) {
|
||||
this.ownerName = ownerName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,4 +34,6 @@ public interface ClassReader extends ElementReader {
|
|||
FieldReader getField(String name);
|
||||
|
||||
Collection<? extends FieldReader> getFields();
|
||||
|
||||
String getOwnerName();
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ public class CopyClassHolderSource implements ClassHolderSource {
|
|||
for (FieldHolder field : original.getFields()) {
|
||||
copy.addField(copyField(field));
|
||||
}
|
||||
copy.setOwnerName(original.getOwnerName());
|
||||
copyAnnotations(original.getAnnotations(), copy.getAnnotations());
|
||||
return copy;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,9 @@ class ClassRefsRenamer implements InstructionVisitor {
|
|||
cls.removeField(field);
|
||||
renamedCls.addField(field);
|
||||
}
|
||||
if (cls.getOwnerName() != null) {
|
||||
renamedCls.setOwnerName(classNameMapper.map(cls.getOwnerName()));
|
||||
}
|
||||
rename(cls.getAnnotations(), renamedCls.getAnnotations());
|
||||
for (String iface : cls.getInterfaces()) {
|
||||
renamedCls.getInterfaces().add(classNameMapper.map(iface));
|
||||
|
|
|
@ -64,6 +64,14 @@ public class Parser {
|
|||
MethodNode methodNode = (MethodNode)obj;
|
||||
cls.addMethod(parseMethod(methodNode, node.name));
|
||||
}
|
||||
if (node.outerClass != null) {
|
||||
cls.setOwnerName(node.outerClass.replace('/', '.'));
|
||||
} else {
|
||||
int lastIndex = node.name.lastIndexOf('$');
|
||||
if (lastIndex != -1) {
|
||||
cls.setOwnerName(node.name.substring(0, lastIndex).replace('/', '.'));
|
||||
}
|
||||
}
|
||||
parseAnnotations(cls.getAnnotations(), node);
|
||||
return cls;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user