mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix abstract classes are considered by dependency analysis when constructed by reflection
Also fix #592
This commit is contained in:
parent
f0d805fda8
commit
7fe79a1768
|
@ -201,13 +201,22 @@ public class ReflectionDependencyListener extends AbstractDependencyListener {
|
||||||
.addLocation(location)
|
.addLocation(location)
|
||||||
.getVariable(0).getClassValueNode();
|
.getVariable(0).getClassValueNode();
|
||||||
classValueNode.addConsumer(reflectedType -> {
|
classValueNode.addConsumer(reflectedType -> {
|
||||||
if (reflectedType.getName().startsWith("[")) {
|
if (reflectedType.getName().startsWith("[") || reflectedType.getName().startsWith("~")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassReader cls = agent.getClassSource().get(reflectedType.getName());
|
||||||
|
if (cls == null || cls.hasModifier(ElementModifier.ABSTRACT)
|
||||||
|
|| cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<MethodDescriptor> accessibleMethods = getAccessibleMethods(agent, reflectedType.getName());
|
Set<MethodDescriptor> accessibleMethods = getAccessibleMethods(agent, reflectedType.getName());
|
||||||
ClassReader cls = agent.getClassSource().get(reflectedType.getName());
|
|
||||||
for (MethodDescriptor methodDescriptor : accessibleMethods) {
|
for (MethodDescriptor methodDescriptor : accessibleMethods) {
|
||||||
|
if (!methodDescriptor.getName().equals("<init>")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
MethodReader calledMethod = cls.getMethod(methodDescriptor);
|
MethodReader calledMethod = cls.getMethod(methodDescriptor);
|
||||||
MethodDependency calledMethodDep = agent.linkMethod(calledMethod.getReference()).addLocation(location);
|
MethodDependency calledMethodDep = agent.linkMethod(calledMethod.getReference()).addLocation(location);
|
||||||
calledMethodDep.use();
|
calledMethodDep.use();
|
||||||
|
@ -218,8 +227,9 @@ public class ReflectionDependencyListener extends AbstractDependencyListener {
|
||||||
calledMethodDep.getVariable(0).propagate(reflectedType);
|
calledMethodDep.getVariable(0).propagate(reflectedType);
|
||||||
linkClassIfNecessary(agent, calledMethod, location);
|
linkClassIfNecessary(agent, calledMethod, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
method.getResult().propagate(reflectedType);
|
||||||
});
|
});
|
||||||
classValueNode.connect(method.getResult());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleInvoke(DependencyAgent agent, MethodDependency method) {
|
private void handleInvoke(DependencyAgent agent, MethodDependency method) {
|
||||||
|
@ -235,6 +245,9 @@ public class ReflectionDependencyListener extends AbstractDependencyListener {
|
||||||
Set<MethodDescriptor> accessibleMethods = getAccessibleMethods(agent, reflectedType.getName());
|
Set<MethodDescriptor> accessibleMethods = getAccessibleMethods(agent, reflectedType.getName());
|
||||||
ClassReader cls = agent.getClassSource().get(reflectedType.getName());
|
ClassReader cls = agent.getClassSource().get(reflectedType.getName());
|
||||||
for (MethodDescriptor methodDescriptor : accessibleMethods) {
|
for (MethodDescriptor methodDescriptor : accessibleMethods) {
|
||||||
|
if (methodDescriptor.getName().equals("<init>")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
MethodReader calledMethod = cls.getMethod(methodDescriptor);
|
MethodReader calledMethod = cls.getMethod(methodDescriptor);
|
||||||
MethodDependency calledMethodDep = agent.linkMethod(calledMethod.getReference()).addLocation(location);
|
MethodDependency calledMethodDep = agent.linkMethod(calledMethod.getReference()).addLocation(location);
|
||||||
calledMethodDep.use();
|
calledMethodDep.use();
|
||||||
|
|
|
@ -67,7 +67,16 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||||
switch (method.getReference().getName()) {
|
switch (method.getReference().getName()) {
|
||||||
case "newEmptyInstance":
|
case "newEmptyInstance":
|
||||||
method.getVariable(0).getClassValueNode().connect(method.getResult());
|
method.getVariable(0).getClassValueNode().addConsumer(type -> {
|
||||||
|
String className = type.getName();
|
||||||
|
if (!className.startsWith("[") && !className.startsWith("~")) {
|
||||||
|
ClassReader cls = agent.getClassSource().get(className);
|
||||||
|
if (cls != null && !cls.hasModifier(ElementModifier.ABSTRACT)
|
||||||
|
&& !cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
|
method.getResult().propagate(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case "getSuperclass":
|
case "getSuperclass":
|
||||||
reachGetSuperclass(agent, method);
|
reachGetSuperclass(agent, method);
|
||||||
|
|
|
@ -108,6 +108,11 @@ public class DependencyTest {
|
||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reflectionConstructor() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
private void doTest() {
|
private void doTest() {
|
||||||
TeaVM vm = new TeaVMBuilder(new JavaScriptTarget())
|
TeaVM vm = new TeaVMBuilder(new JavaScriptTarget())
|
||||||
.setClassLoader(DependencyTest.class.getClassLoader())
|
.setClassLoader(DependencyTest.class.getClassLoader())
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.AbstractList;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class DependencyTestData {
|
public class DependencyTestData {
|
||||||
private DependencyTestData() {
|
private DependencyTestData() {
|
||||||
}
|
}
|
||||||
|
@ -114,6 +118,14 @@ public class DependencyTestData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void reflectionConstructor() throws Exception {
|
||||||
|
var classes = new Class<?>[] { AbstractList.class, ArrayList.class };
|
||||||
|
for (var cls : classes) {
|
||||||
|
var instance = cls.getConstructor().newInstance();
|
||||||
|
MetaAssertions.assertTypes(instance, ArrayList.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface I {
|
interface I {
|
||||||
Object foo();
|
Object foo();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user