mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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 {
|
public class NewInstanceDependencySupport implements DependencyListener {
|
||||||
private DependencyNode allClassesNode;
|
private DependencyNode allClassesNode;
|
||||||
|
private DependencyStack newInstanceStack;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void started(DependencyChecker dependencyChecker) {
|
public void started(DependencyChecker dependencyChecker) {
|
||||||
|
@ -36,19 +37,31 @@ public class NewInstanceDependencySupport implements DependencyListener {
|
||||||
if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) {
|
if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
return;
|
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);
|
allClassesNode.propagate(className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
public void methodAchieved(final DependencyChecker dependencyChecker, MethodDependency method) {
|
||||||
MethodReader reader = method.getMethod();
|
MethodReader reader = method.getMethod();
|
||||||
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
||||||
|
newInstanceStack = method.getStack();
|
||||||
allClassesNode.connect(method.getResult());
|
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
|
@Override
|
||||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,9 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
||||||
case "newInstance":
|
case "newInstance":
|
||||||
generateNewInstance(context, writer);
|
generateNewInstance(context, writer);
|
||||||
break;
|
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.append("$rt_throw(ex);").softNewLine();
|
||||||
writer.outdent().append("}").softNewLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
writer.append("var instance = new cls();").softNewLine();
|
writer.append("var instance = new cls();").softNewLine();
|
||||||
writer.append("ctor(instance)");
|
writer.append("ctor(instance);").softNewLine();
|
||||||
writer.append("return instance");
|
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
|
@Override
|
||||||
|
@ -154,6 +176,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
||||||
case "getSuperclass":
|
case "getSuperclass":
|
||||||
case "getComponentType0":
|
case "getComponentType0":
|
||||||
case "forNameImpl":
|
case "forNameImpl":
|
||||||
|
case "getDeclaringClass":
|
||||||
graph.getResult().propagate("java.lang.Class");
|
graph.getResult().propagate("java.lang.Class");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,4 +134,8 @@ public class TClass<T extends TObject> extends TObject {
|
||||||
|
|
||||||
@GeneratedBy(ClassNativeGenerator.class)
|
@GeneratedBy(ClassNativeGenerator.class)
|
||||||
public native T newInstance() throws TInstantiationException, TIllegalAccessException;
|
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(TestObject.class, instance.getClass());
|
||||||
assertEquals(1, ((TestObject)instance).getCounter());
|
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 Set<String> interfaces = new HashSet<>();
|
||||||
private Map<MethodDescriptor, MethodHolder> methods = new HashMap<>();
|
private Map<MethodDescriptor, MethodHolder> methods = new HashMap<>();
|
||||||
private Map<String, FieldHolder> fields = new HashMap<>();
|
private Map<String, FieldHolder> fields = new HashMap<>();
|
||||||
|
private String ownerName;
|
||||||
|
|
||||||
public ClassHolder(String name) {
|
public ClassHolder(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
|
@ -106,4 +107,13 @@ public class ClassHolder extends ElementHolder implements ClassReader {
|
||||||
fields.remove(field.getName());
|
fields.remove(field.getName());
|
||||||
field.setOwner(null);
|
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);
|
FieldReader getField(String name);
|
||||||
|
|
||||||
Collection<? extends FieldReader> getFields();
|
Collection<? extends FieldReader> getFields();
|
||||||
|
|
||||||
|
String getOwnerName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ public class CopyClassHolderSource implements ClassHolderSource {
|
||||||
for (FieldHolder field : original.getFields()) {
|
for (FieldHolder field : original.getFields()) {
|
||||||
copy.addField(copyField(field));
|
copy.addField(copyField(field));
|
||||||
}
|
}
|
||||||
|
copy.setOwnerName(original.getOwnerName());
|
||||||
copyAnnotations(original.getAnnotations(), copy.getAnnotations());
|
copyAnnotations(original.getAnnotations(), copy.getAnnotations());
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,9 @@ class ClassRefsRenamer implements InstructionVisitor {
|
||||||
cls.removeField(field);
|
cls.removeField(field);
|
||||||
renamedCls.addField(field);
|
renamedCls.addField(field);
|
||||||
}
|
}
|
||||||
|
if (cls.getOwnerName() != null) {
|
||||||
|
renamedCls.setOwnerName(classNameMapper.map(cls.getOwnerName()));
|
||||||
|
}
|
||||||
rename(cls.getAnnotations(), renamedCls.getAnnotations());
|
rename(cls.getAnnotations(), renamedCls.getAnnotations());
|
||||||
for (String iface : cls.getInterfaces()) {
|
for (String iface : cls.getInterfaces()) {
|
||||||
renamedCls.getInterfaces().add(classNameMapper.map(iface));
|
renamedCls.getInterfaces().add(classNameMapper.map(iface));
|
||||||
|
|
|
@ -64,6 +64,14 @@ public class Parser {
|
||||||
MethodNode methodNode = (MethodNode)obj;
|
MethodNode methodNode = (MethodNode)obj;
|
||||||
cls.addMethod(parseMethod(methodNode, node.name));
|
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);
|
parseAnnotations(cls.getAnnotations(), node);
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user